juice-json-schemas 0.0.1__py3-none-any.whl
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.
- juice_json_schemas/__init__.py +0 -0
- juice_json_schemas/cli.py +59 -0
- juice_json_schemas/py.typed +0 -0
- juice_json_schemas/validation.py +72 -0
- juice_json_schemas-0.0.1.dist-info/LICENSE +20 -0
- juice_json_schemas-0.0.1.dist-info/METADATA +106 -0
- juice_json_schemas-0.0.1.dist-info/RECORD +9 -0
- juice_json_schemas-0.0.1.dist-info/WHEEL +4 -0
- juice_json_schemas-0.0.1.dist-info/entry_points.txt +5 -0
|
File without changes
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import logging
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
from juice_json_schemas.validation import ValidationError, validate_json
|
|
6
|
+
|
|
7
|
+
logging.basicConfig(level=logging.INFO)
|
|
8
|
+
logger = logging.getLogger(__name__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def parse(instance_file, schema_file_or_url):
|
|
12
|
+
try:
|
|
13
|
+
validate_json(instance_file, schema_file_or_url)
|
|
14
|
+
except ValidationError as e:
|
|
15
|
+
logger.exception(e.get_message())
|
|
16
|
+
sys.exit(1)
|
|
17
|
+
|
|
18
|
+
errors = validate_json(instance_file, schema_file_or_url)
|
|
19
|
+
|
|
20
|
+
if not errors:
|
|
21
|
+
logger.info("✅ JSON is valid according to the schema.")
|
|
22
|
+
else:
|
|
23
|
+
logger.error("❌ Found %d validation error(s):\n", len(errors))
|
|
24
|
+
for i, error in enumerate(errors, 1):
|
|
25
|
+
path = "/".join(map(str, error.path)) or "(root)"
|
|
26
|
+
logger.info(" %d. Path: %s", i, path)
|
|
27
|
+
logger.info(" Message: %s\n", error.message)
|
|
28
|
+
sys.exit(1)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def main():
|
|
32
|
+
argparser = argparse.ArgumentParser()
|
|
33
|
+
argparser.description = "Validate a JSON file against a generic schema."
|
|
34
|
+
argparser.add_argument("json_file", help="Path to the JSON file to be validated")
|
|
35
|
+
argparser.add_argument("schema_file_or_url", help="Path to the schema file or URL")
|
|
36
|
+
args = argparser.parse_args()
|
|
37
|
+
parse(args.json_file, args.schema_file_or_url)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def apl():
|
|
41
|
+
argparser = argparse.ArgumentParser()
|
|
42
|
+
argparser.description = "Validate a JSON file against the JUICE APL schema."
|
|
43
|
+
argparser.add_argument("json_file", help="Path to the APL file to be validated")
|
|
44
|
+
args = argparser.parse_args()
|
|
45
|
+
parse(
|
|
46
|
+
args.json_file,
|
|
47
|
+
"https://juicesoc.esac.esa.int/data/schemas/jsoc-apl-schema.json",
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def opl():
|
|
52
|
+
argparser = argparse.ArgumentParser()
|
|
53
|
+
argparser.description = "Validate a OPL file against the JUICE OPL schema."
|
|
54
|
+
argparser.add_argument("json_file", help="Path to the OPL file to be validated")
|
|
55
|
+
args = argparser.parse_args()
|
|
56
|
+
parse(
|
|
57
|
+
args.json_file,
|
|
58
|
+
"https://juicesoc.esac.esa.int/data/schemas/jsoc-opl-schema.json",
|
|
59
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from urllib.parse import urlparse
|
|
4
|
+
from urllib.request import urlopen
|
|
5
|
+
|
|
6
|
+
from jsonschema import Draft202012Validator
|
|
7
|
+
from jsonschema.exceptions import SchemaError
|
|
8
|
+
from referencing import Registry, Resource
|
|
9
|
+
from referencing.exceptions import CannotDetermineSpecification
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ValidationError(Exception):
|
|
13
|
+
def get_message(self):
|
|
14
|
+
return self.__str__()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class JsonFileError(ValidationError):
|
|
18
|
+
def __init__(self, file_path):
|
|
19
|
+
super().__init__(f"JSON file error: {file_path}")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class RemoteJsonFileError(ValidationError):
|
|
23
|
+
def __init__(self, url):
|
|
24
|
+
super().__init__(f"Remote JSON file error: {url}")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class InvalidJsonError(ValidationError):
|
|
28
|
+
def __init__(self, path):
|
|
29
|
+
super().__init__(f"Invalid JSON: {path}")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class InvalidSchemaError(ValidationError):
|
|
33
|
+
def __init__(self, path):
|
|
34
|
+
super().__init__(f"Invalid schema: {path}")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def load_json_from_path_or_url(path_or_url):
|
|
38
|
+
"""Load JSON either from a local file or from a URL."""
|
|
39
|
+
parsed = urlparse(path_or_url)
|
|
40
|
+
|
|
41
|
+
if parsed.scheme in ("http", "https"):
|
|
42
|
+
try:
|
|
43
|
+
with urlopen(path_or_url) as response: # noqa: S310
|
|
44
|
+
return json.load(response)
|
|
45
|
+
except Exception as e:
|
|
46
|
+
raise RemoteJsonFileError(path_or_url) from e
|
|
47
|
+
try:
|
|
48
|
+
path = Path(path_or_url)
|
|
49
|
+
with path.open(encoding="utf-8") as f:
|
|
50
|
+
return json.load(f)
|
|
51
|
+
except FileNotFoundError as e:
|
|
52
|
+
raise JsonFileError(path_or_url) from e
|
|
53
|
+
except json.JSONDecodeError as e:
|
|
54
|
+
raise InvalidJsonError(path_or_url) from e
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def validate_json(instance_path, schema_path):
|
|
58
|
+
"""Validate JSON instance against schema (local or remote), reporting all errors."""
|
|
59
|
+
instance = load_json_from_path_or_url(instance_path)
|
|
60
|
+
schema = load_json_from_path_or_url(schema_path)
|
|
61
|
+
|
|
62
|
+
try:
|
|
63
|
+
# Build a registry that knows where to find the root schema
|
|
64
|
+
registry = Registry().with_resource(schema_path, Resource.from_contents(schema))
|
|
65
|
+
validator = Draft202012Validator(schema, registry=registry)
|
|
66
|
+
except SchemaError as e:
|
|
67
|
+
raise InvalidSchemaError(schema_path) from e
|
|
68
|
+
except CannotDetermineSpecification as e:
|
|
69
|
+
raise InvalidSchemaError(schema_path) from e
|
|
70
|
+
|
|
71
|
+
# Return all errors sorted by their path
|
|
72
|
+
return sorted(validator.iter_errors(instance), key=lambda e: e.path)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 JUICE SOC Team <juice_uplink@cosmos.esa.int>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
7
|
+
the Software without restriction, including without limitation the rights to
|
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
|
10
|
+
subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: juice-json-schemas
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: A short description of the project
|
|
5
|
+
Home-page: https://.github.io/juice-json-schemas
|
|
6
|
+
License: MIT
|
|
7
|
+
Author: JUICE SOC Team
|
|
8
|
+
Author-email: juice_uplink@cosmos.esa.int
|
|
9
|
+
Requires-Python: >=3.9,<4.0
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Dist: jsonschema (>=4.25.1,<5.0.0)
|
|
24
|
+
Project-URL: Documentation, https://.github.io/juice-json-schemas
|
|
25
|
+
Project-URL: Repository, https://github.com//juice-json-schemas
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
# juice-json-schemas
|
|
29
|
+
|
|
30
|
+
[](https://pypi.python.org/pypi/juice-json-schemas/)
|
|
31
|
+
[](https://pypi.python.org/pypi/juice-json-schemas/)
|
|
32
|
+
[](https://pypi.python.org/pypi/juice-json-schemas/)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
**Documentation**: [https://juice-soc.io.esa.int/juice-uplink/spm/juice-json-schemas/](https://juice-soc.io.esa.int/juice-uplink/spm/juice-json-schemas/)
|
|
38
|
+
|
|
39
|
+
**Source Code**: [https://gitlab.esa.int/juice-soc/juice-uplink/spm/juice-json-schemas.git](https://gitlab.esa.int/juice-soc/juice-uplink/spm/juice-json-schemas.git)
|
|
40
|
+
|
|
41
|
+
**PyPI**: [https://pypi.org/project/juice-json-schemas/](https://pypi.org/project/juice-json-schemas/)
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
Library and utilities for validating JSON files against [JUICE mission](https://www.cosmos.esa.int/web/juice) data schemas or custom JSON Schemas.
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
pip install juice-json-schemas
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Development
|
|
54
|
+
|
|
55
|
+
* Clone this repository
|
|
56
|
+
* Requirements:
|
|
57
|
+
* [Poetry](https://python-poetry.org/)
|
|
58
|
+
* Python 3.9+
|
|
59
|
+
* Create a virtual environment and install the dependencies
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
poetry install
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
* Activate the virtual environment
|
|
66
|
+
|
|
67
|
+
```sh
|
|
68
|
+
poetry shell
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Testing
|
|
72
|
+
|
|
73
|
+
```sh
|
|
74
|
+
pytest
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Documentation
|
|
78
|
+
|
|
79
|
+
The documentation is automatically generated from the content of the [docs directory](https://github.com//juice-json-schemas/tree/master/docs) and from the docstrings
|
|
80
|
+
of the public signatures of the source code. The documentation is updated and published as a [Gitlab Pages page](https://pages.github.com/) automatically as part each release.
|
|
81
|
+
|
|
82
|
+
### Pre-commit
|
|
83
|
+
|
|
84
|
+
Pre-commit hooks run all the auto-formatting (`ruff format`), linters (e.g. `ruff`), and other quality
|
|
85
|
+
checks to make sure the changeset is in good shape before a commit/push happens.
|
|
86
|
+
|
|
87
|
+
You can install the hooks with (runs for each commit):
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
pre-commit install
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Or if you want them to run only for each push:
|
|
94
|
+
|
|
95
|
+
```sh
|
|
96
|
+
pre-commit install -t pre-push
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Or if you want e.g. want to run all checks manually for all files:
|
|
100
|
+
|
|
101
|
+
```sh
|
|
102
|
+
pre-commit run --all-files
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
juice_json_schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
juice_json_schemas/cli.py,sha256=HwETpZXVS3IMC44W-eX7Pno_YknEvy5NYu0NFjfRikw,2008
|
|
3
|
+
juice_json_schemas/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
juice_json_schemas/validation.py,sha256=iEbg2Nx9xKOKkuqjAmY4_CZ8MNuxOL4u7qnWGJHNotU,2386
|
|
5
|
+
juice_json_schemas-0.0.1.dist-info/LICENSE,sha256=xsT1xf3P0LmVw_7Z1CnJdLEJeT93puD72bAAddNkWXw,1111
|
|
6
|
+
juice_json_schemas-0.0.1.dist-info/METADATA,sha256=3cSqml-qSvd9koLoWfGrtyJkCBGXw6aO7zS-8tAEYeU,3337
|
|
7
|
+
juice_json_schemas-0.0.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
8
|
+
juice_json_schemas-0.0.1.dist-info/entry_points.txt,sha256=pQn6KZIdIH2cG_mNOO-DM3wA0-qAf3JbtuWIexPta7M,132
|
|
9
|
+
juice_json_schemas-0.0.1.dist-info/RECORD,,
|