def test_replace_child(self): individual_name = Node(names.INDIVIDUALNAME) sur_name_1 = Node(names.SURNAME, parent=individual_name) sur_name_1.content = 'Gaucho' individual_name.add_child(sur_name_1) sur_name_2 = Node(names.SURNAME, parent=individual_name) sur_name_2.content = 'Carroll' self.assertIn(sur_name_1, individual_name.children) self.assertNotIn(sur_name_2, individual_name.children) individual_name.replace_child(old_child=sur_name_1, new_child=sur_name_2) self.assertIn(sur_name_2, individual_name.children) self.assertNotIn(sur_name_1, individual_name.children) # Test for old child removal from node store self.assertNotIn(sur_name_1.id, Node.store) # Test for child node type mismatch given_name = Node(names.GIVENNAME) given_name.content = 'Chase' try: individual_name.replace_child(old_child=sur_name_2, new_child=given_name) except ValueError as e: self.assertIsNotNone(e)
def test_child_insert_index(): # Part 1 eml = Node(names.EML) eml.add_attribute("packageId", "edi.23.1") eml.add_attribute("system", "metapype") access = Node(names.ACCESS, parent=eml) eml.add_child(access) additional_metadata = Node(names.ADDITIONALMETADATA, parent=eml) eml.add_child(additional_metadata) r = rule.get_rule(names.EML) dataset = Node(names.DATASET, parent=eml) index = r.child_insert_index(eml, dataset) eml.add_child(dataset, index=index) validate.node(eml) # Part 2 r = rule.get_rule(names.ASSOCIATEDPARTY) associated_party = Node(names.ASSOCIATEDPARTY) organization_name = Node(names.ORGANIZATIONNAME) index = r.child_insert_index(associated_party, organization_name) associated_party.add_child(organization_name, index) address = Node(names.ADDRESS) associated_party.add_child(address) online_url = Node(names.ONLINEURL) associated_party.add_child(online_url) position_name = Node(names.POSITIONNAME) index = r.child_insert_index(associated_party, position_name) associated_party.add_child(position_name, index) role = Node(names.ROLE) index = r.child_insert_index(associated_party, role) associated_party.add_child(role, index) validate.node(associated_party)
def test_find_all_nodes_by_path(node): access = Node(names.ACCESS) node.add_child(access) children = node.find_all_nodes_by_path([names.ACCESS]) assert children == [access] allow = Node(names.ALLOW) access.add_child(allow) grandchildren = node.find_all_nodes_by_path([names.ACCESS, names.ALLOW]) assert grandchildren == [allow] principal_1 = Node(names.PRINCIPAL) allow.add_child(principal_1) principal_2 = Node(names.PRINCIPAL) allow.add_child(principal_2) great_grandchildren = node.find_all_nodes_by_path( [names.ACCESS, names.ALLOW, names.PRINCIPAL]) assert great_grandchildren == [principal_1, principal_2] child = node.find_all_nodes_by_path( [names.ACCESS, names.ALLOW, "nonesuch"]) assert child == [] child = node.find_all_nodes_by_path([]) assert child == [] child = node.find_all_nodes_by_path(None) assert child == []
def test_find_single_node_by_path(node): access = Node(names.ACCESS) node.add_child(access) child = node.find_single_node_by_path([names.ACCESS]) assert access is child allow = Node(names.ALLOW) access.add_child(allow) grandchild = node.find_single_node_by_path([names.ACCESS, names.ALLOW]) assert grandchild is allow permission = Node(names.PERMISSION) allow.add_child(permission) great_grandchild = node.find_single_node_by_path( [names.ACCESS, names.ALLOW, names.PERMISSION]) assert great_grandchild is permission child = node.find_single_node_by_path( [names.ACCESS, names.ALLOW, "nonesuch"]) assert child is None child = node.find_single_node_by_path([]) assert child is None child = node.find_single_node_by_path(None) assert child is None
def test_add_child(self): child_1 = Node(names.ACCESS) self.node.add_child(child_1) children = self.node.children self.assertIs(child_1, children[0]) child_2 = Node(names.DATASET) self.node.add_child(child_2, 0) self.assertIs(child_2, children[0])
def test_add_child(node): child_1 = Node(names.ACCESS) node.add_child(child_1) children = node.children assert child_1 is children[0] child_2 = Node(names.DATASET) node.add_child(child_2, 0) assert child_2 is children[0]
def test_validate_sequence(): errs = list() entity_code_list = Node(names.ENTITYCODELIST) entity_reference = Node(names.ENTITYREFERENCE) entity_code_list.add_child(entity_reference) value_attribute_reference = Node(names.VALUEATTRIBUTEREFERENCE) entity_code_list.add_child(value_attribute_reference) definition_attribute_reference = Node(names.DEFINITIONATTRIBUTEREFERENCE) entity_code_list.add_child(definition_attribute_reference) validate.node(entity_code_list)
def test_validate_layered_choice(): responsible_party = Node(names.CONTACT) individual_name = Node(names.INDIVIDUALNAME) responsible_party.add_child(individual_name) responsible_party.add_child(individual_name) position_name = Node(names.POSITIONNAME) responsible_party.add_child(position_name) phone = Node(names.PHONE) responsible_party.add_child(phone) validate.node(responsible_party)
def test_responsible_party_with_role(): personnel = Node(names.PERSONNEL) personnel.add_attribute("id", "personnel") personnel.add_namespace("eml", "https://eml.ecoinformatics.org/eml-2.2.0") individual_name = Node(names.INDIVIDUALNAME) personnel.add_child(individual_name) given_name = Node(names.GIVENNAME, content="Chase") given_name.add_attribute("lang", "Spanish") individual_name.add_child(given_name) sur_name = Node(names.SURNAME, content="Gaucho") sur_name.add_attribute("lang", "Spanish") individual_name.add_child(sur_name) individual_name = Node(names.INDIVIDUALNAME) personnel.add_child(individual_name) given_name = Node(names.GIVENNAME, content="Cactus") individual_name.add_child(given_name) sur_name = Node(names.SURNAME, content="Jack") individual_name.add_child(sur_name) phone = Node(names.PHONE, content="999-999-9999") personnel.add_child(phone) errs = [] # Without role, should get an error with pytest.raises(MetapypeRuleError): validate.tree(personnel) # Error should name 'role' as the cause validate.tree(personnel, errs) for err_code, msg, node, *args in errs: err_cause, min = args assert err_cause == 'role' # With role, it should be ok role = Node(names.ROLE, content="drummer") personnel.add_child(role) validate.tree(personnel, errs)
def test_validate_annotation(): annotation = Node(names.ANNOTATION) property_uri = Node(names.PROPERTYURI) property_uri.content = "http://purl.obolibrary.org/obo/IAO_0000136" property_uri.add_attribute("label", "some property label") annotation.add_child(property_uri) value_uri = Node(names.VALUEURI) value_uri.content = "http://purl.obolibrary.org/obo/IAO_0000136" value_uri.add_attribute("label", "some value label") annotation.add_child(value_uri) validate.tree(annotation)
def test_validate_choice(): attribute = Node(names.ATTRIBUTE) attribute_name = Node(names.ATTRIBUTENAME) attribute.add_child(attribute_name) attribute_definition = Node(names.ATTRIBUTEDEFINITION) attribute.add_child(attribute_definition) measurement_scale = Node(names.MEASUREMENTSCALE) attribute.add_child(measurement_scale) # references = Node(names.REFERENCES) # attribute.add_child(references) validate.node(attribute)
def test_child_insert_index(self): eml = Node(names.EML) access = Node(names.ACCESS, parent=eml) eml.add_child(access) additional_metadata = Node(names.ADDITIONALMETADATA, parent=eml) eml.add_child(additional_metadata) r = rule.get_rule(names.EML) dataset = Node(names.DATASET, parent=eml) index = r.child_insert_index(eml, dataset) eml.add_child(dataset, index=index) self.assertIsInstance(index, int)
def test_validate_sequence_bad_order(): externally_defined_format = Node(names.EXTERNALLYDEFINEDFORMAT) format_name = Node(names.FORMATNAME) externally_defined_format.add_child(format_name) format_version = Node(names.FORMATVERSION) citation = Node(names.CITATION) externally_defined_format.add_child(citation) externally_defined_format.add_child(format_version) try: validate.node(externally_defined_format) except ChildNotAllowedError as e: assert isinstance(e, ChildNotAllowedError)
def test_is_in_path(): associated_party = Node(names.ASSOCIATEDPARTY) organization_name = Node(names.ORGANIZATIONNAME) associated_party.add_child(organization_name) address = Node(names.ADDRESS) associated_party.add_child(address) online_url = Node(names.ONLINEURL) associated_party.add_child(online_url) phone = Node(names.PHONE) r = rule.get_rule(names.ASSOCIATEDPARTY) print("\n") assert Rule._is_in_path(r.children, phone)
def add_geo_coverage_node(eml_node, description, north, south, east, west): dataset_node = eml_node.find_child(names.DATASET) if not dataset_node: dataset_node = Node(names.DATASET) coverage_node = dataset_node.find_child(names.COVERAGE) if not coverage_node: coverage_node = Node(names.COVERAGE, parent=dataset_node) add_child(dataset_node, coverage_node) gc_node = Node(names.GEOGRAPHICCOVERAGE, parent=coverage_node) add_child(coverage_node, gc_node) create_geographic_coverage(gc_node, description, west, east, north, south)
def load_other_entity(dataset_node: Node = None, uploads_path: str = None, data_file: str = ''): full_path = f'{uploads_path}/{data_file}' other_entity_node = Node(names.OTHERENTITY, parent=dataset_node) add_child(dataset_node, other_entity_node) physical_node = Node(names.PHYSICAL, parent=other_entity_node) add_child(other_entity_node, physical_node) physical_node.add_attribute('system', 'EDI') entity_name_node = Node(names.ENTITYNAME, parent=other_entity_node) add_child(other_entity_node, entity_name_node) entity_name = entity_name_from_data_file(data_file) entity_name_node.content = entity_name object_name_node = Node(names.OBJECTNAME, parent=physical_node) add_child(physical_node, object_name_node) object_name_node.content = data_file file_size = get_file_size(full_path) if file_size is not None: size_node = Node(names.SIZE, parent=physical_node) add_child(physical_node, size_node) size_node.add_attribute('unit', 'byte') size_node.content = str(file_size) md5_hash = get_md5_hash(full_path) if md5_hash is not None: hash_node = Node(names.AUTHENTICATION, parent=physical_node) add_child(physical_node, hash_node) hash_node.add_attribute('method', 'MD5') hash_node.content = str(md5_hash) data_format_node = Node(names.DATAFORMAT, parent=physical_node) add_child(physical_node, data_format_node) externally_defined_format_node = Node(names.EXTERNALLYDEFINEDFORMAT, parent=data_format_node) add_child(data_format_node, externally_defined_format_node) format_name_node = Node(names.FORMATNAME, parent=externally_defined_format_node) add_child(externally_defined_format_node, format_name_node) format_name_node.content = format_name_from_data_file(data_file) entity_type_node = new_child_node(names.ENTITYTYPE, parent=other_entity_node) entity_type_node.content = format_name_from_data_file(data_file) delete_data_files(uploads_path) return other_entity_node
def test_remove_child(node): access = Node(names.ACCESS) node.add_child(access) child = node.children[0] assert access is child node.remove_child(child) assert access not in node.children
def test_remove_child(self): access = Node(names.ACCESS) self.node.add_child(access) child = self.node.children[0] self.assertIs(access, child) self.node.remove_child(child) self.assertNotIn(access, self.node.children)
def test_missing_numerical_unit(): unit = Node(names.UNIT, parent=None) r = rule.get_rule(names.UNIT) with pytest.raises(MetapypeRuleError): r.validate_rule(unit) # Check error errs = [] validate.tree(unit, errs) assert len(errs) == 1 err_code, msg, node, *args = errs[0] assert err_code == ValidationError.MIN_CHOICE_UNMET assert args[0] == 'unit' # With a customUnit, it should be ok custom_unit = Node(names.CUSTOMUNIT, parent=unit) custom_unit.content = 'bushels per parsec' unit.add_child(custom_unit) validate.tree(unit)
def test_taxonid(): taxonId = Node(names.TAXONID, parent=None) taxonId.content = "42" # without the provider, we should get an error with pytest.raises(MetapypeRuleError): validate.node(taxonId) # with the provider, it should be ok taxonId.add_attribute("provider", "https://www.itis.gov") validate.node(taxonId)
def test_find_descendant(node): access = Node(names.ACCESS) node.add_child(access) child = node.find_descendant(names.ACCESS) assert access is child allow = Node(names.ALLOW) access.add_child(allow) grandchild = node.find_descendant(names.ALLOW) assert grandchild is allow permission = Node(names.PERMISSION) allow.add_child(permission) great_grandchild = node.find_descendant(names.PERMISSION) assert great_grandchild is permission child = node.find_descendant("nonesuch") assert child is None
def test_to_json(self): eml = Node(names.EML) eml.add_attribute('packageId', 'edi.23.1') eml.add_attribute('system', 'metapype') access = Node(names.ACCESS, parent=eml) access.add_attribute('authSystem', 'pasta') access.add_attribute('order', 'allowFirst') eml.add_child(access) allow = Node(names.ALLOW, parent=access) access.add_child(allow) principal = Node(names.PRINCIPAL, parent=allow) principal.content = 'uid=gaucho,o=EDI,dc=edirepository,dc=org' allow.add_child(principal) permission = Node(names.PERMISSION, parent=allow) permission.content = 'all' allow.add_child(permission) j = mp_io.to_json(eml) self.assertIsInstance(j, str)
def test_find_child(self): access = Node(names.ACCESS) self.node.add_child(access) child = self.node.find_child(names.ACCESS) self.assertIs(access, child) allow = Node(names.ALLOW) access.add_child(allow) grandchild = self.node.find_child(names.ALLOW) self.assertIs(grandchild, allow) permission = Node(names.PERMISSION) allow.add_child(permission) great_grandchild = self.node.find_child(names.PERMISSION) self.assertIs(great_grandchild, permission) child = self.node.find_child('nonesuch') self.assertIs(child, None)
def _process_element(e, clean, literals) -> Node: """ Process an lxml etree element into a Metapype node. If the clean attribute is true, then remove leading and trailing whitespace from the element content. Args: e: lxml etree element clean: boolean to clean leading and trailing whitespace from node content literals: tuple of XML elements whose content should not be altered Returns: Node """ tag = e.tag[e.tag.find("}") + 1:] # Remove any prepended namespace node = Node(tag) node.nsmap = e.nsmap node.prefix = e.prefix if clean: if e.text is not None: if tag in literals: node.content = e.text else: # if text consists entirely of one or more spaces and/or non-breaking spaces, keep it if re.search("^[ \xA0]+$", e.text): node.content = e.text else: node.content = None if e.text.strip() == '' else " ".join( e.text.split()) if e.tail is not None: # if tail consists entirely of one or more spaces and/or non-breaking spaces, keep it if re.search("^[ \xA0]+$", e.tail): node.tail = e.tail else: node.tail = None if e.tail.strip() == '' else " ".join( e.tail.split()) else: node.content = e.text node.tail = e.tail for name, value in e.attrib.items(): if "{" not in name: node.add_attribute(name, value) else: nsname = _format_extras(name, node.nsmap) node.add_extras(nsname, value) for _ in e: if _.tag is not etree.Comment: node.add_child(_process_element(_, clean, literals)) for child in node.children: child.parent = node if child.nsmap == node.nsmap: child.nsmap = node.nsmap # Map to single instance of nsmap return node
def test_delete_node_no_children(): eml = Node(names.EML) eml.add_attribute("packageId", "edi.23.1") eml.add_attribute("system", "metapype") access = Node(names.ACCESS, parent=eml) access.add_attribute("authSystem", "pasta") access.add_attribute("order", "allowFirst") eml.add_child(access) allow = Node(names.ALLOW, parent=access) access.add_child(allow) principal = Node(names.PRINCIPAL, parent=allow) principal.content = "uid=gaucho,o=EDI,dc=edirepository,dc=org" allow.add_child(principal) permission = Node(names.PERMISSION, parent=allow) permission.content = "all" allow.add_child(permission) node = Node.get_node_instance(principal.id) assert principal is node Node.delete_node_instance(eml.id, children=False) assert principal.id in Node.store
def test_delete_node_no_children(self): eml = Node(names.EML) eml.add_attribute('packageId', 'edi.23.1') eml.add_attribute('system', 'metapype') access = Node(names.ACCESS, parent=eml) access.add_attribute('authSystem', 'pasta') access.add_attribute('order', 'allowFirst') eml.add_child(access) allow = Node(names.ALLOW, parent=access) access.add_child(allow) principal = Node(names.PRINCIPAL, parent=allow) principal.content = 'uid=gaucho,o=EDI,dc=edirepository,dc=org' allow.add_child(principal) permission = Node(names.PERMISSION, parent=allow) permission.content = 'all' allow.add_child(permission) node = Node.get_node_instance(principal.id) self.assertIs(principal, node) Node.delete_node_instance(eml.id, children=False) self.assertIn(principal.id, Node.store)
def maintenance(filename=None): form = MaintenanceForm(filename=filename) eml_node = load_eml(filename=filename) if eml_node: dataset_node = eml_node.find_child(names.DATASET) if not dataset_node: dataset_node = Node(names.DATASET, parent=eml_node) add_child(eml_node, dataset_node) # Process POST if request.method == 'POST' and BTN_CANCEL in request.form: url = url_for(PAGE_MAINTENANCE, filename=filename) return redirect(url) if request.method == 'POST' and form.validate_on_submit(): save = False if is_dirty_form(form): save = True if save: maintenace_description = form.description.data valid, msg = is_valid_xml_fragment(maintenace_description, names.MAINTENANCE) if not valid: flash(invalid_xml_error_message(msg, False, names.DESCRIPTION), 'error') return render_get_maintenance_page(eml_node, form, filename) update_frequency = form.update_frequency.data create_maintenance(dataset_node, maintenace_description, update_frequency) save_both_formats(filename=filename, eml_node=eml_node) form_value = request.form form_dict = form_value.to_dict(flat=False) new_page = PAGE_MAINTENANCE if form_dict: for key in form_dict: val = form_dict[key][0] # value is the first list element if val == BTN_SAVE_AND_CONTINUE: new_page = PAGE_PUBLISHER else: new_page = handle_hidden_buttons(new_page, PAGE_MAINTENANCE) return redirect(url_for(new_page, filename=filename)) # Process GET if dataset_node: maintenance_node = dataset_node.find_child(names.MAINTENANCE) if maintenance_node: populate_maintenance_form(form, maintenance_node) return render_get_maintenance_page(eml_node, form, filename)
def test_validate_prune(): if "TEST_DATA" in os.environ: xml_path = os.environ["TEST_DATA"] else: xml_path = tests.test_data_path with open(f"{xml_path}/eml.xml", "r") as f: xml = "".join(f.readlines()) eml = metapype_io.from_xml(xml) assert isinstance(eml, Node) referencePublication = Node("referencePublication") usageCitation = Node("usageCitation") dataset = eml.find_single_node_by_path([names.DATASET]) dataset.add_child(referencePublication) dataset.add_child(usageCitation) errs = list() validate.tree(eml, errs) assert len(errs) > 0 validate.prune(eml) errs = list() validate.tree(eml, errs) assert len(errs) == 0
def test_replace_child(): individual_name = Node(names.INDIVIDUALNAME) sur_name_1 = Node(names.SURNAME, parent=individual_name) sur_name_1.content = "Gaucho" individual_name.add_child(sur_name_1) sur_name_2 = Node(names.SURNAME, parent=individual_name) sur_name_2.content = "Carroll" assert sur_name_1 in individual_name.children assert sur_name_2 not in individual_name.children individual_name.replace_child(old_child=sur_name_1, new_child=sur_name_2) assert sur_name_2 in individual_name.children assert sur_name_1 not in individual_name.children # Test for old child removal from node store assert sur_name_1.id not in Node.store # Test for child node type mismatch given_name = Node(names.GIVENNAME) given_name.content = "Chase" with pytest.raises(ValueError): individual_name.replace_child(old_child=sur_name_2, new_child=given_name)
def _from_dict(node: dict, parent: Node = None) -> Node: """ Build a Metapype model from a dict. Args: node: dict representation of a Metapype model parent: parent node of current node (root node will be None) Returns: Node: current node of Metapype model """ name, body = node.popitem() node = Node(name, id=body[0]["id"]) if parent is not None: node.parent = parent nsmap = body[1]["nsmap"] if nsmap is not None: for nsp in nsmap: node.add_namespace(nsp, nsmap[nsp]) prefix = body[2]["prefix"] if prefix is not None: node.prefix = prefix attributes = body[3]["attributes"] if attributes is not None: for attribute in attributes: node.add_attribute(attribute, attributes[attribute]) extras = body[4]["extras"] if extras is not None: for extra in extras: node.add_extras(extra, extras[extra]) content = body[5]["content"] if content is not None: node.content = content tail = body[6]["tail"] if tail is not None: node.tail = tail children = body[7]["children"] for child in children: child_node = _from_dict(child, node) node.add_child(child_node) return node