def _message(reader, elem): """Start of a Message.""" # <mes:Structure> within <mes:Header> of a data message is handled by # _header_structure() below. if getattr(elem.getparent(), "tag", None) == qname("mes", "Header"): return ss_without_dsd = False # With 'dsd' argument, the message should be structure-specific if ( "StructureSpecific" in elem.tag and reader.get_single(model.DataStructureDefinition) is None ): log.warning(f"sdmxml.Reader got no dsd=… argument for {QName(elem).localname}") ss_without_dsd = True # The following seems to only confuse users. # Thus it is commented out post v1.1.0 # elif "StructureSpecific" not in elem.tag and reader.get_single( # model.DataStructureDefinition # log.warning("Ambiguous: dsd=… argument for non–structure-specific message") # Store values for other methods reader.push("SS without DSD", ss_without_dsd) if "Data" in elem.tag: reader.push("DataSetClass", model.get_class(f"{QName(elem).localname}Set")) # Instantiate the message object cls = class_for_tag(elem.tag) return cls()
def __init__(self, elem, cls_hint=None): parent_tag = elem.tag try: # Use the first child elem = elem[0] except IndexError: raise NotReference # Extract information from the XML element if elem.tag == "Ref": # Element attributes give target_id, id, and version target_id = elem.attrib["id"] agency_id = elem.attrib.get("agencyID", None) id = elem.attrib.get("maintainableParentID", target_id) version = elem.attrib.get( "maintainableParentVersion", None ) or elem.attrib.get("version", None) # Attributes of the element itself, if any args = (elem.attrib.get("class", None), elem.attrib.get("package", None)) elif elem.tag == "URN": match = pandasdmx.urn.match(elem.text) # If the URN doesn't specify an item ID, it is probably a reference to a # MaintainableArtefact, so target_id and id are the same target_id = match["item_id"] or match["id"] agency_id = match["agency"] id = match["id"] version = match["version"] args = (match["class"], match["package"]) else: raise NotReference # Find the target class target_cls = model.get_class(*args) if target_cls is None: # Try the parent tag name target_cls = class_for_tag(parent_tag) if cls_hint and (target_cls is None or issubclass(cls_hint, target_cls)): # Hinted class is more specific than target_cls, or failed to find a target # class above target_cls = cls_hint self.maintainable = issubclass(target_cls, model.MaintainableArtefact) if self.maintainable: # MaintainableArtefact is the same as the target cls, id = target_cls, target_id else: # Get the class for the parent MaintainableArtefact cls = model.parent_class(target_cls) # Store self.cls = cls self.agency = model.Agency(id=agency_id) if agency_id else _NO_AGENCY self.id = id self.version = version self.target_cls = target_cls self.target_id = target_id
def test_get_class(): with pytest.raises(ValueError, match="Package 'codelist' invalid for Category"): model.get_class(name="Category", package="codelist")