diff options
author | Matthias Baumgartner <dev@igsor.net> | 2023-01-15 20:57:42 +0100 |
---|---|---|
committer | Matthias Baumgartner <dev@igsor.net> | 2023-01-15 20:57:42 +0100 |
commit | ccaee71e2b6135d3b324fe551c8652940b67aab3 (patch) | |
tree | b480189eccac8699b8c75763db7b38e838f38055 /test/schema | |
parent | 60257ed3c2aa6ea2891f362a691bde9d7ef17831 (diff) | |
download | bsfs-ccaee71e2b6135d3b324fe551c8652940b67aab3.tar.gz bsfs-ccaee71e2b6135d3b324fe551c8652940b67aab3.tar.bz2 bsfs-ccaee71e2b6135d3b324fe551c8652940b67aab3.zip |
Feature as Literal instead of Predicate subtype
Diffstat (limited to 'test/schema')
-rw-r--r-- | test/schema/test_schema.py | 34 | ||||
-rw-r--r-- | test/schema/test_serialize.py | 308 | ||||
-rw-r--r-- | test/schema/test_types.py | 52 |
3 files changed, 107 insertions, 287 deletions
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: <http://www.w3.org/2000/01/rdf-schema#> - prefix xsd: <http://www.w3.org/2001/XMLSchema#> - prefix bsfs: <http://bsfs.ai/schema/> - prefix bse: <http://bsfs.ai/schema/Entity#> - - 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: <http://www.w3.org/2000/01/rdf-schema#> - prefix xsd: <http://www.w3.org/2001/XMLSchema#> - prefix bsfs: <http://bsfs.ai/schema/> - prefix bse: <http://bsfs.ai/schema/Entity#> - - 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: <http://www.w3.org/2000/01/rdf-schema#> - prefix xsd: <http://www.w3.org/2001/XMLSchema#> - prefix bsfs: <http://bsfs.ai/schema/> - prefix bse: <http://bsfs.ai/schema/Entity#> - - 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: <http://www.w3.org/2000/01/rdf-schema#> prefix xsd: <http://www.w3.org/2001/XMLSchema#> prefix bsfs: <http://bsfs.ai/schema/> prefix bse: <http://bsfs.ai/schema/Entity#> - 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: <http://www.w3.org/2000/01/rdf-schema#> - prefix xsd: <http://www.w3.org/2001/XMLSchema#> - prefix bsfs: <http://bsfs.ai/schema/> - prefix bse: <http://bsfs.ai/schema/Entity#> - - 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: <http://www.w3.org/2000/01/rdf-schema#> - prefix xsd: <http://www.w3.org/2001/XMLSchema#> - prefix bsfs: <http://bsfs.ai/schema/> - prefix bse: <http://bsfs.ai/schema/Entity#> - - 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: <http://www.w3.org/2000/01/rdf-schema#> prefix xsd: <http://www.w3.org/2001/XMLSchema#> prefix bsfs: <http://bsfs.ai/schema/> prefix bse: <http://bsfs.ai/schema/Entity#> - 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: <http://www.w3.org/2000/01/rdf-schema#> prefix xsd: <http://www.w3.org/2001/XMLSchema#> prefix bsfs: <http://bsfs.ai/schema/> prefix bse: <http://bsfs.ai/schema/Entity#> - 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: <http://bsfs.ai/schema/> prefix bse: <http://bsfs.ai/schema/Entity#> - 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: <http://www.w3.org/2000/01/rdf-schema#> - prefix xsd: <http://www.w3.org/2001/XMLSchema#> - prefix bsfs: <http://bsfs.ai/schema/> - prefix bse: <http://bsfs.ai/schema/Entity#> - - 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: <http://www.w3.org/2000/01/rdf-schema#> - prefix xsd: <http://www.w3.org/2001/XMLSchema#> - prefix bsfs: <http://bsfs.ai/schema/> - prefix bse: <http://bsfs.ai/schema/Entity#> - - 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: <http://www.w3.org/2000/01/rdf-schema#> - prefix xsd: <http://www.w3.org/2001/XMLSchema#> - prefix bsfs: <http://bsfs.ai/schema/> - prefix bse: <http://bsfs.ai/schema/Entity#> - - 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: <http://www.w3.org/2000/01/rdf-schema#> @@ -812,15 +660,15 @@ class TestFromString(unittest.TestCase): prefix bsfs: <http://bsfs.ai/schema/> prefix bse: <http://bsfs.ai/schema/Entity#> - 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: <http://bsfs.ai/schema/> prefix bse: <http://bsfs.ai/schema/Entity#> - 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: <http://bsfs.ai/schema/> prefix bse: <http://bsfs.ai/schema/Entity#> - 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: <http://bsfs.ai/schema/> prefix bse: <http://bsfs.ai/schema/Entity#> - 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: <http://www.w3.org/2000/01/rdf-schema#> prefix xsd: <http://www.w3.org/2001/XMLSchema#> prefix bsfs: <http://bsfs.ai/schema/> prefix bse: <http://bsfs.ai/schema/Entity#> - 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 <http://bsfs.ai/schema/Feature/colors_spatial> 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: <http://www.w3.org/2000/01/rdf-schema#> + prefix bsfs: <http://bsfs.ai/schema/> + 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('<http://bsfs.ai/schema/Feature/colors', schema_str) self.assertIn('<http://bsfs.ai/schema/Feature/colors#1234', schema_str) self.assertIn('<http://bsfs.ai/schema/Feature/colors#4321', schema_str) # inherited properties are not serialized - self.assertIsNotNone(re.search(r'<http://bsfs\.ai/schema/Feature/colors#1234>[^\.]*rdfs:domain[^\.]', schema_str)) self.assertIsNotNone(re.search(r'<http://bsfs\.ai/schema/Feature/colors#1234>[^\.]*bsfs:dimension[^\.]', schema_str)) - self.assertIsNone(re.search(r'<http://bsfs\.ai/schema/Feature/colors#1234>[^\.]*rdfs:range[^\.]', schema_str)) self.assertIsNone(re.search(r'<http://bsfs\.ai/schema/Feature/colors#1234>[^\.]*bsfs:dtype[^\.]', schema_str)) self.assertIsNone(re.search(r'<http://bsfs\.ai/schema/Feature/colors#1234>[^\.]*bsfs:distance[^\.]', schema_str)) self.assertIsNotNone(re.search(r'<http://bsfs\.ai/schema/Feature/colors#4321>[^\.]*bsfs:dimension[^\.]', schema_str)) self.assertIsNotNone(re.search(r'<http://bsfs\.ai/schema/Feature/colors#4321>[^\.]*bsfs:distance[^\.]', schema_str)) - self.assertIsNone(re.search(r'<http://bsfs\.ai/schema/Feature/colors#4321>[^\.]*rdfs:domain[^\.]', schema_str)) - self.assertIsNone(re.search(r'<http://bsfs\.ai/schema/Feature/colors#4321>[^\.]*rdfs:range[^\.]', schema_str)) self.assertIsNone(re.search(r'<http://bsfs\.ai/schema/Feature/colors#4321>[^\.]*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 ## |