aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/referencing/jsonschema.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/referencing/jsonschema.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are hereHEADmaster
Diffstat (limited to '.venv/lib/python3.12/site-packages/referencing/jsonschema.py')
-rw-r--r--.venv/lib/python3.12/site-packages/referencing/jsonschema.py642
1 files changed, 642 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/referencing/jsonschema.py b/.venv/lib/python3.12/site-packages/referencing/jsonschema.py
new file mode 100644
index 00000000..169e109d
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/referencing/jsonschema.py
@@ -0,0 +1,642 @@
+"""
+Referencing implementations for JSON Schema specs (historic & current).
+"""
+
+from __future__ import annotations
+
+from collections.abc import Iterable, Sequence, Set
+from typing import Any, Union
+
+from referencing import Anchor, Registry, Resource, Specification, exceptions
+from referencing._attrs import frozen
+from referencing._core import (
+ _UNSET, # type: ignore[reportPrivateUsage]
+ Resolved as _Resolved,
+ Resolver as _Resolver,
+ _Unset, # type: ignore[reportPrivateUsage]
+)
+from referencing.typing import URI, Anchor as AnchorType, Mapping
+
+#: A JSON Schema which is a JSON object
+ObjectSchema = Mapping[str, Any]
+
+#: A JSON Schema of any kind
+Schema = Union[bool, ObjectSchema]
+
+#: A Resource whose contents are JSON Schemas
+SchemaResource = Resource[Schema]
+
+#: A JSON Schema Registry
+SchemaRegistry = Registry[Schema]
+
+#: The empty JSON Schema Registry
+EMPTY_REGISTRY: SchemaRegistry = Registry()
+
+
+@frozen
+class UnknownDialect(Exception):
+ """
+ A dialect identifier was found for a dialect unknown by this library.
+
+ If it's a custom ("unofficial") dialect, be sure you've registered it.
+ """
+
+ uri: URI
+
+
+def _dollar_id(contents: Schema) -> URI | None:
+ if isinstance(contents, bool):
+ return
+ return contents.get("$id")
+
+
+def _legacy_dollar_id(contents: Schema) -> URI | None:
+ if isinstance(contents, bool) or "$ref" in contents:
+ return
+ id = contents.get("$id")
+ if id is not None and not id.startswith("#"):
+ return id
+
+
+def _legacy_id(contents: ObjectSchema) -> URI | None:
+ if "$ref" in contents:
+ return
+ id = contents.get("id")
+ if id is not None and not id.startswith("#"):
+ return id
+
+
+def _anchor(
+ specification: Specification[Schema],
+ contents: Schema,
+) -> Iterable[AnchorType[Schema]]:
+ if isinstance(contents, bool):
+ return
+ anchor = contents.get("$anchor")
+ if anchor is not None:
+ yield Anchor(
+ name=anchor,
+ resource=specification.create_resource(contents),
+ )
+
+ dynamic_anchor = contents.get("$dynamicAnchor")
+ if dynamic_anchor is not None:
+ yield DynamicAnchor(
+ name=dynamic_anchor,
+ resource=specification.create_resource(contents),
+ )
+
+
+def _anchor_2019(
+ specification: Specification[Schema],
+ contents: Schema,
+) -> Iterable[Anchor[Schema]]:
+ if isinstance(contents, bool):
+ return []
+ anchor = contents.get("$anchor")
+ if anchor is None:
+ return []
+ return [
+ Anchor(
+ name=anchor,
+ resource=specification.create_resource(contents),
+ ),
+ ]
+
+
+def _legacy_anchor_in_dollar_id(
+ specification: Specification[Schema],
+ contents: Schema,
+) -> Iterable[Anchor[Schema]]:
+ if isinstance(contents, bool):
+ return []
+ id = contents.get("$id", "")
+ if not id.startswith("#"):
+ return []
+ return [
+ Anchor(
+ name=id[1:],
+ resource=specification.create_resource(contents),
+ ),
+ ]
+
+
+def _legacy_anchor_in_id(
+ specification: Specification[ObjectSchema],
+ contents: ObjectSchema,
+) -> Iterable[Anchor[ObjectSchema]]:
+ id = contents.get("id", "")
+ if not id.startswith("#"):
+ return []
+ return [
+ Anchor(
+ name=id[1:],
+ resource=specification.create_resource(contents),
+ ),
+ ]
+
+
+def _subresources_of(
+ in_value: Set[str] = frozenset(),
+ in_subvalues: Set[str] = frozenset(),
+ in_subarray: Set[str] = frozenset(),
+):
+ """
+ Create a callable returning JSON Schema specification-style subschemas.
+
+ Relies on specifying the set of keywords containing subschemas in their
+ values, in a subobject's values, or in a subarray.
+ """
+
+ def subresources_of(contents: Schema) -> Iterable[ObjectSchema]:
+ if isinstance(contents, bool):
+ return
+ for each in in_value:
+ if each in contents:
+ yield contents[each]
+ for each in in_subarray:
+ if each in contents:
+ yield from contents[each]
+ for each in in_subvalues:
+ if each in contents:
+ yield from contents[each].values()
+
+ return subresources_of
+
+
+def _subresources_of_with_crazy_items(
+ in_value: Set[str] = frozenset(),
+ in_subvalues: Set[str] = frozenset(),
+ in_subarray: Set[str] = frozenset(),
+):
+ """
+ Specifically handle older drafts where there are some funky keywords.
+ """
+
+ def subresources_of(contents: Schema) -> Iterable[ObjectSchema]:
+ if isinstance(contents, bool):
+ return
+ for each in in_value:
+ if each in contents:
+ yield contents[each]
+ for each in in_subarray:
+ if each in contents:
+ yield from contents[each]
+ for each in in_subvalues:
+ if each in contents:
+ yield from contents[each].values()
+
+ items = contents.get("items")
+ if items is not None:
+ if isinstance(items, Sequence):
+ yield from items
+ else:
+ yield items
+
+ return subresources_of
+
+
+def _subresources_of_with_crazy_items_dependencies(
+ in_value: Set[str] = frozenset(),
+ in_subvalues: Set[str] = frozenset(),
+ in_subarray: Set[str] = frozenset(),
+):
+ """
+ Specifically handle older drafts where there are some funky keywords.
+ """
+
+ def subresources_of(contents: Schema) -> Iterable[ObjectSchema]:
+ if isinstance(contents, bool):
+ return
+ for each in in_value:
+ if each in contents:
+ yield contents[each]
+ for each in in_subarray:
+ if each in contents:
+ yield from contents[each]
+ for each in in_subvalues:
+ if each in contents:
+ yield from contents[each].values()
+
+ items = contents.get("items")
+ if items is not None:
+ if isinstance(items, Sequence):
+ yield from items
+ else:
+ yield items
+ dependencies = contents.get("dependencies")
+ if dependencies is not None:
+ values = iter(dependencies.values())
+ value = next(values, None)
+ if isinstance(value, Mapping):
+ yield value
+ yield from values
+
+ return subresources_of
+
+
+def _subresources_of_with_crazy_aP_items_dependencies(
+ in_value: Set[str] = frozenset(),
+ in_subvalues: Set[str] = frozenset(),
+ in_subarray: Set[str] = frozenset(),
+):
+ """
+ Specifically handle even older drafts where there are some funky keywords.
+ """
+
+ def subresources_of(contents: ObjectSchema) -> Iterable[ObjectSchema]:
+ for each in in_value:
+ if each in contents:
+ yield contents[each]
+ for each in in_subarray:
+ if each in contents:
+ yield from contents[each]
+ for each in in_subvalues:
+ if each in contents:
+ yield from contents[each].values()
+
+ items = contents.get("items")
+ if items is not None:
+ if isinstance(items, Sequence):
+ yield from items
+ else:
+ yield items
+ dependencies = contents.get("dependencies")
+ if dependencies is not None:
+ values = iter(dependencies.values())
+ value = next(values, None)
+ if isinstance(value, Mapping):
+ yield value
+ yield from values
+
+ for each in "additionalItems", "additionalProperties":
+ value = contents.get(each)
+ if isinstance(value, Mapping):
+ yield value
+
+ return subresources_of
+
+
+def _maybe_in_subresource(
+ in_value: Set[str] = frozenset(),
+ in_subvalues: Set[str] = frozenset(),
+ in_subarray: Set[str] = frozenset(),
+):
+ in_child = in_subvalues | in_subarray
+
+ def maybe_in_subresource(
+ segments: Sequence[int | str],
+ resolver: _Resolver[Any],
+ subresource: Resource[Any],
+ ) -> _Resolver[Any]:
+ _segments = iter(segments)
+ for segment in _segments:
+ if segment not in in_value and (
+ segment not in in_child or next(_segments, None) is None
+ ):
+ return resolver
+ return resolver.in_subresource(subresource)
+
+ return maybe_in_subresource
+
+
+def _maybe_in_subresource_crazy_items(
+ in_value: Set[str] = frozenset(),
+ in_subvalues: Set[str] = frozenset(),
+ in_subarray: Set[str] = frozenset(),
+):
+ in_child = in_subvalues | in_subarray
+
+ def maybe_in_subresource(
+ segments: Sequence[int | str],
+ resolver: _Resolver[Any],
+ subresource: Resource[Any],
+ ) -> _Resolver[Any]:
+ _segments = iter(segments)
+ for segment in _segments:
+ if segment == "items" and isinstance(
+ subresource.contents,
+ Mapping,
+ ):
+ return resolver.in_subresource(subresource)
+ if segment not in in_value and (
+ segment not in in_child or next(_segments, None) is None
+ ):
+ return resolver
+ return resolver.in_subresource(subresource)
+
+ return maybe_in_subresource
+
+
+def _maybe_in_subresource_crazy_items_dependencies(
+ in_value: Set[str] = frozenset(),
+ in_subvalues: Set[str] = frozenset(),
+ in_subarray: Set[str] = frozenset(),
+):
+ in_child = in_subvalues | in_subarray
+
+ def maybe_in_subresource(
+ segments: Sequence[int | str],
+ resolver: _Resolver[Any],
+ subresource: Resource[Any],
+ ) -> _Resolver[Any]:
+ _segments = iter(segments)
+ for segment in _segments:
+ if segment in {"items", "dependencies"} and isinstance(
+ subresource.contents,
+ Mapping,
+ ):
+ return resolver.in_subresource(subresource)
+ if segment not in in_value and (
+ segment not in in_child or next(_segments, None) is None
+ ):
+ return resolver
+ return resolver.in_subresource(subresource)
+
+ return maybe_in_subresource
+
+
+#: JSON Schema draft 2020-12
+DRAFT202012 = Specification(
+ name="draft2020-12",
+ id_of=_dollar_id,
+ subresources_of=_subresources_of(
+ in_value={
+ "additionalProperties",
+ "contains",
+ "contentSchema",
+ "else",
+ "if",
+ "items",
+ "not",
+ "propertyNames",
+ "then",
+ "unevaluatedItems",
+ "unevaluatedProperties",
+ },
+ in_subarray={"allOf", "anyOf", "oneOf", "prefixItems"},
+ in_subvalues={
+ "$defs",
+ "definitions",
+ "dependentSchemas",
+ "patternProperties",
+ "properties",
+ },
+ ),
+ anchors_in=_anchor,
+ maybe_in_subresource=_maybe_in_subresource(
+ in_value={
+ "additionalProperties",
+ "contains",
+ "contentSchema",
+ "else",
+ "if",
+ "items",
+ "not",
+ "propertyNames",
+ "then",
+ "unevaluatedItems",
+ "unevaluatedProperties",
+ },
+ in_subarray={"allOf", "anyOf", "oneOf", "prefixItems"},
+ in_subvalues={
+ "$defs",
+ "definitions",
+ "dependentSchemas",
+ "patternProperties",
+ "properties",
+ },
+ ),
+)
+#: JSON Schema draft 2019-09
+DRAFT201909 = Specification(
+ name="draft2019-09",
+ id_of=_dollar_id,
+ subresources_of=_subresources_of_with_crazy_items(
+ in_value={
+ "additionalItems",
+ "additionalProperties",
+ "contains",
+ "contentSchema",
+ "else",
+ "if",
+ "not",
+ "propertyNames",
+ "then",
+ "unevaluatedItems",
+ "unevaluatedProperties",
+ },
+ in_subarray={"allOf", "anyOf", "oneOf"},
+ in_subvalues={
+ "$defs",
+ "definitions",
+ "dependentSchemas",
+ "patternProperties",
+ "properties",
+ },
+ ),
+ anchors_in=_anchor_2019,
+ maybe_in_subresource=_maybe_in_subresource_crazy_items(
+ in_value={
+ "additionalItems",
+ "additionalProperties",
+ "contains",
+ "contentSchema",
+ "else",
+ "if",
+ "not",
+ "propertyNames",
+ "then",
+ "unevaluatedItems",
+ "unevaluatedProperties",
+ },
+ in_subarray={"allOf", "anyOf", "oneOf"},
+ in_subvalues={
+ "$defs",
+ "definitions",
+ "dependentSchemas",
+ "patternProperties",
+ "properties",
+ },
+ ),
+)
+#: JSON Schema draft 7
+DRAFT7 = Specification(
+ name="draft-07",
+ id_of=_legacy_dollar_id,
+ subresources_of=_subresources_of_with_crazy_items_dependencies(
+ in_value={
+ "additionalItems",
+ "additionalProperties",
+ "contains",
+ "else",
+ "if",
+ "not",
+ "propertyNames",
+ "then",
+ },
+ in_subarray={"allOf", "anyOf", "oneOf"},
+ in_subvalues={"definitions", "patternProperties", "properties"},
+ ),
+ anchors_in=_legacy_anchor_in_dollar_id,
+ maybe_in_subresource=_maybe_in_subresource_crazy_items_dependencies(
+ in_value={
+ "additionalItems",
+ "additionalProperties",
+ "contains",
+ "else",
+ "if",
+ "not",
+ "propertyNames",
+ "then",
+ },
+ in_subarray={"allOf", "anyOf", "oneOf"},
+ in_subvalues={"definitions", "patternProperties", "properties"},
+ ),
+)
+#: JSON Schema draft 6
+DRAFT6 = Specification(
+ name="draft-06",
+ id_of=_legacy_dollar_id,
+ subresources_of=_subresources_of_with_crazy_items_dependencies(
+ in_value={
+ "additionalItems",
+ "additionalProperties",
+ "contains",
+ "not",
+ "propertyNames",
+ },
+ in_subarray={"allOf", "anyOf", "oneOf"},
+ in_subvalues={"definitions", "patternProperties", "properties"},
+ ),
+ anchors_in=_legacy_anchor_in_dollar_id,
+ maybe_in_subresource=_maybe_in_subresource_crazy_items_dependencies(
+ in_value={
+ "additionalItems",
+ "additionalProperties",
+ "contains",
+ "not",
+ "propertyNames",
+ },
+ in_subarray={"allOf", "anyOf", "oneOf"},
+ in_subvalues={"definitions", "patternProperties", "properties"},
+ ),
+)
+#: JSON Schema draft 4
+DRAFT4 = Specification(
+ name="draft-04",
+ id_of=_legacy_id,
+ subresources_of=_subresources_of_with_crazy_aP_items_dependencies(
+ in_value={"not"},
+ in_subarray={"allOf", "anyOf", "oneOf"},
+ in_subvalues={"definitions", "patternProperties", "properties"},
+ ),
+ anchors_in=_legacy_anchor_in_id,
+ maybe_in_subresource=_maybe_in_subresource_crazy_items_dependencies(
+ in_value={"additionalItems", "additionalProperties", "not"},
+ in_subarray={"allOf", "anyOf", "oneOf"},
+ in_subvalues={"definitions", "patternProperties", "properties"},
+ ),
+)
+#: JSON Schema draft 3
+DRAFT3 = Specification(
+ name="draft-03",
+ id_of=_legacy_id,
+ subresources_of=_subresources_of_with_crazy_aP_items_dependencies(
+ in_subarray={"extends"},
+ in_subvalues={"definitions", "patternProperties", "properties"},
+ ),
+ anchors_in=_legacy_anchor_in_id,
+ maybe_in_subresource=_maybe_in_subresource_crazy_items_dependencies(
+ in_value={"additionalItems", "additionalProperties"},
+ in_subarray={"extends"},
+ in_subvalues={"definitions", "patternProperties", "properties"},
+ ),
+)
+
+
+_SPECIFICATIONS: Registry[Specification[Schema]] = Registry(
+ {
+ dialect_id: Resource.opaque(specification)
+ for dialect_id, specification in [
+ ("https://json-schema.org/draft/2020-12/schema", DRAFT202012),
+ ("https://json-schema.org/draft/2019-09/schema", DRAFT201909),
+ ("http://json-schema.org/draft-07/schema", DRAFT7),
+ ("http://json-schema.org/draft-06/schema", DRAFT6),
+ ("http://json-schema.org/draft-04/schema", DRAFT4),
+ ("http://json-schema.org/draft-03/schema", DRAFT3),
+ ]
+ },
+)
+
+
+def specification_with(
+ dialect_id: URI,
+ default: Specification[Any] | _Unset = _UNSET,
+) -> Specification[Any]:
+ """
+ Retrieve the `Specification` with the given dialect identifier.
+
+ Raises:
+
+ `UnknownDialect`
+
+ if the given ``dialect_id`` isn't known
+
+ """
+ resource = _SPECIFICATIONS.get(dialect_id.rstrip("#"))
+ if resource is not None:
+ return resource.contents
+ if default is _UNSET:
+ raise UnknownDialect(dialect_id)
+ return default
+
+
+@frozen
+class DynamicAnchor:
+ """
+ Dynamic anchors, introduced in draft 2020.
+ """
+
+ name: str
+ resource: SchemaResource
+
+ def resolve(self, resolver: _Resolver[Schema]) -> _Resolved[Schema]:
+ """
+ Resolve this anchor dynamically.
+ """
+ last = self.resource
+ for uri, registry in resolver.dynamic_scope():
+ try:
+ anchor = registry.anchor(uri, self.name).value
+ except exceptions.NoSuchAnchor:
+ continue
+ if isinstance(anchor, DynamicAnchor):
+ last = anchor.resource
+ return _Resolved(
+ contents=last.contents,
+ resolver=resolver.in_subresource(last),
+ )
+
+
+def lookup_recursive_ref(resolver: _Resolver[Schema]) -> _Resolved[Schema]:
+ """
+ Recursive references (via recursive anchors), present only in draft 2019.
+
+ As per the 2019 specification (ยง 8.2.4.2.1), only the ``#`` recursive
+ reference is supported (and is therefore assumed to be the relevant
+ reference).
+ """
+ resolved = resolver.lookup("#")
+ if isinstance(resolved.contents, Mapping) and resolved.contents.get(
+ "$recursiveAnchor",
+ ):
+ for uri, _ in resolver.dynamic_scope():
+ next_resolved = resolver.lookup(uri)
+ if not isinstance(
+ next_resolved.contents,
+ Mapping,
+ ) or not next_resolved.contents.get("$recursiveAnchor"):
+ break
+ resolved = next_resolved
+ return resolved