@@ -169,6 +169,7 @@ class Validator:
169
169
schema = attr .ib (repr = reprlib .repr )
170
170
resolver = attr .ib (default = None , repr = False )
171
171
format_checker = attr .ib (default = None )
172
+ evolve = attr .evolve
172
173
173
174
def __attrs_post_init__ (self ):
174
175
if self .resolver is None :
@@ -182,9 +183,6 @@ def check_schema(cls, schema):
182
183
for error in cls (cls .META_SCHEMA ).iter_errors (schema ):
183
184
raise exceptions .SchemaError .create_from (error )
184
185
185
- def evolve (self , ** kwargs ):
186
- return attr .evolve (self , ** kwargs )
187
-
188
186
def iter_errors (self , instance , _schema = None ):
189
187
if _schema is not None :
190
188
warnings .warn (
@@ -757,6 +755,10 @@ def resolving(self, ref):
757
755
finally :
758
756
self .pop_scope ()
759
757
758
+ @lru_cache ()
759
+ def _find_in_referrer (self , key ):
760
+ return list (self ._finditem (self .referrer , key ))
761
+
760
762
def _finditem (self , schema , key ):
761
763
values = deque ([schema ])
762
764
while values :
@@ -767,22 +769,35 @@ def _finditem(self, schema, key):
767
769
yield each
768
770
values .extendleft (each .values ())
769
771
770
- def resolve (self , ref ):
771
- """
772
- Resolve the given reference.
773
- """
774
- url = self ._urljoin_cache (self .resolution_scope , ref ).rstrip ("/" )
772
+ @lru_cache ()
773
+ def _find_subschemas (self ):
774
+ return list (self ._finditem (self .referrer , "$id" ))
775
775
776
+ @lru_cache ()
777
+ def _find_in_subschemas (self , url ):
778
+ subschemas = self ._find_subschemas ()
779
+ if not subschemas :
780
+ return None
776
781
uri , fragment = urldefrag (url )
777
-
778
- for subschema in self ._finditem (self .referrer , "$id" ):
782
+ for subschema in subschemas :
779
783
target_uri = self ._urljoin_cache (
780
784
self .resolution_scope , subschema ["$id" ],
781
785
)
782
786
if target_uri .rstrip ("/" ) == uri .rstrip ("/" ):
783
787
if fragment :
784
788
subschema = self .resolve_fragment (subschema , fragment )
785
789
return url , subschema
790
+ return None
791
+
792
+ def resolve (self , ref ):
793
+ """
794
+ Resolve the given reference.
795
+ """
796
+ url = self ._urljoin_cache (self .resolution_scope , ref ).rstrip ("/" )
797
+
798
+ match = self ._find_in_subschemas (url )
799
+ if match is not None :
800
+ return match
786
801
787
802
return url , self ._remote_cache (url )
788
803
@@ -821,12 +836,19 @@ def resolve_fragment(self, document, fragment):
821
836
if not fragment :
822
837
return document
823
838
839
+ if document is self .referrer :
840
+ find = self ._find_in_referrer
841
+ else :
842
+
843
+ def find (key ):
844
+ return self ._finditem (document , key )
845
+
824
846
for keyword in ["$anchor" , "$dynamicAnchor" ]:
825
- for subschema in self . _finditem ( document , keyword ):
847
+ for subschema in find ( keyword ):
826
848
if fragment == subschema [keyword ]:
827
849
return subschema
828
850
for keyword in ["id" , "$id" ]:
829
- for subschema in self . _finditem ( document , keyword ):
851
+ for subschema in find ( keyword ):
830
852
if "#" + fragment == subschema [keyword ]:
831
853
return subschema
832
854
0 commit comments