Source code for pydov.types.fields

# -*- coding: utf-8 -*-
"""Module grouping all classes related to pydov field definitions."""


[docs] class XsdType(object): """Class for specifying an XSD type from an XSD schema. This will be resolved at runtime in a list of possible values and their definitions.""" def __init__(self, xsd_schema, typename): """Initialise a XSD type reference. Parameters ---------- xsd_schema : str URL of XSD schema record containing the specified typename. typename : str Name of the type. """ self.xsd_schema = xsd_schema self.typename = typename
[docs] class AbstractField(dict): """Abstract base class for pydov field definitions. Not to be instantiated directly.""" def __init__(self, name, source, datatype, **kwargs): """Initialise a field. Parameters ---------- name : str Name of this field in the return dataframe. source : one of 'wfs', 'xml', 'custom_wfs', 'custom_xml' Source of this field. datatype : one of 'string', 'integer', 'float', 'date', 'datetime' \ or 'boolean' Datatype of the values of this field in the return dataframe. """ super(AbstractField, self).__init__(**kwargs) self.__setitem__('name', name) self.__setitem__('source', source) self.__setitem__('type', datatype)
[docs] class WfsField(AbstractField): """Class for a field available in the WFS service.""" def __init__(self, name, source_field, datatype): """Initialise a WFS field. Parameters ---------- name : str Name of this field in the return dataframe. source_field : str Name of this field in the source WFS service. datatype : one of 'string', 'integer', 'float', 'date', 'datetime' \ or 'boolean' Datatype of the values of this field in the return dataframe. """ super(WfsField, self).__init__(name, 'wfs', datatype) self.__setitem__('sourcefield', source_field)
class _WfsInjectedField(WfsField): """Class for a field available in the WFS service, but not included in the default dataframe output.""" def __init__(self, name, datatype): """Initialise a WFS injected field. This is a field not normally present in the dataframe, but usable as a query and returnfield as it is available in the WFS service. Parameters ---------- name : str Name of this field in the return dataframe. datatype : one of 'string', 'integer', 'float', 'date', 'datetime' \ or 'boolean' Datatype of the values of this field in the return dataframe. """ super(_WfsInjectedField, self).__init__(name, name, datatype) self.__setitem__('wfs_injected', True)
[docs] class XmlField(AbstractField): """Class for a field available in the XML document.""" def __init__(self, name, source_xpath, datatype, definition='', notnull=False, xsd_type=None): """Initialise an XML field. Parameters ---------- name : str Name of this field in the return dataframe. source_xpath : str XPath expression of the values of this field in the source XML document. datatype : one of 'string', 'integer', 'float', 'date', 'datetime' \ or 'boolean' Datatype of the values of this field in the return dataframe. definition : str, optional Definition of this field. notnull : bool, optional, defaults to False True if this field is always present (mandatory), False otherwise. xsd_type : pydov.types.abstract.XsdType, optional XSD type associated with this field. """ super(XmlField, self).__init__(name, 'xml', datatype) self.__setitem__('sourcefield', source_xpath) self.__setitem__('definition', definition) self.__setitem__('notnull', notnull) if xsd_type is not None: self.__setitem__('xsd_schema', xsd_type.xsd_schema) self.__setitem__('xsd_type', xsd_type.typename)
class _CustomWfsField(AbstractField): """Class for a custom field, created explicitly in pydov from other WFS fields.""" def __init__(self, name, datatype, definition='', notnull=False): """Initialise a custom field. Parameters ---------- name : str Name of this field in the return dataframe. datatype : one of 'string', 'integer', 'float', 'date', 'datetime' \ or 'boolean' Datatype of the values of this field in the return dataframe. definition : str, optional Definition of this field. notnull : bool, optional, defaults to False True if this field is always present (mandatory), False otherwise. """ super(_CustomWfsField, self).__init__(name, 'custom_wfs', datatype) self.__setitem__('definition', definition) self.__setitem__('notnull', notnull) def requires_wfs_fields(self): """Get a list of WFS fields that are required by (the calculation of) this custom field. Returns ------- list of str List of WFS fieldnames that is required by this custom field. Raises ------ NotImplementedError Implement this in a subclass. """ raise NotImplementedError def calculate(self, instance): """Calculate the value of this custom field for the given instance. Parameters ---------- instance : AbstractDovType Instance of the corresponding type, containing all WFS values in its data dictionary. Returns ------- Value to be used for this custom field for this instance. Its datatype should match the one set in the initialisation of the custom field. Raises ------ NotImplementedError Implement this in a subclass. """ raise NotImplementedError class _CustomXmlField(AbstractField): """Class for a custom field, created explicitly in pydov from other XML fields.""" def __init__(self, name, datatype, definition='', notnull=False): """Initialise a custom field. Parameters ---------- name : str Name of this field in the return dataframe. datatype : one of 'string', 'integer', 'float', 'date', 'datetime' \ or 'boolean' Datatype of the values of this field in the return dataframe. definition : str, optional Definition of this field. notnull : bool, optional, defaults to False True if this field is always present (mandatory), False otherwise. """ super(_CustomXmlField, self).__init__(name, 'custom_xml', datatype) self.__setitem__('definition', definition) self.__setitem__('notnull', notnull) def calculate(self, cls, tree): """Calculate the value of this custom field from the given XML tree. Parameters ---------- cls : AbstractDovType Class of the type this field belongs to. tree : etree.ElementTree ElementTree of the DOV XML for this instance. Returns ------- Value to be used for this custom field for this instance. Its datatype should match the one set in the initialisation of the custom field. Raises ------ NotImplementedError Implement this in a subclass. """ raise NotImplementedError
[docs] class ReturnFieldList(list): """List of return fields used in search methods. """ def __contains__(self, __key: object): """Overwrite the default method. Checks on field name. Parameters ---------- __key The key to check. Returns ------- boolean Whether the key is one of the names in the ReturnFieldList. """ return __key in [i.name for i in self]
[docs] def get_names(self): """Return a list with all the names of the fields in this ReturnFieldList. Returns ------- list of str List of field names. """ return [f.name for f in self]
[docs] @classmethod def from_field_names(self, *return_fields): """Initiale a ReturnFieldList from a list of return field names. Parameters ---------- return_fields : list or set or tuple of str List, set or tuple of return field names. Returns ------- ReturnFieldList Equivalent ReturnFieldList. Raises ------ AttributeError If the value of return_fields is not a list, set or tuple. """ if len(return_fields) == 0: return None if len(return_fields) == 1: return_fields = return_fields[0] if isinstance(return_fields, str): return_fields = (return_fields,) if return_fields is None: return None if not isinstance(return_fields, (list, set, tuple)): # FIXME: this should be TypeError instead raise AttributeError( 'return_fields should be a list, set or tuple') result = ReturnFieldList() for rf in return_fields: if isinstance(rf, AbstractReturnField): result.append(rf) else: result.append(ReturnField.from_field_name(rf)) return result
[docs] class AbstractReturnField: """Base class of ReturnField and GeometryReturnField.""" def __init__(self, name): """Initialisation. Parameters ---------- name : str Name of the return field. """ self.name = name
[docs] @classmethod def from_field_name(cls, name): """Initialise a new instance from a field name. Parameters ---------- name : str Field name. Returns ------- Instance of this class. Instance of ReturnField or GeometryReturnField. """ return cls(name)
[docs] class ReturnField(AbstractReturnField): """Normal (non-geometry) return field.""" def __init__(self, name): """Initialisation. Parameters ---------- name : str Name of the return field. """ super().__init__(name)
[docs] class GeometryReturnField(AbstractReturnField): def __init__(self, geometry_field, epsg=None): """Initialise a geometry return field. Parameters ---------- geometry_field : str Name of the geometry field. epsg : int, optional EPSG code of the CRS of the geometries that will be returned. Defaults to None, which means the default CRS of the WFS layer. """ super().__init__(geometry_field) if epsg is not None: if not isinstance(epsg, int): raise TypeError('epsg should be an integer value') self.epsg = epsg