shacl2code 0.0.14__tar.gz → 0.0.16__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.14 → shacl2code-0.0.16}/.github/workflows/coverage-generate.yaml +3 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/.github/workflows/test.yaml +1 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/PKG-INFO +35 -6
- {shacl2code-0.0.14 → shacl2code-0.0.16}/README.md +34 -4
- {shacl2code-0.0.14 → shacl2code-0.0.16}/src/shacl2code/lang/__init__.py +2 -1
- {shacl2code-0.0.14 → shacl2code-0.0.16}/src/shacl2code/lang/common.py +55 -34
- shacl2code-0.0.16/src/shacl2code/lang/cpp.py +224 -0
- shacl2code-0.0.16/src/shacl2code/lang/sources/cpp/json.hpp +24765 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/Doxyfile.j2 +2623 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/Makefile.j2 +90 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/api.hpp.j2 +47 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/datetime.cpp.j2 +154 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/datetime.hpp.j2 +105 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/decode.cpp.j2 +56 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/decode.hpp.j2 +299 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/encode.cpp.j2 +106 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/encode.hpp.j2 +342 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/errorhandler.cpp.j2 +64 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/errorhandler.hpp.j2 +141 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/exceptions.hpp.j2 +101 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/extensible.cpp.j2 +199 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/extensible.hpp.j2 +190 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/header.j2 +193 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/jsonld-header.j2 +340 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/jsonld-source.j2 +496 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/link.cpp.j2 +48 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/link.hpp.j2 +54 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/namedindividual.cpp.j2 +71 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/namedindividual.hpp.j2 +109 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/object.cpp.j2 +317 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/object.hpp.j2 +341 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/objectpath.cpp.j2 +106 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/objectpath.hpp.j2 +170 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/objectset.cpp.j2 +340 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/objectset.hpp.j2 +227 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/pkgconfig.pc.j2 +10 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/prop.hpp.j2 +235 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/property.cpp.j2 +478 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/property.hpp.j2 +481 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/propertyvalue.cpp.j2 +65 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/propertyvalue.hpp.j2 +1036 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/ref.hpp.j2 +431 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/refproperty.cpp.j2 +49 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/refproperty.hpp.j2 +210 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/source.j2 +122 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/type.cpp.j2 +39 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/type.hpp.j2 +292 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/util.cpp.j2 +48 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/util.hpp.j2 +37 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/validate.j2 +149 -0
- shacl2code-0.0.16/src/shacl2code/lang/templates/cpp/walk.hpp.j2 +86 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/src/shacl2code/lang/templates/python.j2 +3 -3
- {shacl2code-0.0.14 → shacl2code-0.0.16}/src/shacl2code/model.py +9 -1
- shacl2code-0.0.16/src/shacl2code/version.py +1 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/testfixtures/jsonvalidation.py +16 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/conftest.py +16 -1
- shacl2code-0.0.16/tests/data/bad-prop-type.ttl +15 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/data/model/test-context.json +2 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/data/model/test.ttl +12 -0
- shacl2code-0.0.16/tests/expect/cpp/context/Doxyfile +2623 -0
- shacl2code-0.0.16/tests/expect/cpp/context/Makefile +106 -0
- shacl2code-0.0.16/tests/expect/cpp/context/api.hpp +51 -0
- shacl2code-0.0.16/tests/expect/cpp/context/datetime.cpp +143 -0
- shacl2code-0.0.16/tests/expect/cpp/context/datetime.hpp +125 -0
- shacl2code-0.0.16/tests/expect/cpp/context/decode.cpp +45 -0
- shacl2code-0.0.16/tests/expect/cpp/context/decode.hpp +319 -0
- shacl2code-0.0.16/tests/expect/cpp/context/encode.cpp +95 -0
- shacl2code-0.0.16/tests/expect/cpp/context/encode.hpp +362 -0
- shacl2code-0.0.16/tests/expect/cpp/context/errorhandler.cpp +54 -0
- shacl2code-0.0.16/tests/expect/cpp/context/errorhandler.hpp +161 -0
- shacl2code-0.0.16/tests/expect/cpp/context/exceptions.hpp +121 -0
- shacl2code-0.0.16/tests/expect/cpp/context/extensible.cpp +201 -0
- shacl2code-0.0.16/tests/expect/cpp/context/extensible.hpp +209 -0
- shacl2code-0.0.16/tests/expect/cpp/context/link.cpp +37 -0
- shacl2code-0.0.16/tests/expect/cpp/context/link.hpp +74 -0
- shacl2code-0.0.16/tests/expect/cpp/context/namedindividual.cpp +60 -0
- shacl2code-0.0.16/tests/expect/cpp/context/namedindividual.hpp +128 -0
- shacl2code-0.0.16/tests/expect/cpp/context/object.cpp +319 -0
- shacl2code-0.0.16/tests/expect/cpp/context/object.hpp +360 -0
- shacl2code-0.0.16/tests/expect/cpp/context/objectpath.cpp +96 -0
- shacl2code-0.0.16/tests/expect/cpp/context/objectpath.hpp +189 -0
- shacl2code-0.0.16/tests/expect/cpp/context/objectset.cpp +327 -0
- shacl2code-0.0.16/tests/expect/cpp/context/objectset.hpp +247 -0
- shacl2code-0.0.16/tests/expect/cpp/context/prop.hpp +254 -0
- shacl2code-0.0.16/tests/expect/cpp/context/property.cpp +467 -0
- shacl2code-0.0.16/tests/expect/cpp/context/property.hpp +500 -0
- shacl2code-0.0.16/tests/expect/cpp/context/propertyvalue.cpp +54 -0
- shacl2code-0.0.16/tests/expect/cpp/context/propertyvalue.hpp +1055 -0
- shacl2code-0.0.16/tests/expect/cpp/context/ref.hpp +450 -0
- shacl2code-0.0.16/tests/expect/cpp/context/refproperty.cpp +38 -0
- shacl2code-0.0.16/tests/expect/cpp/context/refproperty.hpp +229 -0
- shacl2code-0.0.16/tests/expect/cpp/context/test-context-jsonld.cpp +25250 -0
- shacl2code-0.0.16/tests/expect/cpp/context/test-context-jsonld.hpp +329 -0
- shacl2code-0.0.16/tests/expect/cpp/context/test-context-validate.cpp +144 -0
- shacl2code-0.0.16/tests/expect/cpp/context/test-context.cpp +830 -0
- shacl2code-0.0.16/tests/expect/cpp/context/test-context.hpp +1202 -0
- shacl2code-0.0.16/tests/expect/cpp/context/test-context.pc +10 -0
- shacl2code-0.0.16/tests/expect/cpp/context/type.cpp +41 -0
- shacl2code-0.0.16/tests/expect/cpp/context/type.hpp +311 -0
- shacl2code-0.0.16/tests/expect/cpp/context/util.cpp +37 -0
- shacl2code-0.0.16/tests/expect/cpp/context/util.hpp +56 -0
- shacl2code-0.0.16/tests/expect/cpp/context/walk.hpp +105 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/Doxyfile +2623 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/Makefile +106 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/api.hpp +51 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/datetime.cpp +143 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/datetime.hpp +125 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/decode.cpp +45 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/decode.hpp +319 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/encode.cpp +95 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/encode.hpp +362 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/errorhandler.cpp +54 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/errorhandler.hpp +161 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/exceptions.hpp +121 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/extensible.cpp +201 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/extensible.hpp +209 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/link.cpp +37 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/link.hpp +74 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/namedindividual.cpp +60 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/namedindividual.hpp +128 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/object.cpp +319 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/object.hpp +360 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/objectpath.cpp +96 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/objectpath.hpp +189 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/objectset.cpp +326 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/objectset.hpp +247 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/prop.hpp +254 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/property.cpp +467 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/property.hpp +500 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/propertyvalue.cpp +54 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/propertyvalue.hpp +1055 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/ref.hpp +450 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/refproperty.cpp +38 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/refproperty.hpp +229 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/test-jsonld.cpp +25250 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/test-jsonld.hpp +329 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/test-validate.cpp +144 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/test.cpp +815 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/test.hpp +1076 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/test.pc +10 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/type.cpp +41 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/type.hpp +311 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/util.cpp +37 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/util.hpp +56 -0
- shacl2code-0.0.16/tests/expect/cpp/nocontext/walk.hpp +105 -0
- {shacl2code-0.0.14/tests/expect/jsonschema → shacl2code-0.0.16/tests/expect/jsonschema/context}/test-context.json +62 -0
- {shacl2code-0.0.14/tests/expect/jsonschema → shacl2code-0.0.16/tests/expect/jsonschema/nocontext}/test.json +62 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/expect/make_expect.py +7 -7
- {shacl2code-0.0.14/tests/expect/python → shacl2code-0.0.16/tests/expect/python/context}/test-context.py +18 -3
- {shacl2code-0.0.14/tests/expect/python → shacl2code-0.0.16/tests/expect/python/nocontext}/test.py +18 -3
- {shacl2code-0.0.14/tests/expect/raw → shacl2code-0.0.16/tests/expect/raw/context}/test-context.txt +4 -0
- {shacl2code-0.0.14/tests/expect/raw → shacl2code-0.0.16/tests/expect/raw/nocontext}/test.txt +2 -0
- shacl2code-0.0.16/tests/test_cpp.py +1483 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/test_jsonschema.py +3 -3
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/test_model_source.py +2 -2
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/test_python.py +4 -17
- shacl2code-0.0.14/src/shacl2code/version.py +0 -1
- {shacl2code-0.0.14 → shacl2code-0.0.16}/.flake8 +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/.github/workflows/coverage-report.yaml +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/.github/workflows/publish.yaml +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/.gitignore +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/LICENSE +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/pyproject.toml +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/src/shacl2code/__init__.py +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/src/shacl2code/__main__.py +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/src/shacl2code/context.py +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/src/shacl2code/lang/jinja.py +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/src/shacl2code/lang/jsonschema.py +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/src/shacl2code/lang/lang.py +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/src/shacl2code/lang/python.py +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/src/shacl2code/lang/templates/jsonschema.j2 +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/src/shacl2code/main.py +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/src/shacl2code/urlcontext.py +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/testfixtures/httpserver.py +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/data/abort.j2 +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/data/bad-id.j2 +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/data/bad-node-kind.ttl +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/data/bad-pattern-class.ttl +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/data/bad-pattern-integer.ttl +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/data/bad-reference.jsonld +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/data/context-url.j2 +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/data/context.j2 +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/data/missing-range.ttl +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/data/python/bad-object-type-inline.json +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/data/python/bad-object-type-ref-after.json +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/data/python/bad-object-type-ref-before.json +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/data/python/links.json +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/data/raw.j2 +0 -0
- {shacl2code-0.0.14/tests/data/python → shacl2code-0.0.16/tests/data}/roundtrip.json +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/test_cli.py +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/test_common_jinja.py +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/test_common_prefix.py +0 -0
- {shacl2code-0.0.14 → shacl2code-0.0.16}/tests/test_context.py +0 -0
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: shacl2code
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.16
|
|
4
4
|
Summary: Convert SHACL model file to code bindings
|
|
5
5
|
Project-URL: Homepage, https://github.com/JPEWdev/shacl2code
|
|
6
6
|
Project-URL: Repository, https://github.com/JPEWdev/shacl2code.git
|
|
7
7
|
Project-URL: Issues, https://github.com/JPEWdev/shacl2code/issues
|
|
8
8
|
Author-email: Joshua Watt <JPEWhacker@gmail.com>
|
|
9
|
-
License-File: LICENSE
|
|
10
9
|
Classifier: Development Status :: 4 - Beta
|
|
11
10
|
Classifier: Intended Audience :: Developers
|
|
12
11
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -183,7 +182,36 @@ from an extensible type.
|
|
|
183
182
|
By default, classes generated by `shacl2code` are all instantiable (i.e. they
|
|
184
183
|
can be created). In some instances, it may be desirable to declare a class as
|
|
185
184
|
abstract (meaning that it cannot be instantiated, but non-abstract derived
|
|
186
|
-
classes can).
|
|
185
|
+
classes can). There are several ways of marking a class as abstract listed
|
|
186
|
+
below, in order of preference (with the most preferred being first).
|
|
187
|
+
|
|
188
|
+
#### SHACL Validated Abstract Classes
|
|
189
|
+
|
|
190
|
+
A class can be prevented from being directly instantiated using SHACL by adding
|
|
191
|
+
a constraint on the shape that it cannot be of its own type. This can be done
|
|
192
|
+
with the following turtle:
|
|
193
|
+
|
|
194
|
+
```ttl
|
|
195
|
+
|
|
196
|
+
<MyClass> a owl:Class, sh:NodeShape ;
|
|
197
|
+
# SHACL to prevent a class from being instansiated as this exact type
|
|
198
|
+
sh:property [
|
|
199
|
+
sh:path rdf:type ;
|
|
200
|
+
sh:not [ sh:hasValue <MyClass> ]
|
|
201
|
+
] .
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
`shacl2code` will detect this pattern and generate abstract bindings for
|
|
206
|
+
`MyClass`.
|
|
207
|
+
|
|
208
|
+
This method is most preferred, since it is enforced by SHACL and not just
|
|
209
|
+
`shacl2code` bindings
|
|
210
|
+
|
|
211
|
+
#### shacl2code Annotation
|
|
212
|
+
|
|
213
|
+
`shacl2code` has a custom annotation that can be used to mark a class as
|
|
214
|
+
abstract. This can be done with the boolean `isAbstract` property. For
|
|
187
215
|
example, the following turtle will declare a class as abstract:
|
|
188
216
|
|
|
189
217
|
```ttl
|
|
@@ -196,9 +224,10 @@ example, the following turtle will declare a class as abstract:
|
|
|
196
224
|
The `isAbstract` property is _not_ inherited by derived classes, so any derived
|
|
197
225
|
classes are automatically concrete unless they indicate otherwise.
|
|
198
226
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
227
|
+
#### SPDX Abstract Class Parent
|
|
228
|
+
|
|
229
|
+
It is also possible to define a class as abstract by declaring it to be of
|
|
230
|
+
type: `http://spdx.invalid./AbstractClass`, but this is not preferred.
|
|
202
231
|
|
|
203
232
|
[pytest]: https://www.pytest.org
|
|
204
233
|
[pytest-cov]: https://pytest-cov.readthedocs.io/en/latest/
|
|
@@ -153,7 +153,36 @@ from an extensible type.
|
|
|
153
153
|
By default, classes generated by `shacl2code` are all instantiable (i.e. they
|
|
154
154
|
can be created). In some instances, it may be desirable to declare a class as
|
|
155
155
|
abstract (meaning that it cannot be instantiated, but non-abstract derived
|
|
156
|
-
classes can).
|
|
156
|
+
classes can). There are several ways of marking a class as abstract listed
|
|
157
|
+
below, in order of preference (with the most preferred being first).
|
|
158
|
+
|
|
159
|
+
#### SHACL Validated Abstract Classes
|
|
160
|
+
|
|
161
|
+
A class can be prevented from being directly instantiated using SHACL by adding
|
|
162
|
+
a constraint on the shape that it cannot be of its own type. This can be done
|
|
163
|
+
with the following turtle:
|
|
164
|
+
|
|
165
|
+
```ttl
|
|
166
|
+
|
|
167
|
+
<MyClass> a owl:Class, sh:NodeShape ;
|
|
168
|
+
# SHACL to prevent a class from being instansiated as this exact type
|
|
169
|
+
sh:property [
|
|
170
|
+
sh:path rdf:type ;
|
|
171
|
+
sh:not [ sh:hasValue <MyClass> ]
|
|
172
|
+
] .
|
|
173
|
+
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
`shacl2code` will detect this pattern and generate abstract bindings for
|
|
177
|
+
`MyClass`.
|
|
178
|
+
|
|
179
|
+
This method is most preferred, since it is enforced by SHACL and not just
|
|
180
|
+
`shacl2code` bindings
|
|
181
|
+
|
|
182
|
+
#### shacl2code Annotation
|
|
183
|
+
|
|
184
|
+
`shacl2code` has a custom annotation that can be used to mark a class as
|
|
185
|
+
abstract. This can be done with the boolean `isAbstract` property. For
|
|
157
186
|
example, the following turtle will declare a class as abstract:
|
|
158
187
|
|
|
159
188
|
```ttl
|
|
@@ -166,9 +195,10 @@ example, the following turtle will declare a class as abstract:
|
|
|
166
195
|
The `isAbstract` property is _not_ inherited by derived classes, so any derived
|
|
167
196
|
classes are automatically concrete unless they indicate otherwise.
|
|
168
197
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
198
|
+
#### SPDX Abstract Class Parent
|
|
199
|
+
|
|
200
|
+
It is also possible to define a class as abstract by declaring it to be of
|
|
201
|
+
type: `http://spdx.invalid./AbstractClass`, but this is not preferred.
|
|
172
202
|
|
|
173
203
|
[pytest]: https://www.pytest.org
|
|
174
204
|
[pytest-cov]: https://pytest-cov.readthedocs.io/en/latest/
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
from .lang import LANGUAGES # noqa: F401
|
|
7
7
|
|
|
8
8
|
# All renderers must be imported here to be registered
|
|
9
|
+
from .cpp import CppRender # noqa: F401
|
|
9
10
|
from .jinja import JinjaRender # noqa: F401
|
|
10
|
-
from .python import PythonRender # noqa: F401
|
|
11
11
|
from .jsonschema import JsonSchemaRender # noqa: F401
|
|
12
|
+
from .python import PythonRender # noqa: F401
|
|
@@ -7,9 +7,12 @@ import sys
|
|
|
7
7
|
import os
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
from contextlib import contextmanager
|
|
10
|
+
import jinja2
|
|
10
11
|
from jinja2 import Environment, FileSystemLoader, TemplateRuntimeError
|
|
12
|
+
from markupsafe import Markup
|
|
11
13
|
from rdflib.namespace import SH
|
|
12
14
|
from ..model import SHACL2CODE
|
|
15
|
+
from ..version import VERSION
|
|
13
16
|
|
|
14
17
|
THIS_DIR = Path(__file__).parent
|
|
15
18
|
|
|
@@ -19,7 +22,7 @@ class OutputFile(object):
|
|
|
19
22
|
self.path = path
|
|
20
23
|
|
|
21
24
|
@contextmanager
|
|
22
|
-
def open(self):
|
|
25
|
+
def open(self, mode):
|
|
23
26
|
if self.path == "-":
|
|
24
27
|
yield sys.stdout
|
|
25
28
|
else:
|
|
@@ -27,34 +30,15 @@ class OutputFile(object):
|
|
|
27
30
|
yield f
|
|
28
31
|
|
|
29
32
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
Renderers that only use a single Jinja file can derive from this class. For
|
|
35
|
-
example:
|
|
36
|
-
|
|
37
|
-
@language("my-lang")
|
|
38
|
-
class MyRendered(BasicJinjaRenderer):
|
|
39
|
-
HELP = "Generates my-lang bindings"
|
|
33
|
+
@jinja2.pass_context
|
|
34
|
+
def include_file(ctx, name):
|
|
35
|
+
env = ctx.environment
|
|
36
|
+
return Markup(env.loader.get_source(env, name)[0])
|
|
40
37
|
|
|
41
|
-
def __init__(self, args):
|
|
42
|
-
super().__init__(args, PATH / TO / TEMPLATE)
|
|
43
|
-
"""
|
|
44
|
-
|
|
45
|
-
def __init__(self, args, template):
|
|
46
|
-
self.__output = args.output
|
|
47
|
-
self.__template = template
|
|
48
38
|
|
|
49
|
-
|
|
50
|
-
def
|
|
51
|
-
|
|
52
|
-
"--output",
|
|
53
|
-
"-o",
|
|
54
|
-
type=OutputFile,
|
|
55
|
-
help="Output file or '-' for stdout",
|
|
56
|
-
required=True,
|
|
57
|
-
)
|
|
39
|
+
class JinjaTemplateRender(object):
|
|
40
|
+
def __init__(self):
|
|
41
|
+
pass
|
|
58
42
|
|
|
59
43
|
def get_additional_render_args(self):
|
|
60
44
|
return {}
|
|
@@ -72,6 +56,7 @@ class BasicJinjaRender(object):
|
|
|
72
56
|
env.globals["abort"] = abort_helper
|
|
73
57
|
env.globals["SHACL2CODE"] = SHACL2CODE
|
|
74
58
|
env.globals["SH"] = SH
|
|
59
|
+
env.globals["SHACL2CODE_VERSION"] = VERSION
|
|
75
60
|
template = env.get_template(template.name)
|
|
76
61
|
|
|
77
62
|
render = template.render(
|
|
@@ -141,13 +126,49 @@ class BasicJinjaRender(object):
|
|
|
141
126
|
env = {
|
|
142
127
|
"get_all_derived": get_all_derived,
|
|
143
128
|
"get_all_named_individuals": get_all_named_individuals,
|
|
129
|
+
"include_file": include_file,
|
|
144
130
|
**self.get_extra_env(),
|
|
145
131
|
}
|
|
146
132
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
self.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
133
|
+
for output, template, args in self.get_outputs():
|
|
134
|
+
with output.open("w") as f:
|
|
135
|
+
self.render(
|
|
136
|
+
template,
|
|
137
|
+
f,
|
|
138
|
+
extra_env=env,
|
|
139
|
+
render_args={**render_args, **args},
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class BasicJinjaRender(JinjaTemplateRender):
|
|
144
|
+
"""
|
|
145
|
+
Common Jinja Template Renderer
|
|
146
|
+
|
|
147
|
+
Renderers that only use a single Jinja file can derive from this class. For
|
|
148
|
+
example:
|
|
149
|
+
|
|
150
|
+
@language("my-lang")
|
|
151
|
+
class MyRendered(BasicJinjaRenderer):
|
|
152
|
+
HELP = "Generates my-lang bindings"
|
|
153
|
+
|
|
154
|
+
def __init__(self, args):
|
|
155
|
+
super().__init__(args, PATH / TO / TEMPLATE)
|
|
156
|
+
"""
|
|
157
|
+
|
|
158
|
+
def __init__(self, args, template):
|
|
159
|
+
super().__init__()
|
|
160
|
+
self.__output = args.output
|
|
161
|
+
self.__template = template
|
|
162
|
+
|
|
163
|
+
@classmethod
|
|
164
|
+
def get_arguments(cls, parser):
|
|
165
|
+
parser.add_argument(
|
|
166
|
+
"--output",
|
|
167
|
+
"-o",
|
|
168
|
+
type=OutputFile,
|
|
169
|
+
help="Output file or '-' for stdout",
|
|
170
|
+
required=True,
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
def get_outputs(self):
|
|
174
|
+
yield self.__output, self.__template, {}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (c) 2024 Joshua Watt
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
from .common import JinjaTemplateRender
|
|
7
|
+
from .lang import language, TEMPLATE_DIR
|
|
8
|
+
from ..version import VERSION
|
|
9
|
+
|
|
10
|
+
import re
|
|
11
|
+
import textwrap
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def varname(*name):
|
|
16
|
+
name = "_".join(name)
|
|
17
|
+
# Any invalid characters at the beginning of the name are removed (except
|
|
18
|
+
# "@")
|
|
19
|
+
name = re.sub(r"^[^a-zA-Z0-9_@]*", "", name)
|
|
20
|
+
# Any other invalid characters are replaced with "_" (including "@")
|
|
21
|
+
name = re.sub(r"[^a-zA-Z0-9_]", "_", name)
|
|
22
|
+
# Consolidate runs of "_" to a single one
|
|
23
|
+
name = re.sub(r"__+", "_", name)
|
|
24
|
+
return name
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def parent_cpp_classes(cls, classes):
|
|
28
|
+
if cls.parent_ids:
|
|
29
|
+
parents = [varname(*classes.get(i).clsname) for i in cls.parent_ids]
|
|
30
|
+
else:
|
|
31
|
+
parents = ["SHACLObject"]
|
|
32
|
+
|
|
33
|
+
if cls.is_extensible:
|
|
34
|
+
parents = [f"SHACLExtensibleObject<{p}>" for p in parents]
|
|
35
|
+
|
|
36
|
+
return parents
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def prop_is_list(prop):
|
|
40
|
+
return prop.max_count is None or prop.max_count != 1
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def id_str(s):
|
|
44
|
+
return re.sub(r"[^a-zA-Z0-9_]", "_", s)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def comment_wrap(s):
|
|
48
|
+
return "\n".join(["*/", s, "/*"])
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@language("cpp")
|
|
52
|
+
class CppRender(JinjaTemplateRender):
|
|
53
|
+
HELP = "C++ Language Bindings"
|
|
54
|
+
|
|
55
|
+
SOURCES = (
|
|
56
|
+
"datetime.cpp",
|
|
57
|
+
"decode.cpp",
|
|
58
|
+
"encode.cpp",
|
|
59
|
+
"errorhandler.cpp",
|
|
60
|
+
"extensible.cpp",
|
|
61
|
+
"link.cpp",
|
|
62
|
+
"namedindividual.cpp",
|
|
63
|
+
"object.cpp",
|
|
64
|
+
"objectpath.cpp",
|
|
65
|
+
"objectset.cpp",
|
|
66
|
+
"property.cpp",
|
|
67
|
+
"propertyvalue.cpp",
|
|
68
|
+
"refproperty.cpp",
|
|
69
|
+
"type.cpp",
|
|
70
|
+
"util.cpp",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
HEADERS = (
|
|
74
|
+
"api.hpp",
|
|
75
|
+
"datetime.hpp",
|
|
76
|
+
"decode.hpp",
|
|
77
|
+
"encode.hpp",
|
|
78
|
+
"errorhandler.hpp",
|
|
79
|
+
"exceptions.hpp",
|
|
80
|
+
"extensible.hpp",
|
|
81
|
+
"link.hpp",
|
|
82
|
+
"namedindividual.hpp",
|
|
83
|
+
"object.hpp",
|
|
84
|
+
"objectpath.hpp",
|
|
85
|
+
"objectset.hpp",
|
|
86
|
+
"prop.hpp",
|
|
87
|
+
"property.hpp",
|
|
88
|
+
"propertyvalue.hpp",
|
|
89
|
+
"ref.hpp",
|
|
90
|
+
"refproperty.hpp",
|
|
91
|
+
"type.hpp",
|
|
92
|
+
"util.hpp",
|
|
93
|
+
"walk.hpp",
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
def __init__(self, args):
|
|
97
|
+
super().__init__()
|
|
98
|
+
self.basename = args.basename
|
|
99
|
+
self.namespace = args.namespace or id_str(args.basename.name)
|
|
100
|
+
self.lib_version = args.version
|
|
101
|
+
self.description = (
|
|
102
|
+
args.description or f"shacl2code generated binding {args.basename.name}"
|
|
103
|
+
)
|
|
104
|
+
self.macro_prefix = id_str("SHACL2CODE_" + self.basename.name).upper()
|
|
105
|
+
|
|
106
|
+
@classmethod
|
|
107
|
+
def get_arguments(cls, parser):
|
|
108
|
+
parser.add_argument(
|
|
109
|
+
"--output",
|
|
110
|
+
"-o",
|
|
111
|
+
type=Path,
|
|
112
|
+
help="Output file basename",
|
|
113
|
+
dest="basename",
|
|
114
|
+
required=True,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
parser.add_argument(
|
|
118
|
+
"--namespace",
|
|
119
|
+
"-n",
|
|
120
|
+
help="Output namespace. If unspecified, defaults to output basename",
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
parser.add_argument(
|
|
124
|
+
"--version",
|
|
125
|
+
metavar="MAJOR[.MINOR[.MICRO]]",
|
|
126
|
+
default=VERSION,
|
|
127
|
+
help="Library version",
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
parser.add_argument(
|
|
131
|
+
"--description",
|
|
132
|
+
help="Library description",
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
def get_outputs(self):
|
|
136
|
+
def suffix(s):
|
|
137
|
+
return self.basename.parent / (self.basename.name + s)
|
|
138
|
+
|
|
139
|
+
t = TEMPLATE_DIR / "cpp"
|
|
140
|
+
|
|
141
|
+
for s in self.SOURCES:
|
|
142
|
+
yield self.basename.parent / s, t / (s + ".j2"), {}
|
|
143
|
+
|
|
144
|
+
for s in self.HEADERS:
|
|
145
|
+
guard = f"_{self.macro_prefix}_{id_str(s).upper()}"
|
|
146
|
+
yield self.basename.parent / s, t / (s + ".j2"), {
|
|
147
|
+
"guard_begin": comment_wrap(
|
|
148
|
+
textwrap.dedent(
|
|
149
|
+
f"""\
|
|
150
|
+
#ifndef {guard}
|
|
151
|
+
#define {guard}
|
|
152
|
+
"""
|
|
153
|
+
)
|
|
154
|
+
),
|
|
155
|
+
"guard_end": comment_wrap(f"#endif // {guard}"),
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
yield suffix(".cpp"), t / "source.j2", {}
|
|
159
|
+
yield suffix(".hpp"), t / "header.j2", {
|
|
160
|
+
"headers": self.HEADERS,
|
|
161
|
+
}
|
|
162
|
+
yield suffix("-jsonld.cpp"), t / "jsonld-source.j2", {}
|
|
163
|
+
yield suffix("-jsonld.hpp"), t / "jsonld-header.j2", {}
|
|
164
|
+
|
|
165
|
+
yield self.basename.parent / "Makefile", t / "Makefile.j2", {
|
|
166
|
+
"lib_obj_files": " ".join(
|
|
167
|
+
s.replace(".cpp", ".o")
|
|
168
|
+
for s in self.SOURCES
|
|
169
|
+
+ (
|
|
170
|
+
f"{self.basename.name}.cpp",
|
|
171
|
+
f"{self.basename.name}-jsonld.cpp",
|
|
172
|
+
)
|
|
173
|
+
),
|
|
174
|
+
"headers": self.HEADERS
|
|
175
|
+
+ (
|
|
176
|
+
f"{self.basename.name}.hpp",
|
|
177
|
+
f"{self.basename.name}-jsonld.hpp",
|
|
178
|
+
),
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
yield suffix("-validate.cpp"), t / "validate.j2", {}
|
|
182
|
+
yield suffix(".pc"), t / "pkgconfig.pc.j2", {}
|
|
183
|
+
yield self.basename.parent / "Doxyfile", t / "Doxyfile.j2", {}
|
|
184
|
+
|
|
185
|
+
def get_extra_env(self):
|
|
186
|
+
return {
|
|
187
|
+
"varname": varname,
|
|
188
|
+
"prop_is_list": prop_is_list,
|
|
189
|
+
"parent_cpp_classes": parent_cpp_classes,
|
|
190
|
+
"macro_prefix": self.macro_prefix,
|
|
191
|
+
"api_def_begin": comment_wrap(
|
|
192
|
+
textwrap.dedent(
|
|
193
|
+
f"""\
|
|
194
|
+
#ifndef DOXYGEN_SKIP
|
|
195
|
+
#include "api.hpp"
|
|
196
|
+
// These are so that we don't have to use Jinja templates below since that messes up the formatting
|
|
197
|
+
#define EXPORT {self.macro_prefix}_API
|
|
198
|
+
#define LOCAL {self.macro_prefix}_LOCAL
|
|
199
|
+
#endif // DOXYGEN_SKIP
|
|
200
|
+
"""
|
|
201
|
+
)
|
|
202
|
+
),
|
|
203
|
+
"api_def_end": comment_wrap(
|
|
204
|
+
textwrap.dedent(
|
|
205
|
+
"""\
|
|
206
|
+
#undef EXPORT
|
|
207
|
+
#undef LOCAL
|
|
208
|
+
"""
|
|
209
|
+
)
|
|
210
|
+
),
|
|
211
|
+
"ns_begin": comment_wrap(
|
|
212
|
+
"\n".join(f"namespace {n} {{" for n in self.namespace.split("::"))
|
|
213
|
+
),
|
|
214
|
+
"ns_end": comment_wrap("\n".join("}" for n in self.namespace.split("::"))),
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
def get_additional_render_args(self):
|
|
218
|
+
return {
|
|
219
|
+
"basename": self.basename.name,
|
|
220
|
+
"namespace": self.namespace,
|
|
221
|
+
"nsprefix": f"::{self.namespace}" if self.namespace else "",
|
|
222
|
+
"lib_version": self.lib_version,
|
|
223
|
+
"lib_description": self.description,
|
|
224
|
+
}
|