def test_error_paths(self): """ Test various loader error situations""" fn = env.input_path('loadererror1.yaml') with self.assertRaises(ValueError, msg="Unknown slot domain should fail") as e: SchemaLoader(fn).resolve() self.assertIn('loadererror1.yaml", line 11, col 13', str(e.exception)) fn = env.input_path('loadererror2.yaml') with self.assertRaises(ValueError, msg="No Type URI") as e: SchemaLoader(fn).resolve() self.assertIn('type "string" does not declare a URI', str(e.exception)) fn = env.input_path('loadererror2a.yaml') with self.assertRaises(ValueError, msg="Optional key slot should fail") as e: SchemaLoader(fn).resolve() self.assertIn('slot: s1 - key and identifier slots cannot be optional', str(e.exception)) fn = env.input_path('loadertest1.yaml') schema = SchemaLoader(fn).resolve() self.assertEqual('string', schema.slots['s1'].range) fn = env.input_path('loadererror4.yaml') with self.assertRaises(ValueError, msg="Default prefix is not defined") as e: SchemaLoader(fn).resolve() self.assertIn('loadererror4.yaml", line 6, col 17', str(e.exception))
def test_missing_type_uri(self): """ A type with neither a typeof or uri is an error """ fn = env.input_path('loadererror10.yaml') with self.assertRaises(ValueError, msg="A non-typeof type has to have a URI") as e: _ = SchemaLoader(fn).resolve() self.assertIn('loadererror10.yaml", line 12, col 3', str(e.exception)) fn = env.input_path('loaderpass11.yaml') _ = SchemaLoader(fn).resolve()
def __init__(self, schema: Union[str, TextIO, SchemaDefinition], **kwargs) -> None: super().__init__(schema, **kwargs) self.graph: Optional[Graph] = None self.metamodel = SchemaLoader(LOCAL_METAMODEL_YAML_FILE, importmap=kwargs.get('importmap', None), mergeimports=self.merge_imports) \ if os.path.exists(LOCAL_METAMODEL_YAML_FILE) else\ SchemaLoader(METAMODEL_YAML_URI, base_dir=META_BASE_URI, importmap=kwargs.get('importmap', None), mergeimports=self.merge_imports) self.metamodel.resolve() self.top_value_uri: Optional[URIRef] = None
def test_csolink_model(self): """ Make sure the csolink model is valid """ schema = SchemaLoader(CSOLINK_MODEL_YAML) errors = [] try: schema.resolve() except ValueError as e: errors.append(str(e)) if not errors: errors = schema.synopsis.errors() self.assertEqual([], errors, "csolink-model.yaml - errors detected")
def cli(inputs, view: bool): """ Generates SQL VIEW commands from hints embedded in linkml """ for input in inputs: with open(input, 'r') as stream: schema = load_raw_schema(input) print('-- ** REWRITE TABLES AS VIEWS **') print(f'-- SCHEMA: {schema.id}') loader = SchemaLoader(schema, mergeimports=True) loader.resolve() generate_views_from_linkml(schema, view)
def test_default_range(self): """ Validate default slot range settings """ schema = SchemaLoader(env.input_path('resolver1.yaml')).resolve() self.assertEqual({ 's1': 't1', 's2': 't2' }, {slot.name: slot.range for slot in schema.slots.values()}) schema = SchemaLoader(env.input_path('resolver2.yaml')).resolve() self.assertEqual({ 's1': 'string', 's2': 't2' }, {slot.name: slot.range for slot in schema.slots.values()})
def test_representation_errors(self): """ Test misformed schema elements """ fn = env.input_path('typeerror1.yaml') with self.assertRaises(ValueError): SchemaLoader(fn) fn = env.input_path('typeerror2.yaml') with self.assertRaises(ValueError): SchemaLoader(fn) fn = env.input_path('typeerror3.yaml') with self.assertRaises(ValueError): SchemaLoader(fn) fn = env.input_path('typeerror4.yaml') with self.assertRaises(ValueError): SchemaLoader(fn)
def test_multi_key(self): """ Multiple keys are not supported """ fn = env.input_path('loadererror6.yaml') with self.assertRaises( ValueError, msg='Multiple keys/identifiers not allowed') as e: _ = SchemaLoader(fn).resolve() self.assertIn('multiple keys/identifiers not allowed', str(e.exception)) fn = env.input_path('loadererror7.yaml') with self.assertRaises(ValueError, msg="Two or more keys are not allowed") as e: _ = SchemaLoader(fn).resolve() self.assertIn('multiple keys/identifiers not allowed', str(e.exception))
def test_empty_range(self): """ A type must have either a base or a parent """ fn = env.input_path('loadererror5.yaml') with self.assertRaises(ValueError, msg="Range error should be raised") as e: _ = SchemaLoader(fn).resolve() self.assertIn('loadererror5.yaml", line 9, col 3', str(e.exception))
def eval_loader(self, base_name: str, logger: Optional[logging.Logger] = None, source: Optional[str] = None) -> None: loader = SchemaLoader(source or self.env.input_path(base_name + '.yaml'), logger=logger) self.env.generate_single_file(base_name + '.json', lambda: as_json(loader.resolve()), filtr=json_metadata_filter, value_is_returned=True) self.env.generate_single_file( base_name + '.errs', lambda: '\n'.join(loader.synopsis.errors()), filtr=json_metadata_filter, value_is_returned=True)
def test_undefined_subset(self): """ Throw an error on an undefined subset reference """ fn = env.input_path('loadererror11.yaml') with self.assertRaises(ValueError, msg="Subset references must be valid") as e: _ = SchemaLoader(fn).resolve() self.assertIn('loadererror11.yaml", line 22, col 16', str(e.exception))
def eval_synopsis(self, base_name: str, source: Optional[str] = None) -> None: schema = SchemaLoader(source if source else env.input_path(base_name + '.yaml'), importmap=env.import_map) schema.resolve() self.summary = schema.synopsis.summary() self.env.generate_single_file( base_name + '.errs', lambda: '\n'.join(schema.synopsis.errors()), value_is_returned=True) self.env.generate_single_file(base_name + '.synopsis', lambda: self.summary, value_is_returned=True)
def test_multi_usages_3(self): """ Illegal alias usage """ with self.assertRaises(ValueError) as e: schema = SchemaLoader( env.input_path('multi_usages_3.yaml')).resolve() self.assertIn( 'Class: "child_class1" - alias not permitted in slot_usage slot: foo', str(e.exception))
def test_mergeerror1(self): """ Test conflicting definitions path """ fn = env.input_path('mergeerror1.yaml') with self.assertRaises(ValueError) as ve: SchemaLoader(fn) self.assertEqual( "Conflicting URIs (http://example.org/schema2, http://example.org/schema1) for item: c1", str(ve.exception))
def test_issue_177_dup(self): env.generate_single_file( 'issue_177_error.yaml', lambda: as_yaml( SchemaLoader(env.input_path('issue_177_error.yaml')).resolve() ), value_is_returned=True, filtr=yaml_filter)
def test_issue_18(self): """ Make sure that inverses are automatically generated """ env.generate_single_file( 'issue_18.yaml', lambda: as_yaml( SchemaLoader(env.input_path('issue_18.yaml')).resolve()), filtr=yaml_filter, value_is_returned=True)
def test_missing_inverse(self): with self.assertRaises(ValueError) as e: env.generate_single_file( 'issue_18_error2.yaml', lambda: as_yaml( SchemaLoader(env.input_path('issue_18_error2.yaml')). resolve()), value_is_returned=True) self.assertEqual('Slot s1.inverse (s2) is not defined', str(e.exception).strip())
def test_key_and_id(self): """ A slot cannot be both a key and an identifier """ fn = env.input_path('loadererror8.yaml') with self.assertRaises( ValueError, msg="A slot cannot be both a key and identifier") as e: _ = SchemaLoader(fn).resolve() self.assertIn( 'A slot cannot be both a key and identifier at the same time', str(e.exception)) fn = env.input_path('loadererror9.yaml') with self.assertRaises( ValueError, msg="A slot cannot be both a key and identifier") as e: _ = SchemaLoader(fn).resolve() self.assertIn( 'A slot cannot be both a key and identifier at the same time', str(e.exception))
def test_issue_58(self): """ Reject non NSNAME model names""" with self.assertRaises(ValueError) as ve: env.generate_single_file( 'issue_58_error1.yaml', lambda: as_yaml( SchemaLoader(env.input_path('issue_58_error1.yaml')). resolve()), value_is_returned=True) self.assertIn('issue 58: Not a valid NCName', str(ve.exception))
def test_no_inverse_domain(self): with self.assertRaises(ValueError) as e: env.generate_single_file( 'issue_18_error3.yaml', lambda: as_yaml( SchemaLoader(env.input_path('issue_18_error3.yaml')). resolve()), value_is_returned=True) self.assertEqual( "Unable to determine the range of slot `s1'. Its inverse (s2) has no declared domain", str(e.exception).strip())
def test_type_uri(self): """ Validate type URI's and the fact that they aren't inherited """ schema = SchemaLoader(env.input_path('resolver2.yaml')).resolve() self.assertEqual( { 'string': 'xsd:string', 't1': 'xsd:string', 't2': 'xsd:int', 't3': 'xsd:string' }, {t.name: t.uri for t in schema.types.values()})
def cli(inputs, limit: int): """ Generates SQL VIEW commands from hints embedded in linkml linkml """ for input in inputs: with open(input, 'r') as stream: schema = load_raw_schema(input) print('-- ** REWRITE TABLES AS VIEWS **') print(f'-- SCHEMA: {schema.id}') loader = SchemaLoader(schema, mergeimports=True) loader.resolve() for cn, c in schema.classes.items(): if c.mixin: continue if len(c.slots) > 0: if not c.abstract and not c.mixin: sql_table = underscore(cn) print(f'SELECT * FROM {sql_table} LIMIT {limit};') else: print(f'-- No slots for {cn}')
def test_inverse_mismatch(self): """ Test error detection when inverses don't match """ with self.assertRaises(ValueError) as e: env.generate_single_file( 'issue_18_error1.yaml', lambda: as_yaml( SchemaLoader(env.input_path('issue_18_error1.yaml')). resolve()), value_is_returned=True) self.assertEqual( 'Slot s1.inverse (s2) does not match slot s2.inverse (s3)', str(e.exception).strip())
def test_multi_domains(self): with self.redirect_logstream() as logger: env.generate_single_file( 'issue_18_warning1.yaml', lambda: as_yaml( SchemaLoader(env.input_path('issue_18_warning1.yaml'), logger=logger).resolve()), filtr=yaml_filter, value_is_returned=True) self.assertIn( 'Slot s2.inverse (s1), has multi domains (c1, c2) Multi ranges not yet implemented', logger.result)
def test_importmap(self): """ Test the importmap parameter """ fn = env.input_path('import_test_1.yaml') importmap = { "http://example.org/import_test_2": "import_test_2", "loc/imp3": "import_test_3", "base:import_test_4": "http://example.org/import_test_4", "http://example.org/import_test_4": "import_test_4", "types": "http://w3id.org/linkml/types" } self.env.generate_single_file( 'import_test_1.json', lambda: as_json(SchemaLoader(fn, importmap=importmap).resolve()), filtr=json_metadata_filter)
def test_multi_usages_2(self): """ Slot usage chain with starting alias """ schema = SchemaLoader(env.input_path('multi_usages_2.yaml')).resolve() self._eval_expected(schema, 's1', 'value', 'root_class', None, None, 'string') self._eval_expected(schema, 'child_class1_s1', 'value', 'child_class1', 's1', 's1', 'boolean') self._eval_expected(schema, 'child_class2_s1', 'value', 'child_class2', 'child_class1_s1', 's1', 'integer') self._eval_expected(schema, 'child_class3_s1', 'value', 'child_class3', 'child_class2_s1', 's1', 'integer') env.eval_single_file(env.expected_path('multi_usages_2.yaml'), as_yaml(schema), filtr=yaml_filter)
def test_element_slots(self): """ Test all element slots and their inheritence """ schema = SchemaLoader(env.input_path('resolver3.yaml')).resolve() x = { k: v for k, v in as_dict(schema.slots['s1']).items() if v is not None and v != [] } outfile = env.expected_path('resolver3.json') if not os.path.exists(outfile): with open(outfile, 'w') as f: f.write(as_json(JsonObj(**x))) with open(outfile) as f: expected = as_dict(load(f)) self.assertEqual(expected, x)
def test_biolink(self): """ SchemaLoader should be monotonic - metamodel test """ biolink_schema = SchemaLoader(LOCAL_METAMODEL_YAML_FILE).resolve() biolink_schema_2 = SchemaLoader(biolink_schema).resolve() self.assertEqual(biolink_schema, biolink_schema_2)
class OwlSchemaGenerator(Generator): generatorname = os.path.basename(__file__) generatorversion = "0.1.1" valid_formats = ['owl', 'ttl'] + [ x.name for x in rdflib_plugins(None, rdflib_Parser) if '/' not in str(x.name) ] visits_are_sorted = True def __init__(self, schema: Union[str, TextIO, SchemaDefinition], **kwargs) -> None: super().__init__(schema, **kwargs) self.graph: Optional[Graph] = None self.metamodel = SchemaLoader(LOCAL_METAMODEL_YAML_FILE, importmap=kwargs.get('importmap', None), mergeimports=self.merge_imports) \ if os.path.exists(LOCAL_METAMODEL_YAML_FILE) else\ SchemaLoader(METAMODEL_YAML_URI, base_dir=META_BASE_URI, importmap=kwargs.get('importmap', None), mergeimports=self.merge_imports) self.metamodel.resolve() self.top_value_uri: Optional[URIRef] = None def visit_schema(self, output: Optional[str] = None, **_): base = URIRef(self.schema.id) self.graph = Graph(identifier=base) for prefix in self.metamodel.schema.emit_prefixes: self.graph.bind(prefix, self.metamodel.namespaces[prefix]) self.graph.add((base, RDF.type, OWL.Ontology)) self._add_element_properties(base, self.schema) # add the model types for name in [ 'class_definition', 'type_definition', 'slot_definition', 'subset_definition' ]: self._add_metamodel_class(name) # add value placeholder self.top_value_uri = self.metamodel.namespaces[ METAMODEL_NAMESPACE_NAME]['topValue'] self.graph.add((self.top_value_uri, RDF.type, OWL.DatatypeProperty)) self.graph.add((self.top_value_uri, RDFS.label, Literal("value"))) def end_schema(self, output: Optional[str] = None, **_) -> None: data = self.graph.serialize(format='turtle' if self.format in ['owl', 'ttl'] else self.format).decode() if output: with open(output, 'w') as outf: outf.write(data) else: print(data) def add_metadata(self, e: SchemaDefinition, uri: URIRef) -> None: if e.aliases is not None: for s in e.aliases: self.graph.add((uri, SKOS.altLabel, Literal(s))) if e.mappings is not None: for m in e.mappings: m_uri = self.namespaces.uri_for(m) if m_uri is not None: self.graph.add((uri, SKOS.exactMatch, m_uri)) else: logging.warning(f'No URI for {m}') if e.exact_mappings is not None: for m in e.exact_mappings: m_uri = self.namespaces.uri_for(m) if m_uri is not None: self.graph.add((uri, SKOS.exactMatch, m_uri)) else: logging.warning(f'No URI for {m}') if e.close_mappings is not None: for m in e.close_mappings: m_uri = self.namespaces.uri_for(m) if m_uri is not None: self.graph.add((uri, SKOS.closeMatch, m_uri)) else: logging.warning(f'No URI for {m}') if e.narrow_mappings is not None: for m in e.narrow_mappings: m_uri = self.namespaces.uri_for(m) if m_uri is not None: self.graph.add((uri, SKOS.narrowMatch, m_uri)) else: logging.warning(f'No URI for {m}') if e.broad_mappings is not None: for m in e.broad_mappings: m_uri = self.namespaces.uri_for(m) if m_uri is not None: self.graph.add((uri, SKOS.broadMatch, m_uri)) else: logging.warning(f'No URI for {m}') if e.related_mappings is not None: for m in e.related_mappings: m_uri = self.namespaces.uri_for(m) if m_uri is not None: self.graph.add((uri, SKOS.relatedMatch, m_uri)) else: logging.warning(f'No URI for {m}') def visit_class(self, cls: ClassDefinition) -> bool: cls_uri = self._class_uri(cls.name) self.add_metadata(cls, cls_uri) self.graph.add((cls_uri, RDF.type, OWL.Class)) self.graph.add((cls_uri, RDF.type, self.metamodel.namespaces[METAMODEL_NAMESPACE_NAME][ camelcase('class definition')])) self._add_element_properties(cls_uri, cls) # Parent classes # TODO: reintroduce this # if not cls.defining_slots: if True: if cls.is_a: self.graph.add( (cls_uri, RDFS.subClassOf, self._class_uri(cls.is_a))) if cls.mixin: self.graph.add( (cls_uri, RDFS.subClassOf, METAMODEL_NAMESPACE.mixin)) for mixin in sorted(cls.mixins): self.graph.add( (cls_uri, RDFS.subClassOf, self._class_uri(mixin))) if cls.name in self.synopsis.applytorefs: for appl in sorted( self.synopsis.applytorefs[cls.name].classrefs): self.graph.add( (cls_uri, RDFS.subClassOf, self._class_uri(appl))) else: raise NotImplementedError("Defining slots need to be implemented") # If defining slots, we generate an equivalentClass entry # equ_node = BNode() # self.graph.add((cls_uri, OWL.equivalentClass, equ_node)) # self.graph.add((equ_node, RDF.type, OWL.Class)) # # elts = [] # if cls.is_a: # elts.append(self._class_uri(cls.is_a)) # if cls.mixin: # self.graph.add((cls_uri, RDFS.subClassOf, META_NS.mixin)) # for mixin in cls.mixins: # self.graph.add((cls_uri, RDFS.subClassOf, self._class_uri(mixin))) # if cls.name in self.synopsis.applytorefs: # for appl in self.synopsis.applytorefs[cls.name].classrefs: # self.graph.add((cls_uri, RDFS.subClassOf, self._class_uri(appl))) # # for slotname in cls.defining_slots: # restr_node = BNode() # slot = self.schema.slots[slotname] # # self.graph.add((restr_node, RDF.type, OWL.Restriction)) # self.graph.add((restr_node, OWL.onProperty, self._prop_uri(slotname))) # self._add_cardinality(restr_node, slot) # # TODO: fix this # # self.graph.add((restr_node, OWL.someValuesFrom, self._build_range(slot))) # elts.append(restr_node) # # coll_bnode = BNode() # Collection(self.graph, coll_bnode, elts) # self.graph.add((equ_node, OWL.intersectionOf, coll_bnode)) # TODO: see whether unions belong # if cls.union_of: # union_node = BNode() # Collection(self.graph, union_coll, [self.class_uri(union_node) for union_node in cls.union_of]) # self.graph.add((union_node, OWL.unionOf, union_coll)) # self.graph.add((cls_uri, RDFS.subClassOf, union_node)) for sn in sorted(self.own_slot_names(cls)): # Defining_slots are covered above if sn not in cls.defining_slots: slot = self.schema.slots[sn] # Non-inherited slots are annotation properties if self.is_slot_object_property(slot): slot_node = BNode() self.graph.add((cls_uri, RDFS.subClassOf, slot_node)) # required multivalued if slot.required: if slot.multivalued: # y y intersectionOf(restriction(slot only type) restriction(slot some type) restr1 = BNode() self.graph.add((restr1, RDF.type, OWL.Restriction)) self.graph.add((restr1, OWL.allValuesFrom, self._range_uri(slot))) self.graph.add( (restr1, OWL.onProperty, self._prop_uri(self.aliased_slot_name(slot)))) restr2 = BNode() self.graph.add((restr2, RDF.type, OWL.Restriction)) self.graph.add((restr2, OWL.someValuesFrom, self._range_uri(slot))) self.graph.add( (restr2, OWL.onProperty, self._prop_uri(self.aliased_slot_name(slot)))) coll_bnode = BNode() Collection(self.graph, coll_bnode, [restr1, restr2]) self.graph.add( (slot_node, OWL.intersectionOf, coll_bnode)) self.graph.add((slot_node, RDF.type, OWL.Class)) else: # y n restriction(slot exactly 1 type) self.graph.add( (slot_node, RDF.type, OWL.Restriction)) self.graph.add( (slot_node, OWL.qualifiedCardinality, Literal(1))) self.graph.add( (slot_node, OWL.onProperty, self._prop_uri(self.aliased_slot_name(slot)))) self.graph.add((slot_node, OWL.onClass, self._range_uri(slot))) else: if slot.multivalued: # n y restriction(slot only type) self.graph.add( (slot_node, RDF.type, OWL.Restriction)) self.graph.add((slot_node, OWL.allValuesFrom, self._range_uri(slot))) self.graph.add( (slot_node, OWL.onProperty, self._prop_uri(self.aliased_slot_name(slot)))) else: # n n intersectionOf(restriction(slot only type) restriction(slot max 1 type)) self.graph.add( (slot_node, RDF.type, OWL.Restriction)) self.graph.add((slot_node, OWL.onClass, self._range_uri(slot))) self.graph.add( (slot_node, OWL.maxQualifiedCardinality, Literal(1))) self.graph.add( (slot_node, OWL.onProperty, self._prop_uri(self.aliased_slot_name(slot)))) return True def visit_slot(self, slot_name: str, slot: SlotDefinition) -> None: """ Add a slot definition per slot @param slot_name: @param slot: @return: """ # Note: We use the raw name in OWL and add a subProperty arc slot_uri = self._prop_uri(slot.name) self._add_element_properties(slot_uri, slot) # Inherited slots are object or data properties # All others are annotation properties self.graph.add( (slot_uri, RDF.type, OWL.ObjectProperty if self.is_slot_object_property(slot) else OWL.AnnotationProperty)) self.graph.add((slot_uri, RDF.type, self.metamodel.namespaces[METAMODEL_NAMESPACE_NAME][ camelcase('slot definition')])) self.graph.add((slot_uri, RDFS.range, self._range_uri(slot))) if slot.domain: self.graph.add( (slot_uri, RDFS.domain, self._class_uri(slot.domain))) if slot.inverse: self.graph.add( (slot_uri, OWL.inverseOf, self._prop_uri(slot.inverse))) if slot.symmetric: self.graph.add((slot_uri, RDF.type, OWL.SymmetricProperty)) # Parent slots if slot.is_a: self.graph.add( (slot_uri, RDFS.subPropertyOf, self._prop_uri(slot.is_a))) for mixin in slot.mixins: self.graph.add( (slot_uri, RDFS.subPropertyOf, self._prop_uri(mixin))) if slot.name in self.synopsis.applytorefs: for appl in self.synopsis.applytorefs[slot.name].slotrefs: self.graph.add( (slot_uri, RDFS.subClassOf, self._prop_uri(appl))) def visit_type(self, typ: TypeDefinition) -> None: type_uri = self._type_uri(typ.name) self.graph.add((type_uri, RDF.type, OWL.Class)) self.graph.add((type_uri, RDF.type, self.metamodel.namespaces[METAMODEL_NAMESPACE_NAME][ camelcase('type definition')])) self._add_element_properties(type_uri, typ) if typ.typeof: self.graph.add( (type_uri, RDFS.subClassOf, self._type_uri(typ.typeof))) else: restr = BNode() self.graph.add((restr, RDF.type, OWL.Restriction)) self.graph.add((restr, OWL.qualifiedCardinality, Literal(1))) self.graph.add((restr, OWL.onProperty, self.top_value_uri)) self.graph.add( (restr, OWL.onDataRange, self.namespaces.uri_for(typ.uri))) self.graph.add((type_uri, RDFS.subClassOf, restr)) def _add_element_properties(self, uri: URIRef, el: Element) -> None: for k, v in el.__dict__.items(): if k in self.metamodel.schema.slots: defining_slot = self.metamodel.schema.slots[k] if v is not None and 'owl' in defining_slot.in_subset: ve = v if isinstance(v, list) else [v] for e in ve: self.graph.add( (uri, URIRef( self.metamodel.namespaces.uri_for( defining_slot.slot_uri)), Literal(e))) def _add_cardinality(self, subj: Union[BNode, URIRef], slot) -> None: """ Add cardinality restrictions to node """ if slot.required: if slot.multivalued: self.graph.add((subj, OWL.minCardinality, Literal(1))) else: self.graph.add((subj, OWL.cardinality, Literal(1))) elif not slot.multivalued: self.graph.add((subj, OWL.maxCardinality, Literal(1))) def _range_uri(self, slot: SlotDefinition) -> URIRef: if slot.range in self.schema.types: return self._type_uri(TypeDefinitionName(slot.range)) elif slot.range in self.schema.enums: # TODO: enums fill this in return self._enum_uri(EnumDefinitionName(slot.range)) else: return self._class_uri(ClassDefinitionName(slot.range)) def _class_uri(self, cn: ClassDefinitionName) -> URIRef: c = self.schema.classes[cn] return URIRef(c.definition_uri) def _enum_uri(self, en: EnumDefinitionName) -> URIRef: # TODO: enums e = self.schema.enums[en] return URIRef(f"http://UNKNOWN.org/{en}") def _prop_uri(self, pn: SlotDefinitionName) -> URIRef: p = self.schema.slots.get(pn, None) if p is None or p.definition_uri is None: return self.metamodel.namespaces[METAMODEL_NAMESPACE_NAME][ underscore(pn)] else: return URIRef(p.definition_uri) def _type_uri(self, tn: TypeDefinitionName) -> URIRef: t = self.schema.types[tn] return URIRef(t.definition_uri) def _add_metamodel_class(self, cname: str) -> None: metac = self.metamodel.schema.classes[cname] metac_uri = self.metamodel.namespaces[METAMODEL_NAMESPACE_NAME][ camelcase(metac.name)] self.graph.add((metac_uri, RDF.type, OWL.Class)) self._add_element_properties(metac_uri, metac) def is_slot_object_property(self, slot: SlotDefinition) -> bool: return True
def test_references_typeerror(self): """ TypeError: sequence item 0: expected str instance, NoneType found is generated from schemasynopsis """ SchemaLoader(env.input_path('issue_tccm', 'resourcedescription.yaml'), mergeimports=False).resolve()