diff options
author | Dmitry Dygalo <dmitry@dygalo.dev> | 2021-12-15 21:21:58 +0100 |
---|---|---|
committer | Dmitry Dygalo <dmitry@dygalo.dev> | 2021-12-16 09:59:30 +0100 |
commit | 9f86718f4fa8573dccf5f1c004b977b04ec9a624 (patch) | |
tree | 908cefe342429fe27ef85d79f0b6274b494248d4 | |
parent | 60242e770882f2ae2dea772350a6de3f767817ad (diff) | |
download | jsonschema-9f86718f4fa8573dccf5f1c004b977b04ec9a624.tar.gz |
perf: Use cached lookups for resolving fragments if the referent document is known
-rw-r--r-- | CHANGELOG.rst | 1 | ||||
-rw-r--r-- | jsonschema/validators.py | 20 |
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 |