11from __future__ import annotations
22
3- from collections .abc import Mapping , Sequence
4- from typing import TYPE_CHECKING , Any , Union
3+ from collections .abc import Sequence
4+ from typing import TYPE_CHECKING
55from urllib .parse import unquote , urldefrag , urljoin
66
77from pyrsistent import m , plist , s
88from pyrsistent .typing import PList , PMap , PSet
99
10- try :
11- Mapping [str , str ]
12- except TypeError :
13- from typing import Mapping
14-
1510
1611class UnsupportedSubclassing (Exception ):
1712 @classmethod
@@ -29,6 +24,8 @@ class UnidentifiedResource(Exception):
2924
3025if TYPE_CHECKING :
3126 from attrs import define , evolve , field , frozen
27+
28+ from referencing .typing import AnchorType , Schema , Specification
3229else :
3330 from attrs import define as _define , evolve , field , frozen as _frozen
3431
@@ -41,9 +38,6 @@ def frozen(cls):
4138 return _frozen (cls )
4239
4340
44- Schema = Union [bool , Mapping [str , Any ]]
45-
46-
4741@frozen
4842class Anchor :
4943
@@ -73,7 +67,15 @@ def resolve(self, dynamic_scope, uri) -> tuple[Schema, str]:
7367 return last , id_of (last ) or "" # FIXME: consider when this can be None
7468
7569
76- AnchorType = Union [Anchor , DynamicAnchor ]
70+ class OpaqueSpecification :
71+ """
72+ A non-specification `Specification` which treats resources opaquely.
73+
74+ In particular, they have no subresources.
75+ """
76+
77+ def subresources_of (self , resource : Schema ):
78+ return ()
7779
7880
7981@frozen
@@ -83,7 +85,8 @@ class Registry:
8385 default = m (),
8486 repr = lambda value : f"({ len (value )} entries)" ,
8587 )
86- _uncrawled : PSet [str ] = field (default = s ())
88+ _uncrawled : PSet [str ] = s ()
89+ _specification : Specification = OpaqueSpecification ()
8790
8891 def update (self , * registries : Registry ) -> Registry :
8992 contents = (each ._contents for each in registries )
@@ -167,27 +170,17 @@ def _crawl(self) -> Registry:
167170 resource = resource ,
168171 ),
169172 )
170-
171- resources .extend ( # TODO: delay finding anchors in subresources...
172- (uri , resource [k ]) for k in SUBRESOURCE if k in resource
173- )
174- resources .extend (
175- (uri , subresource )
176- for k in SUBRESOURCE_VALUES
177- if k in resource
178- for subresource in resource [k ].values ()
179- )
180173 resources .extend (
181- (uri , subresource )
182- for k in SUBRESOURCE_ITEMS
183- if k in resource
184- for subresource in resource [k ]
174+ (uri , each )
175+ for each in self ._specification .subresources_of (resource )
176+ if each is not True and each is not False
185177 )
186178 return evolve (registry , uncrawled = s ())
187179
188- def resolver (self , root ) -> Resolver :
180+ def resolver (self , root , specification ) -> Resolver :
189181 uri = id_of (root ) or ""
190182 registry = self .with_identified_resource (uri = uri , resource = root )
183+ registry = evolve (registry , specification = specification )
191184 return Resolver (base_uri = uri , registry = registry )
192185
193186
@@ -243,11 +236,6 @@ def dynamic_scope(self):
243236 yield resource , self ._registry .anchors_at (uri )
244237
245238
246- SUBRESOURCE = {"items" , "not" }
247- SUBRESOURCE_ITEMS = {"allOf" }
248- SUBRESOURCE_VALUES = {"$defs" , "properties" }
249-
250-
251239def id_of (resource ) -> str | None :
252240 if resource is True or resource is False :
253241 return None
0 commit comments