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.
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
+ [![PyPI](https://img.shields.io/pypi/v/juice-json-schemas?style=flat-square)](https://pypi.python.org/pypi/juice-json-schemas/)
31
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/juice-json-schemas?style=flat-square)](https://pypi.python.org/pypi/juice-json-schemas/)
32
+ [![PyPI - License](https://img.shields.io/pypi/l/juice-json-schemas?style=flat-square)](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,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 1.9.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,5 @@
1
+ [console_scripts]
2
+ apl-check=juice_json_schemas.cli:apl
3
+ json-check=juice_json_schemas.cli:main
4
+ opl-check=juice_json_schemas.cli:opl
5
+