summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Berman <Julian@GrayVines.com>2022-05-05 16:54:57 -0400
committerJulian Berman <Julian@GrayVines.com>2022-05-05 16:55:32 -0400
commitfb85c6620ff26823362ebd27b8577995c0841028 (patch)
treee6c6ed824a02cf725079f22965610da57bdfeacd
parent3b2f0f36c73b61fd72a87ab468e46b24119ae9e0 (diff)
downloadjsonschema-fb85c6620ff26823362ebd27b8577995c0841028.tar.gz
Revert "Extend dynamicRef keyword"v4.5.1
It needs performance optimization. See python-jsonschema/jsonschema#941. This reverts commit 12c791ee81baf27e54d18baf95b975bd48387dc6.
-rw-r--r--CHANGELOG.rst1
-rw-r--r--jsonschema/_utils.py83
-rw-r--r--jsonschema/_validators.py12
-rw-r--r--jsonschema/tests/test_jsonschema_test_suite.py10
-rw-r--r--jsonschema/validators.py28
5 files changed, 34 insertions, 100 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 17c09da..7a19b9b 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -3,7 +3,6 @@ v4.5.0
* Validator classes for each version now maintain references to the correct
corresponding format checker (#905)
-* Support for ``$dynamicRef`` has been improved (#886)
* Development has moved to a `GitHub organization
<https://github.com/python-jsonschema/>`_.
No functional behavior changes are expected from the change.
diff --git a/jsonschema/_utils.py b/jsonschema/_utils.py
index a4ab2ad..a2ad5a9 100644
--- a/jsonschema/_utils.py
+++ b/jsonschema/_utils.py
@@ -1,4 +1,3 @@
-from collections import deque
from collections.abc import Mapping, MutableMapping, Sequence
from urllib.parse import urlsplit
import itertools
@@ -347,85 +346,3 @@ def find_evaluated_property_keys_by_schema(validator, instance, schema):
)
return evaluated_keys
-
-
-def _schema_is_referenced(schema, parent_schema):
- """
- Checks if a schema is referenced by another schema
- """
- return (
- "$id" in schema
- and "$ref" in parent_schema
- and parent_schema["$ref"] == schema["$id"]
- )
-
-
-def _find_dynamic_anchor_extender(validator, scopes, fragment, schema):
- """
- Find a schema that extends the dynamic anchor
- """
- for url in scopes:
- with validator.resolver.resolving(url) as parent_schema:
- if _schema_is_referenced(schema, parent_schema):
- return validator.resolver.resolve_fragment(
- parent_schema,
- fragment,
- )
-
-
-def _find_dynamic_anchor_intermediate(validator, scopes, fragment):
- """
- Find a schema that extends the dynamic anchor by an intermediate schema
- """
- for url in scopes:
- with validator.resolver.resolving(url) as schema:
- if "$id" in schema:
- for intermediate_url in scopes:
- with validator.resolver.resolving(
- intermediate_url) as intermediate_schema:
- for subschema in search_schema(
- intermediate_schema, match_keyword("$ref")):
- if _schema_is_referenced(subschema, schema):
- return _find_dynamic_anchor_extender(
- validator,
- scopes,
- fragment,
- subschema,
- )
-
-
-def dynamic_anchor_extender(validator, scopes, fragment, schema, subschema):
- extender_schema = _find_dynamic_anchor_extender(
- validator, scopes, fragment, schema,
- )
- if not extender_schema:
- extender_schema = _find_dynamic_anchor_extender(
- validator, scopes, fragment, subschema,
- )
- if not extender_schema:
- extender_schema = _find_dynamic_anchor_intermediate(
- validator, scopes, fragment,
- )
-
- return extender_schema
-
-
-def match_keyword(keyword):
- def matcher(value):
- if keyword in value:
- yield value
- return matcher
-
-
-def search_schema(schema, matcher):
- """Breadth-first search routine."""
- values = deque([schema])
- while values:
- value = values.pop()
- if isinstance(value, list):
- values.extendleft(value)
- continue
- if not isinstance(value, dict):
- continue
- yield from matcher(value)
- values.extendleft(value.values())
diff --git a/jsonschema/_validators.py b/jsonschema/_validators.py
index 8caaa7e..9a07f5e 100644
--- a/jsonschema/_validators.py
+++ b/jsonschema/_validators.py
@@ -3,7 +3,6 @@ from urllib.parse import urldefrag, urljoin
import re
from jsonschema._utils import (
- dynamic_anchor_extender,
ensure_list,
equal,
extras_msg,
@@ -303,21 +302,14 @@ def ref(validator, ref, instance, schema):
def dynamicRef(validator, dynamicRef, instance, schema):
_, fragment = urldefrag(dynamicRef)
+
for url in validator.resolver._scopes_stack:
lookup_url = urljoin(url, dynamicRef)
with validator.resolver.resolving(lookup_url) as subschema:
if ("$dynamicAnchor" in subschema
and fragment == subschema["$dynamicAnchor"]):
- scope_stack = list(validator.resolver._scopes_stack)
- scope_stack.reverse()
- extended_schema = dynamic_anchor_extender(
- validator, scope_stack, fragment, schema, subschema,
- )
- if extended_schema:
- yield from validator.descend(instance, extended_schema)
- break
-
yield from validator.descend(instance, subschema)
+ break
else:
with validator.resolver.resolving(dynamicRef) as subschema:
yield from validator.descend(instance, subschema)
diff --git a/jsonschema/tests/test_jsonschema_test_suite.py b/jsonschema/tests/test_jsonschema_test_suite.py
index a656ab8..2d807b7 100644
--- a/jsonschema/tests/test_jsonschema_test_suite.py
+++ b/jsonschema/tests/test_jsonschema_test_suite.py
@@ -395,7 +395,15 @@ TestDraft202012 = DRAFT202012.to_unittest_testcase(
skip=lambda test: (
narrow_unicode_build(test)
or skip(
- message="These tests require an extension or the url resolver.",
+ message="dynamicRef support isn't working yet.",
+ subject="dynamicRef",
+ )(test)
+ or skip(
+ message="These tests depends on dynamicRef working.",
+ subject="defs",
+ )(test)
+ or skip(
+ message="These tests depends on dynamicRef working.",
subject="anchor",
case_description="same $anchor with different base uri",
)(test)
diff --git a/jsonschema/validators.py b/jsonschema/validators.py
index ccf4e2c..5a0b8b9 100644
--- a/jsonschema/validators.py
+++ b/jsonschema/validators.py
@@ -3,6 +3,7 @@ Creation and extension of validators, with implementations for existing drafts.
"""
from __future__ import annotations
+from collections import deque
from collections.abc import Sequence
from functools import lru_cache
from urllib.parse import unquote, urldefrag, urljoin, urlsplit
@@ -805,7 +806,7 @@ class RefResolver(object):
@lru_cache() # noqa: B019
def _get_subschemas_cache(self):
cache = {key: [] for key in _SUBSCHEMAS_KEYWORDS}
- for keyword, subschema in _utils.search_schema(
+ for keyword, subschema in _search_schema(
self.referrer, _match_subschema_keywords,
):
cache[keyword].append(subschema)
@@ -879,10 +880,7 @@ class RefResolver(object):
else:
def find(key):
- yield from _utils.search_schema(
- document,
- _utils.match_keyword(key),
- )
+ yield from _search_schema(document, _match_keyword(key))
for keyword in ["$anchor", "$dynamicAnchor"]:
for subschema in find(keyword):
@@ -968,12 +966,32 @@ class RefResolver(object):
_SUBSCHEMAS_KEYWORDS = ("$id", "id", "$anchor", "$dynamicAnchor")
+def _match_keyword(keyword):
+
+ def matcher(value):
+ if keyword in value:
+ yield value
+
+ return matcher
+
+
def _match_subschema_keywords(value):
for keyword in _SUBSCHEMAS_KEYWORDS:
if keyword in value:
yield keyword, value
+def _search_schema(schema, matcher):
+ """Breadth-first search routine."""
+ values = deque([schema])
+ while values:
+ value = values.pop()
+ if not isinstance(value, dict):
+ continue
+ yield from matcher(value)
+ values.extendleft(value.values())
+
+
def validate(instance, schema, cls=None, *args, **kwargs):
"""
Validate an instance under the given schema.