@@ -169,6 +169,7 @@ class Validator:
169169 schema = attr .ib (repr = reprlib .repr )
170170 resolver = attr .ib (default = None , repr = False )
171171 format_checker = attr .ib (default = None )
172+ evolve = attr .evolve
172173
173174 def __attrs_post_init__ (self ):
174175 if self .resolver is None :
@@ -182,9 +183,6 @@ def check_schema(cls, schema):
182183 for error in cls (cls .META_SCHEMA ).iter_errors (schema ):
183184 raise exceptions .SchemaError .create_from (error )
184185
185- def evolve (self , ** kwargs ):
186- return attr .evolve (self , ** kwargs )
187-
188186 def iter_errors (self , instance , _schema = None ):
189187 if _schema is not None :
190188 warnings .warn (
@@ -757,6 +755,10 @@ def resolving(self, ref):
757755 finally :
758756 self .pop_scope ()
759757
758+ @lru_cache ()
759+ def _find_in_referrer (self , key ):
760+ return list (self ._finditem (self .referrer , key ))
761+
760762 def _finditem (self , schema , key ):
761763 values = deque ([schema ])
762764 while values :
@@ -767,22 +769,35 @@ def _finditem(self, schema, key):
767769 yield each
768770 values .extendleft (each .values ())
769771
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" ))
775775
776+ @lru_cache ()
777+ def _find_in_subschemas (self , url ):
778+ subschemas = self ._find_subschemas ()
779+ if not subschemas :
780+ return None
776781 uri , fragment = urldefrag (url )
777-
778- for subschema in self ._finditem (self .referrer , "$id" ):
782+ for subschema in subschemas :
779783 target_uri = self ._urljoin_cache (
780784 self .resolution_scope , subschema ["$id" ],
781785 )
782786 if target_uri .rstrip ("/" ) == uri .rstrip ("/" ):
783787 if fragment :
784788 subschema = self .resolve_fragment (subschema , fragment )
785789 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
786801
787802 return url , self ._remote_cache (url )
788803
@@ -821,12 +836,19 @@ def resolve_fragment(self, document, fragment):
821836 if not fragment :
822837 return document
823838
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+
824846 for keyword in ["$anchor" , "$dynamicAnchor" ]:
825- for subschema in self . _finditem ( document , keyword ):
847+ for subschema in find ( keyword ):
826848 if fragment == subschema [keyword ]:
827849 return subschema
828850 for keyword in ["id" , "$id" ]:
829- for subschema in self . _finditem ( document , keyword ):
851+ for subschema in find ( keyword ):
830852 if "#" + fragment == subschema [keyword ]:
831853 return subschema
832854
0 commit comments