summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Dygalo <dmitry@dygalo.dev>2021-12-15 21:21:58 +0100
committerDmitry Dygalo <dmitry@dygalo.dev>2021-12-16 09:59:30 +0100
commit9f86718f4fa8573dccf5f1c004b977b04ec9a624 (patch)
tree908cefe342429fe27ef85d79f0b6274b494248d4
parent60242e770882f2ae2dea772350a6de3f767817ad (diff)
downloadjsonschema-9f86718f4fa8573dccf5f1c004b977b04ec9a624.tar.gz
perf: Use cached lookups for resolving fragments if the referent document is known
-rw-r--r--CHANGELOG.rst1
-rw-r--r--jsonschema/validators.py20
2 files changed, 18 insertions, 3 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 507b112..a57e5ba 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -4,6 +4,7 @@ v4.3.0
* Fix undesired fallback to brute force container uniqueness check on
certain input types (#893)
* Cache reference lookups for subschemas (#893)
+* Use cached lookups for resolving fragments if the referent document is known (#893)
* Implement a PEP544 Protocol for validator classes (#890)
v4.2.1
diff --git a/jsonschema/validators.py b/jsonschema/validators.py
index 46cd8e1..93c2929 100644
--- a/jsonschema/validators.py
+++ b/jsonschema/validators.py
@@ -757,6 +757,10 @@ class RefResolver(object):
finally:
self.pop_scope()
+ @lru_cache()
+ def _find_in_referrer(self, key):
+ return list(self._finditem(self.referrer, key))
+
def _finditem(self, schema, key):
values = deque([schema])
while values:
@@ -773,8 +777,11 @@ class RefResolver(object):
@lru_cache()
def _find_in_subschemas(self, url):
+ subschemas = self._find_subschemas()
+ if not subschemas:
+ return None
uri, fragment = urldefrag(url)
- for subschema in self._find_subschemas():
+ for subschema in subschemas:
target_uri = self._urljoin_cache(
self.resolution_scope, subschema["$id"],
)
@@ -831,12 +838,19 @@ class RefResolver(object):
if not fragment:
return document
+ if document is self.referrer:
+ find = self._find_in_referrer
+ else:
+
+ def find(key):
+ return self._finditem(document, key)
+
for keyword in ["$anchor", "$dynamicAnchor"]:
- for subschema in self._finditem(document, keyword):
+ for subschema in find(keyword):
if fragment == subschema[keyword]:
return subschema
for keyword in ["id", "$id"]:
- for subschema in self._finditem(document, keyword):
+ for subschema in find(keyword):
if "#" + fragment == subschema[keyword]:
return subschema