JSONSchemata 0.0.0.dev62__tar.gz → 0.1.1__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.
Files changed (73) hide show
  1. jsonschemata-0.1.1/PKG-INFO +8 -0
  2. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/pyproject.toml +5 -5
  3. jsonschemata-0.1.1/src/JSONSchemata.egg-info/PKG-INFO +8 -0
  4. jsonschemata-0.1.1/src/JSONSchemata.egg-info/requires.txt +4 -0
  5. jsonschemata-0.1.1/src/jsonschemata/__init__.py +5 -0
  6. jsonschemata-0.1.1/src/jsonschemata/edit.py +192 -0
  7. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/registry.py +51 -31
  8. jsonschemata-0.0.0.dev62/PKG-INFO +0 -8
  9. jsonschemata-0.0.0.dev62/src/JSONSchemata.egg-info/PKG-INFO +0 -8
  10. jsonschemata-0.0.0.dev62/src/JSONSchemata.egg-info/requires.txt +0 -4
  11. jsonschemata-0.0.0.dev62/src/jsonschemata/__init__.py +0 -1
  12. jsonschemata-0.0.0.dev62/src/jsonschemata/edit.py +0 -80
  13. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/MANIFEST.in +0 -0
  14. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/setup.cfg +0 -0
  15. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/JSONSchemata.egg-info/SOURCES.txt +0 -0
  16. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/JSONSchemata.egg-info/dependency_links.txt +0 -0
  17. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/JSONSchemata.egg-info/not-zip-safe +0 -0
  18. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/JSONSchemata.egg-info/top_level.txt +0 -0
  19. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/array/unique-strings.yaml +0 -0
  20. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/color/css-name.yaml +0 -0
  21. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/color/css.yaml +0 -0
  22. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/color/hex-string.yaml +0 -0
  23. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/color/hsl-array.yaml +0 -0
  24. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/color/hsl-string.yaml +0 -0
  25. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/color/hsla-array.yaml +0 -0
  26. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/color/rgb-array.yaml +0 -0
  27. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/color/rgb-string.yaml +0 -0
  28. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/color/rgba-array.yaml +0 -0
  29. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/config/github/form/body.yaml +0 -0
  30. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/config/github/funding.yaml +0 -0
  31. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/config/github/label/description.yaml +0 -0
  32. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/config/pydata-sphinx-theme.yaml +0 -0
  33. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/config/python/pyproject-entrypoint.yaml +0 -0
  34. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/config/python/pyproject-person.yaml +0 -0
  35. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/config/python/pyproject.yaml +0 -0
  36. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/config/setuptools.yaml +0 -0
  37. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/config/sphinx.yaml +0 -0
  38. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/config/versioningit.yaml +0 -0
  39. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/date/yyyy-mm-dd.yaml +0 -0
  40. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/id/doi.yaml +0 -0
  41. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/id/email.yaml +0 -0
  42. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/id/github/node.yaml +0 -0
  43. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/id/github/rest.yaml +0 -0
  44. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/id/github/user.yaml +0 -0
  45. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/id/linkedin.yaml +0 -0
  46. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/id/orcid.yaml +0 -0
  47. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/id/researchgate.yaml +0 -0
  48. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/id/spdx-license.yaml +0 -0
  49. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/id/twitter.yaml +0 -0
  50. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/integer/non-negative.yaml +0 -0
  51. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/number/non-negative.yaml +0 -0
  52. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/path/dir-name.yaml +0 -0
  53. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/path/posix/absolute-from-cwd.yaml +0 -0
  54. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/string/nonempty.yaml +0 -0
  55. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/string/oneline.yaml +0 -0
  56. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/uri/mailto.yaml +0 -0
  57. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/url/README.md +0 -0
  58. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/url/ftp.yaml +0 -0
  59. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/url/github/user.yaml +0 -0
  60. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/url/http-explicit.yaml +0 -0
  61. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/url/http-ftp-sftp.yaml +0 -0
  62. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/url/http-implicit.yaml +0 -0
  63. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/url/https.yaml +0 -0
  64. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/url/linkedin/company.yaml +0 -0
  65. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/url/linkedin/person.yaml +0 -0
  66. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/url/linkedin/user.yaml +0 -0
  67. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/url/orcid/user.yaml +0 -0
  68. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/url/researchgate/institution.yaml +0 -0
  69. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/url/researchgate/lab.yaml +0 -0
  70. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/url/researchgate/person.yaml +0 -0
  71. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/url/researchgate/user.yaml +0 -0
  72. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/url/sftp.yaml +0 -0
  73. {jsonschemata-0.0.0.dev62 → jsonschemata-0.1.1}/src/jsonschemata/_data/url/twitter/user.yaml +0 -0
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.4
2
+ Name: JSONSchemata
3
+ Version: 0.1.1
4
+ Requires-Python: >=3.10
5
+ Requires-Dist: referencing<0.37,>=0.35
6
+ Requires-Dist: PkgData<0.2,>=0.1
7
+ Requires-Dist: PySerials<0.2,>=0.1
8
+ Requires-Dist: PyLinks<0.2,>=0.1
@@ -17,12 +17,12 @@ namespaces = true
17
17
  # ----------------------------------------- Project Metadata -------------------------------------
18
18
  #
19
19
  [project]
20
- version = "0.0.0.dev62"
20
+ version = "0.1.1"
21
21
  name = "JSONSchemata"
22
22
  dependencies = [
23
- "referencing >= 0.35.1",
24
- "PkgData == 0.0.0.dev5",
25
- "PySerials == 0.0.0.dev66",
26
- "PyLinks == 0.0.0.dev76",
23
+ "referencing >=0.35,<0.37",
24
+ "PkgData >=0.1,<0.2",
25
+ "PySerials >=0.1,<0.2",
26
+ "PyLinks >=0.1,<0.2",
27
27
  ]
28
28
  requires-python = ">=3.10"
@@ -0,0 +1,8 @@
1
+ Metadata-Version: 2.4
2
+ Name: JSONSchemata
3
+ Version: 0.1.1
4
+ Requires-Python: >=3.10
5
+ Requires-Dist: referencing<0.37,>=0.35
6
+ Requires-Dist: PkgData<0.2,>=0.1
7
+ Requires-Dist: PySerials<0.2,>=0.1
8
+ Requires-Dist: PyLinks<0.2,>=0.1
@@ -0,0 +1,4 @@
1
+ referencing<0.37,>=0.35
2
+ PkgData<0.2,>=0.1
3
+ PySerials<0.2,>=0.1
4
+ PyLinks<0.2,>=0.1
@@ -0,0 +1,5 @@
1
+ """JSONSchemata: JSON Schema registry and utilities."""
2
+
3
+ from jsonschemata import edit, registry
4
+
5
+ __all__ = ["edit", "registry"]
@@ -0,0 +1,192 @@
1
+ """Utilities for modifying JSON schemas."""
2
+
3
+ from __future__ import annotations as _annotations
4
+
5
+ from typing import TYPE_CHECKING as _TYPE_CHECKING
6
+
7
+ if _TYPE_CHECKING:
8
+ from collections.abc import Callable
9
+
10
+
11
+ def required_last(schema: dict) -> dict:
12
+ """Recursively move ``required`` fields to the end of their schema dict.
13
+
14
+ Some JSON Schema validators (e.g. ``jsonschema`` with a default-filling extension)
15
+ process keywords in the order they appear in the schema dict.
16
+ When ``required`` is encountered *before* ``default`` values have been filled in,
17
+ validation fails even though the missing keys
18
+ would have been supplied by the defaults.
19
+ Moving ``required`` to the end of every schema dict
20
+ ensures that defaults are applied before presence is checked.
21
+
22
+ The function traverses the full schema tree,
23
+ following all standard JSON Schema locations
24
+ that can contain subschemas:
25
+
26
+ * **Single subschemas**: ``if``, ``then``, ``else``, ``not``, ``items``,
27
+ ``unevaluatedItems``, ``contains``, ``additionalProperties``,
28
+ ``unevaluatedProperties``.
29
+ * **Lists of subschemas**: ``anyOf``, ``allOf``, ``oneOf``, ``prefixItems``.
30
+ * **Dicts of subschemas**: ``properties``, ``patternProperties``,
31
+ ``dependentSchemas``.
32
+
33
+ Parameters
34
+ ----------
35
+ schema : dict
36
+ The JSON schema to modify. Modified **in-place**.
37
+
38
+ Returns
39
+ -------
40
+ dict
41
+ The same (now modified) schema dict that was passed in.
42
+ """
43
+ if "required" in schema:
44
+ schema["required"] = schema.pop("required")
45
+ for key in ["anyOf", "allOf", "oneOf", "prefixItems"]:
46
+ if key in schema:
47
+ for subschema in schema[key]:
48
+ required_last(subschema)
49
+ for key in [
50
+ "if",
51
+ "then",
52
+ "else",
53
+ "not",
54
+ "items",
55
+ "unevaluatedItems",
56
+ "contains",
57
+ "additionalProperties",
58
+ "unevaluatedProperties",
59
+ ]:
60
+ if key in schema and isinstance(schema[key], dict):
61
+ required_last(schema[key])
62
+ for key in ["properties", "patternProperties", "dependentSchemas"]:
63
+ if key in schema and isinstance(schema[key], dict):
64
+ for subschema in schema[key].values():
65
+ required_last(subschema)
66
+ return schema
67
+
68
+
69
+ def add_property(
70
+ schema: dict,
71
+ prop: str,
72
+ value: dict,
73
+ conditioner: Callable[[dict, list], bool] | None = None,
74
+ current_path: list[str] | None = None,
75
+ ) -> dict:
76
+ """Inject a property into every ``properties`` block in a JSON schema tree.
77
+
78
+ The function walks the entire schema tree and,
79
+ at each node whose ``properties`` mapping passes the optional ``conditioner``,
80
+ adds ``prop: value`` to that mapping.
81
+ This makes it possible to, for example,
82
+ allow a sentinel key everywhere in a schema
83
+ that would otherwise reject unknown keys
84
+ via ``additionalProperties: false``.
85
+
86
+ Injection rule
87
+ --------------
88
+ ``prop`` is added to ``schema["properties"]``
89
+ at a given node when **both** of the following hold:
90
+
91
+ 1. The current schema dict contains a ``"properties"`` key.
92
+ 2. Either no ``conditioner`` was supplied, or
93
+ ``conditioner(schema, current_path)`` returns ``True``.
94
+
95
+ Traversal
96
+ ---------
97
+ After the (optional) injection at the current node, the function recurses into every
98
+ standard JSON Schema location that may contain nested subschemas:
99
+
100
+ * **Single subschemas** — ``if``, ``then``, ``else``, ``not``, ``items``,
101
+ ``unevaluatedItems``, ``contains``, ``additionalProperties``,
102
+ ``unevaluatedProperties``.
103
+ * **Lists of subschemas** — ``anyOf``, ``allOf``, ``oneOf``, ``prefixItems``:
104
+ each element is visited individually.
105
+ * **Dicts of subschemas** — ``properties``, ``patternProperties``,
106
+ ``dependentSchemas``: each *value* is visited individually (the values are the
107
+ subschemas; the dict itself is not).
108
+
109
+ Parameters
110
+ ----------
111
+ schema : dict
112
+ The root JSON schema to modify. Modified **in-place**.
113
+ prop : str
114
+ Name of the property to inject (e.g. ``"__temp__"``).
115
+ value : dict
116
+ The subschema to assign to the injected property
117
+ (e.g. ``{}`` to accept any value).
118
+ conditioner : Callable[[dict, list[str]], bool] | None, optional
119
+ A callable invoked before each potential injection with two arguments:
120
+
121
+ * ``schema`` — the candidate schema dict at the current traversal node.
122
+ * ``current_path`` — a list of strings tracing the path from the root schema
123
+ to the current node (e.g.
124
+ ``["properties[foo]", "anyOf[0]", "patternProperties[^bar_]"]``).
125
+ Useful for context-sensitive decisions such as skipping injection under
126
+ certain branches.
127
+
128
+ Return ``True`` to allow the injection at this node; ``False`` to skip it.
129
+ Recursion into child nodes continues regardless of the return value.
130
+ When ``None``, the property is injected at every node that has
131
+ a ``"properties"`` key.
132
+ current_path : list[str] | None, optional
133
+ Path from the schema root to the current node, used internally during
134
+ recursion and forwarded to ``conditioner``. Callers should leave this as
135
+ ``None``; it is initialised to ``[]`` automatically on the first call.
136
+
137
+ Returns
138
+ -------
139
+ dict
140
+ The same (now modified) schema dict that was passed in.
141
+ """
142
+ if current_path is None:
143
+ current_path = []
144
+
145
+ # Add the property to the current schema
146
+ # if it has a "properties" field and passes the conditioner (if any).
147
+ if "properties" in schema and (
148
+ not conditioner or conditioner(schema, current_path)
149
+ ):
150
+ schema["properties"][prop] = value
151
+
152
+ # Recurse into subschemas
153
+
154
+ # Single subschemas
155
+ for key in [
156
+ "if",
157
+ "then",
158
+ "else",
159
+ "not",
160
+ "items",
161
+ "unevaluatedItems",
162
+ "contains",
163
+ "additionalProperties",
164
+ "unevaluatedProperties",
165
+ ]:
166
+ if key in schema and isinstance(schema[key], dict):
167
+ add_property(schema[key], prop, value, conditioner, [*current_path, key])
168
+
169
+ # List of subschemas
170
+ for key in ["anyOf", "allOf", "oneOf", "prefixItems"]:
171
+ for idx, subschema in enumerate(schema.get(key, [])):
172
+ add_property(
173
+ subschema,
174
+ prop,
175
+ value,
176
+ conditioner,
177
+ [*current_path, f"{key}[{idx}]"],
178
+ )
179
+
180
+ # Dict of subschemas
181
+ for key in ["properties", "patternProperties", "dependentSchemas"]:
182
+ if key in schema and isinstance(schema[key], dict):
183
+ for property_name, subschema in schema[key].items():
184
+ add_property(
185
+ subschema,
186
+ prop,
187
+ value,
188
+ conditioner,
189
+ [*current_path, f"{key}[{property_name}]"],
190
+ )
191
+
192
+ return schema
@@ -1,34 +1,41 @@
1
+ """Utilities for creating and managing JSON Schema registries."""
2
+
1
3
  from __future__ import annotations as _annotations
2
4
 
3
5
  from typing import TYPE_CHECKING as _TYPE_CHECKING
4
6
 
5
- import referencing as _referencing
6
- from referencing import jsonschema as _ref_jsonschema, retrieval as _ref_retrieval
7
7
  import pkgdata as _pkgdata
8
- import pyserials as _ps
9
8
  import pylinks as _pl
9
+ import pyserials as _ps
10
+ import referencing as _referencing
11
+ from referencing import jsonschema as _ref_jsonschema
12
+ from referencing import retrieval as _ref_retrieval
10
13
 
11
14
  from jsonschemata import edit as _edit
12
15
 
13
16
  if _TYPE_CHECKING:
14
- from typing import Callable, Sequence
17
+ from collections.abc import Callable, Sequence
15
18
 
16
19
 
17
20
  def make(
18
- resources: Sequence[dict | _referencing.Resource | tuple[str, dict | _referencing.Resource]] | None = None,
21
+ resources: Sequence[
22
+ dict | _referencing.Resource | tuple[str, dict | _referencing.Resource]
23
+ ]
24
+ | None = None,
19
25
  default_specification: _referencing.Specification = _ref_jsonschema.DRAFT202012,
26
+ *,
20
27
  crawl: bool = True,
21
28
  clean: bool = False,
22
29
  dynamic: bool = True,
23
- retrieval_function: Callable[[str], str | _referencing.Resource] = None,
30
+ retrieval_function: Callable[[str], str | _referencing.Resource] | None = None,
24
31
  ) -> _referencing.Registry:
25
32
  """Create a JSON Schema registry.
26
33
 
27
34
  Parameters
28
35
  ----------
29
36
  resources
30
- A list of schema resources to add to the registry. Each resource can be a dictionary or
31
- a [`referencing.Resource`](https://referencing.readthedocs.io/en/stable/api/#referencing.Resource)
37
+ A list of schema resources to add to the registry. Each resource can be
38
+ a dictionary or a [`referencing.Resource`](https://referencing.readthedocs.io/en/stable/api/#referencing.Resource)
32
39
  object. If a schema does not have an "$id",
33
40
  the ID must be provided along with the resource as a tuple of (ID, schema).
34
41
  default_specification
@@ -45,8 +52,10 @@ def make(
45
52
  [Dynamically retrieve](https://referencing.readthedocs.io/en/stable/intro/#dynamically-retrieving-resources)
46
53
  and [cache](https://referencing.readthedocs.io/en/stable/intro/#caching)
47
54
  references that are not found in the registry.
48
- If set to True, the default behaviour is as follows (see `retrieval_function` for customization):
49
- If the reference URI starts with "http" or "https", the URI is fetched using an HTTP GET request.
55
+ If set to True, the default behaviour is as follows
56
+ (see `retrieval_function` for customization):
57
+ If the reference URI starts with "http" or "https",
58
+ the URI is fetched using an HTTP GET request.
50
59
  Otherwise, the URI is assumed to be a local filepath,
51
60
  which can be either absolute or relative to the current working directory.
52
61
  retrieval_function: Callable[[str], str | referencing.Resource], optional
@@ -55,57 +64,68 @@ def make(
55
64
  If you want the retrieval function to also cache the retrieved references,
56
65
  the function must be decorated with the
57
66
  [`@referencing.retrieval.to_cached_resource`](https://referencing.readthedocs.io/en/stable/api/#referencing.retrieval.to_cached_resource)
58
- decorator, in which case the function must return the reference schema as a JSON string
67
+ decorator, in which case the function must return the reference schema as
68
+ a JSON string
59
69
  (cf. [Referencing Docs](https://referencing.readthedocs.io/en/stable/intro/#caching)).
60
- If the decorator is not used, the function must return the schema as a `referencing.Resource` instead.
70
+ If the decorator is not used, the function must return the schema as a
71
+ `referencing.Resource` instead.
72
+
61
73
  Returns
62
74
  -------
63
75
  referencing.Registry
64
76
  A [`referencing.Registry`](https://referencing.readthedocs.io/en/stable/api/#referencing.Registry)
65
77
  object containing all resources.
66
78
  """
67
-
68
- @_ref_retrieval.to_cached_resource()
69
- def retrieve_url(uri: str) -> str:
70
- if uri.startswith(("http://", "https://")):
71
- return _pl.http.request(url=uri, response_type="str")
72
- return _ps.write.to_json_string(_ps.read.from_file(path=uri, toml_as_dict=True), sort_keys=False)
73
-
74
79
  full_resources = []
75
80
  id_resources: list[tuple[str, _referencing.Resource]] = []
76
81
 
77
82
  if not clean:
78
- schema_dir_path = _pkgdata.get_package_path_from_caller(top_level=True) / "_data"
83
+ pkg_path = _pkgdata.get_package_path_from_caller(top_level=True)
84
+ schema_dir_path = pkg_path / "_data"
79
85
  for schema_filepath in schema_dir_path.glob("**/*.yaml"):
80
86
  schema_dict = _ps.read.yaml_from_file(path=schema_filepath)
81
87
  _edit.required_last(schema_dict)
82
88
  schema = _referencing.Resource.from_contents(
83
- schema_dict, default_specification=_ref_jsonschema.DRAFT202012
89
+ schema_dict,
90
+ default_specification=_ref_jsonschema.DRAFT202012,
84
91
  )
85
92
  full_resources.append(schema)
86
93
  for add_resource in resources or []:
87
94
  resource_id = None
95
+ resource = add_resource
88
96
  if isinstance(add_resource, dict):
89
- add_resource = _referencing.Resource.from_contents(
90
- add_resource, default_specification=default_specification
97
+ resource = _referencing.Resource.from_contents(
98
+ add_resource,
99
+ default_specification=default_specification,
91
100
  )
92
101
  elif isinstance(add_resource, (list, tuple)):
93
102
  resource_id, resource_dict = add_resource
94
- add_resource = _referencing.Resource.from_contents(
95
- resource_dict, default_specification=default_specification,
103
+ resource = _referencing.Resource.from_contents(
104
+ resource_dict,
105
+ default_specification=default_specification,
96
106
  )
97
107
  if resource_id:
98
- id_resources.append((resource_id, add_resource))
108
+ id_resources.append((resource_id, resource))
99
109
  else:
100
- full_resources.append(add_resource)
110
+ full_resources.append(resource)
101
111
 
102
- registry = _referencing.Registry(
103
- retrieve=retrieval_function or retrieve_url
104
- ) if dynamic else _referencing.Registry()
112
+ registry = (
113
+ _referencing.Registry(retrieve=retrieval_function or _retrieve_url)
114
+ if dynamic
115
+ else _referencing.Registry()
116
+ )
105
117
  if full_resources:
106
118
  registry = full_resources @ registry
107
119
  if id_resources:
108
120
  registry = registry.with_resources(id_resources)
109
121
  if crawl:
110
- registry.crawl()
122
+ registry = registry.crawl()
111
123
  return registry
124
+
125
+
126
+ @_ref_retrieval.to_cached_resource()
127
+ def _retrieve_url(uri: str) -> str:
128
+ if uri.startswith(("http://", "https://")):
129
+ return _pl.http.request(url=uri, response_type="str")
130
+ file_schema = _ps.read.from_file(path=uri, toml_as_dict=True)
131
+ return _ps.write.to_json_string(file_schema, sort_keys=False)
@@ -1,8 +0,0 @@
1
- Metadata-Version: 2.2
2
- Name: JSONSchemata
3
- Version: 0.0.0.dev62
4
- Requires-Python: >=3.10
5
- Requires-Dist: referencing>=0.35.1
6
- Requires-Dist: PkgData==0.0.0.dev5
7
- Requires-Dist: PySerials==0.0.0.dev66
8
- Requires-Dist: PyLinks==0.0.0.dev76
@@ -1,8 +0,0 @@
1
- Metadata-Version: 2.2
2
- Name: JSONSchemata
3
- Version: 0.0.0.dev62
4
- Requires-Python: >=3.10
5
- Requires-Dist: referencing>=0.35.1
6
- Requires-Dist: PkgData==0.0.0.dev5
7
- Requires-Dist: PySerials==0.0.0.dev66
8
- Requires-Dist: PyLinks==0.0.0.dev76
@@ -1,4 +0,0 @@
1
- referencing>=0.35.1
2
- PkgData==0.0.0.dev5
3
- PySerials==0.0.0.dev66
4
- PyLinks==0.0.0.dev76
@@ -1 +0,0 @@
1
- from jsonschemata import edit, registry
@@ -1,80 +0,0 @@
1
- from __future__ import annotations as _annotations
2
-
3
- from typing import TYPE_CHECKING as _TYPE_CHECKING
4
-
5
- if _TYPE_CHECKING:
6
- from typing import Callable
7
-
8
-
9
- def required_last(schema: dict) -> dict:
10
- """Modify JSON schema to recursively put all 'required' fields at the end of the schema.
11
-
12
- This is done because otherwise the 'required' fields
13
- are checked by jsonschema before filling the defaults,
14
- which can cause the validation to fail.
15
-
16
- Returns
17
- -------
18
- dict
19
- Modified schema.
20
- Note that the input schema is modified in-place,
21
- so the return value is a reference to the (now modified) input schema.
22
- """
23
- if "required" in schema:
24
- schema["required"] = schema.pop("required")
25
- for key in ["anyOf", "allOf", "oneOf", "prefixItems"]:
26
- if key in schema:
27
- for subschema in schema[key]:
28
- required_last(subschema)
29
- for key in ["if", "then", "else", "not", "items", "unevaluatedItems", "contains", "additionalProperties", "unevaluatedProperties"]:
30
- if key in schema and isinstance(schema[key], dict):
31
- required_last(schema[key])
32
- for key in ["properties", "patternProperties"]:
33
- if key in schema and isinstance(schema[key], dict):
34
- for subschema in schema[key].values():
35
- required_last(subschema)
36
- return schema
37
-
38
-
39
- def add_property(
40
- schema: dict,
41
- prop: str,
42
- value: dict,
43
- conditioner: Callable[[dict, list], bool] | None = None,
44
- current_path: list[str] | None = None,
45
- ) -> dict:
46
- """Recursively add a property to a JSON schema.
47
-
48
- Parameters
49
- ----------
50
- schema : dict
51
- The JSON schema to modify.
52
- prop : str
53
- The name of the property to add.
54
- value : Any
55
- The value of the property to add.
56
- conditioner : Callable[[dict, list], bool], optional
57
- A function that takes a schema and the path to the current schema as arguments
58
- and returns a boolean indicating whether to add the property to the schema.
59
- current_path : list[str], optional
60
- The path to the current schema in the JSON schema hierarchy.
61
- Returns
62
- -------
63
- dict
64
- The modified schema.
65
- """
66
- if current_path is None:
67
- current_path = []
68
- for key in ["anyOf", "allOf", "oneOf", "prefixItems"]:
69
- if key in schema:
70
- for idx, subschema in enumerate(schema[key]):
71
- add_property(subschema, prop, value, conditioner, current_path + [f"{key}[{idx}]"])
72
- for key in ["if", "then", "else", "not", "items", "unevaluatedItems", "contains", "additionalProperties", "patternProperties", "unevaluatedProperties"]:
73
- if key in schema and isinstance(schema[key], dict):
74
- add_property(schema[key], prop, value, conditioner, current_path + [key])
75
- if "properties" in schema:
76
- for property_name, subschema in schema["properties"].items():
77
- add_property(subschema, prop, value, conditioner, current_path + [f"properties[{property_name}]"])
78
- if not conditioner or conditioner(schema, current_path):
79
- schema["properties"][prop] = value
80
- return schema