shacl2code 0.0.11__tar.gz → 0.0.12__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {shacl2code-0.0.11 → shacl2code-0.0.12}/PKG-INFO +1 -1
- {shacl2code-0.0.11 → shacl2code-0.0.12}/src/shacl2code/lang/templates/jsonschema.j2 +18 -2
- {shacl2code-0.0.11 → shacl2code-0.0.12}/src/shacl2code/lang/templates/python.j2 +47 -2
- shacl2code-0.0.12/src/shacl2code/version.py +1 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/data/model/test-context.json +5 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/data/model/test.ttl +25 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/data/python/roundtrip.json +12 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/expect/jsonschema/test-context.json +93 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/expect/jsonschema/test.json +88 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/expect/python/test-context.py +71 -2
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/expect/python/test.py +62 -2
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/expect/raw/test-context.txt +4 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/expect/raw/test.txt +3 -1
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/test_jsonschema.py +36 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/test_python.py +46 -0
- shacl2code-0.0.11/src/shacl2code/version.py +0 -1
- {shacl2code-0.0.11 → shacl2code-0.0.12}/.flake8 +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/.github/workflows/coverage-generate.yaml +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/.github/workflows/coverage-report.yaml +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/.github/workflows/publish.yaml +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/.github/workflows/test.yaml +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/.gitignore +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/LICENSE +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/README.md +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/pyproject.toml +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/src/shacl2code/__init__.py +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/src/shacl2code/__main__.py +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/src/shacl2code/context.py +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/src/shacl2code/lang/__init__.py +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/src/shacl2code/lang/common.py +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/src/shacl2code/lang/jinja.py +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/src/shacl2code/lang/jsonschema.py +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/src/shacl2code/lang/lang.py +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/src/shacl2code/lang/python.py +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/src/shacl2code/main.py +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/src/shacl2code/model.py +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/src/shacl2code/urlcontext.py +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/conftest.py +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/data/abort.j2 +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/data/bad-id.j2 +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/data/bad-node-kind.ttl +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/data/bad-pattern-class.ttl +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/data/bad-pattern-integer.ttl +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/data/bad-reference.jsonld +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/data/context-url.j2 +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/data/context.j2 +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/data/missing-range.ttl +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/data/python/bad-object-type-inline.json +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/data/python/bad-object-type-ref-after.json +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/data/python/bad-object-type-ref-before.json +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/data/python/links.json +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/data/raw.j2 +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/expect/make_expect.py +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/test_cli.py +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/test_common_jinja.py +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/test_common_prefix.py +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/test_context.py +0 -0
- {shacl2code-0.0.11 → shacl2code-0.0.12}/tests/test_model_source.py +0 -0
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
{#- Classes are divided into 2 parts. The properties are separated into a separate object #}
|
|
60
60
|
{#- so that a object can references the properties of its parent without needing the const #}
|
|
61
61
|
{#- @type tag #}
|
|
62
|
-
{%- if not class.is_abstract %}
|
|
62
|
+
{%- if not class.is_abstract or class.is_extensible %}
|
|
63
63
|
"{{ varname(*class.clsname) }}": {
|
|
64
64
|
"allOf": [
|
|
65
65
|
{
|
|
@@ -70,12 +70,20 @@
|
|
|
70
70
|
"properties": {
|
|
71
71
|
"{{ class.id_property or "@id" }}": { "$ref": "#/$defs/{{ class.node_kind.split("#")[-1] }}" },
|
|
72
72
|
"{{ context.compact("@type") }}": {
|
|
73
|
+
{#- Abstract Extensible classes are weird; any type _except_ the specific class type is allowed #}
|
|
74
|
+
{%- if class.is_abstract and class.is_extensible %}
|
|
75
|
+
"allOf": [
|
|
76
|
+
{ "$ref": "#/$defs/IRI" },
|
|
77
|
+
{ "not": { "const": "{{ context.compact_vocab(class._id) }}" } }
|
|
78
|
+
]
|
|
79
|
+
{%- else %}
|
|
73
80
|
"oneOf": [
|
|
74
81
|
{%- if class.is_extensible %}
|
|
75
82
|
{ "$ref": "#/$defs/IRI" },
|
|
76
83
|
{%- endif %}
|
|
77
84
|
{ "const": "{{ context.compact_vocab(class._id) }}" }
|
|
78
85
|
]
|
|
86
|
+
{%- endif %}
|
|
79
87
|
}
|
|
80
88
|
}{%- if class.node_kind == SH.IRI %},
|
|
81
89
|
"required": ["{{ class.id_property or "@id" }}"]
|
|
@@ -86,9 +94,14 @@
|
|
|
86
94
|
},
|
|
87
95
|
{%- endif %}
|
|
88
96
|
"{{ varname(*class.clsname) }}_derived": {
|
|
89
|
-
{%- set ns = namespace(
|
|
97
|
+
{%- set ns = namespace(json_refs=[], named_individuals=[]) %}
|
|
90
98
|
{%- for d in get_all_derived(class) + [class._id] %}
|
|
91
99
|
{%- set ns.json_refs = ns.json_refs + ["#/$defs/" + varname(*classes.get(d).clsname)] %}
|
|
100
|
+
{%- for n in classes.get(d).named_individuals %}
|
|
101
|
+
{%- if context.compact(n._id) != n._id %}
|
|
102
|
+
{%- set ns.named_individuals = ns.named_individuals + [context.compact(n._id)] %}
|
|
103
|
+
{%- endif %}
|
|
104
|
+
{%- endfor %}
|
|
92
105
|
{%- endfor %}
|
|
93
106
|
"anyOf": [
|
|
94
107
|
{%- if ns.json_refs %}
|
|
@@ -104,6 +117,9 @@
|
|
|
104
117
|
]
|
|
105
118
|
},
|
|
106
119
|
{%- endif %}
|
|
120
|
+
{%- for n in ns.named_individuals %}
|
|
121
|
+
{ "const": "{{ n }}" },
|
|
122
|
+
{%- endfor %}
|
|
107
123
|
{ "$ref": "#/$defs/BlankNodeOrIRI" }
|
|
108
124
|
]
|
|
109
125
|
},
|
|
@@ -264,6 +264,7 @@ class ObjectProp(Property):
|
|
|
264
264
|
raise ValueError("Object cannot be None")
|
|
265
265
|
|
|
266
266
|
if isinstance(value, str):
|
|
267
|
+
value = _NI_ENCODE_CONTEXT.get(value, value)
|
|
267
268
|
encoder.write_iri(value)
|
|
268
269
|
return
|
|
269
270
|
|
|
@@ -274,6 +275,8 @@ class ObjectProp(Property):
|
|
|
274
275
|
if iri is None:
|
|
275
276
|
return self.cls.decode(decoder, objectset=objectset)
|
|
276
277
|
|
|
278
|
+
iri = _NI_DECODE_CONTEXT.get(iri, iri)
|
|
279
|
+
|
|
277
280
|
if objectset is None:
|
|
278
281
|
return iri
|
|
279
282
|
|
|
@@ -506,6 +509,8 @@ def register(type_iri, *, compact_type=None, abstract=False):
|
|
|
506
509
|
SHACLObject.CLASSES[key] = c
|
|
507
510
|
|
|
508
511
|
def decorator(c):
|
|
512
|
+
global NAMED_INDIVIDUALS
|
|
513
|
+
|
|
509
514
|
assert issubclass(
|
|
510
515
|
c, SHACLObject
|
|
511
516
|
), f"{c.__name__} is not derived from SHACLObject"
|
|
@@ -518,6 +523,8 @@ def register(type_iri, *, compact_type=None, abstract=False):
|
|
|
518
523
|
if compact_type:
|
|
519
524
|
add_class(compact_type, c)
|
|
520
525
|
|
|
526
|
+
NAMED_INDIVIDUALS |= set(c.NAMED_INDIVIDUALS.values())
|
|
527
|
+
|
|
521
528
|
# Registration is deferred until the first instance of class is created
|
|
522
529
|
# so that it has access to any other defined class
|
|
523
530
|
c._NEEDS_REG = True
|
|
@@ -527,6 +534,7 @@ def register(type_iri, *, compact_type=None, abstract=False):
|
|
|
527
534
|
|
|
528
535
|
|
|
529
536
|
register_lock = threading.Lock()
|
|
537
|
+
NAMED_INDIVIDUALS = set()
|
|
530
538
|
|
|
531
539
|
|
|
532
540
|
@functools.total_ordering
|
|
@@ -537,7 +545,7 @@ class SHACLObject(object):
|
|
|
537
545
|
IS_ABSTRACT = True
|
|
538
546
|
|
|
539
547
|
def __init__(self, **kwargs):
|
|
540
|
-
if self.
|
|
548
|
+
if self._is_abstract():
|
|
541
549
|
raise NotImplementedError(
|
|
542
550
|
f"{self.__class__.__name__} is abstract and cannot be implemented"
|
|
543
551
|
)
|
|
@@ -559,6 +567,9 @@ class SHACLObject(object):
|
|
|
559
567
|
for k, v in kwargs.items():
|
|
560
568
|
setattr(self, k, v)
|
|
561
569
|
|
|
570
|
+
def _is_abstract(self):
|
|
571
|
+
return self.__class__.IS_ABSTRACT
|
|
572
|
+
|
|
562
573
|
@classmethod
|
|
563
574
|
def _register_props(cls):
|
|
564
575
|
cls._add_property("_id", StringProp(), iri="@id")
|
|
@@ -875,11 +886,20 @@ class SHACLExtensibleObject(object):
|
|
|
875
886
|
CLOSED = False
|
|
876
887
|
|
|
877
888
|
def __init__(self, typ=None, **kwargs):
|
|
878
|
-
super().__init__(**kwargs)
|
|
879
889
|
if typ:
|
|
880
890
|
self.__dict__["_obj_TYPE"] = (typ, None)
|
|
881
891
|
else:
|
|
882
892
|
self.__dict__["_obj_TYPE"] = (self._OBJ_TYPE, self._OBJ_COMPACT_TYPE)
|
|
893
|
+
super().__init__(**kwargs)
|
|
894
|
+
|
|
895
|
+
def _is_abstract(self):
|
|
896
|
+
# Unknown classes are assumed to not be abstract so that they can be
|
|
897
|
+
# deserialized
|
|
898
|
+
typ = self.__dict__["_obj_TYPE"][0]
|
|
899
|
+
if typ in self.__class__.CLASSES:
|
|
900
|
+
return self.__class__.CLASSES[typ].IS_ABSTRACT
|
|
901
|
+
|
|
902
|
+
return False
|
|
883
903
|
|
|
884
904
|
@classmethod
|
|
885
905
|
def _make_object(cls, typ):
|
|
@@ -1079,6 +1099,8 @@ class SHACLObjectSet(object):
|
|
|
1079
1099
|
return self._link()
|
|
1080
1100
|
|
|
1081
1101
|
def _link(self):
|
|
1102
|
+
global NAMED_INDIVIDUALS
|
|
1103
|
+
|
|
1082
1104
|
self.missing_ids = set()
|
|
1083
1105
|
visited = set()
|
|
1084
1106
|
|
|
@@ -1101,6 +1123,9 @@ class SHACLObjectSet(object):
|
|
|
1101
1123
|
obj_by_id[_id] = obj
|
|
1102
1124
|
self.obj_by_id = obj_by_id
|
|
1103
1125
|
|
|
1126
|
+
# Named individuals aren't considered missing
|
|
1127
|
+
self.missing_ids -= NAMED_INDIVIDUALS
|
|
1128
|
+
|
|
1104
1129
|
return self.missing_ids
|
|
1105
1130
|
|
|
1106
1131
|
def find_by_id(self, _id, default=None):
|
|
@@ -1938,6 +1963,26 @@ CONTEXT_URLS = [
|
|
|
1938
1963
|
{%- endfor %}
|
|
1939
1964
|
]
|
|
1940
1965
|
|
|
1966
|
+
_NI_ENCODE_CONTEXT = {
|
|
1967
|
+
{%- for class in classes %}
|
|
1968
|
+
{%- for member in class.named_individuals %}
|
|
1969
|
+
{%- if context.compact(member._id) != member._id %}
|
|
1970
|
+
"{{ member._id }}": "{{ context.compact(member._id) }}",
|
|
1971
|
+
{%- endif %}
|
|
1972
|
+
{%- endfor %}
|
|
1973
|
+
{%- endfor %}
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1976
|
+
_NI_DECODE_CONTEXT = {
|
|
1977
|
+
{%- for class in classes %}
|
|
1978
|
+
{%- for member in class.named_individuals %}
|
|
1979
|
+
{%- if context.compact(member._id) != member._id %}
|
|
1980
|
+
"{{ context.compact(member._id) }}": "{{ member._id }}",
|
|
1981
|
+
{%- endif %}
|
|
1982
|
+
{%- endfor %}
|
|
1983
|
+
{%- endfor %}
|
|
1984
|
+
}
|
|
1985
|
+
|
|
1941
1986
|
|
|
1942
1987
|
# CLASSES
|
|
1943
1988
|
{%- for class in classes %}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VERSION = "0.0.12"
|
|
@@ -87,6 +87,7 @@
|
|
|
87
87
|
"@id": "test:test-class/enum-prop-no-class",
|
|
88
88
|
"@type": "@id"
|
|
89
89
|
},
|
|
90
|
+
"test-class/named": "test:test-class/named",
|
|
90
91
|
"test-class/regex": {
|
|
91
92
|
"@id": "test:test-class/regex",
|
|
92
93
|
"@type": "xsd:string"
|
|
@@ -130,6 +131,10 @@
|
|
|
130
131
|
"extensible-class/required": {
|
|
131
132
|
"@id": "test:extensible-class/required",
|
|
132
133
|
"@type": "xsd:string"
|
|
134
|
+
},
|
|
135
|
+
"uses-extensible-abstract-class/prop": {
|
|
136
|
+
"@id": "test:uses-extensible-abstract-class/prop",
|
|
137
|
+
"@type": "@id"
|
|
133
138
|
}
|
|
134
139
|
}
|
|
135
140
|
}
|
|
@@ -166,6 +166,10 @@
|
|
|
166
166
|
]
|
|
167
167
|
.
|
|
168
168
|
|
|
169
|
+
<test-class/named> a owl:NamedIndividual, <test-class> ;
|
|
170
|
+
rdfs:label "A named individual of the test class"
|
|
171
|
+
.
|
|
172
|
+
|
|
169
173
|
<test-class-required> a sh:NodeShape, owl:Class ;
|
|
170
174
|
rdfs:subClassOf <test-class> ;
|
|
171
175
|
sh:property [
|
|
@@ -510,3 +514,24 @@
|
|
|
510
514
|
rdfs:comment "A required abstract class property" ;
|
|
511
515
|
rdfs:range <abstract-class>
|
|
512
516
|
.
|
|
517
|
+
|
|
518
|
+
<extensible-abstract-class> a rdf:Class, sh:NodeShape, owl:Class ;
|
|
519
|
+
sh-to-code:isExtensible true ;
|
|
520
|
+
sh-to-code:isAbstract true ;
|
|
521
|
+
rdfs:comment "An extensible abstract class"
|
|
522
|
+
.
|
|
523
|
+
|
|
524
|
+
<uses-extensible-abstract-class> a rdf:Class, sh:NodeShape, owl:Class ;
|
|
525
|
+
rdfs:comment "A class that uses an abstract extensible class" ;
|
|
526
|
+
sh:property [
|
|
527
|
+
sh:class <extensible-abstract-class> ;
|
|
528
|
+
sh:path <uses-extensible-abstract-class/prop> ;
|
|
529
|
+
sh:minCount 1 ;
|
|
530
|
+
sh:maxCount 1
|
|
531
|
+
]
|
|
532
|
+
.
|
|
533
|
+
|
|
534
|
+
<uses-extensible-abstract-class/prop> a rdf:Property ;
|
|
535
|
+
rdfs:comment "A property that references and abstract extensible class" ;
|
|
536
|
+
rdfs:range <extensible-abstract-class>
|
|
537
|
+
.
|
|
@@ -76,10 +76,22 @@
|
|
|
76
76
|
"@id": "http://serialize.example.com/test-derived",
|
|
77
77
|
"@type": "test-derived-class"
|
|
78
78
|
},
|
|
79
|
+
{
|
|
80
|
+
"@type": "test-class",
|
|
81
|
+
"@id": "http://serialize.example.com/test-named-individual-reference",
|
|
82
|
+
"test-class/class-prop": "test-class/named"
|
|
83
|
+
},
|
|
79
84
|
{
|
|
80
85
|
"@type": "test-class",
|
|
81
86
|
"@id": "http://serialize.example.com/test-special-chars",
|
|
82
87
|
"test-class/string-scalar-prop": "special chars \"\n\r:{}[]"
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"@type": "uses-extensible-abstract-class",
|
|
91
|
+
"@id": "http://serialize.example.com/test-uses-extensible-abstract",
|
|
92
|
+
"uses-extensible-abstract-class/prop": {
|
|
93
|
+
"@type": " http://serialize.example.com/custom-extensible"
|
|
94
|
+
}
|
|
83
95
|
}
|
|
84
96
|
]
|
|
85
97
|
}
|
|
@@ -178,6 +178,9 @@
|
|
|
178
178
|
{ "$ref": "#/$defs/enumType" }
|
|
179
179
|
]
|
|
180
180
|
},
|
|
181
|
+
{ "const": "enumType/foo" },
|
|
182
|
+
{ "const": "enumType/bar" },
|
|
183
|
+
{ "const": "enumType/nolabel" },
|
|
181
184
|
{ "$ref": "#/$defs/BlankNodeOrIRI" }
|
|
182
185
|
]
|
|
183
186
|
},
|
|
@@ -191,6 +194,45 @@
|
|
|
191
194
|
}
|
|
192
195
|
]
|
|
193
196
|
},
|
|
197
|
+
"extensibleabstractclass": {
|
|
198
|
+
"allOf": [
|
|
199
|
+
{
|
|
200
|
+
"type": "object",
|
|
201
|
+
"unevaluatedProperties": true,
|
|
202
|
+
"properties": {
|
|
203
|
+
"@id": { "$ref": "#/$defs/BlankNodeOrIRI" },
|
|
204
|
+
"@type": {
|
|
205
|
+
"allOf": [
|
|
206
|
+
{ "$ref": "#/$defs/IRI" },
|
|
207
|
+
{ "not": { "const": "extensible-abstract-class" } }
|
|
208
|
+
]
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
{ "$ref": "#/$defs/extensibleabstractclass_props" }
|
|
213
|
+
]
|
|
214
|
+
},
|
|
215
|
+
"extensibleabstractclass_derived": {
|
|
216
|
+
"anyOf": [
|
|
217
|
+
{
|
|
218
|
+
"type": "object",
|
|
219
|
+
"anyOf": [
|
|
220
|
+
{ "$ref": "#/$defs/extensibleabstractclass" }
|
|
221
|
+
]
|
|
222
|
+
},
|
|
223
|
+
{ "$ref": "#/$defs/BlankNodeOrIRI" }
|
|
224
|
+
]
|
|
225
|
+
},
|
|
226
|
+
"extensibleabstractclass_props": {
|
|
227
|
+
"allOf": [
|
|
228
|
+
{ "$ref": "#/$defs/SHACLClass" },
|
|
229
|
+
{
|
|
230
|
+
"type": "object",
|
|
231
|
+
"properties": {
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
]
|
|
235
|
+
},
|
|
194
236
|
"idpropclass": {
|
|
195
237
|
"allOf": [
|
|
196
238
|
{
|
|
@@ -564,6 +606,7 @@
|
|
|
564
606
|
{ "$ref": "#/$defs/parentclass" }
|
|
565
607
|
]
|
|
566
608
|
},
|
|
609
|
+
{ "const": "test-class/named" },
|
|
567
610
|
{ "$ref": "#/$defs/BlankNodeOrIRI" }
|
|
568
611
|
]
|
|
569
612
|
},
|
|
@@ -689,6 +732,7 @@
|
|
|
689
732
|
{ "$ref": "#/$defs/testclass" }
|
|
690
733
|
]
|
|
691
734
|
},
|
|
735
|
+
{ "const": "test-class/named" },
|
|
692
736
|
{ "$ref": "#/$defs/BlankNodeOrIRI" }
|
|
693
737
|
]
|
|
694
738
|
},
|
|
@@ -1065,6 +1109,53 @@
|
|
|
1065
1109
|
"prop_testderivedclass_testderivedclassstringprop": {
|
|
1066
1110
|
"type": "string"
|
|
1067
1111
|
},
|
|
1112
|
+
"usesextensibleabstractclass": {
|
|
1113
|
+
"allOf": [
|
|
1114
|
+
{
|
|
1115
|
+
"type": "object",
|
|
1116
|
+
"properties": {
|
|
1117
|
+
"@id": { "$ref": "#/$defs/BlankNodeOrIRI" },
|
|
1118
|
+
"@type": {
|
|
1119
|
+
"oneOf": [
|
|
1120
|
+
{ "const": "uses-extensible-abstract-class" }
|
|
1121
|
+
]
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
},
|
|
1125
|
+
{ "$ref": "#/$defs/usesextensibleabstractclass_props" }
|
|
1126
|
+
]
|
|
1127
|
+
},
|
|
1128
|
+
"usesextensibleabstractclass_derived": {
|
|
1129
|
+
"anyOf": [
|
|
1130
|
+
{
|
|
1131
|
+
"type": "object",
|
|
1132
|
+
"unevaluatedProperties": false,
|
|
1133
|
+
"anyOf": [
|
|
1134
|
+
{ "$ref": "#/$defs/usesextensibleabstractclass" }
|
|
1135
|
+
]
|
|
1136
|
+
},
|
|
1137
|
+
{ "$ref": "#/$defs/BlankNodeOrIRI" }
|
|
1138
|
+
]
|
|
1139
|
+
},
|
|
1140
|
+
"usesextensibleabstractclass_props": {
|
|
1141
|
+
"allOf": [
|
|
1142
|
+
{ "$ref": "#/$defs/SHACLClass" },
|
|
1143
|
+
{
|
|
1144
|
+
"type": "object",
|
|
1145
|
+
"properties": {
|
|
1146
|
+
"uses-extensible-abstract-class/prop": {
|
|
1147
|
+
"$ref": "#/$defs/prop_usesextensibleabstractclass_usesextensibleabstractclassprop"
|
|
1148
|
+
}
|
|
1149
|
+
},
|
|
1150
|
+
"required": [
|
|
1151
|
+
"uses-extensible-abstract-class/prop"
|
|
1152
|
+
]
|
|
1153
|
+
}
|
|
1154
|
+
]
|
|
1155
|
+
},
|
|
1156
|
+
"prop_usesextensibleabstractclass_usesextensibleabstractclassprop": {
|
|
1157
|
+
"$ref": "#/$defs/extensibleabstractclass_derived"
|
|
1158
|
+
},
|
|
1068
1159
|
"aaaderivedclass": {
|
|
1069
1160
|
"allOf": [
|
|
1070
1161
|
{
|
|
@@ -1238,6 +1329,7 @@
|
|
|
1238
1329
|
"test-class",
|
|
1239
1330
|
"test-class-required",
|
|
1240
1331
|
"test-derived-class",
|
|
1332
|
+
"uses-extensible-abstract-class",
|
|
1241
1333
|
"aaa-derived-class",
|
|
1242
1334
|
"derived-node-kind-iri",
|
|
1243
1335
|
"extensible-class"
|
|
@@ -1267,6 +1359,7 @@
|
|
|
1267
1359
|
{ "$ref": "#/$defs/testclass" },
|
|
1268
1360
|
{ "$ref": "#/$defs/testclassrequired" },
|
|
1269
1361
|
{ "$ref": "#/$defs/testderivedclass" },
|
|
1362
|
+
{ "$ref": "#/$defs/usesextensibleabstractclass" },
|
|
1270
1363
|
{ "$ref": "#/$defs/aaaderivedclass" },
|
|
1271
1364
|
{ "$ref": "#/$defs/derivednodekindiri" },
|
|
1272
1365
|
{ "$ref": "#/$defs/extensibleclass" }
|
|
@@ -187,6 +187,45 @@
|
|
|
187
187
|
}
|
|
188
188
|
]
|
|
189
189
|
},
|
|
190
|
+
"http_exampleorgextensibleabstractclass": {
|
|
191
|
+
"allOf": [
|
|
192
|
+
{
|
|
193
|
+
"type": "object",
|
|
194
|
+
"unevaluatedProperties": true,
|
|
195
|
+
"properties": {
|
|
196
|
+
"@id": { "$ref": "#/$defs/BlankNodeOrIRI" },
|
|
197
|
+
"@type": {
|
|
198
|
+
"allOf": [
|
|
199
|
+
{ "$ref": "#/$defs/IRI" },
|
|
200
|
+
{ "not": { "const": "http://example.org/extensible-abstract-class" } }
|
|
201
|
+
]
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
{ "$ref": "#/$defs/http_exampleorgextensibleabstractclass_props" }
|
|
206
|
+
]
|
|
207
|
+
},
|
|
208
|
+
"http_exampleorgextensibleabstractclass_derived": {
|
|
209
|
+
"anyOf": [
|
|
210
|
+
{
|
|
211
|
+
"type": "object",
|
|
212
|
+
"anyOf": [
|
|
213
|
+
{ "$ref": "#/$defs/http_exampleorgextensibleabstractclass" }
|
|
214
|
+
]
|
|
215
|
+
},
|
|
216
|
+
{ "$ref": "#/$defs/BlankNodeOrIRI" }
|
|
217
|
+
]
|
|
218
|
+
},
|
|
219
|
+
"http_exampleorgextensibleabstractclass_props": {
|
|
220
|
+
"allOf": [
|
|
221
|
+
{ "$ref": "#/$defs/SHACLClass" },
|
|
222
|
+
{
|
|
223
|
+
"type": "object",
|
|
224
|
+
"properties": {
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
]
|
|
228
|
+
},
|
|
190
229
|
"http_exampleorgidpropclass": {
|
|
191
230
|
"allOf": [
|
|
192
231
|
{
|
|
@@ -1061,6 +1100,53 @@
|
|
|
1061
1100
|
"prop_http_exampleorgtestderivedclass_stringprop": {
|
|
1062
1101
|
"type": "string"
|
|
1063
1102
|
},
|
|
1103
|
+
"http_exampleorgusesextensibleabstractclass": {
|
|
1104
|
+
"allOf": [
|
|
1105
|
+
{
|
|
1106
|
+
"type": "object",
|
|
1107
|
+
"properties": {
|
|
1108
|
+
"@id": { "$ref": "#/$defs/BlankNodeOrIRI" },
|
|
1109
|
+
"@type": {
|
|
1110
|
+
"oneOf": [
|
|
1111
|
+
{ "const": "http://example.org/uses-extensible-abstract-class" }
|
|
1112
|
+
]
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
},
|
|
1116
|
+
{ "$ref": "#/$defs/http_exampleorgusesextensibleabstractclass_props" }
|
|
1117
|
+
]
|
|
1118
|
+
},
|
|
1119
|
+
"http_exampleorgusesextensibleabstractclass_derived": {
|
|
1120
|
+
"anyOf": [
|
|
1121
|
+
{
|
|
1122
|
+
"type": "object",
|
|
1123
|
+
"unevaluatedProperties": false,
|
|
1124
|
+
"anyOf": [
|
|
1125
|
+
{ "$ref": "#/$defs/http_exampleorgusesextensibleabstractclass" }
|
|
1126
|
+
]
|
|
1127
|
+
},
|
|
1128
|
+
{ "$ref": "#/$defs/BlankNodeOrIRI" }
|
|
1129
|
+
]
|
|
1130
|
+
},
|
|
1131
|
+
"http_exampleorgusesextensibleabstractclass_props": {
|
|
1132
|
+
"allOf": [
|
|
1133
|
+
{ "$ref": "#/$defs/SHACLClass" },
|
|
1134
|
+
{
|
|
1135
|
+
"type": "object",
|
|
1136
|
+
"properties": {
|
|
1137
|
+
"http://example.org/uses-extensible-abstract-class/prop": {
|
|
1138
|
+
"$ref": "#/$defs/prop_http_exampleorgusesextensibleabstractclass_prop"
|
|
1139
|
+
}
|
|
1140
|
+
},
|
|
1141
|
+
"required": [
|
|
1142
|
+
"http://example.org/uses-extensible-abstract-class/prop"
|
|
1143
|
+
]
|
|
1144
|
+
}
|
|
1145
|
+
]
|
|
1146
|
+
},
|
|
1147
|
+
"prop_http_exampleorgusesextensibleabstractclass_prop": {
|
|
1148
|
+
"$ref": "#/$defs/http_exampleorgextensibleabstractclass_derived"
|
|
1149
|
+
},
|
|
1064
1150
|
"http_exampleorgaaaderivedclass": {
|
|
1065
1151
|
"allOf": [
|
|
1066
1152
|
{
|
|
@@ -1234,6 +1320,7 @@
|
|
|
1234
1320
|
"http://example.org/test-class",
|
|
1235
1321
|
"http://example.org/test-class-required",
|
|
1236
1322
|
"http://example.org/test-derived-class",
|
|
1323
|
+
"http://example.org/uses-extensible-abstract-class",
|
|
1237
1324
|
"http://example.org/aaa-derived-class",
|
|
1238
1325
|
"http://example.org/derived-node-kind-iri",
|
|
1239
1326
|
"http://example.org/extensible-class"
|
|
@@ -1263,6 +1350,7 @@
|
|
|
1263
1350
|
{ "$ref": "#/$defs/http_exampleorgtestclass" },
|
|
1264
1351
|
{ "$ref": "#/$defs/http_exampleorgtestclassrequired" },
|
|
1265
1352
|
{ "$ref": "#/$defs/http_exampleorgtestderivedclass" },
|
|
1353
|
+
{ "$ref": "#/$defs/http_exampleorgusesextensibleabstractclass" },
|
|
1266
1354
|
{ "$ref": "#/$defs/http_exampleorgaaaderivedclass" },
|
|
1267
1355
|
{ "$ref": "#/$defs/http_exampleorgderivednodekindiri" },
|
|
1268
1356
|
{ "$ref": "#/$defs/http_exampleorgextensibleclass" }
|
|
@@ -264,6 +264,7 @@ class ObjectProp(Property):
|
|
|
264
264
|
raise ValueError("Object cannot be None")
|
|
265
265
|
|
|
266
266
|
if isinstance(value, str):
|
|
267
|
+
value = _NI_ENCODE_CONTEXT.get(value, value)
|
|
267
268
|
encoder.write_iri(value)
|
|
268
269
|
return
|
|
269
270
|
|
|
@@ -274,6 +275,8 @@ class ObjectProp(Property):
|
|
|
274
275
|
if iri is None:
|
|
275
276
|
return self.cls.decode(decoder, objectset=objectset)
|
|
276
277
|
|
|
278
|
+
iri = _NI_DECODE_CONTEXT.get(iri, iri)
|
|
279
|
+
|
|
277
280
|
if objectset is None:
|
|
278
281
|
return iri
|
|
279
282
|
|
|
@@ -506,6 +509,8 @@ def register(type_iri, *, compact_type=None, abstract=False):
|
|
|
506
509
|
SHACLObject.CLASSES[key] = c
|
|
507
510
|
|
|
508
511
|
def decorator(c):
|
|
512
|
+
global NAMED_INDIVIDUALS
|
|
513
|
+
|
|
509
514
|
assert issubclass(
|
|
510
515
|
c, SHACLObject
|
|
511
516
|
), f"{c.__name__} is not derived from SHACLObject"
|
|
@@ -518,6 +523,8 @@ def register(type_iri, *, compact_type=None, abstract=False):
|
|
|
518
523
|
if compact_type:
|
|
519
524
|
add_class(compact_type, c)
|
|
520
525
|
|
|
526
|
+
NAMED_INDIVIDUALS |= set(c.NAMED_INDIVIDUALS.values())
|
|
527
|
+
|
|
521
528
|
# Registration is deferred until the first instance of class is created
|
|
522
529
|
# so that it has access to any other defined class
|
|
523
530
|
c._NEEDS_REG = True
|
|
@@ -527,6 +534,7 @@ def register(type_iri, *, compact_type=None, abstract=False):
|
|
|
527
534
|
|
|
528
535
|
|
|
529
536
|
register_lock = threading.Lock()
|
|
537
|
+
NAMED_INDIVIDUALS = set()
|
|
530
538
|
|
|
531
539
|
|
|
532
540
|
@functools.total_ordering
|
|
@@ -537,7 +545,7 @@ class SHACLObject(object):
|
|
|
537
545
|
IS_ABSTRACT = True
|
|
538
546
|
|
|
539
547
|
def __init__(self, **kwargs):
|
|
540
|
-
if self.
|
|
548
|
+
if self._is_abstract():
|
|
541
549
|
raise NotImplementedError(
|
|
542
550
|
f"{self.__class__.__name__} is abstract and cannot be implemented"
|
|
543
551
|
)
|
|
@@ -559,6 +567,9 @@ class SHACLObject(object):
|
|
|
559
567
|
for k, v in kwargs.items():
|
|
560
568
|
setattr(self, k, v)
|
|
561
569
|
|
|
570
|
+
def _is_abstract(self):
|
|
571
|
+
return self.__class__.IS_ABSTRACT
|
|
572
|
+
|
|
562
573
|
@classmethod
|
|
563
574
|
def _register_props(cls):
|
|
564
575
|
cls._add_property("_id", StringProp(), iri="@id")
|
|
@@ -875,11 +886,20 @@ class SHACLExtensibleObject(object):
|
|
|
875
886
|
CLOSED = False
|
|
876
887
|
|
|
877
888
|
def __init__(self, typ=None, **kwargs):
|
|
878
|
-
super().__init__(**kwargs)
|
|
879
889
|
if typ:
|
|
880
890
|
self.__dict__["_obj_TYPE"] = (typ, None)
|
|
881
891
|
else:
|
|
882
892
|
self.__dict__["_obj_TYPE"] = (self._OBJ_TYPE, self._OBJ_COMPACT_TYPE)
|
|
893
|
+
super().__init__(**kwargs)
|
|
894
|
+
|
|
895
|
+
def _is_abstract(self):
|
|
896
|
+
# Unknown classes are assumed to not be abstract so that they can be
|
|
897
|
+
# deserialized
|
|
898
|
+
typ = self.__dict__["_obj_TYPE"][0]
|
|
899
|
+
if typ in self.__class__.CLASSES:
|
|
900
|
+
return self.__class__.CLASSES[typ].IS_ABSTRACT
|
|
901
|
+
|
|
902
|
+
return False
|
|
883
903
|
|
|
884
904
|
@classmethod
|
|
885
905
|
def _make_object(cls, typ):
|
|
@@ -1079,6 +1099,8 @@ class SHACLObjectSet(object):
|
|
|
1079
1099
|
return self._link()
|
|
1080
1100
|
|
|
1081
1101
|
def _link(self):
|
|
1102
|
+
global NAMED_INDIVIDUALS
|
|
1103
|
+
|
|
1082
1104
|
self.missing_ids = set()
|
|
1083
1105
|
visited = set()
|
|
1084
1106
|
|
|
@@ -1101,6 +1123,9 @@ class SHACLObjectSet(object):
|
|
|
1101
1123
|
obj_by_id[_id] = obj
|
|
1102
1124
|
self.obj_by_id = obj_by_id
|
|
1103
1125
|
|
|
1126
|
+
# Named individuals aren't considered missing
|
|
1127
|
+
self.missing_ids -= NAMED_INDIVIDUALS
|
|
1128
|
+
|
|
1104
1129
|
return self.missing_ids
|
|
1105
1130
|
|
|
1106
1131
|
def find_by_id(self, _id, default=None):
|
|
@@ -1924,6 +1949,20 @@ CONTEXT_URLS = [
|
|
|
1924
1949
|
"https://spdx.github.io/spdx-3-model/context.json",
|
|
1925
1950
|
]
|
|
1926
1951
|
|
|
1952
|
+
_NI_ENCODE_CONTEXT = {
|
|
1953
|
+
"http://example.org/enumType/foo": "enumType/foo",
|
|
1954
|
+
"http://example.org/enumType/bar": "enumType/bar",
|
|
1955
|
+
"http://example.org/enumType/nolabel": "enumType/nolabel",
|
|
1956
|
+
"http://example.org/test-class/named": "test-class/named",
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
_NI_DECODE_CONTEXT = {
|
|
1960
|
+
"enumType/foo": "http://example.org/enumType/foo",
|
|
1961
|
+
"enumType/bar": "http://example.org/enumType/bar",
|
|
1962
|
+
"enumType/nolabel": "http://example.org/enumType/nolabel",
|
|
1963
|
+
"test-class/named": "http://example.org/test-class/named",
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1927
1966
|
|
|
1928
1967
|
# CLASSES
|
|
1929
1968
|
# An Abstract class
|
|
@@ -1975,6 +2014,14 @@ class enumType(SHACLObject):
|
|
|
1975
2014
|
nolabel = "http://example.org/enumType/nolabel"
|
|
1976
2015
|
|
|
1977
2016
|
|
|
2017
|
+
# An extensible abstract class
|
|
2018
|
+
@register("http://example.org/extensible-abstract-class", compact_type="extensible-abstract-class", abstract=True)
|
|
2019
|
+
class extensible_abstract_class(SHACLExtensibleObject, SHACLObject):
|
|
2020
|
+
NODE_KIND = NodeKind.BlankNodeOrIRI
|
|
2021
|
+
NAMED_INDIVIDUALS = {
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
|
|
1978
2025
|
# A class with an ID alias
|
|
1979
2026
|
@register("http://example.org/id-prop-class", compact_type="id-prop-class", abstract=False)
|
|
1980
2027
|
class id_prop_class(SHACLObject):
|
|
@@ -2114,7 +2161,9 @@ class test_another_class(SHACLObject):
|
|
|
2114
2161
|
class test_class(parent_class):
|
|
2115
2162
|
NODE_KIND = NodeKind.BlankNodeOrIRI
|
|
2116
2163
|
NAMED_INDIVIDUALS = {
|
|
2164
|
+
"named": "http://example.org/test-class/named",
|
|
2117
2165
|
}
|
|
2166
|
+
named = "http://example.org/test-class/named"
|
|
2118
2167
|
|
|
2119
2168
|
@classmethod
|
|
2120
2169
|
def _register_props(cls):
|
|
@@ -2365,6 +2414,26 @@ class test_derived_class(test_class):
|
|
|
2365
2414
|
)
|
|
2366
2415
|
|
|
2367
2416
|
|
|
2417
|
+
# A class that uses an abstract extensible class
|
|
2418
|
+
@register("http://example.org/uses-extensible-abstract-class", compact_type="uses-extensible-abstract-class", abstract=False)
|
|
2419
|
+
class uses_extensible_abstract_class(SHACLObject):
|
|
2420
|
+
NODE_KIND = NodeKind.BlankNodeOrIRI
|
|
2421
|
+
NAMED_INDIVIDUALS = {
|
|
2422
|
+
}
|
|
2423
|
+
|
|
2424
|
+
@classmethod
|
|
2425
|
+
def _register_props(cls):
|
|
2426
|
+
super()._register_props()
|
|
2427
|
+
# A property that references and abstract extensible class
|
|
2428
|
+
cls._add_property(
|
|
2429
|
+
"uses_extensible_abstract_class_prop",
|
|
2430
|
+
ObjectProp(extensible_abstract_class, True),
|
|
2431
|
+
iri="http://example.org/uses-extensible-abstract-class/prop",
|
|
2432
|
+
min_count=1,
|
|
2433
|
+
compact="uses-extensible-abstract-class/prop",
|
|
2434
|
+
)
|
|
2435
|
+
|
|
2436
|
+
|
|
2368
2437
|
# Derived class that sorts before the parent to test ordering
|
|
2369
2438
|
@register("http://example.org/aaa-derived-class", compact_type="aaa-derived-class", abstract=False)
|
|
2370
2439
|
class aaa_derived_class(parent_class):
|
|
@@ -264,6 +264,7 @@ class ObjectProp(Property):
|
|
|
264
264
|
raise ValueError("Object cannot be None")
|
|
265
265
|
|
|
266
266
|
if isinstance(value, str):
|
|
267
|
+
value = _NI_ENCODE_CONTEXT.get(value, value)
|
|
267
268
|
encoder.write_iri(value)
|
|
268
269
|
return
|
|
269
270
|
|
|
@@ -274,6 +275,8 @@ class ObjectProp(Property):
|
|
|
274
275
|
if iri is None:
|
|
275
276
|
return self.cls.decode(decoder, objectset=objectset)
|
|
276
277
|
|
|
278
|
+
iri = _NI_DECODE_CONTEXT.get(iri, iri)
|
|
279
|
+
|
|
277
280
|
if objectset is None:
|
|
278
281
|
return iri
|
|
279
282
|
|
|
@@ -506,6 +509,8 @@ def register(type_iri, *, compact_type=None, abstract=False):
|
|
|
506
509
|
SHACLObject.CLASSES[key] = c
|
|
507
510
|
|
|
508
511
|
def decorator(c):
|
|
512
|
+
global NAMED_INDIVIDUALS
|
|
513
|
+
|
|
509
514
|
assert issubclass(
|
|
510
515
|
c, SHACLObject
|
|
511
516
|
), f"{c.__name__} is not derived from SHACLObject"
|
|
@@ -518,6 +523,8 @@ def register(type_iri, *, compact_type=None, abstract=False):
|
|
|
518
523
|
if compact_type:
|
|
519
524
|
add_class(compact_type, c)
|
|
520
525
|
|
|
526
|
+
NAMED_INDIVIDUALS |= set(c.NAMED_INDIVIDUALS.values())
|
|
527
|
+
|
|
521
528
|
# Registration is deferred until the first instance of class is created
|
|
522
529
|
# so that it has access to any other defined class
|
|
523
530
|
c._NEEDS_REG = True
|
|
@@ -527,6 +534,7 @@ def register(type_iri, *, compact_type=None, abstract=False):
|
|
|
527
534
|
|
|
528
535
|
|
|
529
536
|
register_lock = threading.Lock()
|
|
537
|
+
NAMED_INDIVIDUALS = set()
|
|
530
538
|
|
|
531
539
|
|
|
532
540
|
@functools.total_ordering
|
|
@@ -537,7 +545,7 @@ class SHACLObject(object):
|
|
|
537
545
|
IS_ABSTRACT = True
|
|
538
546
|
|
|
539
547
|
def __init__(self, **kwargs):
|
|
540
|
-
if self.
|
|
548
|
+
if self._is_abstract():
|
|
541
549
|
raise NotImplementedError(
|
|
542
550
|
f"{self.__class__.__name__} is abstract and cannot be implemented"
|
|
543
551
|
)
|
|
@@ -559,6 +567,9 @@ class SHACLObject(object):
|
|
|
559
567
|
for k, v in kwargs.items():
|
|
560
568
|
setattr(self, k, v)
|
|
561
569
|
|
|
570
|
+
def _is_abstract(self):
|
|
571
|
+
return self.__class__.IS_ABSTRACT
|
|
572
|
+
|
|
562
573
|
@classmethod
|
|
563
574
|
def _register_props(cls):
|
|
564
575
|
cls._add_property("_id", StringProp(), iri="@id")
|
|
@@ -875,11 +886,20 @@ class SHACLExtensibleObject(object):
|
|
|
875
886
|
CLOSED = False
|
|
876
887
|
|
|
877
888
|
def __init__(self, typ=None, **kwargs):
|
|
878
|
-
super().__init__(**kwargs)
|
|
879
889
|
if typ:
|
|
880
890
|
self.__dict__["_obj_TYPE"] = (typ, None)
|
|
881
891
|
else:
|
|
882
892
|
self.__dict__["_obj_TYPE"] = (self._OBJ_TYPE, self._OBJ_COMPACT_TYPE)
|
|
893
|
+
super().__init__(**kwargs)
|
|
894
|
+
|
|
895
|
+
def _is_abstract(self):
|
|
896
|
+
# Unknown classes are assumed to not be abstract so that they can be
|
|
897
|
+
# deserialized
|
|
898
|
+
typ = self.__dict__["_obj_TYPE"][0]
|
|
899
|
+
if typ in self.__class__.CLASSES:
|
|
900
|
+
return self.__class__.CLASSES[typ].IS_ABSTRACT
|
|
901
|
+
|
|
902
|
+
return False
|
|
883
903
|
|
|
884
904
|
@classmethod
|
|
885
905
|
def _make_object(cls, typ):
|
|
@@ -1079,6 +1099,8 @@ class SHACLObjectSet(object):
|
|
|
1079
1099
|
return self._link()
|
|
1080
1100
|
|
|
1081
1101
|
def _link(self):
|
|
1102
|
+
global NAMED_INDIVIDUALS
|
|
1103
|
+
|
|
1082
1104
|
self.missing_ids = set()
|
|
1083
1105
|
visited = set()
|
|
1084
1106
|
|
|
@@ -1101,6 +1123,9 @@ class SHACLObjectSet(object):
|
|
|
1101
1123
|
obj_by_id[_id] = obj
|
|
1102
1124
|
self.obj_by_id = obj_by_id
|
|
1103
1125
|
|
|
1126
|
+
# Named individuals aren't considered missing
|
|
1127
|
+
self.missing_ids -= NAMED_INDIVIDUALS
|
|
1128
|
+
|
|
1104
1129
|
return self.missing_ids
|
|
1105
1130
|
|
|
1106
1131
|
def find_by_id(self, _id, default=None):
|
|
@@ -1923,6 +1948,12 @@ def print_tree(objects, all_fields=False):
|
|
|
1923
1948
|
CONTEXT_URLS = [
|
|
1924
1949
|
]
|
|
1925
1950
|
|
|
1951
|
+
_NI_ENCODE_CONTEXT = {
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
_NI_DECODE_CONTEXT = {
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1926
1957
|
|
|
1927
1958
|
# CLASSES
|
|
1928
1959
|
# An Abstract class
|
|
@@ -1974,6 +2005,14 @@ class http_example_org_enumType(SHACLObject):
|
|
|
1974
2005
|
nolabel = "http://example.org/enumType/nolabel"
|
|
1975
2006
|
|
|
1976
2007
|
|
|
2008
|
+
# An extensible abstract class
|
|
2009
|
+
@register("http://example.org/extensible-abstract-class", abstract=True)
|
|
2010
|
+
class http_example_org_extensible_abstract_class(SHACLExtensibleObject, SHACLObject):
|
|
2011
|
+
NODE_KIND = NodeKind.BlankNodeOrIRI
|
|
2012
|
+
NAMED_INDIVIDUALS = {
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
|
|
1977
2016
|
# A class with an ID alias
|
|
1978
2017
|
@register("http://example.org/id-prop-class", abstract=False)
|
|
1979
2018
|
class http_example_org_id_prop_class(SHACLObject):
|
|
@@ -2108,7 +2147,9 @@ class http_example_org_test_another_class(SHACLObject):
|
|
|
2108
2147
|
class http_example_org_test_class(http_example_org_parent_class):
|
|
2109
2148
|
NODE_KIND = NodeKind.BlankNodeOrIRI
|
|
2110
2149
|
NAMED_INDIVIDUALS = {
|
|
2150
|
+
"named": "http://example.org/test-class/named",
|
|
2111
2151
|
}
|
|
2152
|
+
named = "http://example.org/test-class/named"
|
|
2112
2153
|
|
|
2113
2154
|
@classmethod
|
|
2114
2155
|
def _register_props(cls):
|
|
@@ -2330,6 +2371,25 @@ class http_example_org_test_derived_class(http_example_org_test_class):
|
|
|
2330
2371
|
)
|
|
2331
2372
|
|
|
2332
2373
|
|
|
2374
|
+
# A class that uses an abstract extensible class
|
|
2375
|
+
@register("http://example.org/uses-extensible-abstract-class", abstract=False)
|
|
2376
|
+
class http_example_org_uses_extensible_abstract_class(SHACLObject):
|
|
2377
|
+
NODE_KIND = NodeKind.BlankNodeOrIRI
|
|
2378
|
+
NAMED_INDIVIDUALS = {
|
|
2379
|
+
}
|
|
2380
|
+
|
|
2381
|
+
@classmethod
|
|
2382
|
+
def _register_props(cls):
|
|
2383
|
+
super()._register_props()
|
|
2384
|
+
# A property that references and abstract extensible class
|
|
2385
|
+
cls._add_property(
|
|
2386
|
+
"prop",
|
|
2387
|
+
ObjectProp(http_example_org_extensible_abstract_class, True),
|
|
2388
|
+
iri="http://example.org/uses-extensible-abstract-class/prop",
|
|
2389
|
+
min_count=1,
|
|
2390
|
+
)
|
|
2391
|
+
|
|
2392
|
+
|
|
2333
2393
|
# Derived class that sorts before the parent to test ordering
|
|
2334
2394
|
@register("http://example.org/aaa-derived-class", abstract=False)
|
|
2335
2395
|
class http_example_org_aaa_derived_class(http_example_org_parent_class):
|
|
@@ -11,6 +11,8 @@ http://example.org/concrete-spdx-class: concrete-spdx-class
|
|
|
11
11
|
|
|
12
12
|
http://example.org/enumType: enumType
|
|
13
13
|
|
|
14
|
+
http://example.org/extensible-abstract-class: extensible-abstract-class
|
|
15
|
+
|
|
14
16
|
http://example.org/id-prop-class: id-prop-class
|
|
15
17
|
|
|
16
18
|
http://example.org/inherited-id-prop-class: inherited-id-prop-class
|
|
@@ -39,6 +41,8 @@ http://example.org/test-class-required: test-class-required
|
|
|
39
41
|
|
|
40
42
|
http://example.org/test-derived-class: test-derived-class
|
|
41
43
|
|
|
44
|
+
http://example.org/uses-extensible-abstract-class: uses-extensible-abstract-class
|
|
45
|
+
|
|
42
46
|
http://example.org/aaa-derived-class: aaa-derived-class
|
|
43
47
|
|
|
44
48
|
http://example.org/derived-node-kind-iri: derived-node-kind-iri
|
|
@@ -5,6 +5,7 @@ Class(_id='http://example.org/abstract-spdx-class', clsname=['http', '//example.
|
|
|
5
5
|
Class(_id='http://example.org/concrete-class', clsname=['http', '//example.org/concrete-class'], parent_ids=['http://example.org/abstract-class'], derived_ids=[], properties=[], comment='A concrete class', id_property=None, node_kind=rdflib.term.URIRef('http://www.w3.org/ns/shacl#BlankNodeOrIRI'), is_extensible=False, is_abstract=False, named_individuals=[])
|
|
6
6
|
Class(_id='http://example.org/concrete-spdx-class', clsname=['http', '//example.org/concrete-spdx-class'], parent_ids=['http://example.org/abstract-spdx-class'], derived_ids=[], properties=[], comment='A concrete class', id_property=None, node_kind=rdflib.term.URIRef('http://www.w3.org/ns/shacl#BlankNodeOrIRI'), is_extensible=False, is_abstract=False, named_individuals=[])
|
|
7
7
|
Class(_id='http://example.org/enumType', clsname=['http', '//example.org/enumType'], parent_ids=[], derived_ids=[], properties=[], comment='An enumerated type', id_property=None, node_kind=rdflib.term.URIRef('http://www.w3.org/ns/shacl#BlankNodeOrIRI'), is_extensible=False, is_abstract=False, named_individuals=[Individual(_id='http://example.org/enumType/foo', varname='foo', comment='The foo value of enumType'), Individual(_id='http://example.org/enumType/bar', varname='bar', comment='The bar value of enumType'), Individual(_id='http://example.org/enumType/nolabel', varname='nolabel', comment='This value has no label')])
|
|
8
|
+
Class(_id='http://example.org/extensible-abstract-class', clsname=['http', '//example.org/extensible-abstract-class'], parent_ids=[], derived_ids=[], properties=[], comment='An extensible abstract class', id_property=None, node_kind=rdflib.term.URIRef('http://www.w3.org/ns/shacl#BlankNodeOrIRI'), is_extensible=True, is_abstract=True, named_individuals=[])
|
|
8
9
|
Class(_id='http://example.org/id-prop-class', clsname=['http', '//example.org/id-prop-class'], parent_ids=[], derived_ids=['http://example.org/inherited-id-prop-class'], properties=[], comment='A class with an ID alias', id_property='testid', node_kind=rdflib.term.URIRef('http://www.w3.org/ns/shacl#BlankNodeOrIRI'), is_extensible=False, is_abstract=False, named_individuals=[])
|
|
9
10
|
Class(_id='http://example.org/inherited-id-prop-class', clsname=['http', '//example.org/inherited-id-prop-class'], parent_ids=['http://example.org/id-prop-class'], derived_ids=[], properties=[], comment='A class that inherits its idPropertyName from the parent', id_property='testid', node_kind=rdflib.term.URIRef('http://www.w3.org/ns/shacl#BlankNodeOrIRI'), is_extensible=False, is_abstract=False, named_individuals=[])
|
|
10
11
|
Class(_id='http://example.org/link-class', clsname=['http', '//example.org/link-class'], parent_ids=[], derived_ids=['http://example.org/extensible-class', 'http://example.org/link-derived-class', 'http://example.org/node-kind-blank', 'http://example.org/node-kind-iri', 'http://example.org/node-kind-iri-or-blank'], properties=[Property(path='http://example.org/link-class-extensible', varname='-extensible', comment='A link to an extensible-class', max_count=1, min_count=None, enum_values=None, class_id='http://example.org/extensible-class', datatype='', pattern=''), Property(path='http://example.org/link-class-link-list-prop', varname='-link-list-prop', comment='A link-class list property', max_count=None, min_count=None, enum_values=None, class_id='http://example.org/link-class', datatype='', pattern=''), Property(path='http://example.org/link-class-link-prop', varname='-link-prop', comment='A link-class property', max_count=1, min_count=None, enum_values=None, class_id='http://example.org/link-class', datatype='', pattern=''), Property(path='http://example.org/link-class-link-prop-no-class', varname='-link-prop-no-class', comment='A link-class property with no sh:class', max_count=1, min_count=None, enum_values=None, class_id='http://example.org/link-class', datatype='', pattern='')], comment='A class to test links', id_property=None, node_kind=rdflib.term.URIRef('http://www.w3.org/ns/shacl#BlankNodeOrIRI'), is_extensible=False, is_abstract=False, named_individuals=[])
|
|
@@ -16,9 +17,10 @@ Class(_id='http://example.org/non-shape-class', clsname=['http', '//example.org/
|
|
|
16
17
|
Class(_id='http://example.org/parent-class', clsname=['http', '//example.org/parent-class'], parent_ids=[], derived_ids=['http://example.org/aaa-derived-class', 'http://example.org/test-class'], properties=[], comment='The parent class', id_property=None, node_kind=rdflib.term.URIRef('http://www.w3.org/ns/shacl#BlankNodeOrIRI'), is_extensible=False, is_abstract=False, named_individuals=[])
|
|
17
18
|
Class(_id='http://example.org/required-abstract', clsname=['http', '//example.org/required-abstract'], parent_ids=[], derived_ids=[], properties=[Property(path='http://example.org/required-abstract/abstract-class-prop', varname='abstract-class-prop', comment='A required abstract class property', max_count=1, min_count=1, enum_values=None, class_id='http://example.org/abstract-class', datatype='', pattern='')], comment='A class with a mandatory abstract class', id_property=None, node_kind=rdflib.term.URIRef('http://www.w3.org/ns/shacl#BlankNodeOrIRI'), is_extensible=False, is_abstract=False, named_individuals=[])
|
|
18
19
|
Class(_id='http://example.org/test-another-class', clsname=['http', '//example.org/test-another-class'], parent_ids=[], derived_ids=[], properties=[], comment='Another class', id_property=None, node_kind=rdflib.term.URIRef('http://www.w3.org/ns/shacl#BlankNodeOrIRI'), is_extensible=False, is_abstract=False, named_individuals=[])
|
|
19
|
-
Class(_id='http://example.org/test-class', clsname=['http', '//example.org/test-class'], parent_ids=['http://example.org/parent-class'], derived_ids=['http://example.org/test-class-required', 'http://example.org/test-derived-class'], properties=[Property(path='http://example.org/encode', varname='encode', comment='A property that conflicts with an existing SHACLObject property', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern=''), Property(path='http://example.org/import', varname='import', comment='A property that is a keyword', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern=''), Property(path='http://example.org/test-class/anyuri-prop', varname='anyuri-prop', comment='a URI', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#anyURI', pattern=''), Property(path='http://example.org/test-class/boolean-prop', varname='boolean-prop', comment='a boolean property', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#boolean', pattern=''), Property(path='http://example.org/test-class/class-list-prop', varname='class-list-prop', comment='A test-class list property', max_count=None, min_count=None, enum_values=None, class_id='http://example.org/test-class', datatype='', pattern=''), Property(path='http://example.org/test-class/class-prop', varname='class-prop', comment='A test-class property', max_count=1, min_count=None, enum_values=None, class_id='http://example.org/test-class', datatype='', pattern=''), Property(path='http://example.org/test-class/class-prop-no-class', varname='class-prop-no-class', comment='A test-class property with no sh:class', max_count=1, min_count=None, enum_values=None, class_id='http://example.org/test-class', datatype='', pattern=''), Property(path='http://example.org/test-class/datetime-list-prop', varname='datetime-list-prop', comment='A datetime list property', max_count=None, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#dateTime', pattern=''), Property(path='http://example.org/test-class/datetime-scalar-prop', varname='datetime-scalar-prop', comment='A scalar datetime property', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#dateTime', pattern=''), Property(path='http://example.org/test-class/datetimestamp-scalar-prop', varname='datetimestamp-scalar-prop', comment='A scalar dateTimeStamp property', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#dateTimeStamp', pattern=''), Property(path='http://example.org/test-class/enum-list-prop', varname='enum-list-prop', comment='A enum list property', max_count=None, min_count=None, enum_values=[rdflib.term.URIRef('http://example.org/enumType/bar'), rdflib.term.URIRef('http://example.org/enumType/foo'), rdflib.term.URIRef('http://example.org/enumType/nolabel'), rdflib.term.URIRef('http://example.org/enumType/non-named-individual')], class_id='http://example.org/enumType', datatype='', pattern=''), Property(path='http://example.org/test-class/enum-prop', varname='enum-prop', comment='A enum property', max_count=1, min_count=None, enum_values=[rdflib.term.URIRef('http://example.org/enumType/bar'), rdflib.term.URIRef('http://example.org/enumType/foo'), rdflib.term.URIRef('http://example.org/enumType/nolabel'), rdflib.term.URIRef('http://example.org/enumType/non-named-individual')], class_id='http://example.org/enumType', datatype='', pattern=''), Property(path='http://example.org/test-class/enum-prop-no-class', varname='enum-prop-no-class', comment='A enum property with no sh:class', max_count=1, min_count=None, enum_values=[rdflib.term.URIRef('http://example.org/enumType/bar'), rdflib.term.URIRef('http://example.org/enumType/foo'), rdflib.term.URIRef('http://example.org/enumType/nolabel'), rdflib.term.URIRef('http://example.org/enumType/non-named-individual')], class_id='http://example.org/enumType', datatype='', pattern=''), Property(path='http://example.org/test-class/float-prop', varname='float-prop', comment='a float property', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#decimal', pattern=''), Property(path='http://example.org/test-class/integer-prop', varname='integer-prop', comment='a non-negative integer', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#integer', pattern=''), Property(path='http://example.org/test-class/named-property', varname=rdflib.term.Literal('named_property'), comment='A named property', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern=''), Property(path='http://example.org/test-class/non-shape', varname='non-shape', comment='A class with no shape', max_count=1, min_count=None, enum_values=None, class_id='http://example.org/non-shape-class', datatype='', pattern=''), Property(path='http://example.org/test-class/nonnegative-integer-prop', varname='nonnegative-integer-prop', comment='a non-negative integer', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#nonNegativeInteger', pattern=''), Property(path='http://example.org/test-class/positive-integer-prop', varname='positive-integer-prop', comment='A positive integer', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#positiveInteger', pattern=''), Property(path='http://example.org/test-class/regex', varname='regex', comment='A regex validated string', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern='^foo\\d'), Property(path='http://example.org/test-class/regex-datetime', varname='regex-datetime', comment='A regex dateTime', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#dateTime', pattern='^\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d\\+01:00$'), Property(path='http://example.org/test-class/regex-datetimestamp', varname='regex-datetimestamp', comment='A regex dateTimeStamp', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#dateTimeStamp', pattern='^\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\dZ$'), Property(path='http://example.org/test-class/regex-list', varname='regex-list', comment='A regex validated string list', max_count=None, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern='^foo\\d'), Property(path='http://example.org/test-class/string-list-no-datatype', varname='string-list-no-datatype', comment='A string list property with no sh:datatype', max_count=None, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern=''), Property(path='http://example.org/test-class/string-list-prop', varname='string-list-prop', comment='A string list property', max_count=None, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern=''), Property(path='http://example.org/test-class/string-scalar-prop', varname='string-scalar-prop', comment='A scalar string propery', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern='')], comment='The test class', id_property=None, node_kind=rdflib.term.URIRef('http://www.w3.org/ns/shacl#BlankNodeOrIRI'), is_extensible=False, is_abstract=False, named_individuals=[])
|
|
20
|
+
Class(_id='http://example.org/test-class', clsname=['http', '//example.org/test-class'], parent_ids=['http://example.org/parent-class'], derived_ids=['http://example.org/test-class-required', 'http://example.org/test-derived-class'], properties=[Property(path='http://example.org/encode', varname='encode', comment='A property that conflicts with an existing SHACLObject property', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern=''), Property(path='http://example.org/import', varname='import', comment='A property that is a keyword', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern=''), Property(path='http://example.org/test-class/anyuri-prop', varname='anyuri-prop', comment='a URI', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#anyURI', pattern=''), Property(path='http://example.org/test-class/boolean-prop', varname='boolean-prop', comment='a boolean property', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#boolean', pattern=''), Property(path='http://example.org/test-class/class-list-prop', varname='class-list-prop', comment='A test-class list property', max_count=None, min_count=None, enum_values=None, class_id='http://example.org/test-class', datatype='', pattern=''), Property(path='http://example.org/test-class/class-prop', varname='class-prop', comment='A test-class property', max_count=1, min_count=None, enum_values=None, class_id='http://example.org/test-class', datatype='', pattern=''), Property(path='http://example.org/test-class/class-prop-no-class', varname='class-prop-no-class', comment='A test-class property with no sh:class', max_count=1, min_count=None, enum_values=None, class_id='http://example.org/test-class', datatype='', pattern=''), Property(path='http://example.org/test-class/datetime-list-prop', varname='datetime-list-prop', comment='A datetime list property', max_count=None, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#dateTime', pattern=''), Property(path='http://example.org/test-class/datetime-scalar-prop', varname='datetime-scalar-prop', comment='A scalar datetime property', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#dateTime', pattern=''), Property(path='http://example.org/test-class/datetimestamp-scalar-prop', varname='datetimestamp-scalar-prop', comment='A scalar dateTimeStamp property', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#dateTimeStamp', pattern=''), Property(path='http://example.org/test-class/enum-list-prop', varname='enum-list-prop', comment='A enum list property', max_count=None, min_count=None, enum_values=[rdflib.term.URIRef('http://example.org/enumType/bar'), rdflib.term.URIRef('http://example.org/enumType/foo'), rdflib.term.URIRef('http://example.org/enumType/nolabel'), rdflib.term.URIRef('http://example.org/enumType/non-named-individual')], class_id='http://example.org/enumType', datatype='', pattern=''), Property(path='http://example.org/test-class/enum-prop', varname='enum-prop', comment='A enum property', max_count=1, min_count=None, enum_values=[rdflib.term.URIRef('http://example.org/enumType/bar'), rdflib.term.URIRef('http://example.org/enumType/foo'), rdflib.term.URIRef('http://example.org/enumType/nolabel'), rdflib.term.URIRef('http://example.org/enumType/non-named-individual')], class_id='http://example.org/enumType', datatype='', pattern=''), Property(path='http://example.org/test-class/enum-prop-no-class', varname='enum-prop-no-class', comment='A enum property with no sh:class', max_count=1, min_count=None, enum_values=[rdflib.term.URIRef('http://example.org/enumType/bar'), rdflib.term.URIRef('http://example.org/enumType/foo'), rdflib.term.URIRef('http://example.org/enumType/nolabel'), rdflib.term.URIRef('http://example.org/enumType/non-named-individual')], class_id='http://example.org/enumType', datatype='', pattern=''), Property(path='http://example.org/test-class/float-prop', varname='float-prop', comment='a float property', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#decimal', pattern=''), Property(path='http://example.org/test-class/integer-prop', varname='integer-prop', comment='a non-negative integer', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#integer', pattern=''), Property(path='http://example.org/test-class/named-property', varname=rdflib.term.Literal('named_property'), comment='A named property', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern=''), Property(path='http://example.org/test-class/non-shape', varname='non-shape', comment='A class with no shape', max_count=1, min_count=None, enum_values=None, class_id='http://example.org/non-shape-class', datatype='', pattern=''), Property(path='http://example.org/test-class/nonnegative-integer-prop', varname='nonnegative-integer-prop', comment='a non-negative integer', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#nonNegativeInteger', pattern=''), Property(path='http://example.org/test-class/positive-integer-prop', varname='positive-integer-prop', comment='A positive integer', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#positiveInteger', pattern=''), Property(path='http://example.org/test-class/regex', varname='regex', comment='A regex validated string', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern='^foo\\d'), Property(path='http://example.org/test-class/regex-datetime', varname='regex-datetime', comment='A regex dateTime', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#dateTime', pattern='^\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\d\\+01:00$'), Property(path='http://example.org/test-class/regex-datetimestamp', varname='regex-datetimestamp', comment='A regex dateTimeStamp', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#dateTimeStamp', pattern='^\\d\\d\\d\\d-\\d\\d-\\d\\dT\\d\\d:\\d\\d:\\d\\dZ$'), Property(path='http://example.org/test-class/regex-list', varname='regex-list', comment='A regex validated string list', max_count=None, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern='^foo\\d'), Property(path='http://example.org/test-class/string-list-no-datatype', varname='string-list-no-datatype', comment='A string list property with no sh:datatype', max_count=None, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern=''), Property(path='http://example.org/test-class/string-list-prop', varname='string-list-prop', comment='A string list property', max_count=None, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern=''), Property(path='http://example.org/test-class/string-scalar-prop', varname='string-scalar-prop', comment='A scalar string propery', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern='')], comment='The test class', id_property=None, node_kind=rdflib.term.URIRef('http://www.w3.org/ns/shacl#BlankNodeOrIRI'), is_extensible=False, is_abstract=False, named_individuals=[Individual(_id='http://example.org/test-class/named', varname='named', comment='')])
|
|
20
21
|
Class(_id='http://example.org/test-class-required', clsname=['http', '//example.org/test-class-required'], parent_ids=['http://example.org/test-class'], derived_ids=[], properties=[Property(path='http://example.org/test-class/required-string-list-prop', varname='required-string-list-prop', comment='A required string list property', max_count=2, min_count=1, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern=''), Property(path='http://example.org/test-class/required-string-scalar-prop', varname='required-string-scalar-prop', comment='A required scalar string property', max_count=1, min_count=1, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern='')], comment='', id_property=None, node_kind=rdflib.term.URIRef('http://www.w3.org/ns/shacl#BlankNodeOrIRI'), is_extensible=False, is_abstract=False, named_individuals=[])
|
|
21
22
|
Class(_id='http://example.org/test-derived-class', clsname=['http', '//example.org/test-derived-class'], parent_ids=['http://example.org/test-class'], derived_ids=[], properties=[Property(path='http://example.org/test-derived-class/string-prop', varname='string-prop', comment='A string property in a derived class', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern='')], comment='A class derived from test-class', id_property=None, node_kind=rdflib.term.URIRef('http://www.w3.org/ns/shacl#BlankNodeOrIRI'), is_extensible=False, is_abstract=False, named_individuals=[])
|
|
23
|
+
Class(_id='http://example.org/uses-extensible-abstract-class', clsname=['http', '//example.org/uses-extensible-abstract-class'], parent_ids=[], derived_ids=[], properties=[Property(path='http://example.org/uses-extensible-abstract-class/prop', varname='prop', comment='A property that references and abstract extensible class', max_count=1, min_count=1, enum_values=None, class_id='http://example.org/extensible-abstract-class', datatype='', pattern='')], comment='A class that uses an abstract extensible class', id_property=None, node_kind=rdflib.term.URIRef('http://www.w3.org/ns/shacl#BlankNodeOrIRI'), is_extensible=False, is_abstract=False, named_individuals=[])
|
|
22
24
|
Class(_id='http://example.org/aaa-derived-class', clsname=['http', '//example.org/aaa-derived-class'], parent_ids=['http://example.org/parent-class'], derived_ids=[], properties=[], comment='Derived class that sorts before the parent to test ordering', id_property=None, node_kind=rdflib.term.URIRef('http://www.w3.org/ns/shacl#BlankNodeOrIRI'), is_extensible=False, is_abstract=False, named_individuals=[])
|
|
23
25
|
Class(_id='http://example.org/derived-node-kind-iri', clsname=['http', '//example.org/derived-node-kind-iri'], parent_ids=['http://example.org/node-kind-iri'], derived_ids=[], properties=[], comment='A class that derives its nodeKind from parent', id_property=None, node_kind=rdflib.term.URIRef('http://www.w3.org/ns/shacl#IRI'), is_extensible=False, is_abstract=False, named_individuals=[])
|
|
24
26
|
Class(_id='http://example.org/extensible-class', clsname=['http', '//example.org/extensible-class'], parent_ids=['http://example.org/link-class'], derived_ids=[], properties=[Property(path='http://example.org/extensible-class/property', varname='property', comment='An extensible property', max_count=1, min_count=None, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern=''), Property(path='http://example.org/extensible-class/required', varname='required', comment='A required extensible property', max_count=1, min_count=1, enum_values=None, class_id='', datatype='http://www.w3.org/2001/XMLSchema#string', pattern='')], comment='An extensible class', id_property=None, node_kind=rdflib.term.URIRef('http://www.w3.org/ns/shacl#BlankNodeOrIRI'), is_extensible=True, is_abstract=False, named_individuals=[])
|
|
@@ -701,6 +701,38 @@ def node_kind_tests(name, blank, iri):
|
|
|
701
701
|
"@type": "concrete-spdx-class",
|
|
702
702
|
},
|
|
703
703
|
),
|
|
704
|
+
# An extensible abstract class cannot be instantiated
|
|
705
|
+
(
|
|
706
|
+
False,
|
|
707
|
+
{
|
|
708
|
+
"@context": CONTEXT,
|
|
709
|
+
"@type": "extensible-abstract-class",
|
|
710
|
+
},
|
|
711
|
+
),
|
|
712
|
+
# Any can type can be used where a extensible abstract class is
|
|
713
|
+
# references, except... (SEE NEXT)
|
|
714
|
+
(
|
|
715
|
+
True,
|
|
716
|
+
{
|
|
717
|
+
"@context": CONTEXT,
|
|
718
|
+
"@type": "uses-extensible-abstract-class",
|
|
719
|
+
"uses-extensible-abstract-class/prop": {
|
|
720
|
+
"@type": "http://example.com/extended",
|
|
721
|
+
},
|
|
722
|
+
},
|
|
723
|
+
),
|
|
724
|
+
# ... the exact type of the extensible abstract class is specifically
|
|
725
|
+
# not allowed
|
|
726
|
+
(
|
|
727
|
+
False,
|
|
728
|
+
{
|
|
729
|
+
"@context": CONTEXT,
|
|
730
|
+
"@type": "uses-extensible-abstract-class",
|
|
731
|
+
"uses-extensible-abstract-class/prop": {
|
|
732
|
+
"@type": "extensible-abstract-class",
|
|
733
|
+
},
|
|
734
|
+
},
|
|
735
|
+
),
|
|
704
736
|
# Base object for type tests
|
|
705
737
|
(True, BASE_OBJ),
|
|
706
738
|
],
|
|
@@ -815,10 +847,14 @@ def type_tests(name, *, good=[], bad=[], typ=[]):
|
|
|
815
847
|
{"@type": "test-derived-class"},
|
|
816
848
|
"_:blanknode",
|
|
817
849
|
"http://serialize.example.org/test",
|
|
850
|
+
# Named individual
|
|
851
|
+
"test-class/named",
|
|
818
852
|
],
|
|
819
853
|
bad=[
|
|
820
854
|
{"@type": "test-another-class"},
|
|
821
855
|
{"@type": "parent-class"},
|
|
856
|
+
"not/an/iri",
|
|
857
|
+
"not-an-iri",
|
|
822
858
|
],
|
|
823
859
|
typ=[object, str],
|
|
824
860
|
),
|
|
@@ -754,6 +754,7 @@ def type_tests(name, *typ):
|
|
|
754
754
|
),
|
|
755
755
|
("test_class_class_prop", lambda model: model.test_another_class(), TypeError),
|
|
756
756
|
("test_class_class_prop", lambda model: model.parent_class(), TypeError),
|
|
757
|
+
("test_class_class_prop", lambda model: model.test_class.named, SAME_AS_VALUE),
|
|
757
758
|
("test_class_class_prop", "_:blanknode", "_:blanknode"),
|
|
758
759
|
(
|
|
759
760
|
"test_class_class_prop",
|
|
@@ -1619,6 +1620,11 @@ def test_objset_foreach_type(model, roundtrip):
|
|
|
1619
1620
|
|
|
1620
1621
|
expect.add(objset.find_by_id("http://serialize.example.com/test"))
|
|
1621
1622
|
expect.add(objset.find_by_id("http://serialize.example.com/nested-parent"))
|
|
1623
|
+
expect.add(
|
|
1624
|
+
objset.find_by_id(
|
|
1625
|
+
"http://serialize.example.com/test-named-individual-reference"
|
|
1626
|
+
)
|
|
1627
|
+
)
|
|
1622
1628
|
expect.add(
|
|
1623
1629
|
objset.find_by_id(
|
|
1624
1630
|
"http://serialize.example.com/nested-parent"
|
|
@@ -1739,3 +1745,43 @@ def test_required_abstract_class_property(model, tmp_path):
|
|
|
1739
1745
|
# Deleting an abstract class property should return it to None
|
|
1740
1746
|
del c.required_abstract_abstract_class_prop
|
|
1741
1747
|
assert c.required_abstract_abstract_class_prop is None
|
|
1748
|
+
|
|
1749
|
+
|
|
1750
|
+
def test_extensible_abstract_class(model):
|
|
1751
|
+
@model.register("http://example.org/custom-extension-class")
|
|
1752
|
+
class Extension(model.extensible_abstract_class):
|
|
1753
|
+
pass
|
|
1754
|
+
|
|
1755
|
+
# Test that an extensible abstract class cannot be created
|
|
1756
|
+
with pytest.raises(NotImplementedError):
|
|
1757
|
+
model.extensible_abstract_class()
|
|
1758
|
+
|
|
1759
|
+
# Test that a class derived from an abstract extensible class can be
|
|
1760
|
+
# created
|
|
1761
|
+
Extension()
|
|
1762
|
+
|
|
1763
|
+
|
|
1764
|
+
def test_named_individual(model, roundtrip):
|
|
1765
|
+
objset = model.SHACLObjectSet()
|
|
1766
|
+
with roundtrip.open("r") as f:
|
|
1767
|
+
d = model.JSONLDDeserializer()
|
|
1768
|
+
d.read(f, objset)
|
|
1769
|
+
|
|
1770
|
+
c = objset.find_by_id(
|
|
1771
|
+
"http://serialize.example.com/test-named-individual-reference"
|
|
1772
|
+
)
|
|
1773
|
+
assert c is not None
|
|
1774
|
+
assert c.test_class_class_prop == model.test_class.named
|
|
1775
|
+
|
|
1776
|
+
assert model.test_class.named not in objset.missing_ids
|
|
1777
|
+
|
|
1778
|
+
|
|
1779
|
+
def test_missing_ids(model, roundtrip):
|
|
1780
|
+
objset = model.SHACLObjectSet()
|
|
1781
|
+
with roundtrip.open("r") as f:
|
|
1782
|
+
d = model.JSONLDDeserializer()
|
|
1783
|
+
d.read(f, objset)
|
|
1784
|
+
|
|
1785
|
+
assert objset.missing_ids == {
|
|
1786
|
+
"http://serialize.example.com/non-shape",
|
|
1787
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
VERSION = "0.0.11"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|