Skip to content

Commit 112a156

Browse files
committed
Raise NoSuchAnchor errors instead of KeyErrors.
1 parent 6d56f0f commit 112a156

File tree

3 files changed

+52
-2
lines changed

3 files changed

+52
-2
lines changed

referencing/_core.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,20 @@ def lookup(self, ref: URI) -> Resolved[D]:
368368
369369
`exceptions.Unresolvable`
370370
371-
if the reference isn't resolvable
371+
or a subclass thereof (see below) if the reference isn't
372+
resolvable
373+
374+
`exceptions.NoSuchAnchor`
375+
376+
if the reference is to a URI where a resource exists but
377+
contains a plain name fragment which does not exist within
378+
the resource
379+
380+
`exceptions.PointerToNowhere`
381+
382+
if the reference is to a URI where a resource exists but
383+
contains a JSON pointer to a location within the resource
384+
that does not exist
372385
"""
373386
if ref.startswith("#"):
374387
uri, fragment = self._base_uri, ref[1:]
@@ -393,7 +406,14 @@ def lookup(self, ref: URI) -> Resolved[D]:
393406
except LookupError:
394407
registry = registry.crawl()
395408
resolver = evolve(resolver, registry=registry)
396-
anchor = registry.anchor(uri, fragment)
409+
try:
410+
anchor = registry.anchor(uri, fragment)
411+
except LookupError:
412+
raise exceptions.NoSuchAnchor(
413+
ref=ref,
414+
resource=resource,
415+
anchor=fragment,
416+
)
397417

398418
return anchor.resolve(resolver=resolver)
399419

referencing/exceptions.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,18 @@ class PointerToNowhere(Unresolvable):
4545

4646
def __str__(self):
4747
return f"{self.ref!r} does not exist within {self.resource.contents!r}"
48+
49+
50+
@frozen
51+
class NoSuchAnchor(Unresolvable):
52+
"""
53+
An anchor does not exist within a particular resource.
54+
"""
55+
56+
resource: Any
57+
anchor: str
58+
59+
def __str__(self):
60+
return (
61+
f"{self.anchor!r} does not exist within {self.resource.contents!r}"
62+
)

referencing/tests/test_core.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,21 @@ def test_lookup_non_existent_pointer_to_array_index(self):
443443
resource=resource,
444444
)
445445

446+
def test_lookup_non_existent_anchor(self):
447+
root = ID_AND_CHILDREN.create_resource({"anchors": {}})
448+
resolver = Registry().with_resource("urn:example", root).resolver()
449+
resolved = resolver.lookup("urn:example")
450+
assert resolved.contents == root.contents
451+
452+
ref = "urn:example#noSuchAnchor"
453+
with pytest.raises(exceptions.Unresolvable) as e:
454+
resolver.lookup(ref)
455+
assert e.value == exceptions.NoSuchAnchor(
456+
ref=ref,
457+
resource=root,
458+
anchor="noSuchAnchor",
459+
)
460+
446461
# FIXME: Ideally there'd be some way to represent the tests below in the
447462
# referencing suite, but I can't think of ways to do so yet.
448463

0 commit comments

Comments
 (0)