def parse_header(self, elem): values = self._collect('header', elem) # Handle a reference to a DataStructureDefinition attrs = {} for k in ['id', 'agencyid', 'version', 'urn']: value = values.pop('structure_ref_' + k, None) if not value: continue elif k == 'agencyid': attrs['maintainer'] = Agency(id=value) else: attrs[k] = value if set(attrs.keys()) == {'urn'}: attrs['id'] = values['structure_id'] if 'id' in attrs: # Create the DSD and DFD dsd = self._maintained(DataStructureDefinition, **attrs) dfd = DataflowDefinition(id=values.pop('structure_id'), structure=dsd) # Also store the dimension at observation self._set_obs_dim(values.pop('dim_at_obs')) extra = [dfd] else: extra = [] # Maybe return the DFD; see .initialize() return [Header(**values)] + extra
def codelist(): """A Codelist for writer testing.""" ECB = Agency(id="ECB") cl = Codelist( id="CL_COLLECTION", version="1.0", is_final=False, is_external_reference=False, maintainer=ECB, name={"en": "Collection indicator code list"}, ) # Add items for info in CL_ITEMS: cl.items[info["id"]] = Code(**info) # Add a hierarchical relationship cl.items["B"].append_child(cl.items["B1"]) # Add an annotation cl.items["A"].annotations.append( Annotation(id="A1", type="NOTE", text={"en": "Text annotation on Code A."}) ) return cl
def parse_header(self, elem): # Collect values from *elem* and its children using XPath values = {} for key, xpath in HEADER_XPATH.items(): matches = xpath(elem) if len(matches) == 0: continue values[key] = matches[0] if len(matches) == 1 else matches # Handle a reference to a DataStructureDefinition attrs = {} for k in ['id', 'agencyid', 'version', 'urn']: value = values.pop('structure_ref_' + k, None) if not value: continue elif k == 'agencyid': attrs['maintainer'] = Agency(id=value) else: attrs[k] = value if set(attrs.keys()) == {'urn'}: attrs['id'] = values['structure_id'] extra = [] if 'id' in attrs: # Create or retrieve the DSD. NB if the dsd argument was provided # to read_message(), this should be the same DSD dsd = self._maintained(DataStructureDefinition, **attrs) if 'structure_id' in values: # Add the DSD to the index a second time, using the message # -specific structure ID (rather that the DSD's own ID). key = ('DataStructureDefinition', values['structure_id']) self._index[key] = dsd # Create a DataflowDefinition dfd = DataflowDefinition(id=values.pop('structure_id'), structure=dsd) extra.append(dfd) # Store the observation at dimension level dim_at_obs = values.pop('dim_at_obs') if dim_at_obs == 'AllDimensions': self._obs_dim = AllDimensions else: # Retrieve or create the Dimension args = dict(id=dim_at_obs, order=1e9) if 'TimeSeries' in self._stack[0]: # {,StructureSpecific}TimeSeriesData message → the # dimension at observation level is a TimeDimension args['cls'] = TimeDimension self._obs_dim = dsd.dimensions.get(**args) # Maybe return the DFD; see .initialize() return [Header(**values)] + extra
def _named(self, cls, elem, **kwargs): """Parse a NameableArtefact of *cls* from *elem*. NameableArtefacts may have .name and .description attributes that are InternationalStrings, plus zero or more Annotations. _named() handles these common elements, and returns an object and a _parse()'d dict of other, class-specific child values. Additional *kwargs* are used when parsing the children of *elem*. """ # Apply conversions to attributes convert_attrs = { 'agencyID': ('maintainer', lambda value: Agency(id=value)), 'isExternalReference': ('is_external_reference', bool), 'isFinal': ('is_final', bool), 'isPartial': ('is_partial', bool), 'structureURL': ('structure_url', lambda value: value), 'role': ('role', lambda value: ConstraintRole(role=ConstraintRoleType[value])), 'validFrom': ('valid_from', str), 'validTo': ('valid_to', str), } attr = copy(elem.attrib) for source, (target, xform) in convert_attrs.items(): try: attr[target] = xform(attr.pop(source)) except KeyError: continue try: # Maybe retrieve an existing reference obj = self._maintained(cls, **attr) # Since the object is now being parsed, it's defined in the current # message and no longer an external reference obj.is_external_reference = False except TypeError: # Instantiate the class and store its attributes obj = cls(**attr) # Store object for parsing children self._current[(cls, obj.id)] = obj # Parse children values = self._parse(elem, **kwargs) # Store the name, description and annotations add_localizations(obj.name, values.pop('name')) add_localizations(obj.description, values.pop('description', [])) obj.annotations = wrap(values.pop('annotations', [])) # Return the instance and any non-name values return obj, values
def _named(self, cls, elem, **kwargs): """Parse a NameableArtefact of *cls* from *elem*. NameableArtefacts may have .name and .description attributes that are InternationalStrings, plus zero or more Annotations. _named() handles these common elements, and returns an object and a _parse()'d dict of other, class-specific child values. Additional *kwargs* are used when parsing the children of *elem*. """ # Apply conversions to attributes convert_attrs = { 'agency_id': ('maintainer', lambda value: Agency(id=value)), 'role': ('role', lambda value: ConstraintRole(role=ConstraintRoleType[value])), } attr = {} for name, value in elem.attrib.items(): # Name in snake case name = to_snake(name) # Optional new name and function to transform the value (name, xform) = convert_attrs.get(name, (name, lambda v: v)) # Store transformed value attr[name] = xform(value) try: # Maybe retrieve an existing reference obj = self._maintained(cls, **attr) # Since the object is now being parsed, it's defined in the current # message and no longer an external reference obj.is_external_reference = False except TypeError: # Instantiate the class and store its attributes obj = cls(**attr) # Store object for parsing children self._current[(cls, obj.id)] = obj # Parse children values = self._parse(elem, **kwargs) # Store the name, description and annotations add_localizations(obj.name, values.pop('name')) add_localizations(obj.description, values.pop('description', [])) obj.annotations = wrap(values.pop('annotations', [])) # Return the instance and any non-name values return obj, values