shacl2code 0.0.2__tar.gz → 0.0.4__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.2 → shacl2code-0.0.4}/.github/workflows/publish.yaml +9 -8
- {shacl2code-0.0.2 → shacl2code-0.0.4}/.github/workflows/test.yaml +7 -0
- {shacl2code-0.0.2 → shacl2code-0.0.4}/PKG-INFO +32 -1
- shacl2code-0.0.4/README.md +32 -0
- shacl2code-0.0.4/conftest.py +14 -0
- {shacl2code-0.0.2 → shacl2code-0.0.4}/pyproject.toml +12 -1
- {shacl2code-0.0.2 → shacl2code-0.0.4/src}/shacl2code/__init__.py +1 -0
- shacl2code-0.0.4/src/shacl2code/__main__.py +12 -0
- shacl2code-0.0.4/src/shacl2code/lang/__init__.py +10 -0
- shacl2code-0.0.4/src/shacl2code/lang/common.py +71 -0
- shacl2code-0.0.4/src/shacl2code/lang/lang.py +15 -0
- shacl2code-0.0.4/src/shacl2code/lang/python.py +13 -0
- shacl2code-0.0.4/src/shacl2code/lang/raw.py +13 -0
- shacl2code-0.0.4/src/shacl2code/main.py +93 -0
- {shacl2code-0.0.2 → shacl2code-0.0.4/src}/shacl2code/model.py +0 -19
- {shacl2code-0.0.2 → shacl2code-0.0.4/src}/shacl2code/templates/python.j2 +1 -0
- shacl2code-0.0.4/src/shacl2code/templates/raw.j2 +7 -0
- shacl2code-0.0.4/src/shacl2code/version.py +1 -0
- shacl2code-0.0.4/tests/data/spdx3-model.jsonld +7816 -0
- shacl2code-0.0.4/tests/expect/python/spdx3.py +4039 -0
- shacl2code-0.0.4/tests/expect/raw/spdx3.txt +79 -0
- shacl2code-0.0.4/tests/test_cli.py +44 -0
- shacl2code-0.0.4/tests/test_python.py +107 -0
- shacl2code-0.0.4/tests/test_raw.py +117 -0
- shacl2code-0.0.2/README.md +0 -4
- shacl2code-0.0.2/shacl2code/main.py +0 -69
- shacl2code-0.0.2/shacl2code/version.py +0 -1
- {shacl2code-0.0.2 → shacl2code-0.0.4}/.gitignore +0 -0
- {shacl2code-0.0.2 → shacl2code-0.0.4}/LICENSE +0 -0
- {shacl2code-0.0.2 → shacl2code-0.0.4/src}/shacl2code/const.py +0 -0
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: Upload Python Package
|
|
3
3
|
on:
|
|
4
|
-
|
|
4
|
+
release:
|
|
5
|
+
types:
|
|
6
|
+
- published
|
|
5
7
|
|
|
6
8
|
jobs:
|
|
9
|
+
test:
|
|
10
|
+
uses: ./.github/workflows/test.yaml
|
|
11
|
+
|
|
7
12
|
deploy:
|
|
13
|
+
needs:
|
|
14
|
+
- test
|
|
15
|
+
|
|
8
16
|
runs-on: ubuntu-latest
|
|
9
17
|
permissions:
|
|
10
18
|
id-token: write
|
|
@@ -25,12 +33,5 @@ jobs:
|
|
|
25
33
|
- name: Build package
|
|
26
34
|
run: python -m build
|
|
27
35
|
|
|
28
|
-
- name: Publish distribution to Test PyPI
|
|
29
|
-
uses: pypa/gh-action-pypi-publish@release/v1
|
|
30
|
-
with:
|
|
31
|
-
repository-url: https://test.pypi.org/legacy/
|
|
32
|
-
skip-existing: true
|
|
33
|
-
|
|
34
36
|
- name: Publish distribution to PyPI
|
|
35
|
-
if: startsWith(github.ref, 'refs/tags')
|
|
36
37
|
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -3,6 +3,7 @@ name: Test shacl2code
|
|
|
3
3
|
on:
|
|
4
4
|
- push
|
|
5
5
|
- pull_request
|
|
6
|
+
- workflow_call
|
|
6
7
|
|
|
7
8
|
jobs:
|
|
8
9
|
build:
|
|
@@ -28,6 +29,12 @@ jobs:
|
|
|
28
29
|
- name: Build package
|
|
29
30
|
run: |
|
|
30
31
|
python -m build
|
|
32
|
+
- name: Install package
|
|
33
|
+
run: |
|
|
34
|
+
pip install -e .[dev]
|
|
35
|
+
- name: Run tests
|
|
36
|
+
run: |
|
|
37
|
+
pytest -v
|
|
31
38
|
lint:
|
|
32
39
|
runs-on: ubuntu-latest
|
|
33
40
|
steps:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: shacl2code
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.4
|
|
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
|
|
@@ -19,9 +19,40 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
19
19
|
Classifier: Topic :: Software Development :: Build Tools
|
|
20
20
|
Requires-Dist: jinja2>=3.1.2
|
|
21
21
|
Requires-Dist: pyld>=2.0.3
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: pytest-server-fixtures>=1.7; extra == 'dev'
|
|
24
|
+
Requires-Dist: pytest>=7.4; extra == 'dev'
|
|
22
25
|
Description-Content-Type: text/markdown
|
|
23
26
|
|
|
24
27
|
# Convert SHACL Model to code bindings
|
|
25
28
|
|
|
26
29
|
This tool can be used to convert a JSONLD SHACL model into various code
|
|
27
30
|
bindings
|
|
31
|
+
|
|
32
|
+
## Installation
|
|
33
|
+
|
|
34
|
+
`shacl2code` can be installed using pip:
|
|
35
|
+
|
|
36
|
+
```shell
|
|
37
|
+
python3 -m pip install shacl2code
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Usage
|
|
41
|
+
|
|
42
|
+
`shacl2code` can generate bindings from either a local file:
|
|
43
|
+
```shell
|
|
44
|
+
shacl2code generate -i model.jsonld python -o out.py
|
|
45
|
+
```
|
|
46
|
+
Or from a URL:
|
|
47
|
+
```shell
|
|
48
|
+
shacl2code generate -i https://spdx.github.io/spdx-3-model/model.jsonld python -o out.py
|
|
49
|
+
```
|
|
50
|
+
Or from stdin:
|
|
51
|
+
```shell
|
|
52
|
+
cat model.jsonld | shacl2code generate -i - python -o - > out.py
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
For more information, run:
|
|
56
|
+
```shell
|
|
57
|
+
shacl2code --help
|
|
58
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Convert SHACL Model to code bindings
|
|
2
|
+
|
|
3
|
+
This tool can be used to convert a JSONLD SHACL model into various code
|
|
4
|
+
bindings
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
`shacl2code` can be installed using pip:
|
|
9
|
+
|
|
10
|
+
```shell
|
|
11
|
+
python3 -m pip install shacl2code
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
`shacl2code` can generate bindings from either a local file:
|
|
17
|
+
```shell
|
|
18
|
+
shacl2code generate -i model.jsonld python -o out.py
|
|
19
|
+
```
|
|
20
|
+
Or from a URL:
|
|
21
|
+
```shell
|
|
22
|
+
shacl2code generate -i https://spdx.github.io/spdx-3-model/model.jsonld python -o out.py
|
|
23
|
+
```
|
|
24
|
+
Or from stdin:
|
|
25
|
+
```shell
|
|
26
|
+
cat model.jsonld | shacl2code generate -i - python -o - > out.py
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
For more information, run:
|
|
30
|
+
```shell
|
|
31
|
+
shacl2code --help
|
|
32
|
+
```
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (c) 2024 Joshua Watt
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
from pytest_server_fixtures.http import SimpleHTTPTestServer
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.fixture
|
|
11
|
+
def http_server():
|
|
12
|
+
with SimpleHTTPTestServer() as s:
|
|
13
|
+
s.start()
|
|
14
|
+
yield s
|
|
@@ -24,6 +24,12 @@ classifiers = [
|
|
|
24
24
|
"Programming Language :: Python :: 3.12",
|
|
25
25
|
]
|
|
26
26
|
|
|
27
|
+
[project.optional-dependencies]
|
|
28
|
+
dev = [
|
|
29
|
+
"pytest >= 7.4",
|
|
30
|
+
"pytest-server-fixtures >= 1.7"
|
|
31
|
+
]
|
|
32
|
+
|
|
27
33
|
[project.urls]
|
|
28
34
|
Homepage = "https://github.com/JPEWdev/shacl2code"
|
|
29
35
|
Repository = "https://github.com/JPEWdev/shacl2code.git"
|
|
@@ -37,4 +43,9 @@ requires = ["hatchling"]
|
|
|
37
43
|
build-backend = "hatchling.build"
|
|
38
44
|
|
|
39
45
|
[tool.hatch.version]
|
|
40
|
-
path = "shacl2code/version.py"
|
|
46
|
+
path = "src/shacl2code/version.py"
|
|
47
|
+
|
|
48
|
+
[tool.pytest.ini_options]
|
|
49
|
+
addopts = [
|
|
50
|
+
"--import-mode=importlib",
|
|
51
|
+
]
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (c) 2024 Joshua Watt
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
import sys
|
|
7
|
+
import os
|
|
8
|
+
from contextlib import contextmanager
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from jinja2 import Environment, FileSystemLoader, TemplateRuntimeError
|
|
11
|
+
|
|
12
|
+
from ..const import TEMPLATE_DIR
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class OutputFile(object):
|
|
16
|
+
def __init__(self, path):
|
|
17
|
+
self.path = path
|
|
18
|
+
|
|
19
|
+
@contextmanager
|
|
20
|
+
def open(self):
|
|
21
|
+
if self.path == "-":
|
|
22
|
+
yield sys.stdout
|
|
23
|
+
else:
|
|
24
|
+
with open(self.path, "w") as f:
|
|
25
|
+
yield f
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class BasicJinjaRender(object):
|
|
29
|
+
"""
|
|
30
|
+
Common Jinja Template Renderer
|
|
31
|
+
|
|
32
|
+
Renderers that only use a single Jinja file can derive from this class. The
|
|
33
|
+
class should set the class member variable `TEMPLATE` to indicate which
|
|
34
|
+
template file to use. For example:
|
|
35
|
+
|
|
36
|
+
@language("my-lang")
|
|
37
|
+
class MyRendered(BasicJinjaRenderer):
|
|
38
|
+
HELP = "Generates my-lang bindings"
|
|
39
|
+
TEMPLATE = "my-lang.j2"
|
|
40
|
+
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(self):
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def get_arguments(cls, parser):
|
|
48
|
+
parser.add_argument(
|
|
49
|
+
"--output",
|
|
50
|
+
"-o",
|
|
51
|
+
type=OutputFile,
|
|
52
|
+
help="Output file or '-' for stdout",
|
|
53
|
+
required=True,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
def output(self, args, model):
|
|
57
|
+
def abort_helper(msg):
|
|
58
|
+
raise TemplateRuntimeError(msg)
|
|
59
|
+
|
|
60
|
+
env = Environment(loader=FileSystemLoader(TEMPLATE_DIR))
|
|
61
|
+
env.globals["abort"] = abort_helper
|
|
62
|
+
template = env.get_template(self.TEMPLATE)
|
|
63
|
+
|
|
64
|
+
render = template.render(
|
|
65
|
+
disclaimer=f"This file was automatically generated by {os.path.basename(sys.argv[0])}. DO NOT MANUALLY MODIFY IT",
|
|
66
|
+
enums=model.get_template_enums(),
|
|
67
|
+
classes=model.get_template_classes(),
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
with args.output.open() as f:
|
|
71
|
+
f.write(render)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (c) 2024 Joshua Watt
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
from .common import BasicJinjaRender
|
|
7
|
+
from .lang import language
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@language("python")
|
|
11
|
+
class PythonRender(BasicJinjaRender):
|
|
12
|
+
HELP = "Python Language Bindings"
|
|
13
|
+
TEMPLATE = "python.j2"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Copyright (c) 2024 Joshua Watt
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: MIT
|
|
5
|
+
|
|
6
|
+
from .common import BasicJinjaRender
|
|
7
|
+
from .lang import language
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@language("raw")
|
|
11
|
+
class RawRender(BasicJinjaRender):
|
|
12
|
+
HELP = "Raw Jinja Output (for testing)"
|
|
13
|
+
TEMPLATE = "raw.j2"
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#! /usr/bin/env python3
|
|
2
|
+
#
|
|
3
|
+
# Copyright (c) 2024 Joshua Watt
|
|
4
|
+
#
|
|
5
|
+
# SPDX-License-Identifier: MIT
|
|
6
|
+
|
|
7
|
+
import argparse
|
|
8
|
+
import json
|
|
9
|
+
import sys
|
|
10
|
+
import urllib.request
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
from . import Model
|
|
14
|
+
from .version import VERSION
|
|
15
|
+
from .lang import LANGUAGES
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def main():
|
|
19
|
+
def handle_generate(args):
|
|
20
|
+
if "://" in args.input:
|
|
21
|
+
with urllib.request.urlopen(args.input) as url:
|
|
22
|
+
model_data = json.load(url)
|
|
23
|
+
elif args.input == "-":
|
|
24
|
+
model_data = json.load(sys.stdin)
|
|
25
|
+
else:
|
|
26
|
+
with Path(args.input).open("r") as f:
|
|
27
|
+
model_data = json.load(f)
|
|
28
|
+
|
|
29
|
+
m = Model(model_data)
|
|
30
|
+
|
|
31
|
+
render = args.lang()
|
|
32
|
+
render.output(args, m)
|
|
33
|
+
return 0
|
|
34
|
+
|
|
35
|
+
def handle_list(args):
|
|
36
|
+
width = max(len(lang) for lang in LANGUAGES)
|
|
37
|
+
for k, v in LANGUAGES.items():
|
|
38
|
+
if args.short:
|
|
39
|
+
print(k)
|
|
40
|
+
else:
|
|
41
|
+
print(f"{k:{width}} - {v.HELP}")
|
|
42
|
+
|
|
43
|
+
return 0
|
|
44
|
+
|
|
45
|
+
def handle_version(args):
|
|
46
|
+
print(VERSION)
|
|
47
|
+
return 0
|
|
48
|
+
|
|
49
|
+
parser = argparse.ArgumentParser(
|
|
50
|
+
description=f"Convert JSON-LD model to python. Version {VERSION}"
|
|
51
|
+
)
|
|
52
|
+
command_subparser = parser.add_subparsers(
|
|
53
|
+
title="command",
|
|
54
|
+
description="Command to execute",
|
|
55
|
+
required=True,
|
|
56
|
+
)
|
|
57
|
+
generate_parser = command_subparser.add_parser(
|
|
58
|
+
"generate",
|
|
59
|
+
help="Generate language bindings",
|
|
60
|
+
)
|
|
61
|
+
generate_parser.add_argument(
|
|
62
|
+
"--input",
|
|
63
|
+
"-i",
|
|
64
|
+
help="Input JSON-LD model (path, URL, or '-')",
|
|
65
|
+
required=True,
|
|
66
|
+
)
|
|
67
|
+
generate_parser.set_defaults(func=handle_generate)
|
|
68
|
+
|
|
69
|
+
lang_subparser = generate_parser.add_subparsers(
|
|
70
|
+
title="language",
|
|
71
|
+
description="Language to generate",
|
|
72
|
+
required=True,
|
|
73
|
+
)
|
|
74
|
+
for k, v in LANGUAGES.items():
|
|
75
|
+
p = lang_subparser.add_parser(k, help=v.HELP)
|
|
76
|
+
v.get_arguments(p)
|
|
77
|
+
p.set_defaults(lang=v)
|
|
78
|
+
|
|
79
|
+
list_parser = command_subparser.add_parser("list", help="List languages")
|
|
80
|
+
list_parser.add_argument(
|
|
81
|
+
"--short",
|
|
82
|
+
"-s",
|
|
83
|
+
action="store_true",
|
|
84
|
+
help="Only list languages without descriptions",
|
|
85
|
+
)
|
|
86
|
+
list_parser.set_defaults(func=handle_list)
|
|
87
|
+
|
|
88
|
+
version_parser = command_subparser.add_parser("version", help="Show version")
|
|
89
|
+
version_parser.set_defaults(func=handle_version)
|
|
90
|
+
|
|
91
|
+
args = parser.parse_args()
|
|
92
|
+
|
|
93
|
+
return args.func(args)
|
|
@@ -9,11 +9,6 @@ import re
|
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
|
|
11
11
|
from pyld import jsonld
|
|
12
|
-
from jinja2 import Environment, FileSystemLoader, TemplateRuntimeError
|
|
13
|
-
|
|
14
|
-
from .const import TEMPLATE_DIR
|
|
15
|
-
|
|
16
|
-
THIS_FILE = Path(__file__)
|
|
17
12
|
|
|
18
13
|
|
|
19
14
|
def get_prop(o, name, key, default=None):
|
|
@@ -207,17 +202,3 @@ class Model(object):
|
|
|
207
202
|
done_classes.add(clsname)
|
|
208
203
|
|
|
209
204
|
return template_classes
|
|
210
|
-
|
|
211
|
-
def render_template(self, lang):
|
|
212
|
-
def abort_helper(msg):
|
|
213
|
-
raise TemplateRuntimeError(msg)
|
|
214
|
-
|
|
215
|
-
env = Environment(loader=FileSystemLoader(TEMPLATE_DIR))
|
|
216
|
-
env.globals["abort"] = abort_helper
|
|
217
|
-
template = env.get_template(lang + ".j2")
|
|
218
|
-
|
|
219
|
-
return template.render(
|
|
220
|
-
disclaimer=f"This file was automatically generated by {THIS_FILE.name}. DO NOT MANUALLY MODIFY IT",
|
|
221
|
-
enums=self.get_template_enums(),
|
|
222
|
-
classes=self.get_template_classes(),
|
|
223
|
-
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
VERSION = "0.0.4"
|