|
4 | 4 |
|
5 | 5 | from __future__ import annotations
|
6 | 6 |
|
| 7 | +from urllib.parse import urljoin |
| 8 | + |
7 | 9 | from referencing._attrs import frozen
|
8 |
| -from referencing._core import Anchor, IdentifiedResource |
9 |
| -from referencing.typing import Specification |
| 10 | +from referencing._core import Anchor, IdentifiedResource, Resolver |
| 11 | +from referencing.typing import Schema, Specification |
10 | 12 |
|
11 | 13 |
|
12 | 14 | class Draft202012:
|
@@ -61,7 +63,7 @@ class DynamicAnchor:
|
61 | 63 |
|
62 | 64 | def resolve(self, resolver, uri):
|
63 | 65 | last = self.resource
|
64 |
| - for resource, anchors in resolver.dynamic_scope(): |
| 66 | + for uri, resource, anchors in resolver.dynamic_scope(): |
65 | 67 | anchor = anchors.get(self.name)
|
66 | 68 | if isinstance(anchor, DynamicAnchor):
|
67 | 69 | last = anchor.resource
|
@@ -289,6 +291,21 @@ def subresources_of(self, resource):
|
289 | 291 | yield items
|
290 | 292 |
|
291 | 293 |
|
| 294 | +def lookup_recursive_ref( |
| 295 | + resolver: Resolver, |
| 296 | + recursiveRef: str, |
| 297 | +) -> tuple[Schema, Resolver]: |
| 298 | + subschema, resolver = resolver.lookup(recursiveRef) |
| 299 | + if subschema.get("$recursiveAnchor"): |
| 300 | + for uri, _, _ in resolver.dynamic_scope(): |
| 301 | + ref = urljoin(uri, recursiveRef) |
| 302 | + next_subschema, next_resolver = resolver.lookup(ref) |
| 303 | + if not next_subschema.get("$recursiveAnchor"): |
| 304 | + break |
| 305 | + subschema, resolver = next_subschema, next_resolver |
| 306 | + return subschema, resolver |
| 307 | + |
| 308 | + |
292 | 309 | BY_ID: dict[str, Specification] = {
|
293 | 310 | "https://json-schema.org/draft/2020-12/schema": Draft202012(),
|
294 | 311 | "https://json-schema.org/draft/2019-09/schema": Draft201909(),
|
|
0 commit comments