From c664d19e7d4a0aa0762c30a72ae238cf818891ab Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Wed, 11 Jan 2023 21:20:47 +0100 Subject: Feature support in the schema * Type annotations * Feature type * Moved from_string from Schema to its own file/function * Root predicate has a valid (not-None) range * ROOT_... export in schema.types * Empty as the default Schema constructor * Schema loads some additional default symbols * _Type instances compare along class hierarchy --- test/schema/test_schema.py | 271 ++--------- test/schema/test_serialize.py | 1007 +++++++++++++++++++++++++++++++++++++++++ test/schema/test_types.py | 240 ++++++++-- 3 files changed, 1253 insertions(+), 265 deletions(-) create mode 100644 test/schema/test_serialize.py (limited to 'test/schema') diff --git a/test/schema/test_schema.py b/test/schema/test_schema.py index 888cdca..1b45db0 100644 --- a/test/schema/test_schema.py +++ b/test/schema/test_schema.py @@ -10,7 +10,7 @@ import unittest # bsfs imports from bsfs.namespace import ns -from bsfs.schema import types +from bsfs.schema import types, from_string from bsfs.utils import errors # objects to test @@ -55,7 +55,7 @@ class TestSchema(unittest.TestCase): ''' # nodes - self.n_root = types.Node(ns.bsfs.Node, None) + self.n_root = types.ROOT_NODE self.n_ent = types.Node(ns.bsfs.Entity, types.Node(ns.bsfs.Node, None)) self.n_img = types.Node(ns.bsfs.Image, types.Node(ns.bsfs.Entity, types.Node(ns.bsfs.Node, None))) self.n_tag = types.Node(ns.bsfs.Tag, types.Node(ns.bsfs.Node, None)) @@ -63,24 +63,32 @@ class TestSchema(unittest.TestCase): self.nodes = [self.n_root, self.n_ent, self.n_img, self.n_tag, self.n_unused] # literals - self.l_root = types.Literal(ns.bsfs.Literal, None) + self.l_root = types.ROOT_LITERAL + self.l_number = types.ROOT_NUMBER self.l_string = types.Literal(ns.xsd.string, types.Literal(ns.bsfs.Literal, None)) - self.l_integer = types.Literal(ns.xsd.integer, types.Literal(ns.bsfs.Literal, None)) + self.l_integer = types.Literal(ns.xsd.integer, self.l_number) self.l_unused = types.Literal(ns.xsd.boolean, types.Literal(ns.bsfs.Literal, None)) - self.literals = [self.l_root, self.l_string, self.l_integer, self.l_unused] + self.literals = [self.l_root, self.l_number, self.l_string, self.l_integer, self.l_unused] # predicates - self.p_root = types.Predicate(ns.bsfs.Predicate, None, types.Node(ns.bsfs.Node, None), None, False) + self.p_root = types.ROOT_PREDICATE + self.f_root = types.ROOT_FEATURE self.p_tag = self.p_root.get_child(ns.bse.tag, self.n_ent, self.n_tag, False) self.p_group = self.p_tag.get_child(ns.bse.group, self.n_img, self.n_tag, False) self.p_comment = self.p_root.get_child(ns.bse.comment, self.n_root, self.l_string, True) - self.predicates = [self.p_root, self.p_tag, self.p_group, self.p_comment] + self.predicates = [self.p_root, self.f_root, self.p_tag, self.p_group, self.p_comment] def test_construction(self): + # no args yields a minimal schema + schema = Schema() + self.assertSetEqual(set(schema.nodes()), {self.n_root}) + self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_number}) + self.assertSetEqual(set(schema.predicates()), {self.p_root, self.f_root}) + # nodes and literals are optional schema = Schema(self.predicates) self.assertSetEqual(set(schema.nodes()), {self.n_root, self.n_ent, self.n_img, self.n_tag}) - self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string}) + self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number}) self.assertSetEqual(set(schema.predicates()), set(self.predicates)) # predicates, nodes, and literals are respected @@ -101,21 +109,21 @@ class TestSchema(unittest.TestCase): # literals are complete schema = Schema(self.predicates, self.nodes, None) - self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string}) + self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number}) schema = Schema(self.predicates, self.nodes, []) - self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string}) + self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number}) schema = Schema(self.predicates, self.nodes, [self.l_string]) - self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string}) + self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number}) schema = Schema(self.predicates, self.nodes, [self.l_integer]) - self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_integer}) + self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_integer, self.l_number}) schema = Schema(self.predicates, self.nodes, [self.l_integer, self.l_unused]) self.assertSetEqual(set(schema.literals()), set(self.literals)) # predicates are complete schema = Schema([], self.nodes, self.literals) - self.assertSetEqual(set(schema.predicates()), set()) + self.assertSetEqual(set(schema.predicates()), {self.p_root, self.f_root}) schema = Schema([self.p_group], self.nodes, self.literals) - self.assertSetEqual(set(schema.predicates()), {self.p_root, self.p_tag, self.p_group}) + self.assertSetEqual(set(schema.predicates()), {self.p_root, self.f_root, self.p_tag, self.p_group}) schema = Schema([self.p_group, self.p_comment], self.nodes, self.literals) self.assertSetEqual(set(schema.predicates()), set(self.predicates)) @@ -153,21 +161,28 @@ class TestSchema(unittest.TestCase): self.assertRaises(errors.ConsistencyError, Schema, {}, {types.Node(ns.bsfs.Foo, None)}, {types.Node(ns.bsfs.Foo, None)}) self.assertRaises(errors.ConsistencyError, Schema, - {types.Predicate(ns.bsfs.Foo, None, types.Node(ns.bsfs.Node, None), None, False)}, {}, {types.Node(ns.bsfs.Foo, None)}) + {types.Predicate(ns.bsfs.Foo, None, types.Node(ns.bsfs.Node, None), types.ROOT_VERTEX, False)}, {}, {types.Node(ns.bsfs.Foo, None)}) self.assertRaises(errors.ConsistencyError, Schema, - {types.Predicate(ns.bsfs.Foo, None, types.Node(ns.bsfs.Node, None), None, False)}, {types.Node(ns.bsfs.Foo, None)}, {}) + {types.Predicate(ns.bsfs.Foo, None, types.Node(ns.bsfs.Node, None), types.ROOT_VERTEX, False)}, {types.Node(ns.bsfs.Foo, None)}, {}) self.assertRaises(errors.ConsistencyError, Schema, - {types.Predicate(ns.bsfs.Foo, None, types.Node(ns.bsfs.Node, None), None, False)}, {types.Node(ns.bsfs.Foo, None)}, {types.Node(ns.bsfs.Foo, None)}) + {types.Predicate(ns.bsfs.Foo, None, types.Node(ns.bsfs.Node, None), types.ROOT_VERTEX, False)}, {types.Node(ns.bsfs.Foo, None)}, {types.Node(ns.bsfs.Foo, None)}) + def test_str(self): + # string conversion self.assertEqual(str(Schema([])), 'Schema()') self.assertEqual(str(Schema([], [], [])), 'Schema()') self.assertEqual(str(Schema(self.predicates, self.nodes, self.literals)), 'Schema()') - self.assertEqual(repr(Schema([])), 'Schema([], [], [])') - self.assertEqual(repr(Schema([], [], [])), 'Schema([], [], [])') + # repr conversion with only default nodes, literals, and predicates + n = [ns.bsfs.Node] + l = [ns.bsfs.Literal, ns.bsfs.Number] + p = [ns.bsfs.Feature, ns.bsfs.Predicate] + self.assertEqual(repr(Schema()), f'Schema({n}, {l}, {p})') + self.assertEqual(repr(Schema([], [], [])), f'Schema({n}, {l}, {p})') + # repr conversion n = [ns.bsfs.Entity, ns.bsfs.Image, ns.bsfs.Node, ns.bsfs.Tag, ns.bsfs.Unused] - l = [ns.bsfs.Literal, ns.xsd.boolean, ns.xsd.integer, ns.xsd.string] - p = [ns.bse.comment, ns.bse.group, ns.bse.tag, ns.bsfs.Predicate] + l = [ns.bsfs.Literal, ns.bsfs.Number, ns.xsd.boolean, ns.xsd.integer, ns.xsd.string] + p = [ns.bse.comment, ns.bse.group, ns.bse.tag, ns.bsfs.Feature, ns.bsfs.Predicate] self.assertEqual(repr(Schema(self.predicates, self.nodes, self.literals)), f'Schema({n}, {l}, {p})') def test_equality(self): @@ -258,11 +273,11 @@ class TestSchema(unittest.TestCase): self.assertTrue(operator.lt(Schema({self.p_tag}), Schema({self.p_group}))) self.assertTrue(operator.le(Schema({self.p_tag}), Schema({self.p_group}))) # subset considers differences in predicates and literals - self.assertTrue(operator.lt(Schema.Empty(), Schema({self.p_comment}))) + self.assertTrue(operator.lt(Schema(), Schema({self.p_comment}))) # subset considers differences in predicates, nodes, and literals - self.assertTrue(operator.lt(Schema({}), Schema.Empty())) - self.assertTrue(operator.lt(Schema({self.p_tag}), Schema.from_string(self.schema_str))) - self.assertTrue(operator.le(Schema({self.p_tag}), Schema.from_string(self.schema_str))) + self.assertTrue(operator.le(Schema({}), Schema())) + self.assertTrue(operator.lt(Schema({self.p_tag}), from_string(self.schema_str))) + self.assertTrue(operator.le(Schema({self.p_tag}), from_string(self.schema_str))) self.assertFalse(operator.lt(Schema({self.p_comment}), Schema({self.p_tag}))) self.assertFalse(operator.le(Schema({self.p_comment}), Schema({self.p_tag}))) @@ -280,11 +295,11 @@ class TestSchema(unittest.TestCase): self.assertTrue(operator.gt(Schema({self.p_group}), Schema({self.p_tag}))) self.assertTrue(operator.ge(Schema({self.p_group}), Schema({self.p_tag}))) # superset considers differences in predicates and literals - self.assertTrue(operator.gt(Schema({self.p_comment}), Schema.Empty())) + self.assertTrue(operator.gt(Schema({self.p_comment}), Schema())) # superset considers differences in predicates, nodes, and literals - self.assertTrue(operator.gt(Schema.Empty(), Schema({}))) - self.assertTrue(operator.gt(Schema.from_string(self.schema_str), Schema({self.p_tag}))) - self.assertTrue(operator.ge(Schema.from_string(self.schema_str), Schema({self.p_tag}))) + self.assertTrue(operator.ge(Schema(), Schema({}))) + self.assertTrue(operator.gt(from_string(self.schema_str), Schema({self.p_tag}))) + self.assertTrue(operator.ge(from_string(self.schema_str), Schema({self.p_tag}))) self.assertFalse(operator.gt(Schema({self.p_tag}), Schema({self.p_comment}))) self.assertFalse(operator.ge(Schema({self.p_tag}), Schema({self.p_comment}))) @@ -351,26 +366,26 @@ class TestSchema(unittest.TestCase): # difference does not contain predicates from the RHS diff = Schema({self.p_tag, self.p_comment}).diff(Schema({self.p_group})) self.assertSetEqual(set(diff.nodes), set()) - self.assertSetEqual(set(diff.literals), {self.l_root, self.l_string}) + self.assertSetEqual(set(diff.literals), {self.l_string}) self.assertSetEqual(set(diff.predicates), {self.p_comment}) # difference considers extra nodes and literals diff = Schema({self.p_tag}, {self.n_unused}, {self.l_unused}).diff(Schema({self.p_tag})) self.assertSetEqual(set(diff.nodes), {self.n_unused}) - self.assertSetEqual(set(diff.literals), {self.l_root, self.l_unused}) + self.assertSetEqual(set(diff.literals), {self.l_unused}) self.assertSetEqual(set(diff.predicates), set()) # difference considers inconsistent types diff = Schema({self.p_tag}, {self.n_unused}, {self.l_unused}).diff( Schema({self.p_tag}, {types.Node(ns.bsfs.Unused, None)}, {types.Literal(ns.xsd.boolean, None)})) self.assertSetEqual(set(diff.nodes), {self.n_unused}) - self.assertSetEqual(set(diff.literals), {self.l_root, self.l_unused}) + self.assertSetEqual(set(diff.literals), {self.l_unused}) self.assertSetEqual(set(diff.predicates), set()) # __sub__ is an alias for diff diff = Schema({self.p_comment}, {self.n_unused}, {self.l_unused}) - Schema({self.p_group}) self.assertSetEqual(set(diff.nodes), {self.n_unused}) - self.assertSetEqual(set(diff.literals), {self.l_root, self.l_string, self.l_unused}) + self.assertSetEqual(set(diff.literals), {self.l_string, self.l_unused}) self.assertSetEqual(set(diff.predicates), {self.p_comment}) # __sub__ only accepts Schema instances class Foo(): pass @@ -547,196 +562,6 @@ class TestSchema(unittest.TestCase): self.assertFalse(schema.has_predicate(ns.bse.mimetype)) self.assertFalse(schema.has_predicate(self.p_root)) - def test_empty(self): - self.assertEqual(Schema.Empty(), Schema( - [types.Predicate(ns.bsfs.Predicate, None, types.Node(ns.bsfs.Node, None), None, False)], - [types.Node(ns.bsfs.Node, None)], - [types.Literal(ns.bsfs.Literal, None)], - )) - - def test_from_string(self): - # from_string creates a schema - self.assertEqual( - Schema(self.predicates, self.nodes, self.literals), - Schema.from_string(self.schema_str)) - - # schema contains at least the root types - self.assertEqual(Schema.from_string(''), Schema({self.p_root}, {self.n_root}, {self.l_root})) - - # custom example - self.assertEqual( - Schema({types.Predicate(ns.bsfs.Predicate, None, self.n_root, None, False).get_child( - ns.bse.filename, self.n_ent, self.l_string, False)}), - Schema.from_string(''' - prefix rdfs: - prefix xsd: - prefix bsfs: - prefix bse: - - bsfs:Entity rdfs:subClassOf bsfs:Node . - xsd:string rdfs:subClassOf bsfs:Literal . - - bse:filename rdfs:subClassOf bsfs:Predicate ; - rdfs:domain bsfs:Entity ; - rdfs:range xsd:string ; - bsfs:unique "false"^^xsd:boolean . - ''')) - - # all nodes must be defined - self.assertRaises(errors.ConsistencyError, Schema.from_string, ''' - prefix rdfs: - prefix xsd: - prefix bsfs: - prefix bse: - - xsd:string rdfs:subClassOf bsfs:Literal . - - bse:filename rdfs:subClassOf bsfs:Predicate ; - rdfs:domain bsfs:Entity ; - rdfs:range xsd:string ; - bsfs:unique "false"^^xsd:boolean . - ''') - - # all literals must be defined - self.assertRaises(errors.ConsistencyError, Schema.from_string, ''' - prefix rdfs: - prefix xsd: - prefix bsfs: - prefix bse: - - bsfs:Entity rdfs:subClassOf bsfs:Node . - - bse:filename rdfs:subClassOf bsfs:Predicate ; - rdfs:domain bsfs:Entity ; - rdfs:range xsd:string ; - bsfs:unique "false"^^xsd:boolean . - ''') - - # must not have circular dependencies - self.assertRaises(errors.ConsistencyError, Schema.from_string, ''' - prefix rdfs: - prefix bsfs: - bsfs:Entity rdfs:subClassOf bsfs:Node . - # ah, a nice circular dependency - bsfs:Entity rdfs:subClassOf bsfs:Document . - bsfs:Document rdfs:subClassOf bsfs:Entity . - bsfs:PDF rdfs:subClassOf bsfs:Document . - ''') - - # range must be a node or literal - self.assertRaises(errors.ConsistencyError, Schema.from_string, ''' - prefix rdfs: - prefix xsd: - prefix bsfs: - prefix bse: - - bsfs:Entity rdfs:subClassOf bsfs:Node . - - bse:filename rdfs:subClassOf bsfs:Predicate ; - rdfs:domain bsfs:Entity ; - rdfs:range xsd:string ; - bsfs:unique "false"^^xsd:boolean . - ''') - self.assertRaises(errors.ConsistencyError, Schema.from_string, ''' - prefix rdfs: - prefix xsd: - prefix bsfs: - prefix bse: - - bsfs:Entity rdfs:subClassOf bsfs:Node . - - bse:filename rdfs:subClassOf bsfs:Predicate ; - rdfs:domain bsfs:Entity ; - rdfs:range bsfs:Foo ; - bsfs:unique "false"^^xsd:boolean . - ''') - self.assertRaises(errors.ConsistencyError, Schema.from_string, ''' - prefix rdfs: - prefix xsd: - prefix bsfs: - prefix bse: - - bsfs:Entity rdfs:subClassOf bsfs:Node . - - bse:filename rdfs:subClassOf bsfs:Predicate ; - rdfs:domain bsfs:Entity ; - rdfs:range bsfs:Predicate ; - bsfs:unique "false"^^xsd:boolean . - ''') - - # must be consistent - self.assertRaises(errors.ConsistencyError, Schema.from_string, ''' - prefix rdfs: - prefix xsd: - prefix bsfs: - - bsfs:Entity rdfs:subClassOf bsfs:Node . - bsfs:Document rdfs:subClassOf bsfs:Node . - bsfs:Document rdfs:subClassOf bsfs:Entity. - ''') - self.assertRaises(errors.ConsistencyError, Schema.from_string, ''' - prefix rdfs: - prefix xsd: - prefix bsfs: - - xsd:string rdfs:subClassOf bsfs:Literal . - xsd:name rdfs:subClassOf bsfs:Literal . - xsd:name rdfs:subClassOf xsd:string . - ''') - self.assertRaises(errors.ConsistencyError, Schema.from_string, ''' - prefix rdfs: - prefix xsd: - prefix bsfs: - prefix bse: - - bsfs:Entity rdfs:subClassOf bsfs:Node . - - bse:foo rdfs:subClassOf bsfs:Predicate ; - rdfs:domain bsfs:Node ; - rdfs:range bsfs:Node ; - bsfs:unique "false"^^xsd:boolean . - - bse:foo rdfs:subClassOf bsfs:Predicate ; - rdfs:domain bsfs:Entity . - - ''') - self.assertRaises(errors.ConsistencyError, Schema.from_string, ''' - prefix rdfs: - prefix xsd: - prefix bsfs: - prefix bse: - - bsfs:Entity rdfs:subClassOf bsfs:Node . - - bse:foo rdfs:subClassOf bsfs:Predicate ; - rdfs:domain bsfs:Node ; - rdfs:range bsfs:Node ; - bsfs:unique "false"^^xsd:boolean . - - bse:foo rdfs:subClassOf bsfs:Predicate ; - rdfs:range bsfs:Entity . - - ''') - self.assertRaises(errors.ConsistencyError, Schema.from_string, ''' - prefix rdfs: - prefix xsd: - prefix bsfs: - prefix bse: - - bsfs:Entity rdfs:subClassOf bsfs:Node . - - bse:foo rdfs:subClassOf bsfs:Predicate ; - rdfs:domain bsfs:Node ; - rdfs:range bsfs:Node ; - bsfs:unique "false"^^xsd:boolean . - - bse:foo rdfs:subClassOf bsfs:Predicate ; - bsfs:unique "true"^^xsd:boolean . - - ''') - - - ## main ## if __name__ == '__main__': diff --git a/test/schema/test_serialize.py b/test/schema/test_serialize.py new file mode 100644 index 0000000..7392cc0 --- /dev/null +++ b/test/schema/test_serialize.py @@ -0,0 +1,1007 @@ +""" + +Part of the tagit test suite. +A copy of the license is provided with the project. +Author: Matthias Baumgartner, 2022 +""" +# imports +import unittest + +# bsfs imports +from bsfs.namespace import ns +from bsfs.schema import Schema, types +from bsfs.utils import errors, URI + +# objects to test +from bsfs.schema.serialize import from_string, to_string + + +## code ## + +class TestFromString(unittest.TestCase): + + def test_empty(self): + # schema contains at least the root types + self.assertEqual(from_string(''), Schema()) + + + def test_circular_dependency(self): + # must not have circular dependencies + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix bsfs: + bsfs:Entity rdfs:subClassOf bsfs:Node . + # ah, a nice circular dependency + bsfs:Entity rdfs:subClassOf bsfs:Document . + bsfs:Document rdfs:subClassOf bsfs:Entity . + bsfs:PDF rdfs:subClassOf bsfs:Document . + ''') + + + def test_node(self): + # all nodes must be defined + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + xsd:string rdfs:subClassOf bsfs:Literal . + + bse:filename rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "false"^^xsd:boolean . + ''') + + # node definitions must be consistent (cannot re-use a node uri) + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + bsfs:Document rdfs:subClassOf bsfs:Node . + bsfs:Document rdfs:subClassOf bsfs:Entity . # conflicting parent + ''') + + # additional nodes can be defined + n_unused = types.ROOT_NODE.get_child(ns.bsfs.unused) + self.assertEqual(Schema({}, {n_unused}), from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:unused rdfs:subClassOf bsfs:Node . # unused symbol + ''')) + + # a node can have multiple children + n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) + n_tag = types.ROOT_NODE.get_child(ns.bsfs.Tag) + n_doc = n_ent.get_child(ns.bsfs.Document) + n_image = n_ent.get_child(ns.bsfs.Image) + self.assertEqual(Schema({}, {n_ent, n_tag, n_doc, n_image}), from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + # nodes inherit from same parent + bsfs:Entity rdfs:subClassOf bsfs:Node . + bsfs:Tag rdfs:subClassOf bsfs:Node . + + # nodes inherit from same parent + bsfs:Document rdfs:subClassOf bsfs:Entity . + bsfs:Image rdfs:subClassOf bsfs:Entity . + ''')) + + # additional nodes can be defined and used + n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) + l_string = types.ROOT_LITERAL.get_child(ns.xsd.string) + p_filename = types.ROOT_PREDICATE.get_child(ns.bse.filename, + n_ent, l_string, False) + self.assertEqual(Schema({p_filename}), from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + xsd:string rdfs:subClassOf bsfs:Literal . + + bse:filename rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "false"^^xsd:boolean . + ''')) + + # nodes can have annotations + self.assertDictEqual(from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + + ''').node(ns.bsfs.Entity).annotations, {}) + self.assertDictEqual(from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + + bsfs:Entity rdfs:subClassOf bsfs:Node ; + rdfs:label "hello world"^^xsd:string ; + bsfs:foo "1234"^^xsd:integer . + + ''').node(ns.bsfs.Entity).annotations, { + ns.rdfs.label: 'hello world', + ns.bsfs.foo: 1234, + }) + + + def test_literal(self): + # all literals must be defined + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + + bse:filename rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; # undefined symbol + bsfs:unique "false"^^xsd:boolean . + ''') + + # literal definitions must be consistent (cannot re-use a literal uri) + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + + xsd:string rdfs:subClassOf bsfs:Literal . + xsd:name rdfs:subClassOf bsfs:Literal . + xsd:name rdfs:subClassOf xsd:string . # conflicting parent + ''') + + # additional literals can be defined + l_unused = types.ROOT_LITERAL.get_child(ns.xsd.unused) + self.assertEqual(Schema({}, {}, {l_unused}), from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + xsd:unused rdfs:subClassOf bsfs:Literal . # unused symbol + ''')) + + # a literal can have multiple children + l_string = types.ROOT_LITERAL.get_child(ns.xsd.string) + l_integer = types.ROOT_LITERAL.get_child(ns.xsd.integer) + l_unsigned = l_integer.get_child(ns.xsd.unsigned) + l_signed = l_integer.get_child(ns.xsd.signed) + self.assertEqual(Schema({}, {}, {l_string, l_integer, l_unsigned, l_signed}), from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + # literals inherit from same parent + xsd:string rdfs:subClassOf bsfs:Literal . + xsd:integer rdfs:subClassOf bsfs:Literal . + + # literals inherit from same parent + xsd:unsigned rdfs:subClassOf xsd:integer . + xsd:signed rdfs:subClassOf xsd:integer . + ''')) + + # additional literals can be defined and used + n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) + l_string = types.ROOT_LITERAL.get_child(ns.xsd.string) + p_filename = types.ROOT_PREDICATE.get_child(ns.bse.filename, + n_ent, l_string, False) + self.assertEqual(Schema({p_filename}), from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + xsd:string rdfs:subClassOf bsfs:Literal . + + bse:filename rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "false"^^xsd:boolean . + ''')) + + # literals can have annotations + self.assertDictEqual(from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + + xsd:string rdfs:subClassOf bsfs:Literal . + + ''').literal(ns.xsd.string).annotations, {}) + self.assertDictEqual(from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + + xsd:string rdfs:subClassOf bsfs:Literal ; + rdfs:label "hello world"^^xsd:string ; + bsfs:foo "1234"^^xsd:integer . + + ''').literal(ns.xsd.string).annotations, { + ns.rdfs.label: 'hello world', + ns.bsfs.foo: 1234, + }) + + + def test_predicate(self): + # domain must be defined + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + xsd:string rdfs:subClassOf bsfs:Literal . + + bse:filename rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; # undefined symbol + rdfs:range xsd:string ; + bsfs:unique "false"^^xsd:boolean . + ''') + # domain cannot be a literal + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Literal . + xsd:string rdfs:subClassOf bsfs:Literal . + + bse:filename rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; # literal instead of node + rdfs:range xsd:string ; + bsfs:unique "false"^^xsd:boolean . + ''') + + # range must be defined + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + + bse:filename rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; # undefined symbol + bsfs:unique "false"^^xsd:boolean . + ''') + # range must be defined + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + + bse:filename rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range bsfs:Foo ; # undefined symbol + bsfs:unique "false"^^xsd:boolean . + ''') + # range must be a node or a literal + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + + bse:filename rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range bsfs:Predicate ; # invalid symbol + bsfs:unique "false"^^xsd:boolean . + ''') + + # additional predicates can be defined + n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) + l_string = types.ROOT_LITERAL.get_child(ns.xsd.string) + p_comment = types.ROOT_PREDICATE.get_child(ns.bse.comment, domain=n_ent, range=l_string, unique=False) + self.assertEqual(Schema({p_comment}), from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + xsd:string rdfs:subClassOf bsfs:Literal . + + bse:comment rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string ; + bsfs:unique "false"^^xsd:boolean . + ''')) + + # predicates inherit properties from parents + n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) + l_string = types.ROOT_LITERAL.get_child(ns.xsd.string) + p_annotation = types.ROOT_PREDICATE.get_child(ns.bsfs.Annotation, domain=n_ent, range=l_string) + p_comment = p_annotation.get_child(ns.bse.comment, unique=True) + self.assertEqual(Schema({p_comment}), from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + xsd:string rdfs:subClassOf bsfs:Literal . + + bsfs:Annotation rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range xsd:string . + + bse:comment rdfs:subClassOf bsfs:Annotation ; # inherits domain/range from bsfs:Annotation + bsfs:unique "true"^^xsd:boolean . + ''')) + + # we can define partial predicates (w/o specifying a usable range) + n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) + l_string = types.ROOT_LITERAL.get_child(ns.xsd.string) + p_annotation = types.ROOT_PREDICATE.get_child(ns.bsfs.Annotation, domain=n_ent) + p_comment = p_annotation.get_child(ns.bse.comment, range=l_string, unique=False) + self.assertEqual(Schema({p_comment}), from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + xsd:string rdfs:subClassOf bsfs:Literal . + + bsfs:Annotation rdfs:subClassOf bsfs:Predicate ; # derive predicate w/o setting range + rdfs:domain bsfs:Entity . + + bse:comment rdfs:subClassOf bsfs:Annotation ; # derived predicate w/ setting range + rdfs:range xsd:string ; + bsfs:unique "false"^^xsd:boolean . + ''')) + + # predicate definition can be split across multiple statements. + # statements can be repeated + n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) + p_foo = types.ROOT_PREDICATE.get_child(ns.bse.foo, domain=n_ent, range=types.ROOT_NODE, unique=True) + self.assertEqual(Schema({p_foo}), from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + + bse:foo rdfs:subClassOf bsfs:Predicate ; + rdfs:range bsfs:Node ; + bsfs:unique "true"^^xsd:boolean . + + bse:foo rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity. + ''')) + + # domain must be a subtype of parent's domain + n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) + n_image = n_ent.get_child(ns.bsfs.Image) + p_foo = types.ROOT_PREDICATE.get_child(ns.bse.foo, domain=types.ROOT_NODE) + p_bar = p_foo.get_child(ns.bse.bar, domain=n_ent) + p_foobar = p_bar.get_child(ns.bse.foobar, domain=n_image) + self.assertEqual(Schema({p_foobar}), from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + bsfs:Image rdfs:subClassOf bsfs:Entity . + + bse:foo rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Node . + bse:bar rdfs:subClassOf bse:foo ; + rdfs:domain bsfs:Entity . + bse:foobar rdfs:subClassOf bse:bar ; + rdfs:domain bsfs:Image . + ''')) + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + bsfs:Image rdfs:subClassOf bsfs:Entity . + + bse:foo rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Image . + bse:bar rdfs:subClassOf bse:foo ; + rdfs:domain bsfs:Entity . + bse:foobar rdfs:subClassOf bse:bar ; + rdfs:domain bsfs:Node . + ''') + + # range must be a subtype of parent's range + n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) + n_image = n_ent.get_child(ns.bsfs.Image) + p_foo = types.ROOT_PREDICATE.get_child(ns.bse.foo, range=types.ROOT_NODE) + p_bar = p_foo.get_child(ns.bse.bar, range=n_ent) + p_foobar = p_bar.get_child(ns.bse.foobar, range=n_image) + self.assertEqual(Schema({p_foobar}), from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + bsfs:Image rdfs:subClassOf bsfs:Entity . + + bse:foo rdfs:subClassOf bsfs:Predicate ; + rdfs:range bsfs:Node . + bse:bar rdfs:subClassOf bse:foo ; + rdfs:range bsfs:Entity . + bse:foobar rdfs:subClassOf bse:bar ; + rdfs:range bsfs:Image . + ''')) + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + bsfs:Image rdfs:subClassOf bsfs:Entity . + + bse:foo rdfs:subClassOf bsfs:Predicate ; + rdfs:range bsfs:Image . + bse:bar rdfs:subClassOf bse:foo ; + rdfs:range bsfs:Entity . + bse:foobar rdfs:subClassOf bse:bar ; + rdfs:range bsfs:Node . + ''') + + # cannot define the same predicate from multiple parents + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + bsfs:Annotation rdfs:subClassOf bsfs:Predicate . + + bse:foo rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Node ; + rdfs:range bsfs:Node ; + bsfs:unique "false"^^xsd:boolean . + + bse:foo rdfs:subClassOf bsfs:Annotation ; + rdfs:domain bsfs:Node ; + rdfs:range bsfs:Node ; + bsfs:unique "false"^^xsd:boolean . + + ''') + # cannot assign multiple conflicting domains to the same predicate + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + + bse:foo rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Node ; + rdfs:range bsfs:Node ; + bsfs:unique "false"^^xsd:boolean . + + bse:foo rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity . # conflicting domain + ''') + # cannot assign multiple conflicting ranges to the same predicate + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + + bse:foo rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Node ; + rdfs:range bsfs:Node ; + bsfs:unique "false"^^xsd:boolean . + + bse:foo rdfs:subClassOf bsfs:Predicate ; + rdfs:range bsfs:Entity . # conflicting range + ''') + # cannot assign multiple conflicting uniques to the same predicate + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Entity rdfs:subClassOf bsfs:Node . + + bse:foo rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Node ; + rdfs:range bsfs:Node ; + bsfs:unique "false"^^xsd:boolean . + + bse:foo rdfs:subClassOf bsfs:Predicate ; + bsfs:unique "true"^^xsd:boolean . # conflicting unique + ''') + + # predicates can have annotations + self.assertDictEqual(from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bse:comment rdfs:subClassOf bsfs:Predicate ; + rdfs:range bsfs:Node . + + ''').predicate(ns.bse.comment).annotations, {}) + self.assertDictEqual(from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bse:comment rdfs:subClassOf bsfs:Predicate ; + rdfs:range bsfs:Node ; + rdfs:label "hello world"^^xsd:string ; + bsfs:foo "1234"^^xsd:integer . + + ''').predicate(ns.bse.comment).annotations, { + ns.rdfs.label: 'hello world', + ns.bsfs.foo: 1234, + }) + + + def test_feature(self): + # domain must be defined + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Feature rdfs:subClassOf bsfs:Predicate . + bsfs:array rdfs:subClassOf bsfs:Literal . + + bse:colors rdfs:subClassOf bsfs:Feature ; + rdfs:domain bsfs:Entity ; # undefined symbol + rdfs:range bsfs:array ; + bsfs:unique "false"^^xsd:boolean . + ''') + # domain cannot be a literal + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Feature rdfs:subClassOf bsfs:Predicate . + bsfs:Entity rdfs:subClassOf bsfs:Literal . + bsfs:array rdfs:subClassOf bsfs:Literal . + + bse:colors rdfs:subClassOf bsfs:Feature ; + rdfs:domain bsfs:Entity ; # literal instead of node + rdfs:range bsfs:array ; + bsfs:unique "false"^^xsd:boolean . + ''') + + # range must be defined + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Feature rdfs:subClassOf bsfs:Predicate . + bsfs:Entity rdfs:subClassOf bsfs:Node . + + bse:colors rdfs:subClassOf bsfs:Feature ; + rdfs:domain bsfs:Entity ; + rdfs:range bsfs:array ; # undefined symbol + bsfs:unique "false"^^xsd:boolean . + ''') + # range must be defined + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Feature rdfs:subClassOf bsfs:Predicate . + bsfs:Entity rdfs:subClassOf bsfs:Node . + + bse:colors rdfs:subClassOf bsfs:Feature ; + rdfs:domain bsfs:Entity ; + rdfs:range bsfs:Foo ; # undefined symbol + bsfs:unique "false"^^xsd:boolean . + ''') + # range must be a node or a literal + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Feature rdfs:subClassOf bsfs:Predicate . + bsfs:Entity rdfs:subClassOf bsfs:Node . + + bse:colors rdfs:subClassOf bsfs:Feature ; + rdfs:domain bsfs:Entity ; + rdfs:range bsfs:Predicate ; # invalid symbol + bsfs:unique "false"^^xsd:boolean . + ''') + + # additional predicates can be defined + n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) + l_array = types.ROOT_LITERAL.get_child(ns.bsfs.array) + p_comment = types.ROOT_FEATURE.get_child(ns.bse.colors, domain=n_ent, range=l_array, unique=False) + self.assertEqual(Schema({p_comment}), from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Feature rdfs:subClassOf bsfs:Predicate . + bsfs:Entity rdfs:subClassOf bsfs:Node . + bsfs:array rdfs:subClassOf bsfs:Literal . + + bse:colors rdfs:subClassOf bsfs:Feature ; + rdfs:domain bsfs:Entity ; + rdfs:range bsfs:array ; + bsfs:unique "false"^^xsd:boolean . + ''')) + + # features inherit properties from parents + n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) + l_array = types.ROOT_LITERAL.get_child(ns.bsfs.array) + l_string = types.ROOT_LITERAL.get_child(ns.xsd.string) + p_annotation = types.ROOT_FEATURE.get_child(ns.bsfs.Annotation, domain=n_ent, range=l_array, + dimension=1234, dtype=ns.xsd.string) + p_comment = p_annotation.get_child(ns.bse.colors, unique=True) + self.assertEqual(Schema({p_comment}), from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Feature rdfs:subClassOf bsfs:Predicate . + bsfs:Entity rdfs:subClassOf bsfs:Node . + bsfs:array rdfs:subClassOf bsfs:Literal . + + bsfs:Annotation rdfs:subClassOf bsfs:Feature ; # inherits defaults from bsfs:Feature + rdfs:domain bsfs:Entity ; + rdfs:range bsfs:array ; + bsfs:dimension "1234"^^xsd:integer ; + bsfs:dtype xsd:string . + + bse:colors rdfs:subClassOf bsfs:Annotation ; # inherits domain/range/etc. from bsfs:Annotation + bsfs:unique "true"^^xsd:boolean . # overwrites bsfs:Predicate + ''')) + + # feature definition can be split across multiple statements. + # statements can be repeated + n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) + p_foo = types.ROOT_FEATURE.get_child(ns.bse.foo, domain=n_ent, unique=True, + dimension=1234, dtype=ns.bsfs.f32) + self.assertEqual(Schema({p_foo}), from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Feature rdfs:subClassOf bsfs:Predicate . + bsfs:Entity rdfs:subClassOf bsfs:Node . + + bse:foo rdfs:subClassOf bsfs:Feature ; + bsfs:unique "true"^^xsd:boolean ; + bsfs:dimension "1234"^^xsd:integer . + + bse:foo rdfs:subClassOf bsfs:Feature ; + rdfs:domain bsfs:Entity ; + bsfs:dtype bsfs:f32 . + ''')) + + # cannot define the same feature from multiple parents + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Feature rdfs:subClassOf bsfs:Predicate . + bsfs:Annotation rdfs:subClassOf bsfs:Feature . + bsfs:Entity rdfs:subClassOf bsfs:Node . + + bse:foo rdfs:subClassOf bsfs:Feature ; + rdfs:domain bsfs:Node ; + bsfs:unique "false"^^xsd:boolean . + + bse:foo rdfs:subClassOf bsfs:Annotation ; + rdfs:domain bsfs:Node ; + bsfs:unique "false"^^xsd:boolean . + + ''') + # cannot assign multiple conflicting domains to the same feature + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Feature rdfs:subClassOf bsfs:Predicate . + bsfs:Entity rdfs:subClassOf bsfs:Node . + + bse:foo rdfs:subClassOf bsfs:Feature ; + rdfs:domain bsfs:Node ; + bsfs:unique "false"^^xsd:boolean . + + bse:foo rdfs:subClassOf bsfs:Feature ; + rdfs:domain bsfs:Entity . # conflicting domain + ''') + # cannot assign multiple conflicting ranges to the same feature + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Feature rdfs:subClassOf bsfs:Predicate . + bsfs:Entity rdfs:subClassOf bsfs:Node . + bsfs:array rdfs:subClassOf bsfs:Literal . + bsfs:large_array rdfs:subClassOf bsfs:array . + bsfs:small_array rdfs:subClassOf bsfs:array . + + bse:foo rdfs:subClassOf bsfs:Feature ; + rdfs:domain bsfs:Node ; + rdfs:range bsfs:large_array ; + bsfs:unique "false"^^xsd:boolean . + + bse:foo rdfs:subClassOf bsfs:Feature ; + rdfs:range bsfs:small_array . # conflicting range + ''') + # cannot assign multiple conflicting uniques to the same feature + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Feature rdfs:subClassOf bsfs:Predicate . + bsfs:Entity rdfs:subClassOf bsfs:Node . + + bse:foo rdfs:subClassOf bsfs:Feature ; + rdfs:domain bsfs:Node ; + rdfs:range bsfs:Node ; + bsfs:unique "false"^^xsd:boolean . + + bse:foo rdfs:subClassOf bsfs:Feature ; + bsfs:unique "true"^^xsd:boolean . # conflicting unique + ''') + # cannot assign multiple conflicting dimensions to the same feature + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Feature rdfs:subClassOf bsfs:Predicate . + bsfs:Entity rdfs:subClassOf bsfs:Node . + + bse:foo rdfs:subClassOf bsfs:Feature ; + rdfs:domain bsfs:Node ; + bsfs:dimension "1234"^^xsd:integer . + + bse:foo rdfs:subClassOf bsfs:Feature ; + bsfs:dimension "4321"^^xsd:integer . # conflicting dimension + ''') + # cannot assign multiple conflicting dtypes to the same feature + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Feature rdfs:subClassOf bsfs:Predicate . + bsfs:Entity rdfs:subClassOf bsfs:Node . + + bse:foo rdfs:subClassOf bsfs:Feature ; + rdfs:domain bsfs:Node ; + bsfs:dtype bsfs:f32 . + + bse:foo rdfs:subClassOf bsfs:Feature ; + bsfs:dtype bsfs:f16 . # conflicting dtype + ''') + # cannot assign multiple conflicting distance metrics to the same feature + self.assertRaises(errors.ConsistencyError, from_string, ''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Feature rdfs:subClassOf bsfs:Predicate . + bsfs:Entity rdfs:subClassOf bsfs:Node . + + bse:foo rdfs:subClassOf bsfs:Feature ; + rdfs:domain bsfs:Node ; + bsfs:distance bsfs:euclidean . + + bse:foo rdfs:subClassOf bsfs:Feature ; + bsfs:distance bsfs:cosine . # conflicting distance + ''') + + # features can have annotations + self.assertDictEqual(from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Feature rdfs:subClassOf bsfs:Predicate . + bse:colors rdfs:subClassOf bsfs:Feature ; + bsfs:dimension "1234"^^xsd:integer . + + ''').predicate(ns.bse.colors).annotations, {}) + self.assertDictEqual(from_string(''' + prefix rdfs: + prefix xsd: + prefix bsfs: + prefix bse: + + bsfs:Feature rdfs:subClassOf bsfs:Predicate . + bse:colors rdfs:subClassOf bsfs:Feature ; + bsfs:dimension "1234"^^xsd:integer ; + rdfs:label "hello world"^^xsd:string ; + bsfs:foo "1234"^^xsd:integer . + + ''').predicate(ns.bse.colors).annotations, { + ns.rdfs.label: 'hello world', + ns.bsfs.foo: 1234, + }) + + + def test_integration(self): + # nodes + n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) + n_tag = types.ROOT_NODE.get_child(ns.bsfs.Tag) + n_image = n_ent.get_child(ns.bsfs.Image) + # literals + l_string = types.ROOT_LITERAL.get_child(ns.xsd.string) + l_array = types.ROOT_LITERAL.get_child(ns.bsfs.array) + l_integer = types.ROOT_LITERAL.get_child(ns.xsd.integer) + l_boolean = types.ROOT_LITERAL.get_child(ns.xsd.boolean) + # predicates + p_annotation = types.ROOT_PREDICATE.get_child(ns.bsfs.Annotation) + p_tag = types.ROOT_PREDICATE.get_child(ns.bse.tag, domain=n_ent, range=n_tag) + p_group = p_tag.get_child(ns.bse.group, domain=n_image, unique=True) + p_comment = p_annotation.get_child(ns.bse.comment, range=l_string) + # features + f_colors = types.ROOT_FEATURE.get_child(URI('http://bsfs.ai/schema/Feature/colors_spatial'), + domain=n_ent, range=l_array, unique=True, dtype=ns.bsfs.f16, distance=ns.bsfs.euclidean) + f_colors1234 = f_colors.get_child(URI('http://bsfs.ai/schema/Feature/colors_spatial#1234'), dimension=1024) + f_colors4321 = f_colors.get_child(URI('http://bsfs.ai/schema/Feature/colors_spatial#4321'), dimension=2048) + # schema + ref = Schema( + {p_annotation, p_tag, p_group, p_comment, f_colors, f_colors1234, f_colors4321}, + {n_ent, n_tag, n_image}, + {l_string, l_integer, l_boolean}) + # load from string + gen = from_string(''' + # generic prefixes + prefix rdfs: + prefix xsd: + + # bsfs prefixes + prefix bsfs: + prefix bse: + + # nodes + bsfs:Entity rdfs:subClassOf bsfs:Node ; + rdfs:label "Principal node"^^xsd:string . + bsfs:Tag rdfs:subClassOf bsfs:Node ; + rdfs:label "Tag"^^xsd:string . + bsfs:Image rdfs:subClassOf bsfs:Entity . + + # literals + xsd:string rdfs:subClassOf bsfs:Literal ; + rdfs:label "A sequence of characters"^^xsd:string . + bsfs:array rdfs:subClassOf bsfs:Literal . + xsd:integer rdfs:subClassOf bsfs:Literal . + xsd:boolean rdfs:subClassOf bsfs:Literal . + + # abstract predicates + bsfs:Annotation rdfs:subClassOf bsfs:Predicate ; + rdfs:label "node annotation"^^xsd:string . + bsfs:Feature rdfs:subClassOf bsfs:Predicate . + + # feature instances + rdfs:subClassOf bsfs:Feature ; + rdfs:domain bsfs:Entity ; + rdfs:range bsfs:array ; + bsfs:unique "true"^^xsd:boolean ; + bsfs:dtype bsfs:f16 ; + bsfs:distance bsfs:euclidean ; + # annotations + rdfs:label "ColorsSpatial instances. Dimension depends on instance."^^xsd:string ; + bsfs:first_arg "1234"^^xsd:integer ; + bsfs:second_arg "hello world"^^xsd:string . + + rdfs:subClassOf ; + bsfs:dimension "1024"^^xsd:integer ; + rdfs:label "Main colors spatial instance"^^xsd:string . + + rdfs:subClassOf ; + bsfs:dimension "2048"^^xsd:integer . + + # predicate instances + bse:tag rdfs:subClassOf bsfs:Predicate ; + rdfs:domain bsfs:Entity ; + rdfs:range bsfs:Tag ; + bsfs:unique "false"^^xsd:boolean ; + # annotations + rdfs:label "connect entity to a tag"^^xsd:string . + + bse:group rdfs:subClassOf bse:tag ; # subtype of another predicate + rdfs:domain bsfs:Image ; + bsfs:unique "true"^^xsd:boolean . + + bse:comment rdfs:subClassOf bsfs:Annotation ; # subtype of abstract predicate + rdfs:domain bsfs:Node ; + rdfs:range xsd:string ; + bsfs:unique "false"^^xsd:boolean . + + ''') + # schemas are equal + self.assertEqual(ref, gen) + # check annotations + self.assertDictEqual(gen.node(ns.bsfs.Entity).annotations, {ns.rdfs.label: 'Principal node'}) + self.assertDictEqual(gen.node(ns.bsfs.Tag).annotations, {ns.rdfs.label: 'Tag'}) + self.assertDictEqual(gen.literal(ns.xsd.string).annotations, {ns.rdfs.label: 'A sequence of characters'}) + self.assertDictEqual(gen.predicate(ns.bsfs.Annotation).annotations, {ns.rdfs.label: 'node annotation'}) + self.assertDictEqual(gen.predicate(URI('http://bsfs.ai/schema/Feature/colors_spatial')).annotations, { + ns.rdfs.label: 'ColorsSpatial instances. Dimension depends on instance.', + ns.bsfs.first_arg: 1234, + ns.bsfs.second_arg: 'hello world', + }) + self.assertDictEqual(gen.predicate(URI('http://bsfs.ai/schema/Feature/colors_spatial#1234')).annotations, { + ns.rdfs.label: 'Main colors spatial instance'}) + self.assertDictEqual(gen.predicate(ns.bse.tag).annotations, {ns.rdfs.label: 'connect entity to a tag'}) + + + +class TestToString(unittest.TestCase): + def test_stub(self): + raise NotImplementedError() + + +## main ## + +if __name__ == '__main__': + unittest.main() + +## EOF ## diff --git a/test/schema/test_types.py b/test/schema/test_types.py index 4a49e6e..af47f0d 100644 --- a/test/schema/test_types.py +++ b/test/schema/test_types.py @@ -10,15 +10,17 @@ import unittest # bsfs imports from bsfs.namespace import ns +from bsfs.schema.types import ROOT_PREDICATE, ROOT_VERTEX, ROOT_FEATURE from bsfs.utils import errors # objects to test -from bsfs.schema.types import _Type, _Vertex, Node, Literal, Predicate +from bsfs.schema.types import _Type, _Vertex, Node, Literal, Predicate, Feature ## code ## class TestType(unittest.TestCase): + def test_parents(self): # create some types fst = _Type('First') @@ -31,7 +33,25 @@ class TestType(unittest.TestCase): self.assertListEqual(list(trd.parents()), [snd, fst]) self.assertListEqual(list(frd.parents()), [trd, snd, fst]) - def test_essentials(self): + def test_annotations(self): + # annotations can be empty + self.assertDictEqual(_Type('Foo', None).annotations, {}) + # annotations are stored + self.assertDictEqual(_Type('Foo', None, foo='bar', bar=123).annotations, { + 'foo': 'bar', + 'bar': 123}) + # comparison ignores annotations + self.assertEqual( + _Type('Foo', None, foo='bar', bar='foo'), + _Type('Foo', None, hello='world', foobar=1234)) + self.assertEqual( + hash(_Type('Foo', None, foo='bar', bar='foo')), + hash(_Type('Foo', None, hello='world', foobar=1234))) + # annotations can be passed to get_child + self.assertDictEqual(_Type('First', foo='bar').get_child('Second', bar='foo').annotations, { + 'bar': 'foo'}) + + def test_string_conversion(self): # type w/o parent self.assertEqual(str(_Type('Foo')), '_Type(Foo)') self.assertEqual(repr(_Type('Foo')), '_Type(Foo, None)') @@ -59,6 +79,9 @@ class TestType(unittest.TestCase): # type persists class Foo(_Type): pass self.assertEqual(Foo('First').get_child('Second'), Foo('Second', Foo('First'))) + # annotations are respected + self.assertDictEqual(_Type('First', foo='bar').get_child('Second', bar='foo').annotations, { + 'bar': 'foo'}) def test_equality(self): # equality depends on uri @@ -76,6 +99,13 @@ class TestType(unittest.TestCase): # comparison respects parent self.assertNotEqual(_Type('Foo', _Type('Bar')), _Type('Foo')) self.assertNotEqual(hash(_Type('Foo', _Type('Bar'))), hash(_Type('Foo'))) + # comparison ignores annotations + self.assertEqual( + _Type('Foo', None, foo='bar', bar='foo'), + _Type('Foo', None, hello='world', foobar=1234)) + self.assertEqual( + hash(_Type('Foo', None, foo='bar', bar='foo')), + hash(_Type('Foo', None, hello='world', foobar=1234))) def test_order(self): # create some types. @@ -109,25 +139,40 @@ class TestType(unittest.TestCase): self.assertFalse(bike > bicycle) self.assertFalse(bike >= bicycle) self.assertFalse(bike == bicycle) + + # can compare types along the class hierarchy class Foo(_Type): pass - foo = Foo(bike.uri, bike.parent) - # cannot compare different types - self.assertRaises(TypeError, operator.lt, foo, bike) - self.assertRaises(TypeError, operator.le, foo, bike) - self.assertRaises(TypeError, operator.gt, foo, bike) - self.assertRaises(TypeError, operator.ge, foo, bike) + foo = Foo('Foo', bike) + self.assertTrue(foo < bike) + self.assertTrue(foo <= bike) + self.assertFalse(foo > bike) + self.assertFalse(foo >= bike) # goes both ways - self.assertRaises(TypeError, operator.lt, bike, foo) - self.assertRaises(TypeError, operator.le, bike, foo) - self.assertRaises(TypeError, operator.gt, bike, foo) - self.assertRaises(TypeError, operator.ge, bike, foo) + self.assertFalse(bike < foo) + self.assertFalse(bike <= foo) + self.assertTrue(bike > foo) + self.assertTrue(bike >= foo) + # cannot compare unrelated classes + class Bar(_Type): pass + bar = Bar('Bar', bike) + self.assertRaises(TypeError, operator.lt, foo, bar) + self.assertRaises(TypeError, operator.le, foo, bar) + self.assertRaises(TypeError, operator.gt, foo, bar) + self.assertRaises(TypeError, operator.ge, foo, bar) + # goes both ways + self.assertRaises(TypeError, operator.lt, bar, foo) + self.assertRaises(TypeError, operator.le, bar, foo) + self.assertRaises(TypeError, operator.gt, bar, foo) + self.assertRaises(TypeError, operator.ge, bar, foo) + class TestPredicate(unittest.TestCase): def test_construction(self): # domain must be a node self.assertRaises(TypeError, Predicate, ns.bse.foo, 1234, None, True) self.assertRaises(TypeError, Predicate, ns.bse.foo, None, Literal(ns.bsfs.Foo, None), None, True) - # range must be None, a Literal, or a Node + # range must be a Literal, a Node, or the root Vertex + self.assertRaises(TypeError, Predicate, ns.bse.foo, None, Node(ns.bsfs.Node, None), None, True) self.assertRaises(TypeError, Predicate, ns.bse.foo, None, Node(ns.bsfs.Node, None), 1234, True) self.assertRaises(TypeError, Predicate, ns.bse.foo, None, Node(ns.bsfs.Node, None), _Vertex(ns.bsfs.Foo, None), True) self.assertRaises(TypeError, Predicate, ns.bse.foo, None, Node(ns.bsfs.Node, None), _Type(ns.bsfs.Foo, None), True) @@ -138,54 +183,52 @@ class TestPredicate(unittest.TestCase): n_root = Node(ns.bsfs.Node, None) n_ent = Node(ns.bsfs.Entity, Node(ns.bsfs.Node, None)) n_tag = Node(ns.bsfs.Tag, Node(ns.bsfs.Tag, None)) - root = Predicate( - uri=ns.bsfs.Predicate, - parent=None, + root = ROOT_PREDICATE + tag = Predicate( + uri=ns.bse.tag, + parent=root, domain=n_root, - range=None, + range=n_tag, unique=False, ) # instance is equal to itself - self.assertEqual(root, root) - self.assertEqual(hash(root), hash(root)) + self.assertEqual(tag, tag) + self.assertEqual(hash(tag), hash(tag)) # instance is equal to a clone - self.assertEqual(root, Predicate(ns.bsfs.Predicate, None, n_root, None, False)) - self.assertEqual(hash(root), hash(Predicate(ns.bsfs.Predicate, None, n_root, None, False))) + self.assertEqual(tag, Predicate(ns.bse.tag, root, n_root, n_tag, False)) + self.assertEqual(hash(tag), hash(Predicate(ns.bse.tag, root, n_root, n_tag, False))) # equality respects uri - self.assertNotEqual(root, Predicate(ns.bsfs.Alternative, None, n_root, None, False)) - self.assertNotEqual(hash(root), hash(Predicate(ns.bsfs.Alternative, None, n_root, None, False))) + self.assertNotEqual(tag, Predicate(ns.bsfs.Alternative, root, n_root, n_tag, False)) + self.assertNotEqual(hash(tag), hash(Predicate(ns.bsfs.Alternative, root, n_root, n_tag, False))) # equality respects parent - self.assertNotEqual(root, Predicate(ns.bsfs.Predicate, n_root, n_root, None, False)) - self.assertNotEqual(hash(root), hash(Predicate(ns.bsfs.Predicate, n_root, n_root, None, False))) + self.assertNotEqual(tag, Predicate(ns.bse.tag, n_root, n_root, n_tag, False)) + self.assertNotEqual(hash(tag), hash(Predicate(ns.bse.tag, n_root, n_root, n_tag, False))) # equality respects domain - self.assertNotEqual(root, Predicate(ns.bsfs.Predicate, None, n_ent, None, False)) - self.assertNotEqual(hash(root), hash(Predicate(ns.bsfs.Predicate, None, n_ent, None, False))) + self.assertNotEqual(tag, Predicate(ns.bse.tag, root, n_ent, n_tag, False)) + self.assertNotEqual(hash(tag), hash(Predicate(ns.bse.tag, root, n_ent, n_tag, False))) # equality respects range - self.assertNotEqual(root, Predicate(ns.bsfs.Predicate, None, n_root, n_root, False)) - self.assertNotEqual(hash(root), hash(Predicate(ns.bsfs.Predicate, None, n_root, n_root, False))) + self.assertNotEqual(tag, Predicate(ns.bse.tag, root, n_root, n_root, False)) + self.assertNotEqual(hash(tag), hash(Predicate(ns.bse.tag, root, n_root, n_root, False))) # equality respects unique - self.assertNotEqual(root, Predicate(ns.bsfs.Predicate, None, n_root, None, True)) - self.assertNotEqual(hash(root), hash(Predicate(ns.bsfs.Predicate, None, n_root, None, True))) + self.assertNotEqual(tag, Predicate(ns.bse.tag, root, n_root, n_tag, True)) + self.assertNotEqual(hash(tag), hash(Predicate(ns.bse.tag, root, n_root, n_tag, True))) def test_get_child(self): n_root = Node(ns.bsfs.Node, None) + l_root = Literal(ns.bsfs.Literal, None) n_ent = Node(ns.bsfs.Entity, Node(ns.bsfs.Node, None)) n_tag = Node(ns.bsfs.Tag, Node(ns.bsfs.Tag, None)) - root = Predicate( - uri=ns.bsfs.Predicate, - parent=None, - domain=n_root, - range=None, - unique=False, - ) + root = ROOT_PREDICATE tag = Predicate( - uri=ns.bsfs.Entity, + uri=ns.bse.tag, parent=root, domain=n_ent, range=n_tag, unique=False, ) + # get_child returns Predicate + self.assertIsInstance(tag.get_child(ns.bse.foo), Predicate) # uri is respected self.assertEqual(ns.bse.foo, tag.get_child(ns.bse.foo).uri) # domain is respected @@ -198,10 +241,17 @@ class TestPredicate(unittest.TestCase): self.assertEqual(n_tag, tag.get_child(ns.bse.foo, range=None).range) # unique is respected self.assertTrue(tag.get_child(ns.bse.foo, unique=True).unique) + # annotations are respected + self.assertDictEqual(tag.get_child(ns.bse.foo, foo='bar', bar=123).annotations, { + 'foo': 'bar', + 'bar': 123, + }) # domain is inherited from parent + self.assertEqual(n_root, root.get_child(ns.bse.foo).domain) self.assertEqual(n_ent, tag.get_child(ns.bse.foo).domain) # range is inherited from parent + self.assertEqual(ROOT_VERTEX, root.get_child(ns.bse.foo).range) self.assertEqual(n_tag, tag.get_child(ns.bse.foo).range) # uniqueness is inherited from parent self.assertFalse(tag.get_child(ns.bse.foo).unique) @@ -209,11 +259,118 @@ class TestPredicate(unittest.TestCase): # domain must be subtype of parent's domain self.assertRaises(errors.ConsistencyError, tag.get_child, ns.bse.foo, domain=n_root) self.assertRaises(errors.ConsistencyError, tag.get_child, ns.bse.foo, domain=Node(ns.bsfs.Image, n_root)) - # range cannot be None - self.assertRaises(ValueError, root.get_child, ns.bse.foo) # range must be subtype of parent's range self.assertRaises(errors.ConsistencyError, tag.get_child, ns.bse.foo, range=n_root) self.assertRaises(errors.ConsistencyError, tag.get_child, ns.bse.foo, range=Node(ns.bsfs.Image, n_root)) + self.assertRaises(TypeError, tag.get_child, ns.bse.foo, range=Literal(ns.bsfs.Tag, l_root)) + # range can be subtyped from ROOT_VERTEX to Node or Literal + self.assertEqual(n_root, root.get_child(ns.bse.foo, range=n_root).range) + self.assertEqual(l_root, root.get_child(ns.bse.foo, range=l_root).range) + + +class TestFeature(unittest.TestCase): + def test_construction(self): + n_root = Node(ns.bsfs.Node, None) + l_root = Literal(ns.bsfs.Literal, None) + # dimension, dtype, and distance are respected + feat = Feature(ns.bsfs.Feature, None, n_root, l_root, False, + 1234, ns.bsfs.float, ns.bsfs.euclidean) + self.assertEqual(1234, feat.dimension) + self.assertEqual(ns.bsfs.float, feat.dtype) + self.assertEqual(ns.bsfs.euclidean, feat.distance) + + def test_equality(self): + n_ent = Node(ns.bsfs.Entity, Node(ns.bsfs.Node, None)) + l_array = Literal(ns.bsfs.array, Literal(ns.bsfs.Literal, None)) + colors = Feature( + uri=ns.bse.colors, + parent=ROOT_FEATURE, + domain=n_ent, + range=l_array, + unique=False, + dimension=1234, + dtype=ns.bsfs.float, + distance=ns.bsfs.euclidean, + ) + # instance is equal to itself + self.assertEqual(colors, colors) + self.assertEqual(hash(colors), hash(colors)) + # instance is equal to a clone + self.assertEqual(colors, Feature(ns.bse.colors, ROOT_FEATURE, n_ent, l_array, False, 1234, ns.bsfs.float, ns.bsfs.euclidean)) + self.assertEqual(hash(colors), hash(Feature(ns.bse.colors, ROOT_FEATURE, n_ent, l_array, False, 1234, ns.bsfs.float, ns.bsfs.euclidean))) + # equality respects dimension + self.assertNotEqual(colors, Feature(ns.bse.colors, ROOT_FEATURE, n_ent, l_array, False, 4321, ns.bsfs.float, ns.bsfs.euclidean)) + self.assertNotEqual(hash(colors), hash(Feature(ns.bse.colors, ROOT_FEATURE, n_ent, l_array, False, 4321, ns.bsfs.float, ns.bsfs.euclidean))) + # equality respects dtype + self.assertNotEqual(colors, Feature(ns.bse.colors, ROOT_FEATURE, n_ent, l_array, False, 1234, ns.bsfs.integer, ns.bsfs.euclidean)) + self.assertNotEqual(hash(colors), hash(Feature(ns.bse.colors, ROOT_FEATURE, n_ent, l_array, False, 1234, ns.bsfs.integer, ns.bsfs.euclidean))) + # equality respects distance + self.assertNotEqual(colors, Feature(ns.bse.colors, ROOT_FEATURE, n_ent, l_array, False, 1234, ns.bsfs.float, ns.bsfs.cosine)) + self.assertNotEqual(hash(colors), hash(Feature(ns.bse.colors, ROOT_FEATURE, n_ent, l_array, False, 1234, ns.bsfs.float, ns.bsfs.cosine))) + + def test_get_child(self): + n_root = Node(ns.bsfs.Node, None) + n_ent = Node(ns.bsfs.Entity, n_root) + l_root = Literal(ns.bsfs.Literal, None) + l_array = Literal(ns.bsfs.array, l_root) + colors = Feature( + uri=ns.bse.colors, + parent=ROOT_FEATURE, + domain=n_ent, + range=l_array, + unique=False, + dimension=1234, + dtype=ns.bsfs.float, + distance=ns.bsfs.euclidean, + ) + + # get_child returns Feature + self.assertIsInstance(colors.get_child(ns.bse.foo), Feature) + # uri is respected + self.assertEqual(ns.bse.foo, colors.get_child(ns.bse.foo).uri) + # domain is respected + dom = Node(ns.bsfs.Image, n_ent) + self.assertEqual(dom, colors.get_child(ns.bse.foo, domain=dom).domain) + # range is respected + rng = Literal(ns.bse.foo, l_array) + self.assertEqual(rng, colors.get_child(ns.bse.foo, range=rng).range) + # cannot set range to None + self.assertEqual(l_array, colors.get_child(ns.bse.foo, range=None).range) + # unique is respected + self.assertTrue(colors.get_child(ns.bse.foo, unique=True).unique) + # dimension is respected + self.assertEqual(4321, colors.get_child(ns.bse.foo, dimension=4321).dimension) + # dtype is respected + self.assertEqual(ns.bsfs.integer, colors.get_child(ns.bse.foo, dtype=ns.bsfs.integer).dtype) + # distance is respected + self.assertEqual(ns.bsfs.cosine, colors.get_child(ns.bse.foo, distance=ns.bsfs.cosine).distance) + # annotations are respected + self.assertDictEqual(colors.get_child(ns.bse.foo, foo='bar', bar=123).annotations, { + 'foo': 'bar', + 'bar': 123, + }) + + # domain is inherited from parent + self.assertEqual(n_root, ROOT_FEATURE.get_child(ns.bse.foo).domain) + self.assertEqual(n_ent, colors.get_child(ns.bse.foo).domain) + # range is inherited from parent + self.assertEqual(l_array, colors.get_child(ns.bse.foo).range) + # uniqueness is inherited from parent + self.assertFalse(colors.get_child(ns.bse.foo).unique) + # dimension is inherited from parent + self.assertEqual(1234, colors.get_child(ns.bse.foo).dimension) + # dtype is inherited from parent + self.assertEqual(ns.bsfs.float, colors.get_child(ns.bse.foo).dtype) + # distance is inherited from parent + self.assertEqual(ns.bsfs.euclidean, colors.get_child(ns.bse.foo).distance) + + # domain must be subtype of parent's domain + self.assertRaises(errors.ConsistencyError, colors.get_child, ns.bse.foo, domain=n_root) + self.assertRaises(errors.ConsistencyError, colors.get_child, ns.bse.foo, domain=Node(ns.bsfs.Image, n_root)) + # range must be subtype of parent's range + self.assertRaises(errors.ConsistencyError, colors.get_child, ns.bse.foo, range=Literal(ns.bsfs.Literal, None)) + self.assertRaises(errors.ConsistencyError, colors.get_child, ns.bse.foo, range=Literal(ns.bsfs.foo, Literal(ns.bsfs.Literal, None))) + self.assertRaises(TypeError, colors.get_child, ns.bse.foo, range=Node(ns.bsfs.Tag, n_root)) ## main ## @@ -222,4 +379,3 @@ if __name__ == '__main__': unittest.main() ## EOF ## - -- cgit v1.2.3 From 6fd984e694b0a7b749ab947211d792f5b011ee6f Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Thu, 12 Jan 2023 08:44:25 +0100 Subject: renamed get_child to child in schema.types._Type and _Vertex to Vertex in schema.types --- test/schema/test_schema.py | 40 +++++++------- test/schema/test_serialize.py | 126 +++++++++++++++++++++--------------------- test/schema/test_types.py | 108 ++++++++++++++++++------------------ 3 files changed, 137 insertions(+), 137 deletions(-) (limited to 'test/schema') diff --git a/test/schema/test_schema.py b/test/schema/test_schema.py index 1b45db0..ca21f87 100644 --- a/test/schema/test_schema.py +++ b/test/schema/test_schema.py @@ -73,9 +73,9 @@ class TestSchema(unittest.TestCase): # predicates self.p_root = types.ROOT_PREDICATE self.f_root = types.ROOT_FEATURE - self.p_tag = self.p_root.get_child(ns.bse.tag, self.n_ent, self.n_tag, False) - self.p_group = self.p_tag.get_child(ns.bse.group, self.n_img, self.n_tag, False) - self.p_comment = self.p_root.get_child(ns.bse.comment, self.n_root, self.l_string, True) + self.p_tag = self.p_root.child(ns.bse.tag, self.n_ent, self.n_tag, False) + self.p_group = self.p_tag.child(ns.bse.group, self.n_img, self.n_tag, False) + self.p_comment = self.p_root.child(ns.bse.comment, self.n_root, self.l_string, True) self.predicates = [self.p_root, self.f_root, self.p_tag, self.p_group, self.p_comment] def test_construction(self): @@ -217,16 +217,16 @@ class TestSchema(unittest.TestCase): self.assertNotEqual(hash(schema), hash(Schema([self.p_group, self.p_tag, self.p_root], self.nodes, self.literals))) self.assertNotEqual(schema, - Schema(self.predicates + [self.p_root.get_child(ns.bse.filesize, self.n_ent, self.l_integer)], self.nodes, self.literals)) + Schema(self.predicates + [self.p_root.child(ns.bse.filesize, self.n_ent, self.l_integer)], self.nodes, self.literals)) self.assertNotEqual(hash(schema), - hash(Schema(self.predicates + [self.p_root.get_child(ns.bse.filesize, self.n_ent, self.l_integer)], self.nodes, self.literals))) + hash(Schema(self.predicates + [self.p_root.child(ns.bse.filesize, self.n_ent, self.l_integer)], self.nodes, self.literals))) def test_order(self): # setup class Foo(): pass - p_foo = self.p_root.get_child(ns.bse.foo, self.n_ent, self.l_string, True) - p_sub = p_foo.get_child(ns.bse.sub, self.n_ent, self.l_string, True) - p_bar = self.p_root.get_child(ns.bse.bar, self.n_ent, self.l_string, True) + p_foo = self.p_root.child(ns.bse.foo, self.n_ent, self.l_string, True) + p_sub = p_foo.child(ns.bse.sub, self.n_ent, self.l_string, True) + p_bar = self.p_root.child(ns.bse.bar, self.n_ent, self.l_string, True) # can only compare schema to other schema # < @@ -305,44 +305,44 @@ class TestSchema(unittest.TestCase): # inconsistent schema cannot be a subset self.assertFalse(operator.le(Schema({p_foo}), Schema({ - self.p_root.get_child(ns.bse.foo, self.n_ent, self.l_integer, True)}))) # inconsistent w.r.t. literal + self.p_root.child(ns.bse.foo, self.n_ent, self.l_integer, True)}))) # inconsistent w.r.t. literal self.assertFalse(operator.le(Schema({p_foo}), Schema({ - self.p_root.get_child(ns.bse.foo, self.n_img, self.l_string, True)}))) # inconsistent w.r.t. node + self.p_root.child(ns.bse.foo, self.n_img, self.l_string, True)}))) # inconsistent w.r.t. node self.assertFalse(operator.le(Schema({p_foo}), Schema({ - self.p_root.get_child(ns.bse.foo, self.n_ent, self.l_string, False)}))) # inconsistent w.r.t. unique + self.p_root.child(ns.bse.foo, self.n_ent, self.l_string, False)}))) # inconsistent w.r.t. unique self.assertFalse(operator.le(Schema({}, {self.n_img}), Schema({}, { types.Node(ns.bsfs.Image, types.Node(ns.bsfs.Node, None))}))) self.assertFalse(operator.le(Schema({}, {}, {self.l_integer}), Schema({}, {}, { types.Literal(ns.xsd.integer, types.Literal(ns.xsd.number, types.Literal(ns.bsfs.Literal, None)))}))) # inconsistent schema cannot be a true subset self.assertFalse(operator.lt(Schema({p_foo}), Schema({ - self.p_root.get_child(ns.bse.foo, self.n_ent, self.l_integer, True)}))) # inconsistent w.r.t. literal + self.p_root.child(ns.bse.foo, self.n_ent, self.l_integer, True)}))) # inconsistent w.r.t. literal self.assertFalse(operator.lt(Schema({p_foo}), Schema({ - self.p_root.get_child(ns.bse.foo, self.n_img, self.l_string, True)}))) # inconsistent w.r.t. node + self.p_root.child(ns.bse.foo, self.n_img, self.l_string, True)}))) # inconsistent w.r.t. node self.assertFalse(operator.lt(Schema({p_foo}), Schema({ - self.p_root.get_child(ns.bse.foo, self.n_ent, self.l_string, False)}))) # inconsistent w.r.t. unique + self.p_root.child(ns.bse.foo, self.n_ent, self.l_string, False)}))) # inconsistent w.r.t. unique self.assertFalse(operator.lt(Schema({}, {self.n_img}), Schema({}, { types.Node(ns.bsfs.Image, types.Node(ns.bsfs.Node, None))}))) self.assertFalse(operator.lt(Schema({}, {}, {self.l_integer}), Schema({}, {}, { types.Literal(ns.xsd.integer, types.Literal(ns.xsd.number, types.Literal(ns.bsfs.Literal, None)))}))) # inconsistent schema cannot be a superset self.assertFalse(operator.ge(Schema({p_foo}), Schema({ - self.p_root.get_child(ns.bse.foo, self.n_ent, self.l_integer, True)}))) # inconsistent w.r.t. literal + self.p_root.child(ns.bse.foo, self.n_ent, self.l_integer, True)}))) # inconsistent w.r.t. literal self.assertFalse(operator.ge(Schema({p_foo}), Schema({ - self.p_root.get_child(ns.bse.foo, self.n_img, self.l_string, True)}))) # inconsistent w.r.t. node + self.p_root.child(ns.bse.foo, self.n_img, self.l_string, True)}))) # inconsistent w.r.t. node self.assertFalse(operator.ge(Schema({p_foo}), Schema({ - self.p_root.get_child(ns.bse.foo, self.n_ent, self.l_string, False)}))) # inconsistent w.r.t. unique + self.p_root.child(ns.bse.foo, self.n_ent, self.l_string, False)}))) # inconsistent w.r.t. unique self.assertFalse(operator.ge(Schema({}, {self.n_img}), Schema({}, { types.Node(ns.bsfs.Image, types.Node(ns.bsfs.Node, None))}))) self.assertFalse(operator.ge(Schema({}, {}, {self.l_integer}), Schema({}, {}, { types.Literal(ns.xsd.integer, types.Literal(ns.xsd.number, types.Literal(ns.bsfs.Literal, None)))}))) # inconsistent schema cannot be a true superset self.assertFalse(operator.gt(Schema({p_foo}), Schema({ - self.p_root.get_child(ns.bse.foo, self.n_ent, self.l_integer, True)}))) # inconsistent w.r.t. literal + self.p_root.child(ns.bse.foo, self.n_ent, self.l_integer, True)}))) # inconsistent w.r.t. literal self.assertFalse(operator.gt(Schema({p_foo}), Schema({ - self.p_root.get_child(ns.bse.foo, self.n_img, self.l_string, True)}))) # inconsistent w.r.t. node + self.p_root.child(ns.bse.foo, self.n_img, self.l_string, True)}))) # inconsistent w.r.t. node self.assertFalse(operator.gt(Schema({p_foo}), Schema({ - self.p_root.get_child(ns.bse.foo, self.n_ent, self.l_string, False)}))) # inconsistent w.r.t. unique + self.p_root.child(ns.bse.foo, self.n_ent, self.l_string, False)}))) # inconsistent w.r.t. unique self.assertFalse(operator.gt(Schema({}, {self.n_img}), Schema({}, { types.Node(ns.bsfs.Image, types.Node(ns.bsfs.Node, None))}))) self.assertFalse(operator.gt(Schema({}, {}, {self.l_integer}), Schema({}, {}, { diff --git a/test/schema/test_serialize.py b/test/schema/test_serialize.py index 7392cc0..b9d8599 100644 --- a/test/schema/test_serialize.py +++ b/test/schema/test_serialize.py @@ -66,7 +66,7 @@ class TestFromString(unittest.TestCase): ''') # additional nodes can be defined - n_unused = types.ROOT_NODE.get_child(ns.bsfs.unused) + n_unused = types.ROOT_NODE.child(ns.bsfs.unused) self.assertEqual(Schema({}, {n_unused}), from_string(''' prefix rdfs: prefix xsd: @@ -77,10 +77,10 @@ class TestFromString(unittest.TestCase): ''')) # a node can have multiple children - n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) - n_tag = types.ROOT_NODE.get_child(ns.bsfs.Tag) - n_doc = n_ent.get_child(ns.bsfs.Document) - n_image = n_ent.get_child(ns.bsfs.Image) + n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) + n_tag = types.ROOT_NODE.child(ns.bsfs.Tag) + n_doc = n_ent.child(ns.bsfs.Document) + n_image = n_ent.child(ns.bsfs.Image) self.assertEqual(Schema({}, {n_ent, n_tag, n_doc, n_image}), from_string(''' prefix rdfs: prefix xsd: @@ -97,9 +97,9 @@ class TestFromString(unittest.TestCase): ''')) # additional nodes can be defined and used - n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) - l_string = types.ROOT_LITERAL.get_child(ns.xsd.string) - p_filename = types.ROOT_PREDICATE.get_child(ns.bse.filename, + n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) + l_string = types.ROOT_LITERAL.child(ns.xsd.string) + p_filename = types.ROOT_PREDICATE.child(ns.bse.filename, n_ent, l_string, False) self.assertEqual(Schema({p_filename}), from_string(''' prefix rdfs: @@ -168,7 +168,7 @@ class TestFromString(unittest.TestCase): ''') # additional literals can be defined - l_unused = types.ROOT_LITERAL.get_child(ns.xsd.unused) + l_unused = types.ROOT_LITERAL.child(ns.xsd.unused) self.assertEqual(Schema({}, {}, {l_unused}), from_string(''' prefix rdfs: prefix xsd: @@ -179,10 +179,10 @@ class TestFromString(unittest.TestCase): ''')) # a literal can have multiple children - l_string = types.ROOT_LITERAL.get_child(ns.xsd.string) - l_integer = types.ROOT_LITERAL.get_child(ns.xsd.integer) - l_unsigned = l_integer.get_child(ns.xsd.unsigned) - l_signed = l_integer.get_child(ns.xsd.signed) + l_string = types.ROOT_LITERAL.child(ns.xsd.string) + l_integer = types.ROOT_LITERAL.child(ns.xsd.integer) + l_unsigned = l_integer.child(ns.xsd.unsigned) + l_signed = l_integer.child(ns.xsd.signed) self.assertEqual(Schema({}, {}, {l_string, l_integer, l_unsigned, l_signed}), from_string(''' prefix rdfs: prefix xsd: @@ -199,9 +199,9 @@ class TestFromString(unittest.TestCase): ''')) # additional literals can be defined and used - n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) - l_string = types.ROOT_LITERAL.get_child(ns.xsd.string) - p_filename = types.ROOT_PREDICATE.get_child(ns.bse.filename, + n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) + l_string = types.ROOT_LITERAL.child(ns.xsd.string) + p_filename = types.ROOT_PREDICATE.child(ns.bse.filename, n_ent, l_string, False) self.assertEqual(Schema({p_filename}), from_string(''' prefix rdfs: @@ -317,9 +317,9 @@ class TestFromString(unittest.TestCase): ''') # additional predicates can be defined - n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) - l_string = types.ROOT_LITERAL.get_child(ns.xsd.string) - p_comment = types.ROOT_PREDICATE.get_child(ns.bse.comment, domain=n_ent, range=l_string, unique=False) + n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) + l_string = types.ROOT_LITERAL.child(ns.xsd.string) + p_comment = types.ROOT_PREDICATE.child(ns.bse.comment, domain=n_ent, range=l_string, unique=False) self.assertEqual(Schema({p_comment}), from_string(''' prefix rdfs: prefix xsd: @@ -336,10 +336,10 @@ class TestFromString(unittest.TestCase): ''')) # predicates inherit properties from parents - n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) - l_string = types.ROOT_LITERAL.get_child(ns.xsd.string) - p_annotation = types.ROOT_PREDICATE.get_child(ns.bsfs.Annotation, domain=n_ent, range=l_string) - p_comment = p_annotation.get_child(ns.bse.comment, unique=True) + n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) + l_string = types.ROOT_LITERAL.child(ns.xsd.string) + p_annotation = types.ROOT_PREDICATE.child(ns.bsfs.Annotation, domain=n_ent, range=l_string) + p_comment = p_annotation.child(ns.bse.comment, unique=True) self.assertEqual(Schema({p_comment}), from_string(''' prefix rdfs: prefix xsd: @@ -358,10 +358,10 @@ class TestFromString(unittest.TestCase): ''')) # we can define partial predicates (w/o specifying a usable range) - n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) - l_string = types.ROOT_LITERAL.get_child(ns.xsd.string) - p_annotation = types.ROOT_PREDICATE.get_child(ns.bsfs.Annotation, domain=n_ent) - p_comment = p_annotation.get_child(ns.bse.comment, range=l_string, unique=False) + n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) + l_string = types.ROOT_LITERAL.child(ns.xsd.string) + p_annotation = types.ROOT_PREDICATE.child(ns.bsfs.Annotation, domain=n_ent) + p_comment = p_annotation.child(ns.bse.comment, range=l_string, unique=False) self.assertEqual(Schema({p_comment}), from_string(''' prefix rdfs: prefix xsd: @@ -381,8 +381,8 @@ class TestFromString(unittest.TestCase): # predicate definition can be split across multiple statements. # statements can be repeated - n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) - p_foo = types.ROOT_PREDICATE.get_child(ns.bse.foo, domain=n_ent, range=types.ROOT_NODE, unique=True) + n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) + p_foo = types.ROOT_PREDICATE.child(ns.bse.foo, domain=n_ent, range=types.ROOT_NODE, unique=True) self.assertEqual(Schema({p_foo}), from_string(''' prefix rdfs: prefix xsd: @@ -400,11 +400,11 @@ class TestFromString(unittest.TestCase): ''')) # domain must be a subtype of parent's domain - n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) - n_image = n_ent.get_child(ns.bsfs.Image) - p_foo = types.ROOT_PREDICATE.get_child(ns.bse.foo, domain=types.ROOT_NODE) - p_bar = p_foo.get_child(ns.bse.bar, domain=n_ent) - p_foobar = p_bar.get_child(ns.bse.foobar, domain=n_image) + n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) + n_image = n_ent.child(ns.bsfs.Image) + p_foo = types.ROOT_PREDICATE.child(ns.bse.foo, domain=types.ROOT_NODE) + p_bar = p_foo.child(ns.bse.bar, domain=n_ent) + p_foobar = p_bar.child(ns.bse.foobar, domain=n_image) self.assertEqual(Schema({p_foobar}), from_string(''' prefix rdfs: prefix xsd: @@ -439,11 +439,11 @@ class TestFromString(unittest.TestCase): ''') # range must be a subtype of parent's range - n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) - n_image = n_ent.get_child(ns.bsfs.Image) - p_foo = types.ROOT_PREDICATE.get_child(ns.bse.foo, range=types.ROOT_NODE) - p_bar = p_foo.get_child(ns.bse.bar, range=n_ent) - p_foobar = p_bar.get_child(ns.bse.foobar, range=n_image) + n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) + n_image = n_ent.child(ns.bsfs.Image) + p_foo = types.ROOT_PREDICATE.child(ns.bse.foo, range=types.ROOT_NODE) + p_bar = p_foo.child(ns.bse.bar, range=n_ent) + p_foobar = p_bar.child(ns.bse.foobar, range=n_image) self.assertEqual(Schema({p_foobar}), from_string(''' prefix rdfs: prefix xsd: @@ -658,9 +658,9 @@ class TestFromString(unittest.TestCase): ''') # additional predicates can be defined - n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) - l_array = types.ROOT_LITERAL.get_child(ns.bsfs.array) - p_comment = types.ROOT_FEATURE.get_child(ns.bse.colors, domain=n_ent, range=l_array, unique=False) + n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) + l_array = types.ROOT_LITERAL.child(ns.bsfs.array) + p_comment = types.ROOT_FEATURE.child(ns.bse.colors, domain=n_ent, range=l_array, unique=False) self.assertEqual(Schema({p_comment}), from_string(''' prefix rdfs: prefix xsd: @@ -678,12 +678,12 @@ class TestFromString(unittest.TestCase): ''')) # features inherit properties from parents - n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) - l_array = types.ROOT_LITERAL.get_child(ns.bsfs.array) - l_string = types.ROOT_LITERAL.get_child(ns.xsd.string) - p_annotation = types.ROOT_FEATURE.get_child(ns.bsfs.Annotation, domain=n_ent, range=l_array, + n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) + l_array = types.ROOT_LITERAL.child(ns.bsfs.array) + l_string = types.ROOT_LITERAL.child(ns.xsd.string) + p_annotation = types.ROOT_FEATURE.child(ns.bsfs.Annotation, domain=n_ent, range=l_array, dimension=1234, dtype=ns.xsd.string) - p_comment = p_annotation.get_child(ns.bse.colors, unique=True) + p_comment = p_annotation.child(ns.bse.colors, unique=True) self.assertEqual(Schema({p_comment}), from_string(''' prefix rdfs: prefix xsd: @@ -706,8 +706,8 @@ class TestFromString(unittest.TestCase): # feature definition can be split across multiple statements. # statements can be repeated - n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) - p_foo = types.ROOT_FEATURE.get_child(ns.bse.foo, domain=n_ent, unique=True, + n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) + p_foo = types.ROOT_FEATURE.child(ns.bse.foo, domain=n_ent, unique=True, dimension=1234, dtype=ns.bsfs.f32) self.assertEqual(Schema({p_foo}), from_string(''' prefix rdfs: @@ -887,24 +887,24 @@ class TestFromString(unittest.TestCase): def test_integration(self): # nodes - n_ent = types.ROOT_NODE.get_child(ns.bsfs.Entity) - n_tag = types.ROOT_NODE.get_child(ns.bsfs.Tag) - n_image = n_ent.get_child(ns.bsfs.Image) + n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) + n_tag = types.ROOT_NODE.child(ns.bsfs.Tag) + n_image = n_ent.child(ns.bsfs.Image) # literals - l_string = types.ROOT_LITERAL.get_child(ns.xsd.string) - l_array = types.ROOT_LITERAL.get_child(ns.bsfs.array) - l_integer = types.ROOT_LITERAL.get_child(ns.xsd.integer) - l_boolean = types.ROOT_LITERAL.get_child(ns.xsd.boolean) + l_string = types.ROOT_LITERAL.child(ns.xsd.string) + l_array = types.ROOT_LITERAL.child(ns.bsfs.array) + l_integer = types.ROOT_LITERAL.child(ns.xsd.integer) + l_boolean = types.ROOT_LITERAL.child(ns.xsd.boolean) # predicates - p_annotation = types.ROOT_PREDICATE.get_child(ns.bsfs.Annotation) - p_tag = types.ROOT_PREDICATE.get_child(ns.bse.tag, domain=n_ent, range=n_tag) - p_group = p_tag.get_child(ns.bse.group, domain=n_image, unique=True) - p_comment = p_annotation.get_child(ns.bse.comment, range=l_string) + p_annotation = types.ROOT_PREDICATE.child(ns.bsfs.Annotation) + p_tag = types.ROOT_PREDICATE.child(ns.bse.tag, domain=n_ent, range=n_tag) + p_group = p_tag.child(ns.bse.group, domain=n_image, unique=True) + p_comment = p_annotation.child(ns.bse.comment, range=l_string) # features - f_colors = types.ROOT_FEATURE.get_child(URI('http://bsfs.ai/schema/Feature/colors_spatial'), + f_colors = types.ROOT_FEATURE.child(URI('http://bsfs.ai/schema/Feature/colors_spatial'), domain=n_ent, range=l_array, unique=True, dtype=ns.bsfs.f16, distance=ns.bsfs.euclidean) - f_colors1234 = f_colors.get_child(URI('http://bsfs.ai/schema/Feature/colors_spatial#1234'), dimension=1024) - f_colors4321 = f_colors.get_child(URI('http://bsfs.ai/schema/Feature/colors_spatial#4321'), dimension=2048) + f_colors1234 = f_colors.child(URI('http://bsfs.ai/schema/Feature/colors_spatial#1234'), dimension=1024) + f_colors4321 = f_colors.child(URI('http://bsfs.ai/schema/Feature/colors_spatial#4321'), dimension=2048) # schema ref = Schema( {p_annotation, p_tag, p_group, p_comment, f_colors, f_colors1234, f_colors4321}, diff --git a/test/schema/test_types.py b/test/schema/test_types.py index af47f0d..26da270 100644 --- a/test/schema/test_types.py +++ b/test/schema/test_types.py @@ -14,7 +14,7 @@ from bsfs.schema.types import ROOT_PREDICATE, ROOT_VERTEX, ROOT_FEATURE from bsfs.utils import errors # objects to test -from bsfs.schema.types import _Type, _Vertex, Node, Literal, Predicate, Feature +from bsfs.schema.types import _Type, Vertex, Node, Literal, Predicate, Feature ## code ## @@ -47,8 +47,8 @@ class TestType(unittest.TestCase): self.assertEqual( hash(_Type('Foo', None, foo='bar', bar='foo')), hash(_Type('Foo', None, hello='world', foobar=1234))) - # annotations can be passed to get_child - self.assertDictEqual(_Type('First', foo='bar').get_child('Second', bar='foo').annotations, { + # annotations can be passed to child + self.assertDictEqual(_Type('First', foo='bar').child('Second', bar='foo').annotations, { 'bar': 'foo'}) def test_string_conversion(self): @@ -71,16 +71,16 @@ class TestType(unittest.TestCase): self.assertEqual(str(_Type('Foo', SubType('Bar'))), '_Type(Foo)') self.assertEqual(repr(_Type('Foo', SubType('Bar'))), '_Type(Foo, SubType(Bar, None))') - def test_get_child(self): + def test_child(self): # callee is used as parent - self.assertEqual(_Type('First').get_child('Second'), _Type('Second', _Type('First'))) + self.assertEqual(_Type('First').child('Second'), _Type('Second', _Type('First'))) # works with multiple parents - self.assertEqual(_Type('First').get_child('Second').get_child('Third'), _Type('Third', _Type('Second', _Type('First')))) + self.assertEqual(_Type('First').child('Second').child('Third'), _Type('Third', _Type('Second', _Type('First')))) # type persists class Foo(_Type): pass - self.assertEqual(Foo('First').get_child('Second'), Foo('Second', Foo('First'))) + self.assertEqual(Foo('First').child('Second'), Foo('Second', Foo('First'))) # annotations are respected - self.assertDictEqual(_Type('First', foo='bar').get_child('Second', bar='foo').annotations, { + self.assertDictEqual(_Type('First', foo='bar').child('Second', bar='foo').annotations, { 'bar': 'foo'}) def test_equality(self): @@ -174,7 +174,7 @@ class TestPredicate(unittest.TestCase): # range must be a Literal, a Node, or the root Vertex self.assertRaises(TypeError, Predicate, ns.bse.foo, None, Node(ns.bsfs.Node, None), None, True) self.assertRaises(TypeError, Predicate, ns.bse.foo, None, Node(ns.bsfs.Node, None), 1234, True) - self.assertRaises(TypeError, Predicate, ns.bse.foo, None, Node(ns.bsfs.Node, None), _Vertex(ns.bsfs.Foo, None), True) + self.assertRaises(TypeError, Predicate, ns.bse.foo, None, Node(ns.bsfs.Node, None), Vertex(ns.bsfs.Foo, None), True) self.assertRaises(TypeError, Predicate, ns.bse.foo, None, Node(ns.bsfs.Node, None), _Type(ns.bsfs.Foo, None), True) class Foo(): pass self.assertRaises(TypeError, Predicate, ns.bse.foo, None, Node(ns.bsfs.Node, None), Foo(), True) @@ -213,7 +213,7 @@ class TestPredicate(unittest.TestCase): self.assertNotEqual(tag, Predicate(ns.bse.tag, root, n_root, n_tag, True)) self.assertNotEqual(hash(tag), hash(Predicate(ns.bse.tag, root, n_root, n_tag, True))) - def test_get_child(self): + def test_child(self): n_root = Node(ns.bsfs.Node, None) l_root = Literal(ns.bsfs.Literal, None) n_ent = Node(ns.bsfs.Entity, Node(ns.bsfs.Node, None)) @@ -227,45 +227,45 @@ class TestPredicate(unittest.TestCase): unique=False, ) - # get_child returns Predicate - self.assertIsInstance(tag.get_child(ns.bse.foo), Predicate) + # child returns Predicate + self.assertIsInstance(tag.child(ns.bse.foo), Predicate) # uri is respected - self.assertEqual(ns.bse.foo, tag.get_child(ns.bse.foo).uri) + self.assertEqual(ns.bse.foo, tag.child(ns.bse.foo).uri) # domain is respected dom = Node(ns.bsfs.Image, n_ent) - self.assertEqual(dom, tag.get_child(ns.bse.foo, domain=dom).domain) + self.assertEqual(dom, tag.child(ns.bse.foo, domain=dom).domain) # range is respected rng = Node(ns.bsfs.Group, n_tag) - self.assertEqual(rng, tag.get_child(ns.bse.foo, range=rng).range) + self.assertEqual(rng, tag.child(ns.bse.foo, range=rng).range) # cannot set range to None - self.assertEqual(n_tag, tag.get_child(ns.bse.foo, range=None).range) + self.assertEqual(n_tag, tag.child(ns.bse.foo, range=None).range) # unique is respected - self.assertTrue(tag.get_child(ns.bse.foo, unique=True).unique) + self.assertTrue(tag.child(ns.bse.foo, unique=True).unique) # annotations are respected - self.assertDictEqual(tag.get_child(ns.bse.foo, foo='bar', bar=123).annotations, { + self.assertDictEqual(tag.child(ns.bse.foo, foo='bar', bar=123).annotations, { 'foo': 'bar', 'bar': 123, }) # domain is inherited from parent - self.assertEqual(n_root, root.get_child(ns.bse.foo).domain) - self.assertEqual(n_ent, tag.get_child(ns.bse.foo).domain) + self.assertEqual(n_root, root.child(ns.bse.foo).domain) + self.assertEqual(n_ent, tag.child(ns.bse.foo).domain) # range is inherited from parent - self.assertEqual(ROOT_VERTEX, root.get_child(ns.bse.foo).range) - self.assertEqual(n_tag, tag.get_child(ns.bse.foo).range) + self.assertEqual(ROOT_VERTEX, root.child(ns.bse.foo).range) + self.assertEqual(n_tag, tag.child(ns.bse.foo).range) # uniqueness is inherited from parent - self.assertFalse(tag.get_child(ns.bse.foo).unique) + self.assertFalse(tag.child(ns.bse.foo).unique) # domain must be subtype of parent's domain - self.assertRaises(errors.ConsistencyError, tag.get_child, ns.bse.foo, domain=n_root) - self.assertRaises(errors.ConsistencyError, tag.get_child, ns.bse.foo, domain=Node(ns.bsfs.Image, n_root)) + self.assertRaises(errors.ConsistencyError, tag.child, ns.bse.foo, domain=n_root) + self.assertRaises(errors.ConsistencyError, tag.child, ns.bse.foo, domain=Node(ns.bsfs.Image, n_root)) # range must be subtype of parent's range - self.assertRaises(errors.ConsistencyError, tag.get_child, ns.bse.foo, range=n_root) - self.assertRaises(errors.ConsistencyError, tag.get_child, ns.bse.foo, range=Node(ns.bsfs.Image, n_root)) - self.assertRaises(TypeError, tag.get_child, ns.bse.foo, range=Literal(ns.bsfs.Tag, l_root)) + self.assertRaises(errors.ConsistencyError, tag.child, ns.bse.foo, range=n_root) + self.assertRaises(errors.ConsistencyError, tag.child, ns.bse.foo, range=Node(ns.bsfs.Image, n_root)) + self.assertRaises(TypeError, tag.child, ns.bse.foo, range=Literal(ns.bsfs.Tag, l_root)) # range can be subtyped from ROOT_VERTEX to Node or Literal - self.assertEqual(n_root, root.get_child(ns.bse.foo, range=n_root).range) - self.assertEqual(l_root, root.get_child(ns.bse.foo, range=l_root).range) + self.assertEqual(n_root, root.child(ns.bse.foo, range=n_root).range) + self.assertEqual(l_root, root.child(ns.bse.foo, range=l_root).range) class TestFeature(unittest.TestCase): @@ -308,7 +308,7 @@ class TestFeature(unittest.TestCase): self.assertNotEqual(colors, Feature(ns.bse.colors, ROOT_FEATURE, n_ent, l_array, False, 1234, ns.bsfs.float, ns.bsfs.cosine)) self.assertNotEqual(hash(colors), hash(Feature(ns.bse.colors, ROOT_FEATURE, n_ent, l_array, False, 1234, ns.bsfs.float, ns.bsfs.cosine))) - def test_get_child(self): + def test_child(self): n_root = Node(ns.bsfs.Node, None) n_ent = Node(ns.bsfs.Entity, n_root) l_root = Literal(ns.bsfs.Literal, None) @@ -324,53 +324,53 @@ class TestFeature(unittest.TestCase): distance=ns.bsfs.euclidean, ) - # get_child returns Feature - self.assertIsInstance(colors.get_child(ns.bse.foo), Feature) + # child returns Feature + self.assertIsInstance(colors.child(ns.bse.foo), Feature) # uri is respected - self.assertEqual(ns.bse.foo, colors.get_child(ns.bse.foo).uri) + self.assertEqual(ns.bse.foo, colors.child(ns.bse.foo).uri) # domain is respected dom = Node(ns.bsfs.Image, n_ent) - self.assertEqual(dom, colors.get_child(ns.bse.foo, domain=dom).domain) + self.assertEqual(dom, colors.child(ns.bse.foo, domain=dom).domain) # range is respected rng = Literal(ns.bse.foo, l_array) - self.assertEqual(rng, colors.get_child(ns.bse.foo, range=rng).range) + self.assertEqual(rng, colors.child(ns.bse.foo, range=rng).range) # cannot set range to None - self.assertEqual(l_array, colors.get_child(ns.bse.foo, range=None).range) + self.assertEqual(l_array, colors.child(ns.bse.foo, range=None).range) # unique is respected - self.assertTrue(colors.get_child(ns.bse.foo, unique=True).unique) + self.assertTrue(colors.child(ns.bse.foo, unique=True).unique) # dimension is respected - self.assertEqual(4321, colors.get_child(ns.bse.foo, dimension=4321).dimension) + self.assertEqual(4321, colors.child(ns.bse.foo, dimension=4321).dimension) # dtype is respected - self.assertEqual(ns.bsfs.integer, colors.get_child(ns.bse.foo, dtype=ns.bsfs.integer).dtype) + self.assertEqual(ns.bsfs.integer, colors.child(ns.bse.foo, dtype=ns.bsfs.integer).dtype) # distance is respected - self.assertEqual(ns.bsfs.cosine, colors.get_child(ns.bse.foo, distance=ns.bsfs.cosine).distance) + self.assertEqual(ns.bsfs.cosine, colors.child(ns.bse.foo, distance=ns.bsfs.cosine).distance) # annotations are respected - self.assertDictEqual(colors.get_child(ns.bse.foo, foo='bar', bar=123).annotations, { + self.assertDictEqual(colors.child(ns.bse.foo, foo='bar', bar=123).annotations, { 'foo': 'bar', 'bar': 123, }) # domain is inherited from parent - self.assertEqual(n_root, ROOT_FEATURE.get_child(ns.bse.foo).domain) - self.assertEqual(n_ent, colors.get_child(ns.bse.foo).domain) + self.assertEqual(n_root, ROOT_FEATURE.child(ns.bse.foo).domain) + self.assertEqual(n_ent, colors.child(ns.bse.foo).domain) # range is inherited from parent - self.assertEqual(l_array, colors.get_child(ns.bse.foo).range) + self.assertEqual(l_array, colors.child(ns.bse.foo).range) # uniqueness is inherited from parent - self.assertFalse(colors.get_child(ns.bse.foo).unique) + self.assertFalse(colors.child(ns.bse.foo).unique) # dimension is inherited from parent - self.assertEqual(1234, colors.get_child(ns.bse.foo).dimension) + self.assertEqual(1234, colors.child(ns.bse.foo).dimension) # dtype is inherited from parent - self.assertEqual(ns.bsfs.float, colors.get_child(ns.bse.foo).dtype) + self.assertEqual(ns.bsfs.float, colors.child(ns.bse.foo).dtype) # distance is inherited from parent - self.assertEqual(ns.bsfs.euclidean, colors.get_child(ns.bse.foo).distance) + self.assertEqual(ns.bsfs.euclidean, colors.child(ns.bse.foo).distance) # domain must be subtype of parent's domain - self.assertRaises(errors.ConsistencyError, colors.get_child, ns.bse.foo, domain=n_root) - self.assertRaises(errors.ConsistencyError, colors.get_child, ns.bse.foo, domain=Node(ns.bsfs.Image, n_root)) + self.assertRaises(errors.ConsistencyError, colors.child, ns.bse.foo, domain=n_root) + self.assertRaises(errors.ConsistencyError, colors.child, ns.bse.foo, domain=Node(ns.bsfs.Image, n_root)) # range must be subtype of parent's range - self.assertRaises(errors.ConsistencyError, colors.get_child, ns.bse.foo, range=Literal(ns.bsfs.Literal, None)) - self.assertRaises(errors.ConsistencyError, colors.get_child, ns.bse.foo, range=Literal(ns.bsfs.foo, Literal(ns.bsfs.Literal, None))) - self.assertRaises(TypeError, colors.get_child, ns.bse.foo, range=Node(ns.bsfs.Tag, n_root)) + self.assertRaises(errors.ConsistencyError, colors.child, ns.bse.foo, range=Literal(ns.bsfs.Literal, None)) + self.assertRaises(errors.ConsistencyError, colors.child, ns.bse.foo, range=Literal(ns.bsfs.foo, Literal(ns.bsfs.Literal, None))) + self.assertRaises(TypeError, colors.child, ns.bse.foo, range=Node(ns.bsfs.Tag, n_root)) ## main ## -- cgit v1.2.3 From b0ff4ed674ad78bf113c3cc0c2ccd187ccb91048 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Thu, 12 Jan 2023 10:26:30 +0100 Subject: number literal adaptions --- test/schema/test_schema.py | 17 +++++++++-------- test/schema/test_serialize.py | 10 ++++++---- 2 files changed, 15 insertions(+), 12 deletions(-) (limited to 'test/schema') diff --git a/test/schema/test_schema.py b/test/schema/test_schema.py index ca21f87..c19c226 100644 --- a/test/schema/test_schema.py +++ b/test/schema/test_schema.py @@ -35,7 +35,8 @@ class TestSchema(unittest.TestCase): bsfs:Unused rdfs:subClassOf bsfs:Node . xsd:string rdfs:subClassOf bsfs:Literal . - xsd:integer rdfs:subClassOf bsfs:Literal . + bsfs:Number rdfs:subClassOf bsfs:Literal . + xsd:integer rdfs:subClassOf bsfs:Number . xsd:boolean rdfs:subClassOf bsfs:Literal . bse:tag rdfs:subClassOf bsfs:Predicate ; @@ -56,18 +57,18 @@ class TestSchema(unittest.TestCase): ''' # nodes self.n_root = types.ROOT_NODE - self.n_ent = types.Node(ns.bsfs.Entity, types.Node(ns.bsfs.Node, None)) - self.n_img = types.Node(ns.bsfs.Image, types.Node(ns.bsfs.Entity, types.Node(ns.bsfs.Node, None))) - self.n_tag = types.Node(ns.bsfs.Tag, types.Node(ns.bsfs.Node, None)) - self.n_unused = types.Node(ns.bsfs.Unused, types.Node(ns.bsfs.Node, None)) + self.n_ent = self.n_root.child(ns.bsfs.Entity) + self.n_img = self.n_ent.child(ns.bsfs.Image) + self.n_tag = self.n_root.child(ns.bsfs.Tag) + self.n_unused = self.n_root.child(ns.bsfs.Unused) self.nodes = [self.n_root, self.n_ent, self.n_img, self.n_tag, self.n_unused] # literals self.l_root = types.ROOT_LITERAL self.l_number = types.ROOT_NUMBER - self.l_string = types.Literal(ns.xsd.string, types.Literal(ns.bsfs.Literal, None)) - self.l_integer = types.Literal(ns.xsd.integer, self.l_number) - self.l_unused = types.Literal(ns.xsd.boolean, types.Literal(ns.bsfs.Literal, None)) + self.l_string = self.l_root.child(ns.xsd.string) + self.l_integer = self.l_root.child(ns.xsd.integer) + self.l_unused = self.l_root.child(ns.xsd.boolean) self.literals = [self.l_root, self.l_number, self.l_string, self.l_integer, self.l_unused] # predicates diff --git a/test/schema/test_serialize.py b/test/schema/test_serialize.py index b9d8599..f46b3a4 100644 --- a/test/schema/test_serialize.py +++ b/test/schema/test_serialize.py @@ -180,7 +180,7 @@ class TestFromString(unittest.TestCase): # a literal can have multiple children l_string = types.ROOT_LITERAL.child(ns.xsd.string) - l_integer = types.ROOT_LITERAL.child(ns.xsd.integer) + l_integer = types.ROOT_NUMBER.child(ns.xsd.integer) l_unsigned = l_integer.child(ns.xsd.unsigned) l_signed = l_integer.child(ns.xsd.signed) self.assertEqual(Schema({}, {}, {l_string, l_integer, l_unsigned, l_signed}), from_string(''' @@ -191,7 +191,8 @@ class TestFromString(unittest.TestCase): # literals inherit from same parent xsd:string rdfs:subClassOf bsfs:Literal . - xsd:integer rdfs:subClassOf bsfs:Literal . + bsfs:Number rdfs:subClassOf bsfs:Literal . + xsd:integer rdfs:subClassOf bsfs:Number . # literals inherit from same parent xsd:unsigned rdfs:subClassOf xsd:integer . @@ -893,7 +894,7 @@ class TestFromString(unittest.TestCase): # literals l_string = types.ROOT_LITERAL.child(ns.xsd.string) l_array = types.ROOT_LITERAL.child(ns.bsfs.array) - l_integer = types.ROOT_LITERAL.child(ns.xsd.integer) + l_integer = types.ROOT_NUMBER.child(ns.xsd.integer) l_boolean = types.ROOT_LITERAL.child(ns.xsd.boolean) # predicates p_annotation = types.ROOT_PREDICATE.child(ns.bsfs.Annotation) @@ -931,7 +932,8 @@ class TestFromString(unittest.TestCase): xsd:string rdfs:subClassOf bsfs:Literal ; rdfs:label "A sequence of characters"^^xsd:string . bsfs:array rdfs:subClassOf bsfs:Literal . - xsd:integer rdfs:subClassOf bsfs:Literal . + bsfs:Number rdfs:subClassOf bsfs:Literal . + xsd:integer rdfs:subClassOf bsfs:Number . xsd:boolean rdfs:subClassOf bsfs:Literal . # abstract predicates -- cgit v1.2.3 From 1b7ef16c3795bb7112683662b8c22a774e219269 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Thu, 12 Jan 2023 16:57:58 +0100 Subject: schema to string --- test/schema/test_serialize.py | 173 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 171 insertions(+), 2 deletions(-) (limited to 'test/schema') diff --git a/test/schema/test_serialize.py b/test/schema/test_serialize.py index f46b3a4..205150a 100644 --- a/test/schema/test_serialize.py +++ b/test/schema/test_serialize.py @@ -5,6 +5,7 @@ A copy of the license is provided with the project. Author: Matthias Baumgartner, 2022 """ # imports +import re import unittest # bsfs imports @@ -997,8 +998,176 @@ class TestFromString(unittest.TestCase): class TestToString(unittest.TestCase): - def test_stub(self): - raise NotImplementedError() + + def test_empty(self): + self.assertEqual(Schema(), from_string(to_string(Schema()))) + + def test_literal(self): + # root literals + l_str = types.ROOT_LITERAL.child(ns.xsd.string) + # derived literals + l_int = types.ROOT_NUMBER.child(ns.xsd.integer) + l_unsigned = l_int.child(ns.xsd.unsigned) + # create schema + schema = Schema(literals={l_int, l_str, l_unsigned}) + + schema_str = to_string(schema) + # all symbols are serialized + self.assertIn('xsd:string', schema_str) + self.assertIn('xsd:integer', schema_str) + self.assertIn('xsd:unsigned', schema_str) + # unserialize yields the original schema + self.assertEqual(schema, from_string(schema_str)) + + # literals that have no parent are ignored + schema = Schema(literals={types.Literal(ns.bsfs.Invalid, None)}) + self.assertEqual(Schema(), from_string(to_string(schema))) + self.assertNotIn('Invalid', to_string(schema)) + + # literal annotations are serialized + annotations = { + ns.rdfs.label: 'hello world', + ns.schema.description: 'some text', + ns.bsfs.foo: 1234, + ns.bsfs.bar: True, + } + l_str = types.ROOT_LITERAL.child(ns.xsd.string, **annotations) + self.assertDictEqual( + annotations, + from_string(to_string(Schema(literals={l_str}))).literal(ns.xsd.string).annotations) + + + def test_node(self): + # root nodes + n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) + n_tag = types.ROOT_NODE.child(ns.bsfs.Tag) + # derived nodes + n_img = n_ent.child(ns.bsfs.Image) + n_doc = n_ent.child(ns.bsfs.Document) + n_grp = n_tag.child(ns.bsfs.Group) + # create schema + schema = Schema(nodes={n_ent, n_img, n_doc, n_tag, n_grp}) + + schema_str = to_string(schema) + # all symbols are serialized + self.assertIn('bsfs:Entity', schema_str) + self.assertIn('bsfs:Tag', schema_str) + self.assertIn('bsfs:Image', schema_str) + self.assertIn('bsfs:Document', schema_str) + self.assertIn('bsfs:Group', schema_str) + # unserialize yields the original schema + self.assertEqual(schema, from_string(schema_str)) + + # nodes that have no parent are ignored + schema = Schema(nodes={types.Node(ns.bsfs.Invalid, None)}) + self.assertEqual(Schema(), from_string(to_string(schema))) + self.assertNotIn('Invalid', to_string(schema)) + + # node annotations are serialized + annotations = { + ns.rdfs.label: 'hello world', + ns.schema.description: 'some text', + ns.bsfs.foo: 1234, + ns.bsfs.bar: True, + } + n_ent = types.ROOT_NODE.child(ns.bsfs.Entity, **annotations) + self.assertDictEqual( + annotations, + from_string(to_string(Schema(nodes={n_ent}))).node(ns.bsfs.Entity).annotations) + + + def test_predicate(self): + # auxiliary types + n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) + l_str = types.ROOT_LITERAL.child(ns.xsd.string) + # root predicates + p_annotation = types.ROOT_PREDICATE.child(ns.bsfs.Annotation, domain=n_ent) + p_owner = types.ROOT_PREDICATE.child(ns.bse.owner, range=l_str, unique=True) + # derived predicates + p_comment = p_annotation.child(ns.bse.comment, range=l_str) # inherits domain + p_note = p_comment.child(ns.bse.note, unique=True) # inherits domain/range + # create schema + schema = Schema({p_owner, p_comment, p_note}) + + schema_str = to_string(schema) + # all symbols are serialized + self.assertIn('bsfs:Entity', schema_str) + self.assertIn('xsd:string', schema_str) + self.assertIn('bsfs:Annotation', schema_str) + self.assertIn('bse:comment', schema_str) + self.assertIn('bse:owner', schema_str) + self.assertIn('bse:note', schema_str) + # inherited properties are not serialized + self.assertIsNotNone(re.search(r'bse:comment[^\.]*rdfs:range[^\.]', schema_str)) + self.assertIsNone(re.search(r'bse:comment[^\.]*rdfs:domain[^\.]', schema_str)) + #p_note has no domain/range + self.assertIsNone(re.search(r'bse:note[^\.]*rdfs:domain[^\.]', schema_str)) + self.assertIsNone(re.search(r'bse:note[^\.]*rdfs:range[^\.]', schema_str)) + # unserialize yields the original schema + self.assertEqual(schema, from_string(schema_str)) + + # predicate annotations are serialized + annotations = { + ns.rdfs.label: 'hello world', + ns.schema.description: 'some text', + ns.bsfs.foo: 1234, + ns.bsfs.bar: False, + } + p_annotation = types.ROOT_PREDICATE.child(ns.bsfs.Annotation, **annotations) + self.assertDictEqual( + annotations, + from_string(to_string(Schema({p_annotation}))).predicate(ns.bsfs.Annotation).annotations) + + + def test_feature(self): + # auxiliary types + n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) + l_array = types.ROOT_LITERAL.child(ns.bsfs.array) + # root features + f_colors = types.ROOT_FEATURE.child(URI('http://bsfs.ai/schema/Feature/colors'), + range=l_array, unique=True, distance=ns.bsfs.cosine) + # derived features + f_colors1234 = f_colors.child(URI('http://bsfs.ai/schema/Feature/colors#1234'), + dimension=1024, domain=n_ent) # inherits range/dtype/distance + f_colors4321 = f_colors.child(URI('http://bsfs.ai/schema/Feature/colors#4321'), + dimension=2048, distance=ns.bsfs.euclidean) # inherits domain/range/dtype + # create schema + schema = Schema({f_colors, f_colors1234, f_colors4321}) + + schema_str = to_string(schema) + # all symbols are serialized + self.assertIn('bsfs:Entity', schema_str) + self.assertIn('bsfs:array', schema_str) + self.assertIn('[^\.]*rdfs:domain[^\.]', schema_str)) + self.assertIsNotNone(re.search(r'[^\.]*bsfs:dimension[^\.]', schema_str)) + self.assertIsNone(re.search(r'[^\.]*rdfs:range[^\.]', schema_str)) + self.assertIsNone(re.search(r'[^\.]*bsfs:dtype[^\.]', schema_str)) + self.assertIsNone(re.search(r'[^\.]*bsfs:distance[^\.]', schema_str)) + self.assertIsNotNone(re.search(r'[^\.]*bsfs:dimension[^\.]', schema_str)) + self.assertIsNotNone(re.search(r'[^\.]*bsfs:distance[^\.]', schema_str)) + self.assertIsNone(re.search(r'[^\.]*rdfs:domain[^\.]', schema_str)) + self.assertIsNone(re.search(r'[^\.]*rdfs:range[^\.]', schema_str)) + self.assertIsNone(re.search(r'[^\.]*bsfs:dtype[^\.]', schema_str)) + # unserialize yields the original schema + self.assertEqual(schema, from_string(schema_str)) + + # predicate annotations are serialized + annotations = { + ns.rdfs.label: 'hello world', + ns.schema.description: 'some text', + ns.bsfs.foo: 1234, + ns.bsfs.bar: False, + } + f_colors = types.ROOT_FEATURE.child(URI('http://bsfs.ai/schema/Feature/colors'), + domain=n_ent, range=l_array, unique=True, dtype=ns.bsfs.f16, distance=ns.bsfs.euclidean, + **annotations) + self.assertDictEqual( + annotations, + from_string(to_string(Schema({f_colors}))).predicate(URI('http://bsfs.ai/schema/Feature/colors')).annotations) ## main ## -- cgit v1.2.3 From 60257ed3c2aa6ea2891f362a691bde9d7ef17831 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Fri, 13 Jan 2023 12:22:34 +0100 Subject: schema type comparison across classes --- test/schema/test_types.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'test/schema') diff --git a/test/schema/test_types.py b/test/schema/test_types.py index 26da270..1eeafa1 100644 --- a/test/schema/test_types.py +++ b/test/schema/test_types.py @@ -140,30 +140,31 @@ class TestType(unittest.TestCase): self.assertFalse(bike >= bicycle) self.assertFalse(bike == bicycle) - # can compare types along the class hierarchy + # comparing different classes returns False ... + # ... when classes are hierarchically related class Foo(_Type): pass foo = Foo('Foo', bike) - self.assertTrue(foo < bike) - self.assertTrue(foo <= bike) + self.assertFalse(foo < bike) + self.assertFalse(foo <= bike) self.assertFalse(foo > bike) self.assertFalse(foo >= bike) # goes both ways self.assertFalse(bike < foo) self.assertFalse(bike <= foo) - self.assertTrue(bike > foo) - self.assertTrue(bike >= foo) - # cannot compare unrelated classes + self.assertFalse(bike > foo) + self.assertFalse(bike >= foo) + # ... when classes are unrelated class Bar(_Type): pass bar = Bar('Bar', bike) - self.assertRaises(TypeError, operator.lt, foo, bar) - self.assertRaises(TypeError, operator.le, foo, bar) - self.assertRaises(TypeError, operator.gt, foo, bar) - self.assertRaises(TypeError, operator.ge, foo, bar) + self.assertFalse(foo < bar) + self.assertFalse(foo <= bar) + self.assertFalse(foo > bar) + self.assertFalse(foo >= bar) # goes both ways - self.assertRaises(TypeError, operator.lt, bar, foo) - self.assertRaises(TypeError, operator.le, bar, foo) - self.assertRaises(TypeError, operator.gt, bar, foo) - self.assertRaises(TypeError, operator.ge, bar, foo) + self.assertFalse(bar < foo) + self.assertFalse(bar <= foo) + self.assertFalse(bar > foo) + self.assertFalse(bar >= foo) class TestPredicate(unittest.TestCase): @@ -262,7 +263,7 @@ class TestPredicate(unittest.TestCase): # range must be subtype of parent's range self.assertRaises(errors.ConsistencyError, tag.child, ns.bse.foo, range=n_root) self.assertRaises(errors.ConsistencyError, tag.child, ns.bse.foo, range=Node(ns.bsfs.Image, n_root)) - self.assertRaises(TypeError, tag.child, ns.bse.foo, range=Literal(ns.bsfs.Tag, l_root)) + self.assertRaises(errors.ConsistencyError, tag.child, ns.bse.foo, range=Literal(ns.bsfs.Tag, l_root)) # range can be subtyped from ROOT_VERTEX to Node or Literal self.assertEqual(n_root, root.child(ns.bse.foo, range=n_root).range) self.assertEqual(l_root, root.child(ns.bse.foo, range=l_root).range) @@ -370,7 +371,7 @@ class TestFeature(unittest.TestCase): # range must be subtype of parent's range self.assertRaises(errors.ConsistencyError, colors.child, ns.bse.foo, range=Literal(ns.bsfs.Literal, None)) self.assertRaises(errors.ConsistencyError, colors.child, ns.bse.foo, range=Literal(ns.bsfs.foo, Literal(ns.bsfs.Literal, None))) - self.assertRaises(TypeError, colors.child, ns.bse.foo, range=Node(ns.bsfs.Tag, n_root)) + self.assertRaises(errors.ConsistencyError, colors.child, ns.bse.foo, range=Node(ns.bsfs.Tag, n_root)) ## main ## -- cgit v1.2.3 From ccaee71e2b6135d3b324fe551c8652940b67aab3 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Sun, 15 Jan 2023 20:57:42 +0100 Subject: Feature as Literal instead of Predicate subtype --- test/schema/test_schema.py | 34 ++--- test/schema/test_serialize.py | 308 +++++++++++------------------------------- test/schema/test_types.py | 52 ++----- 3 files changed, 107 insertions(+), 287 deletions(-) (limited to 'test/schema') diff --git a/test/schema/test_schema.py b/test/schema/test_schema.py index c19c226..32dbc93 100644 --- a/test/schema/test_schema.py +++ b/test/schema/test_schema.py @@ -66,30 +66,32 @@ class TestSchema(unittest.TestCase): # literals self.l_root = types.ROOT_LITERAL self.l_number = types.ROOT_NUMBER + self.l_array = types.ROOT_ARRAY + self.l_time = types.ROOT_TIME self.l_string = self.l_root.child(ns.xsd.string) self.l_integer = self.l_root.child(ns.xsd.integer) self.l_unused = self.l_root.child(ns.xsd.boolean) - self.literals = [self.l_root, self.l_number, self.l_string, self.l_integer, self.l_unused] + self.f_root = types.ROOT_FEATURE + self.literals = [self.l_root, self.l_array, self.f_root, self.l_number, self.l_time, self.l_string, self.l_integer, self.l_unused] # predicates self.p_root = types.ROOT_PREDICATE - self.f_root = types.ROOT_FEATURE self.p_tag = self.p_root.child(ns.bse.tag, self.n_ent, self.n_tag, False) self.p_group = self.p_tag.child(ns.bse.group, self.n_img, self.n_tag, False) self.p_comment = self.p_root.child(ns.bse.comment, self.n_root, self.l_string, True) - self.predicates = [self.p_root, self.f_root, self.p_tag, self.p_group, self.p_comment] + self.predicates = [self.p_root, self.p_tag, self.p_group, self.p_comment] def test_construction(self): # no args yields a minimal schema schema = Schema() self.assertSetEqual(set(schema.nodes()), {self.n_root}) - self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_number}) - self.assertSetEqual(set(schema.predicates()), {self.p_root, self.f_root}) + self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_number, self.l_array, self.l_time, self.f_root}) + self.assertSetEqual(set(schema.predicates()), {self.p_root}) # nodes and literals are optional schema = Schema(self.predicates) self.assertSetEqual(set(schema.nodes()), {self.n_root, self.n_ent, self.n_img, self.n_tag}) - self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number}) + self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number, self.l_time, self.l_array, self.f_root}) self.assertSetEqual(set(schema.predicates()), set(self.predicates)) # predicates, nodes, and literals are respected @@ -110,21 +112,21 @@ class TestSchema(unittest.TestCase): # literals are complete schema = Schema(self.predicates, self.nodes, None) - self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number}) + self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number, self.l_array, self.l_time, self.f_root}) schema = Schema(self.predicates, self.nodes, []) - self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number}) + self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number, self.l_array, self.l_time, self.f_root}) schema = Schema(self.predicates, self.nodes, [self.l_string]) - self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number}) + self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number, self.l_array, self.l_time, self.f_root}) schema = Schema(self.predicates, self.nodes, [self.l_integer]) - self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_integer, self.l_number}) + self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_integer, self.l_number, self.l_array, self.l_time, self.f_root}) schema = Schema(self.predicates, self.nodes, [self.l_integer, self.l_unused]) self.assertSetEqual(set(schema.literals()), set(self.literals)) # predicates are complete schema = Schema([], self.nodes, self.literals) - self.assertSetEqual(set(schema.predicates()), {self.p_root, self.f_root}) + self.assertSetEqual(set(schema.predicates()), {self.p_root}) schema = Schema([self.p_group], self.nodes, self.literals) - self.assertSetEqual(set(schema.predicates()), {self.p_root, self.f_root, self.p_tag, self.p_group}) + self.assertSetEqual(set(schema.predicates()), {self.p_root, self.p_tag, self.p_group}) schema = Schema([self.p_group, self.p_comment], self.nodes, self.literals) self.assertSetEqual(set(schema.predicates()), set(self.predicates)) @@ -176,14 +178,14 @@ class TestSchema(unittest.TestCase): self.assertEqual(str(Schema(self.predicates, self.nodes, self.literals)), 'Schema()') # repr conversion with only default nodes, literals, and predicates n = [ns.bsfs.Node] - l = [ns.bsfs.Literal, ns.bsfs.Number] - p = [ns.bsfs.Feature, ns.bsfs.Predicate] + l = [ns.bsfs.Array, ns.bsfs.Feature, ns.bsfs.Literal, ns.bsfs.Number, ns.bsfs.Time] + p = [ns.bsfs.Predicate] self.assertEqual(repr(Schema()), f'Schema({n}, {l}, {p})') self.assertEqual(repr(Schema([], [], [])), f'Schema({n}, {l}, {p})') # repr conversion n = [ns.bsfs.Entity, ns.bsfs.Image, ns.bsfs.Node, ns.bsfs.Tag, ns.bsfs.Unused] - l = [ns.bsfs.Literal, ns.bsfs.Number, ns.xsd.boolean, ns.xsd.integer, ns.xsd.string] - p = [ns.bse.comment, ns.bse.group, ns.bse.tag, ns.bsfs.Feature, ns.bsfs.Predicate] + l = [ns.bsfs.Array, ns.bsfs.Feature, ns.bsfs.Literal, ns.bsfs.Number, ns.bsfs.Time, ns.xsd.boolean, ns.xsd.integer, ns.xsd.string] + p = [ns.bse.comment, ns.bse.group, ns.bse.tag, ns.bsfs.Predicate] self.assertEqual(repr(Schema(self.predicates, self.nodes, self.literals)), f'Schema({n}, {l}, {p})') def test_equality(self): diff --git a/test/schema/test_serialize.py b/test/schema/test_serialize.py index 205150a..fc6b20a 100644 --- a/test/schema/test_serialize.py +++ b/test/schema/test_serialize.py @@ -581,151 +581,60 @@ class TestFromString(unittest.TestCase): def test_feature(self): - # domain must be defined - self.assertRaises(errors.ConsistencyError, from_string, ''' - prefix rdfs: - prefix xsd: - prefix bsfs: - prefix bse: - - bsfs:Feature rdfs:subClassOf bsfs:Predicate . - bsfs:array rdfs:subClassOf bsfs:Literal . - - bse:colors rdfs:subClassOf bsfs:Feature ; - rdfs:domain bsfs:Entity ; # undefined symbol - rdfs:range bsfs:array ; - bsfs:unique "false"^^xsd:boolean . - ''') - # domain cannot be a literal - self.assertRaises(errors.ConsistencyError, from_string, ''' - prefix rdfs: - prefix xsd: - prefix bsfs: - prefix bse: - - bsfs:Feature rdfs:subClassOf bsfs:Predicate . - bsfs:Entity rdfs:subClassOf bsfs:Literal . - bsfs:array rdfs:subClassOf bsfs:Literal . - - bse:colors rdfs:subClassOf bsfs:Feature ; - rdfs:domain bsfs:Entity ; # literal instead of node - rdfs:range bsfs:array ; - bsfs:unique "false"^^xsd:boolean . - ''') - - # range must be defined - self.assertRaises(errors.ConsistencyError, from_string, ''' - prefix rdfs: - prefix xsd: - prefix bsfs: - prefix bse: - - bsfs:Feature rdfs:subClassOf bsfs:Predicate . - bsfs:Entity rdfs:subClassOf bsfs:Node . - - bse:colors rdfs:subClassOf bsfs:Feature ; - rdfs:domain bsfs:Entity ; - rdfs:range bsfs:array ; # undefined symbol - bsfs:unique "false"^^xsd:boolean . - ''') - # range must be defined - self.assertRaises(errors.ConsistencyError, from_string, ''' + # additional features can be defined + f_colors = types.ROOT_FEATURE.child(ns.bsfs.Colors) + self.assertEqual(Schema(literals={f_colors}), from_string(''' prefix rdfs: prefix xsd: prefix bsfs: prefix bse: - bsfs:Feature rdfs:subClassOf bsfs:Predicate . - bsfs:Entity rdfs:subClassOf bsfs:Node . + bsfs:Array rdfs:subClassOf bsfs:Literal . + bsfs:Feature rdfs:subClassOf bsfs:Array. - bse:colors rdfs:subClassOf bsfs:Feature ; - rdfs:domain bsfs:Entity ; - rdfs:range bsfs:Foo ; # undefined symbol - bsfs:unique "false"^^xsd:boolean . - ''') - # range must be a node or a literal - self.assertRaises(errors.ConsistencyError, from_string, ''' - prefix rdfs: - prefix xsd: - prefix bsfs: - prefix bse: - - bsfs:Feature rdfs:subClassOf bsfs:Predicate . - bsfs:Entity rdfs:subClassOf bsfs:Node . - - bse:colors rdfs:subClassOf bsfs:Feature ; - rdfs:domain bsfs:Entity ; - rdfs:range bsfs:Predicate ; # invalid symbol - bsfs:unique "false"^^xsd:boolean . - ''') + bsfs:Colors rdfs:subClassOf bsfs:Feature . - # additional predicates can be defined - n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) - l_array = types.ROOT_LITERAL.child(ns.bsfs.array) - p_comment = types.ROOT_FEATURE.child(ns.bse.colors, domain=n_ent, range=l_array, unique=False) - self.assertEqual(Schema({p_comment}), from_string(''' - prefix rdfs: - prefix xsd: - prefix bsfs: - prefix bse: - - bsfs:Feature rdfs:subClassOf bsfs:Predicate . - bsfs:Entity rdfs:subClassOf bsfs:Node . - bsfs:array rdfs:subClassOf bsfs:Literal . - - bse:colors rdfs:subClassOf bsfs:Feature ; - rdfs:domain bsfs:Entity ; - rdfs:range bsfs:array ; - bsfs:unique "false"^^xsd:boolean . ''')) # features inherit properties from parents - n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) - l_array = types.ROOT_LITERAL.child(ns.bsfs.array) - l_string = types.ROOT_LITERAL.child(ns.xsd.string) - p_annotation = types.ROOT_FEATURE.child(ns.bsfs.Annotation, domain=n_ent, range=l_array, - dimension=1234, dtype=ns.xsd.string) - p_comment = p_annotation.child(ns.bse.colors, unique=True) - self.assertEqual(Schema({p_comment}), from_string(''' + f_colors = types.ROOT_FEATURE.child(ns.bsfs.Colors, dimension=1234, dtype=ns.bsfs.i32) + f_main_colors = f_colors.child(ns.bsfs.MainColor, distance=ns.bsfs.cosine, dtype=ns.bsfs.f16) + self.assertEqual(Schema(literals={f_colors, f_main_colors}), from_string(''' prefix rdfs: prefix xsd: prefix bsfs: prefix bse: - bsfs:Feature rdfs:subClassOf bsfs:Predicate . - bsfs:Entity rdfs:subClassOf bsfs:Node . - bsfs:array rdfs:subClassOf bsfs:Literal . + bsfs:Array rdfs:subClassOf bsfs:Literal . + bsfs:Feature rdfs:subClassOf bsfs:Array. - bsfs:Annotation rdfs:subClassOf bsfs:Feature ; # inherits defaults from bsfs:Feature - rdfs:domain bsfs:Entity ; - rdfs:range bsfs:array ; - bsfs:dimension "1234"^^xsd:integer ; - bsfs:dtype xsd:string . + bsfs:Colors rdfs:subClassOf bsfs:Feature ; # inherits distance from bsfs:Feature + bsfs:dimension "1234"^^xsd:integer ; # overwrites bsfs:Feature + bsfs:dtype bsfs:i32 . # overwrites bsfs:Feature + + bsfs:MainColor rdfs:subClassOf bsfs:Colors ; # inherits dimension from bsfs:Colors + bsfs:distance bsfs:cosine ; # overwrites bsfs:Feature + bsfs:dtype bsfs:f16 . # overwrites bsfs:Colors - bse:colors rdfs:subClassOf bsfs:Annotation ; # inherits domain/range/etc. from bsfs:Annotation - bsfs:unique "true"^^xsd:boolean . # overwrites bsfs:Predicate ''')) # feature definition can be split across multiple statements. # statements can be repeated - n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) - p_foo = types.ROOT_FEATURE.child(ns.bse.foo, domain=n_ent, unique=True, - dimension=1234, dtype=ns.bsfs.f32) - self.assertEqual(Schema({p_foo}), from_string(''' + f_colors = types.ROOT_FEATURE.child(ns.bsfs.Colors, dimension=1234, dtype=ns.bsfs.f32) + self.assertEqual(Schema(literals={f_colors}), from_string(''' prefix rdfs: prefix xsd: prefix bsfs: prefix bse: - bsfs:Feature rdfs:subClassOf bsfs:Predicate . - bsfs:Entity rdfs:subClassOf bsfs:Node . + bsfs:Array rdfs:subClassOf bsfs:Literal . + bsfs:Feature rdfs:subClassOf bsfs:Array. - bse:foo rdfs:subClassOf bsfs:Feature ; - bsfs:unique "true"^^xsd:boolean ; + bsfs:Colors rdfs:subClassOf bsfs:Feature ; bsfs:dimension "1234"^^xsd:integer . - bse:foo rdfs:subClassOf bsfs:Feature ; - rdfs:domain bsfs:Entity ; + bsfs:Colors rdfs:subClassOf bsfs:Feature ; + bsfs:dimension "1234"^^xsd:integer ; # non-conflicting repetition bsfs:dtype bsfs:f32 . ''')) @@ -736,75 +645,14 @@ class TestFromString(unittest.TestCase): prefix bsfs: prefix bse: - bsfs:Feature rdfs:subClassOf bsfs:Predicate . - bsfs:Annotation rdfs:subClassOf bsfs:Feature . - bsfs:Entity rdfs:subClassOf bsfs:Node . + bsfs:Array rdfs:subClassOf bsfs:Literal . + bsfs:Feature rdfs:subClassOf bsfs:Array. + bsfs:ColorSpace rdfs:subClassOf bsfs:Feature . - bse:foo rdfs:subClassOf bsfs:Feature ; - rdfs:domain bsfs:Node ; - bsfs:unique "false"^^xsd:boolean . - - bse:foo rdfs:subClassOf bsfs:Annotation ; - rdfs:domain bsfs:Node ; - bsfs:unique "false"^^xsd:boolean . + bsfs:Colors rdfs:subClassOf bsfs:Feature . + bsfs:Colors rdfs:subClassOf bsfs:ColorSpace . ''') - # cannot assign multiple conflicting domains to the same feature - self.assertRaises(errors.ConsistencyError, from_string, ''' - prefix rdfs: - prefix xsd: - prefix bsfs: - prefix bse: - - bsfs:Feature rdfs:subClassOf bsfs:Predicate . - bsfs:Entity rdfs:subClassOf bsfs:Node . - - bse:foo rdfs:subClassOf bsfs:Feature ; - rdfs:domain bsfs:Node ; - bsfs:unique "false"^^xsd:boolean . - - bse:foo rdfs:subClassOf bsfs:Feature ; - rdfs:domain bsfs:Entity . # conflicting domain - ''') - # cannot assign multiple conflicting ranges to the same feature - self.assertRaises(errors.ConsistencyError, from_string, ''' - prefix rdfs: - prefix xsd: - prefix bsfs: - prefix bse: - - bsfs:Feature rdfs:subClassOf bsfs:Predicate . - bsfs:Entity rdfs:subClassOf bsfs:Node . - bsfs:array rdfs:subClassOf bsfs:Literal . - bsfs:large_array rdfs:subClassOf bsfs:array . - bsfs:small_array rdfs:subClassOf bsfs:array . - - bse:foo rdfs:subClassOf bsfs:Feature ; - rdfs:domain bsfs:Node ; - rdfs:range bsfs:large_array ; - bsfs:unique "false"^^xsd:boolean . - - bse:foo rdfs:subClassOf bsfs:Feature ; - rdfs:range bsfs:small_array . # conflicting range - ''') - # cannot assign multiple conflicting uniques to the same feature - self.assertRaises(errors.ConsistencyError, from_string, ''' - prefix rdfs: - prefix xsd: - prefix bsfs: - prefix bse: - - bsfs:Feature rdfs:subClassOf bsfs:Predicate . - bsfs:Entity rdfs:subClassOf bsfs:Node . - - bse:foo rdfs:subClassOf bsfs:Feature ; - rdfs:domain bsfs:Node ; - rdfs:range bsfs:Node ; - bsfs:unique "false"^^xsd:boolean . - - bse:foo rdfs:subClassOf bsfs:Feature ; - bsfs:unique "true"^^xsd:boolean . # conflicting unique - ''') # cannot assign multiple conflicting dimensions to the same feature self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: @@ -812,15 +660,15 @@ class TestFromString(unittest.TestCase): prefix bsfs: prefix bse: - bsfs:Feature rdfs:subClassOf bsfs:Predicate . - bsfs:Entity rdfs:subClassOf bsfs:Node . + bsfs:Array rdfs:subClassOf bsfs:Literal . + bsfs:Feature rdfs:subClassOf bsfs:Array. - bse:foo rdfs:subClassOf bsfs:Feature ; - rdfs:domain bsfs:Node ; + bsfs:Colors rdfs:subClassOf bsfs:Feature ; bsfs:dimension "1234"^^xsd:integer . - bse:foo rdfs:subClassOf bsfs:Feature ; + bsfs:Colors rdfs:subClassOf bsfs:Feature ; bsfs:dimension "4321"^^xsd:integer . # conflicting dimension + ''') # cannot assign multiple conflicting dtypes to the same feature self.assertRaises(errors.ConsistencyError, from_string, ''' @@ -829,14 +677,13 @@ class TestFromString(unittest.TestCase): prefix bsfs: prefix bse: - bsfs:Feature rdfs:subClassOf bsfs:Predicate . - bsfs:Entity rdfs:subClassOf bsfs:Node . + bsfs:Array rdfs:subClassOf bsfs:Literal . + bsfs:Feature rdfs:subClassOf bsfs:Array. - bse:foo rdfs:subClassOf bsfs:Feature ; - rdfs:domain bsfs:Node ; + bsfs:Colors rdfs:subClassOf bsfs:Feature ; bsfs:dtype bsfs:f32 . - bse:foo rdfs:subClassOf bsfs:Feature ; + bsfs:Colors rdfs:subClassOf bsfs:Feature ; bsfs:dtype bsfs:f16 . # conflicting dtype ''') # cannot assign multiple conflicting distance metrics to the same feature @@ -846,14 +693,13 @@ class TestFromString(unittest.TestCase): prefix bsfs: prefix bse: - bsfs:Feature rdfs:subClassOf bsfs:Predicate . - bsfs:Entity rdfs:subClassOf bsfs:Node . + bsfs:Array rdfs:subClassOf bsfs:Literal . + bsfs:Feature rdfs:subClassOf bsfs:Array. - bse:foo rdfs:subClassOf bsfs:Feature ; - rdfs:domain bsfs:Node ; + bsfs:Colors rdfs:subClassOf bsfs:Feature ; bsfs:distance bsfs:euclidean . - bse:foo rdfs:subClassOf bsfs:Feature ; + bsfs:Colors rdfs:subClassOf bsfs:Feature ; bsfs:distance bsfs:cosine . # conflicting distance ''') @@ -864,24 +710,28 @@ class TestFromString(unittest.TestCase): prefix bsfs: prefix bse: - bsfs:Feature rdfs:subClassOf bsfs:Predicate . - bse:colors rdfs:subClassOf bsfs:Feature ; + bsfs:Array rdfs:subClassOf bsfs:Literal . + bsfs:Feature rdfs:subClassOf bsfs:Array. + + bsfs:Colors rdfs:subClassOf bsfs:Feature ; bsfs:dimension "1234"^^xsd:integer . - ''').predicate(ns.bse.colors).annotations, {}) + ''').literal(ns.bsfs.Colors).annotations, {}) self.assertDictEqual(from_string(''' prefix rdfs: prefix xsd: prefix bsfs: prefix bse: - bsfs:Feature rdfs:subClassOf bsfs:Predicate . - bse:colors rdfs:subClassOf bsfs:Feature ; + bsfs:Array rdfs:subClassOf bsfs:Literal . + bsfs:Feature rdfs:subClassOf bsfs:Array. + + bsfs:Colors rdfs:subClassOf bsfs:Feature ; bsfs:dimension "1234"^^xsd:integer ; rdfs:label "hello world"^^xsd:string ; bsfs:foo "1234"^^xsd:integer . - ''').predicate(ns.bse.colors).annotations, { + ''').literal(ns.bsfs.Colors).annotations, { ns.rdfs.label: 'hello world', ns.bsfs.foo: 1234, }) @@ -904,14 +754,14 @@ class TestFromString(unittest.TestCase): p_comment = p_annotation.child(ns.bse.comment, range=l_string) # features f_colors = types.ROOT_FEATURE.child(URI('http://bsfs.ai/schema/Feature/colors_spatial'), - domain=n_ent, range=l_array, unique=True, dtype=ns.bsfs.f16, distance=ns.bsfs.euclidean) + dtype=ns.bsfs.f16, distance=ns.bsfs.euclidean) f_colors1234 = f_colors.child(URI('http://bsfs.ai/schema/Feature/colors_spatial#1234'), dimension=1024) f_colors4321 = f_colors.child(URI('http://bsfs.ai/schema/Feature/colors_spatial#4321'), dimension=2048) # schema ref = Schema( - {p_annotation, p_tag, p_group, p_comment, f_colors, f_colors1234, f_colors4321}, + {p_annotation, p_tag, p_group, p_comment}, {n_ent, n_tag, n_image}, - {l_string, l_integer, l_boolean}) + {l_string, l_integer, l_boolean, f_colors, f_colors1234, f_colors4321}) # load from string gen = from_string(''' # generic prefixes @@ -932,21 +782,19 @@ class TestFromString(unittest.TestCase): # literals xsd:string rdfs:subClassOf bsfs:Literal ; rdfs:label "A sequence of characters"^^xsd:string . - bsfs:array rdfs:subClassOf bsfs:Literal . + bsfs:Array rdfs:subClassOf bsfs:Literal . + bsfs:Feature rdfs:subClassOf bsfs:Array. bsfs:Number rdfs:subClassOf bsfs:Literal . xsd:integer rdfs:subClassOf bsfs:Number . xsd:boolean rdfs:subClassOf bsfs:Literal . + # abstract predicates bsfs:Annotation rdfs:subClassOf bsfs:Predicate ; rdfs:label "node annotation"^^xsd:string . - bsfs:Feature rdfs:subClassOf bsfs:Predicate . # feature instances rdfs:subClassOf bsfs:Feature ; - rdfs:domain bsfs:Entity ; - rdfs:range bsfs:array ; - bsfs:unique "true"^^xsd:boolean ; bsfs:dtype bsfs:f16 ; bsfs:distance bsfs:euclidean ; # annotations @@ -986,15 +834,22 @@ class TestFromString(unittest.TestCase): self.assertDictEqual(gen.node(ns.bsfs.Tag).annotations, {ns.rdfs.label: 'Tag'}) self.assertDictEqual(gen.literal(ns.xsd.string).annotations, {ns.rdfs.label: 'A sequence of characters'}) self.assertDictEqual(gen.predicate(ns.bsfs.Annotation).annotations, {ns.rdfs.label: 'node annotation'}) - self.assertDictEqual(gen.predicate(URI('http://bsfs.ai/schema/Feature/colors_spatial')).annotations, { + self.assertDictEqual(gen.literal(URI('http://bsfs.ai/schema/Feature/colors_spatial')).annotations, { ns.rdfs.label: 'ColorsSpatial instances. Dimension depends on instance.', ns.bsfs.first_arg: 1234, ns.bsfs.second_arg: 'hello world', }) - self.assertDictEqual(gen.predicate(URI('http://bsfs.ai/schema/Feature/colors_spatial#1234')).annotations, { + self.assertDictEqual(gen.literal(URI('http://bsfs.ai/schema/Feature/colors_spatial#1234')).annotations, { ns.rdfs.label: 'Main colors spatial instance'}) self.assertDictEqual(gen.predicate(ns.bse.tag).annotations, {ns.rdfs.label: 'connect entity to a tag'}) + # blank nodes result in an error + self.assertRaises(errors.BackendError, from_string, ''' + prefix rdfs: + prefix bsfs: + bsfs:Entity rdfs:subClassOf bsfs:Node ; + bsfs:foo _:bar . + ''') class TestToString(unittest.TestCase): @@ -1002,6 +857,11 @@ class TestToString(unittest.TestCase): def test_empty(self): self.assertEqual(Schema(), from_string(to_string(Schema()))) + def test_parse(self): + schema = Schema() + schema._nodes[ns.bsfs.Invalid] = 123 # NOTE: Access protected to force an invalid schema + self.assertRaises(TypeError, to_string, schema) + def test_literal(self): # root literals l_str = types.ROOT_LITERAL.child(ns.xsd.string) @@ -1120,37 +980,29 @@ class TestToString(unittest.TestCase): def test_feature(self): - # auxiliary types - n_ent = types.ROOT_NODE.child(ns.bsfs.Entity) - l_array = types.ROOT_LITERAL.child(ns.bsfs.array) # root features f_colors = types.ROOT_FEATURE.child(URI('http://bsfs.ai/schema/Feature/colors'), - range=l_array, unique=True, distance=ns.bsfs.cosine) + distance=ns.bsfs.cosine) # derived features f_colors1234 = f_colors.child(URI('http://bsfs.ai/schema/Feature/colors#1234'), - dimension=1024, domain=n_ent) # inherits range/dtype/distance + dimension=1024) # inherits dtype, distance f_colors4321 = f_colors.child(URI('http://bsfs.ai/schema/Feature/colors#4321'), - dimension=2048, distance=ns.bsfs.euclidean) # inherits domain/range/dtype + dimension=2048, distance=ns.bsfs.euclidean) # inherits dtype # create schema - schema = Schema({f_colors, f_colors1234, f_colors4321}) + schema = Schema(literals={f_colors, f_colors1234, f_colors4321}) schema_str = to_string(schema) # all symbols are serialized - self.assertIn('bsfs:Entity', schema_str) - self.assertIn('bsfs:array', schema_str) + self.assertIn('bsfs:Array', schema_str) self.assertIn('[^\.]*rdfs:domain[^\.]', schema_str)) self.assertIsNotNone(re.search(r'[^\.]*bsfs:dimension[^\.]', schema_str)) - self.assertIsNone(re.search(r'[^\.]*rdfs:range[^\.]', schema_str)) self.assertIsNone(re.search(r'[^\.]*bsfs:dtype[^\.]', schema_str)) self.assertIsNone(re.search(r'[^\.]*bsfs:distance[^\.]', schema_str)) self.assertIsNotNone(re.search(r'[^\.]*bsfs:dimension[^\.]', schema_str)) self.assertIsNotNone(re.search(r'[^\.]*bsfs:distance[^\.]', schema_str)) - self.assertIsNone(re.search(r'[^\.]*rdfs:domain[^\.]', schema_str)) - self.assertIsNone(re.search(r'[^\.]*rdfs:range[^\.]', schema_str)) self.assertIsNone(re.search(r'[^\.]*bsfs:dtype[^\.]', schema_str)) # unserialize yields the original schema self.assertEqual(schema, from_string(schema_str)) @@ -1163,11 +1015,11 @@ class TestToString(unittest.TestCase): ns.bsfs.bar: False, } f_colors = types.ROOT_FEATURE.child(URI('http://bsfs.ai/schema/Feature/colors'), - domain=n_ent, range=l_array, unique=True, dtype=ns.bsfs.f16, distance=ns.bsfs.euclidean, + dtype=ns.bsfs.f16, distance=ns.bsfs.euclidean, **annotations) self.assertDictEqual( annotations, - from_string(to_string(Schema({f_colors}))).predicate(URI('http://bsfs.ai/schema/Feature/colors')).annotations) + from_string(to_string(Schema(literals={f_colors}))).literal(URI('http://bsfs.ai/schema/Feature/colors')).annotations) ## main ## diff --git a/test/schema/test_types.py b/test/schema/test_types.py index 1eeafa1..c5895d2 100644 --- a/test/schema/test_types.py +++ b/test/schema/test_types.py @@ -274,21 +274,16 @@ class TestFeature(unittest.TestCase): n_root = Node(ns.bsfs.Node, None) l_root = Literal(ns.bsfs.Literal, None) # dimension, dtype, and distance are respected - feat = Feature(ns.bsfs.Feature, None, n_root, l_root, False, - 1234, ns.bsfs.float, ns.bsfs.euclidean) + feat = Feature(ns.bsfs.Feature, None, 1234, ns.bsfs.float, ns.bsfs.euclidean) self.assertEqual(1234, feat.dimension) self.assertEqual(ns.bsfs.float, feat.dtype) self.assertEqual(ns.bsfs.euclidean, feat.distance) def test_equality(self): n_ent = Node(ns.bsfs.Entity, Node(ns.bsfs.Node, None)) - l_array = Literal(ns.bsfs.array, Literal(ns.bsfs.Literal, None)) colors = Feature( uri=ns.bse.colors, parent=ROOT_FEATURE, - domain=n_ent, - range=l_array, - unique=False, dimension=1234, dtype=ns.bsfs.float, distance=ns.bsfs.euclidean, @@ -297,29 +292,25 @@ class TestFeature(unittest.TestCase): self.assertEqual(colors, colors) self.assertEqual(hash(colors), hash(colors)) # instance is equal to a clone - self.assertEqual(colors, Feature(ns.bse.colors, ROOT_FEATURE, n_ent, l_array, False, 1234, ns.bsfs.float, ns.bsfs.euclidean)) - self.assertEqual(hash(colors), hash(Feature(ns.bse.colors, ROOT_FEATURE, n_ent, l_array, False, 1234, ns.bsfs.float, ns.bsfs.euclidean))) + self.assertEqual(colors, Feature(ns.bse.colors, ROOT_FEATURE, 1234, ns.bsfs.float, ns.bsfs.euclidean)) + self.assertEqual(hash(colors), hash(Feature(ns.bse.colors, ROOT_FEATURE, 1234, ns.bsfs.float, ns.bsfs.euclidean))) # equality respects dimension - self.assertNotEqual(colors, Feature(ns.bse.colors, ROOT_FEATURE, n_ent, l_array, False, 4321, ns.bsfs.float, ns.bsfs.euclidean)) - self.assertNotEqual(hash(colors), hash(Feature(ns.bse.colors, ROOT_FEATURE, n_ent, l_array, False, 4321, ns.bsfs.float, ns.bsfs.euclidean))) + self.assertNotEqual(colors, Feature(ns.bse.colors, ROOT_FEATURE, 4321, ns.bsfs.float, ns.bsfs.euclidean)) + self.assertNotEqual(hash(colors), hash(Feature(ns.bse.colors, ROOT_FEATURE, 4321, ns.bsfs.float, ns.bsfs.euclidean))) # equality respects dtype - self.assertNotEqual(colors, Feature(ns.bse.colors, ROOT_FEATURE, n_ent, l_array, False, 1234, ns.bsfs.integer, ns.bsfs.euclidean)) - self.assertNotEqual(hash(colors), hash(Feature(ns.bse.colors, ROOT_FEATURE, n_ent, l_array, False, 1234, ns.bsfs.integer, ns.bsfs.euclidean))) + self.assertNotEqual(colors, Feature(ns.bse.colors, ROOT_FEATURE, 1234, ns.bsfs.integer, ns.bsfs.euclidean)) + self.assertNotEqual(hash(colors), hash(Feature(ns.bse.colors, ROOT_FEATURE, 1234, ns.bsfs.integer, ns.bsfs.euclidean))) # equality respects distance - self.assertNotEqual(colors, Feature(ns.bse.colors, ROOT_FEATURE, n_ent, l_array, False, 1234, ns.bsfs.float, ns.bsfs.cosine)) - self.assertNotEqual(hash(colors), hash(Feature(ns.bse.colors, ROOT_FEATURE, n_ent, l_array, False, 1234, ns.bsfs.float, ns.bsfs.cosine))) + self.assertNotEqual(colors, Feature(ns.bse.colors, ROOT_FEATURE, 1234, ns.bsfs.float, ns.bsfs.cosine)) + self.assertNotEqual(hash(colors), hash(Feature(ns.bse.colors, ROOT_FEATURE, 1234, ns.bsfs.float, ns.bsfs.cosine))) def test_child(self): n_root = Node(ns.bsfs.Node, None) n_ent = Node(ns.bsfs.Entity, n_root) l_root = Literal(ns.bsfs.Literal, None) - l_array = Literal(ns.bsfs.array, l_root) colors = Feature( uri=ns.bse.colors, parent=ROOT_FEATURE, - domain=n_ent, - range=l_array, - unique=False, dimension=1234, dtype=ns.bsfs.float, distance=ns.bsfs.euclidean, @@ -329,16 +320,6 @@ class TestFeature(unittest.TestCase): self.assertIsInstance(colors.child(ns.bse.foo), Feature) # uri is respected self.assertEqual(ns.bse.foo, colors.child(ns.bse.foo).uri) - # domain is respected - dom = Node(ns.bsfs.Image, n_ent) - self.assertEqual(dom, colors.child(ns.bse.foo, domain=dom).domain) - # range is respected - rng = Literal(ns.bse.foo, l_array) - self.assertEqual(rng, colors.child(ns.bse.foo, range=rng).range) - # cannot set range to None - self.assertEqual(l_array, colors.child(ns.bse.foo, range=None).range) - # unique is respected - self.assertTrue(colors.child(ns.bse.foo, unique=True).unique) # dimension is respected self.assertEqual(4321, colors.child(ns.bse.foo, dimension=4321).dimension) # dtype is respected @@ -351,13 +332,6 @@ class TestFeature(unittest.TestCase): 'bar': 123, }) - # domain is inherited from parent - self.assertEqual(n_root, ROOT_FEATURE.child(ns.bse.foo).domain) - self.assertEqual(n_ent, colors.child(ns.bse.foo).domain) - # range is inherited from parent - self.assertEqual(l_array, colors.child(ns.bse.foo).range) - # uniqueness is inherited from parent - self.assertFalse(colors.child(ns.bse.foo).unique) # dimension is inherited from parent self.assertEqual(1234, colors.child(ns.bse.foo).dimension) # dtype is inherited from parent @@ -365,14 +339,6 @@ class TestFeature(unittest.TestCase): # distance is inherited from parent self.assertEqual(ns.bsfs.euclidean, colors.child(ns.bse.foo).distance) - # domain must be subtype of parent's domain - self.assertRaises(errors.ConsistencyError, colors.child, ns.bse.foo, domain=n_root) - self.assertRaises(errors.ConsistencyError, colors.child, ns.bse.foo, domain=Node(ns.bsfs.Image, n_root)) - # range must be subtype of parent's range - self.assertRaises(errors.ConsistencyError, colors.child, ns.bse.foo, range=Literal(ns.bsfs.Literal, None)) - self.assertRaises(errors.ConsistencyError, colors.child, ns.bse.foo, range=Literal(ns.bsfs.foo, Literal(ns.bsfs.Literal, None))) - self.assertRaises(errors.ConsistencyError, colors.child, ns.bse.foo, range=Node(ns.bsfs.Tag, n_root)) - ## main ## -- cgit v1.2.3 From cb819b8c268908b5f6cc680173db86e172847c46 Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Wed, 8 Feb 2023 20:15:41 +0100 Subject: binary blob in schema and sparql triple store --- test/schema/test_schema.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'test/schema') diff --git a/test/schema/test_schema.py b/test/schema/test_schema.py index 32dbc93..414e542 100644 --- a/test/schema/test_schema.py +++ b/test/schema/test_schema.py @@ -66,13 +66,14 @@ class TestSchema(unittest.TestCase): # literals self.l_root = types.ROOT_LITERAL self.l_number = types.ROOT_NUMBER + self.l_blob = types.ROOT_BLOB self.l_array = types.ROOT_ARRAY self.l_time = types.ROOT_TIME self.l_string = self.l_root.child(ns.xsd.string) self.l_integer = self.l_root.child(ns.xsd.integer) self.l_unused = self.l_root.child(ns.xsd.boolean) self.f_root = types.ROOT_FEATURE - self.literals = [self.l_root, self.l_array, self.f_root, self.l_number, self.l_time, self.l_string, self.l_integer, self.l_unused] + self.literals = [self.l_root, self.l_array, self.f_root, self.l_number, self.l_time, self.l_string, self.l_integer, self.l_unused, self.l_blob] # predicates self.p_root = types.ROOT_PREDICATE @@ -85,13 +86,13 @@ class TestSchema(unittest.TestCase): # no args yields a minimal schema schema = Schema() self.assertSetEqual(set(schema.nodes()), {self.n_root}) - self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_number, self.l_array, self.l_time, self.f_root}) + self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_number, self.l_array, self.l_time, self.f_root, self.l_blob}) self.assertSetEqual(set(schema.predicates()), {self.p_root}) # nodes and literals are optional schema = Schema(self.predicates) self.assertSetEqual(set(schema.nodes()), {self.n_root, self.n_ent, self.n_img, self.n_tag}) - self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number, self.l_time, self.l_array, self.f_root}) + self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number, self.l_time, self.l_array, self.f_root, self.l_blob}) self.assertSetEqual(set(schema.predicates()), set(self.predicates)) # predicates, nodes, and literals are respected @@ -112,13 +113,13 @@ class TestSchema(unittest.TestCase): # literals are complete schema = Schema(self.predicates, self.nodes, None) - self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number, self.l_array, self.l_time, self.f_root}) + self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number, self.l_array, self.l_time, self.f_root, self.l_blob}) schema = Schema(self.predicates, self.nodes, []) - self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number, self.l_array, self.l_time, self.f_root}) + self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number, self.l_array, self.l_time, self.f_root, self.l_blob}) schema = Schema(self.predicates, self.nodes, [self.l_string]) - self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number, self.l_array, self.l_time, self.f_root}) + self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_number, self.l_array, self.l_time, self.f_root, self.l_blob}) schema = Schema(self.predicates, self.nodes, [self.l_integer]) - self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_integer, self.l_number, self.l_array, self.l_time, self.f_root}) + self.assertSetEqual(set(schema.literals()), {self.l_root, self.l_string, self.l_integer, self.l_number, self.l_array, self.l_time, self.f_root, self.l_blob}) schema = Schema(self.predicates, self.nodes, [self.l_integer, self.l_unused]) self.assertSetEqual(set(schema.literals()), set(self.literals)) @@ -178,13 +179,13 @@ class TestSchema(unittest.TestCase): self.assertEqual(str(Schema(self.predicates, self.nodes, self.literals)), 'Schema()') # repr conversion with only default nodes, literals, and predicates n = [ns.bsfs.Node] - l = [ns.bsfs.Array, ns.bsfs.Feature, ns.bsfs.Literal, ns.bsfs.Number, ns.bsfs.Time] + l = [ns.bsfs.Array, ns.bsfs.BinaryBlob, ns.bsfs.Feature, ns.bsfs.Literal, ns.bsfs.Number, ns.bsfs.Time] p = [ns.bsfs.Predicate] self.assertEqual(repr(Schema()), f'Schema({n}, {l}, {p})') self.assertEqual(repr(Schema([], [], [])), f'Schema({n}, {l}, {p})') # repr conversion n = [ns.bsfs.Entity, ns.bsfs.Image, ns.bsfs.Node, ns.bsfs.Tag, ns.bsfs.Unused] - l = [ns.bsfs.Array, ns.bsfs.Feature, ns.bsfs.Literal, ns.bsfs.Number, ns.bsfs.Time, ns.xsd.boolean, ns.xsd.integer, ns.xsd.string] + l = [ns.bsfs.Array, ns.bsfs.BinaryBlob, ns.bsfs.Feature, ns.bsfs.Literal, ns.bsfs.Number, ns.bsfs.Time, ns.xsd.boolean, ns.xsd.integer, ns.xsd.string] p = [ns.bse.comment, ns.bse.group, ns.bse.tag, ns.bsfs.Predicate] self.assertEqual(repr(Schema(self.predicates, self.nodes, self.literals)), f'Schema({n}, {l}, {p})') -- cgit v1.2.3 From 2e07f33314c238e42bfadc5f39805f93ffbc622e Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Thu, 2 Mar 2023 15:10:05 +0100 Subject: removed author and license notices from individual files --- test/schema/test_schema.py | 5 ----- test/schema/test_serialize.py | 5 ----- test/schema/test_types.py | 5 ----- 3 files changed, 15 deletions(-) (limited to 'test/schema') diff --git a/test/schema/test_schema.py b/test/schema/test_schema.py index 414e542..f9ddb68 100644 --- a/test/schema/test_schema.py +++ b/test/schema/test_schema.py @@ -1,9 +1,4 @@ -""" -Part of the tagit test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # imports import operator import unittest diff --git a/test/schema/test_serialize.py b/test/schema/test_serialize.py index fc6b20a..84512e9 100644 --- a/test/schema/test_serialize.py +++ b/test/schema/test_serialize.py @@ -1,9 +1,4 @@ -""" -Part of the tagit test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # imports import re import unittest diff --git a/test/schema/test_types.py b/test/schema/test_types.py index c5895d2..f87d857 100644 --- a/test/schema/test_types.py +++ b/test/schema/test_types.py @@ -1,9 +1,4 @@ -""" -Part of the tagit test suite. -A copy of the license is provided with the project. -Author: Matthias Baumgartner, 2022 -""" # imports import operator import unittest -- cgit v1.2.3 From 4fead04055be4967d9ea3b24ff61fe37a93108dd Mon Sep 17 00:00:00 2001 From: Matthias Baumgartner Date: Sat, 4 Mar 2023 13:31:11 +0100 Subject: namespace refactoring and cleanup --- test/schema/test_schema.py | 13 +- test/schema/test_serialize.py | 335 ++++++++++++++++++++++-------------------- test/schema/test_types.py | 2 + 3 files changed, 189 insertions(+), 161 deletions(-) (limited to 'test/schema') diff --git a/test/schema/test_schema.py b/test/schema/test_schema.py index f9ddb68..f52cf95 100644 --- a/test/schema/test_schema.py +++ b/test/schema/test_schema.py @@ -14,6 +14,8 @@ from bsfs.schema.schema import Schema ## code ## +ns.bse = ns.bsfs.Entity() + class TestSchema(unittest.TestCase): def setUp(self): @@ -21,8 +23,9 @@ class TestSchema(unittest.TestCase): prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: + prefix bsl: bsfs:Entity rdfs:subClassOf bsfs:Node . bsfs:Tag rdfs:subClassOf bsfs:Node . @@ -31,7 +34,7 @@ class TestSchema(unittest.TestCase): xsd:string rdfs:subClassOf bsfs:Literal . bsfs:Number rdfs:subClassOf bsfs:Literal . - xsd:integer rdfs:subClassOf bsfs:Number . + xsd:integer rdfs:subClassOf bsl:Number . xsd:boolean rdfs:subClassOf bsfs:Literal . bse:tag rdfs:subClassOf bsfs:Predicate ; @@ -174,13 +177,13 @@ class TestSchema(unittest.TestCase): self.assertEqual(str(Schema(self.predicates, self.nodes, self.literals)), 'Schema()') # repr conversion with only default nodes, literals, and predicates n = [ns.bsfs.Node] - l = [ns.bsfs.Array, ns.bsfs.BinaryBlob, ns.bsfs.Feature, ns.bsfs.Literal, ns.bsfs.Number, ns.bsfs.Time] + l = [ns.bsfs.Literal, ns.bsl.Array, ns.bsl.Array.Feature, ns.bsl.BinaryBlob, ns.bsl.Number, ns.bsl.Time] p = [ns.bsfs.Predicate] self.assertEqual(repr(Schema()), f'Schema({n}, {l}, {p})') self.assertEqual(repr(Schema([], [], [])), f'Schema({n}, {l}, {p})') # repr conversion n = [ns.bsfs.Entity, ns.bsfs.Image, ns.bsfs.Node, ns.bsfs.Tag, ns.bsfs.Unused] - l = [ns.bsfs.Array, ns.bsfs.BinaryBlob, ns.bsfs.Feature, ns.bsfs.Literal, ns.bsfs.Number, ns.bsfs.Time, ns.xsd.boolean, ns.xsd.integer, ns.xsd.string] + l = [ns.xsd.boolean, ns.xsd.integer, ns.xsd.string, ns.bsfs.Literal, ns.bsl.Array, ns.bsl.Array.Feature, ns.bsl.BinaryBlob, ns.bsl.Number, ns.bsl.Time] p = [ns.bse.comment, ns.bse.group, ns.bse.tag, ns.bsfs.Predicate] self.assertEqual(repr(Schema(self.predicates, self.nodes, self.literals)), f'Schema({n}, {l}, {p})') diff --git a/test/schema/test_serialize.py b/test/schema/test_serialize.py index 84512e9..7d5d3ae 100644 --- a/test/schema/test_serialize.py +++ b/test/schema/test_serialize.py @@ -14,6 +14,8 @@ from bsfs.schema.serialize import from_string, to_string ## code ## +ns.bse = ns.bsfs.Entity() + class TestFromString(unittest.TestCase): def test_empty(self): @@ -25,7 +27,7 @@ class TestFromString(unittest.TestCase): # must not have circular dependencies self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: - prefix bsfs: + prefix bsfs: bsfs:Entity rdfs:subClassOf bsfs:Node . # ah, a nice circular dependency bsfs:Entity rdfs:subClassOf bsfs:Document . @@ -39,8 +41,8 @@ class TestFromString(unittest.TestCase): self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: xsd:string rdfs:subClassOf bsfs:Literal . @@ -54,7 +56,7 @@ class TestFromString(unittest.TestCase): self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: + prefix bsfs: bsfs:Entity rdfs:subClassOf bsfs:Node . bsfs:Document rdfs:subClassOf bsfs:Node . @@ -66,8 +68,8 @@ class TestFromString(unittest.TestCase): self.assertEqual(Schema({}, {n_unused}), from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:unused rdfs:subClassOf bsfs:Node . # unused symbol ''')) @@ -80,8 +82,8 @@ class TestFromString(unittest.TestCase): self.assertEqual(Schema({}, {n_ent, n_tag, n_doc, n_image}), from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: # nodes inherit from same parent bsfs:Entity rdfs:subClassOf bsfs:Node . @@ -100,8 +102,8 @@ class TestFromString(unittest.TestCase): self.assertEqual(Schema({p_filename}), from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Node . xsd:string rdfs:subClassOf bsfs:Literal . @@ -116,7 +118,7 @@ class TestFromString(unittest.TestCase): self.assertDictEqual(from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: + prefix bsfs: bsfs:Entity rdfs:subClassOf bsfs:Node . @@ -124,7 +126,7 @@ class TestFromString(unittest.TestCase): self.assertDictEqual(from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: + prefix bsfs: bsfs:Entity rdfs:subClassOf bsfs:Node ; rdfs:label "hello world"^^xsd:string ; @@ -141,8 +143,8 @@ class TestFromString(unittest.TestCase): self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Node . @@ -156,7 +158,7 @@ class TestFromString(unittest.TestCase): self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: + prefix bsfs: xsd:string rdfs:subClassOf bsfs:Literal . xsd:name rdfs:subClassOf bsfs:Literal . @@ -168,8 +170,8 @@ class TestFromString(unittest.TestCase): self.assertEqual(Schema({}, {}, {l_unused}), from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: xsd:unused rdfs:subClassOf bsfs:Literal . # unused symbol ''')) @@ -182,13 +184,14 @@ class TestFromString(unittest.TestCase): self.assertEqual(Schema({}, {}, {l_string, l_integer, l_unsigned, l_signed}), from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: + prefix bsl: # literals inherit from same parent xsd:string rdfs:subClassOf bsfs:Literal . - bsfs:Number rdfs:subClassOf bsfs:Literal . - xsd:integer rdfs:subClassOf bsfs:Number . + bsl:Number rdfs:subClassOf bsfs:Literal . + xsd:integer rdfs:subClassOf bsl:Number . # literals inherit from same parent xsd:unsigned rdfs:subClassOf xsd:integer . @@ -203,8 +206,8 @@ class TestFromString(unittest.TestCase): self.assertEqual(Schema({p_filename}), from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Node . xsd:string rdfs:subClassOf bsfs:Literal . @@ -219,7 +222,7 @@ class TestFromString(unittest.TestCase): self.assertDictEqual(from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: + prefix bsfs: xsd:string rdfs:subClassOf bsfs:Literal . @@ -227,7 +230,7 @@ class TestFromString(unittest.TestCase): self.assertDictEqual(from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: + prefix bsfs: xsd:string rdfs:subClassOf bsfs:Literal ; rdfs:label "hello world"^^xsd:string ; @@ -244,8 +247,8 @@ class TestFromString(unittest.TestCase): self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: xsd:string rdfs:subClassOf bsfs:Literal . @@ -258,8 +261,8 @@ class TestFromString(unittest.TestCase): self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Literal . xsd:string rdfs:subClassOf bsfs:Literal . @@ -274,8 +277,8 @@ class TestFromString(unittest.TestCase): self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Node . @@ -288,8 +291,8 @@ class TestFromString(unittest.TestCase): self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Node . @@ -302,8 +305,8 @@ class TestFromString(unittest.TestCase): self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Node . @@ -320,8 +323,8 @@ class TestFromString(unittest.TestCase): self.assertEqual(Schema({p_comment}), from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Node . xsd:string rdfs:subClassOf bsfs:Literal . @@ -340,8 +343,8 @@ class TestFromString(unittest.TestCase): self.assertEqual(Schema({p_comment}), from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Node . xsd:string rdfs:subClassOf bsfs:Literal . @@ -362,8 +365,8 @@ class TestFromString(unittest.TestCase): self.assertEqual(Schema({p_comment}), from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Node . xsd:string rdfs:subClassOf bsfs:Literal . @@ -383,8 +386,8 @@ class TestFromString(unittest.TestCase): self.assertEqual(Schema({p_foo}), from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Node . @@ -405,8 +408,8 @@ class TestFromString(unittest.TestCase): self.assertEqual(Schema({p_foobar}), from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Node . bsfs:Image rdfs:subClassOf bsfs:Entity . @@ -421,8 +424,8 @@ class TestFromString(unittest.TestCase): self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Node . bsfs:Image rdfs:subClassOf bsfs:Entity . @@ -444,8 +447,8 @@ class TestFromString(unittest.TestCase): self.assertEqual(Schema({p_foobar}), from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Node . bsfs:Image rdfs:subClassOf bsfs:Entity . @@ -460,8 +463,8 @@ class TestFromString(unittest.TestCase): self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Node . bsfs:Image rdfs:subClassOf bsfs:Entity . @@ -478,8 +481,8 @@ class TestFromString(unittest.TestCase): self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Node . bsfs:Annotation rdfs:subClassOf bsfs:Predicate . @@ -499,8 +502,8 @@ class TestFromString(unittest.TestCase): self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Node . @@ -516,8 +519,8 @@ class TestFromString(unittest.TestCase): self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Node . @@ -533,8 +536,8 @@ class TestFromString(unittest.TestCase): self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bsfs:Entity rdfs:subClassOf bsfs:Node . @@ -551,8 +554,8 @@ class TestFromString(unittest.TestCase): self.assertDictEqual(from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bse:comment rdfs:subClassOf bsfs:Predicate ; rdfs:range bsfs:Node . @@ -561,8 +564,8 @@ class TestFromString(unittest.TestCase): self.assertDictEqual(from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: bse:comment rdfs:subClassOf bsfs:Predicate ; rdfs:range bsfs:Node ; @@ -581,70 +584,78 @@ class TestFromString(unittest.TestCase): self.assertEqual(Schema(literals={f_colors}), from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: + prefix bsl: + prefix bsa: - bsfs:Array rdfs:subClassOf bsfs:Literal . - bsfs:Feature rdfs:subClassOf bsfs:Array. + bsl:Array rdfs:subClassOf bsfs:Literal . + bsa:Feature rdfs:subClassOf bsl:Array. - bsfs:Colors rdfs:subClassOf bsfs:Feature . + bsfs:Colors rdfs:subClassOf bsa:Feature . ''')) # features inherit properties from parents - f_colors = types.ROOT_FEATURE.child(ns.bsfs.Colors, dimension=1234, dtype=ns.bsfs.i32) - f_main_colors = f_colors.child(ns.bsfs.MainColor, distance=ns.bsfs.cosine, dtype=ns.bsfs.f16) + f_colors = types.ROOT_FEATURE.child(ns.bsfs.Colors, dimension=1234, dtype=ns.bsfs.dtype().i32) + f_main_colors = f_colors.child(ns.bsfs.MainColor, distance=ns.bsfs.cosine, dtype=ns.bsfs.dtype().f16) self.assertEqual(Schema(literals={f_colors, f_main_colors}), from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: + prefix bsl: + prefix bsa: - bsfs:Array rdfs:subClassOf bsfs:Literal . - bsfs:Feature rdfs:subClassOf bsfs:Array. + bsl:Array rdfs:subClassOf bsfs:Literal . + bsa:Feature rdfs:subClassOf bsl:Array. - bsfs:Colors rdfs:subClassOf bsfs:Feature ; # inherits distance from bsfs:Feature - bsfs:dimension "1234"^^xsd:integer ; # overwrites bsfs:Feature - bsfs:dtype bsfs:i32 . # overwrites bsfs:Feature + bsfs:Colors rdfs:subClassOf bsa:Feature ; # inherits distance from bsa:Feature + bsfs:dimension "1234"^^xsd:integer ; # overwrites bsa:Feature + bsfs:dtype . # overwrites bsa:Feature bsfs:MainColor rdfs:subClassOf bsfs:Colors ; # inherits dimension from bsfs:Colors - bsfs:distance bsfs:cosine ; # overwrites bsfs:Feature - bsfs:dtype bsfs:f16 . # overwrites bsfs:Colors + bsfs:distance bsfs:cosine ; # overwrites bsa:Feature + bsfs:dtype . # overwrites bsfs:Colors ''')) # feature definition can be split across multiple statements. # statements can be repeated - f_colors = types.ROOT_FEATURE.child(ns.bsfs.Colors, dimension=1234, dtype=ns.bsfs.f32) + f_colors = types.ROOT_FEATURE.child(ns.bsfs.Colors, dimension=1234, dtype=ns.bsfs.dtype().f32) self.assertEqual(Schema(literals={f_colors}), from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: + prefix bsl: + prefix bsa: - bsfs:Array rdfs:subClassOf bsfs:Literal . - bsfs:Feature rdfs:subClassOf bsfs:Array. + bsl:Array rdfs:subClassOf bsfs:Literal . + bsa:Feature rdfs:subClassOf bsl:Array. - bsfs:Colors rdfs:subClassOf bsfs:Feature ; + bsfs:Colors rdfs:subClassOf bsa:Feature ; bsfs:dimension "1234"^^xsd:integer . - bsfs:Colors rdfs:subClassOf bsfs:Feature ; + bsfs:Colors rdfs:subClassOf bsa:Feature ; bsfs:dimension "1234"^^xsd:integer ; # non-conflicting repetition - bsfs:dtype bsfs:f32 . + bsfs:dtype . ''')) # cannot define the same feature from multiple parents self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: + prefix bsl: + prefix bsa: - bsfs:Array rdfs:subClassOf bsfs:Literal . - bsfs:Feature rdfs:subClassOf bsfs:Array. - bsfs:ColorSpace rdfs:subClassOf bsfs:Feature . + bsl:Array rdfs:subClassOf bsfs:Literal . + bsa:Feature rdfs:subClassOf bsl:Array. + bsfs:ColorSpace rdfs:subClassOf bsa:Feature . - bsfs:Colors rdfs:subClassOf bsfs:Feature . + bsfs:Colors rdfs:subClassOf bsa:Feature . bsfs:Colors rdfs:subClassOf bsfs:ColorSpace . ''') @@ -652,16 +663,18 @@ class TestFromString(unittest.TestCase): self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: + prefix bsl: + prefix bsa: - bsfs:Array rdfs:subClassOf bsfs:Literal . - bsfs:Feature rdfs:subClassOf bsfs:Array. + bsl:Array rdfs:subClassOf bsfs:Literal . + bsa:Feature rdfs:subClassOf bsl:Array. - bsfs:Colors rdfs:subClassOf bsfs:Feature ; + bsfs:Colors rdfs:subClassOf bsa:Feature ; bsfs:dimension "1234"^^xsd:integer . - bsfs:Colors rdfs:subClassOf bsfs:Feature ; + bsfs:Colors rdfs:subClassOf bsa:Feature ; bsfs:dimension "4321"^^xsd:integer . # conflicting dimension ''') @@ -669,32 +682,36 @@ class TestFromString(unittest.TestCase): self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: + prefix bsl: + prefix bsa: - bsfs:Array rdfs:subClassOf bsfs:Literal . - bsfs:Feature rdfs:subClassOf bsfs:Array. + bsl:Array rdfs:subClassOf bsfs:Literal . + bsa:Feature rdfs:subClassOf bsl:Array. - bsfs:Colors rdfs:subClassOf bsfs:Feature ; - bsfs:dtype bsfs:f32 . + bsfs:Colors rdfs:subClassOf bsa:Feature ; + bsfs:dtype . - bsfs:Colors rdfs:subClassOf bsfs:Feature ; - bsfs:dtype bsfs:f16 . # conflicting dtype + bsfs:Colors rdfs:subClassOf bsa:Feature ; + bsfs:dtype . # conflicting dtype ''') # cannot assign multiple conflicting distance metrics to the same feature self.assertRaises(errors.ConsistencyError, from_string, ''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: + prefix bsl: + prefix bsa: - bsfs:Array rdfs:subClassOf bsfs:Literal . - bsfs:Feature rdfs:subClassOf bsfs:Array. + bsl:Array rdfs:subClassOf bsfs:Literal . + bsa:Feature rdfs:subClassOf bsl:Array. - bsfs:Colors rdfs:subClassOf bsfs:Feature ; + bsfs:Colors rdfs:subClassOf bsa:Feature ; bsfs:distance bsfs:euclidean . - bsfs:Colors rdfs:subClassOf bsfs:Feature ; + bsfs:Colors rdfs:subClassOf bsa:Feature ; bsfs:distance bsfs:cosine . # conflicting distance ''') @@ -702,26 +719,30 @@ class TestFromString(unittest.TestCase): self.assertDictEqual(from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: + prefix bsl: + prefix bsa: - bsfs:Array rdfs:subClassOf bsfs:Literal . - bsfs:Feature rdfs:subClassOf bsfs:Array. + bsl:Array rdfs:subClassOf bsfs:Literal . + bsa:Feature rdfs:subClassOf bsl:Array. - bsfs:Colors rdfs:subClassOf bsfs:Feature ; + bsfs:Colors rdfs:subClassOf bsa:Feature ; bsfs:dimension "1234"^^xsd:integer . ''').literal(ns.bsfs.Colors).annotations, {}) self.assertDictEqual(from_string(''' prefix rdfs: prefix xsd: - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: + prefix bsl: + prefix bsa: - bsfs:Array rdfs:subClassOf bsfs:Literal . - bsfs:Feature rdfs:subClassOf bsfs:Array. + bsl:Array rdfs:subClassOf bsfs:Literal . + bsa:Feature rdfs:subClassOf bsl:Array. - bsfs:Colors rdfs:subClassOf bsfs:Feature ; + bsfs:Colors rdfs:subClassOf bsa:Feature ; bsfs:dimension "1234"^^xsd:integer ; rdfs:label "hello world"^^xsd:string ; bsfs:foo "1234"^^xsd:integer . @@ -748,10 +769,10 @@ class TestFromString(unittest.TestCase): p_group = p_tag.child(ns.bse.group, domain=n_image, unique=True) p_comment = p_annotation.child(ns.bse.comment, range=l_string) # features - f_colors = types.ROOT_FEATURE.child(URI('http://bsfs.ai/schema/Feature/colors_spatial'), - dtype=ns.bsfs.f16, distance=ns.bsfs.euclidean) - f_colors1234 = f_colors.child(URI('http://bsfs.ai/schema/Feature/colors_spatial#1234'), dimension=1024) - f_colors4321 = f_colors.child(URI('http://bsfs.ai/schema/Feature/colors_spatial#4321'), dimension=2048) + f_colors = types.ROOT_FEATURE.child(URI('https://schema.bsfs.io/core/Feature/colors_spatial'), + dtype=ns.bsfs.dtype().f16, distance=ns.bsfs.euclidean) + f_colors1234 = f_colors.child(URI('https://schema.bsfs.io/core/Feature/colors_spatial#1234'), dimension=1024) + f_colors4321 = f_colors.child(URI('https://schema.bsfs.io/core/Feature/colors_spatial#4321'), dimension=2048) # schema ref = Schema( {p_annotation, p_tag, p_group, p_comment}, @@ -764,8 +785,10 @@ class TestFromString(unittest.TestCase): prefix xsd: # bsfs prefixes - prefix bsfs: - prefix bse: + prefix bsfs: + prefix bse: + prefix bsl: + prefix bsa: # nodes bsfs:Entity rdfs:subClassOf bsfs:Node ; @@ -777,10 +800,10 @@ class TestFromString(unittest.TestCase): # literals xsd:string rdfs:subClassOf bsfs:Literal ; rdfs:label "A sequence of characters"^^xsd:string . - bsfs:Array rdfs:subClassOf bsfs:Literal . - bsfs:Feature rdfs:subClassOf bsfs:Array. - bsfs:Number rdfs:subClassOf bsfs:Literal . - xsd:integer rdfs:subClassOf bsfs:Number . + bsl:Array rdfs:subClassOf bsfs:Literal . + bsa:Feature rdfs:subClassOf bsl:Array. + bsl:Number rdfs:subClassOf bsfs:Literal . + xsd:integer rdfs:subClassOf bsl:Number . xsd:boolean rdfs:subClassOf bsfs:Literal . @@ -789,19 +812,19 @@ class TestFromString(unittest.TestCase): rdfs:label "node annotation"^^xsd:string . # feature instances - rdfs:subClassOf bsfs:Feature ; - bsfs:dtype bsfs:f16 ; + rdfs:subClassOf bsa:Feature ; + bsfs:dtype ; bsfs:distance bsfs:euclidean ; # annotations rdfs:label "ColorsSpatial instances. Dimension depends on instance."^^xsd:string ; bsfs:first_arg "1234"^^xsd:integer ; bsfs:second_arg "hello world"^^xsd:string . - rdfs:subClassOf ; + rdfs:subClassOf ; bsfs:dimension "1024"^^xsd:integer ; rdfs:label "Main colors spatial instance"^^xsd:string . - rdfs:subClassOf ; + rdfs:subClassOf ; bsfs:dimension "2048"^^xsd:integer . # predicate instances @@ -829,19 +852,19 @@ class TestFromString(unittest.TestCase): self.assertDictEqual(gen.node(ns.bsfs.Tag).annotations, {ns.rdfs.label: 'Tag'}) self.assertDictEqual(gen.literal(ns.xsd.string).annotations, {ns.rdfs.label: 'A sequence of characters'}) self.assertDictEqual(gen.predicate(ns.bsfs.Annotation).annotations, {ns.rdfs.label: 'node annotation'}) - self.assertDictEqual(gen.literal(URI('http://bsfs.ai/schema/Feature/colors_spatial')).annotations, { + self.assertDictEqual(gen.literal(URI('https://schema.bsfs.io/core/Feature/colors_spatial')).annotations, { ns.rdfs.label: 'ColorsSpatial instances. Dimension depends on instance.', ns.bsfs.first_arg: 1234, ns.bsfs.second_arg: 'hello world', }) - self.assertDictEqual(gen.literal(URI('http://bsfs.ai/schema/Feature/colors_spatial#1234')).annotations, { + self.assertDictEqual(gen.literal(URI('https://schema.bsfs.io/core/Feature/colors_spatial#1234')).annotations, { ns.rdfs.label: 'Main colors spatial instance'}) self.assertDictEqual(gen.predicate(ns.bse.tag).annotations, {ns.rdfs.label: 'connect entity to a tag'}) # blank nodes result in an error self.assertRaises(errors.BackendError, from_string, ''' prefix rdfs: - prefix bsfs: + prefix bsfs: bsfs:Entity rdfs:subClassOf bsfs:Node ; bsfs:foo _:bar . ''') @@ -976,29 +999,29 @@ class TestToString(unittest.TestCase): def test_feature(self): # root features - f_colors = types.ROOT_FEATURE.child(URI('http://bsfs.ai/schema/Feature/colors'), + f_colors = types.ROOT_FEATURE.child(URI('https://schema.bsfs.io/core/Feature/colors'), distance=ns.bsfs.cosine) # derived features - f_colors1234 = f_colors.child(URI('http://bsfs.ai/schema/Feature/colors#1234'), + f_colors1234 = f_colors.child(URI('https://schema.bsfs.io/core/Feature/colors#1234'), dimension=1024) # inherits dtype, distance - f_colors4321 = f_colors.child(URI('http://bsfs.ai/schema/Feature/colors#4321'), + f_colors4321 = f_colors.child(URI('https://schema.bsfs.io/core/Feature/colors#4321'), dimension=2048, distance=ns.bsfs.euclidean) # inherits dtype # create schema schema = Schema(literals={f_colors, f_colors1234, f_colors4321}) schema_str = to_string(schema) # all symbols are serialized - self.assertIn('bsfs:Array', schema_str) - self.assertIn('[^\.]*bsfs:dimension[^\.]', schema_str)) - self.assertIsNone(re.search(r'[^\.]*bsfs:dtype[^\.]', schema_str)) - self.assertIsNone(re.search(r'[^\.]*bsfs:distance[^\.]', schema_str)) - self.assertIsNotNone(re.search(r'[^\.]*bsfs:dimension[^\.]', schema_str)) - self.assertIsNotNone(re.search(r'[^\.]*bsfs:distance[^\.]', schema_str)) - self.assertIsNone(re.search(r'[^\.]*bsfs:dtype[^\.]', schema_str)) + self.assertIsNotNone(re.search(r'.*[^\.]*bsfs:dimension[^\.]', schema_str)) + self.assertIsNone(re.search(r'.*[^\.]*bsfs:dtype[^\.]', schema_str)) + self.assertIsNone(re.search(r'.*[^\.]*bsfs:distance[^\.]', schema_str)) + self.assertIsNotNone(re.search(r'.*[^\.]*bsfs:dimension[^\.]', schema_str)) + self.assertIsNotNone(re.search(r'.*[^\.]*bsfs:distance[^\.]', schema_str)) + self.assertIsNone(re.search(r'.*[^\.]*bsfs:dtype[^\.]', schema_str)) # unserialize yields the original schema self.assertEqual(schema, from_string(schema_str)) @@ -1009,12 +1032,12 @@ class TestToString(unittest.TestCase): ns.bsfs.foo: 1234, ns.bsfs.bar: False, } - f_colors = types.ROOT_FEATURE.child(URI('http://bsfs.ai/schema/Feature/colors'), - dtype=ns.bsfs.f16, distance=ns.bsfs.euclidean, + f_colors = types.ROOT_FEATURE.child(URI('https://schema.bsfs.io/core/Feature/colors'), + dtype=ns.bsfs.dtype().f16, distance=ns.bsfs.euclidean, **annotations) self.assertDictEqual( annotations, - from_string(to_string(Schema(literals={f_colors}))).literal(URI('http://bsfs.ai/schema/Feature/colors')).annotations) + from_string(to_string(Schema(literals={f_colors}))).literal(URI('https://schema.bsfs.io/core/Feature/colors')).annotations) ## main ## diff --git a/test/schema/test_types.py b/test/schema/test_types.py index f87d857..9bfa8c5 100644 --- a/test/schema/test_types.py +++ b/test/schema/test_types.py @@ -14,6 +14,8 @@ from bsfs.schema.types import _Type, Vertex, Node, Literal, Predicate, Feature ## code ## +ns.bse = ns.bsfs.Entity() + class TestType(unittest.TestCase): def test_parents(self): -- cgit v1.2.3