Skip to content

Commit 4a67390

Browse files
authored
Merge pull request #6 from aucampia/iwana-20220426T2144-curie_changes
Fix handling of blank CURIE reference and references with multiple colons
2 parents e8ae054 + 34925b9 commit 4a67390

File tree

2 files changed

+48
-46
lines changed

2 files changed

+48
-46
lines changed

rdflib/namespace/__init__.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -592,27 +592,26 @@ def compute_qname_strict(
592592

593593
def expand_curie(self, curie: str) -> Union[URIRef, None]:
594594
"""
595-
Expand a qname (aka CURIE) of the form <prefix:element>, e.g. "rdf:type"
595+
Expand a CURIE of the form <prefix:element>, e.g. "rdf:type"
596596
into its full expression:
597597
598598
>>> import rdflib
599599
>>> g = rdflib.Graph()
600600
>>> g.namespace_manager.expand_curie("rdf:type")
601-
'http://www.w3.org/1999/02/22-rdf-syntax-ns#type'
602-
603-
Returns None if a namespace is not bound to the prefix.
601+
rdflib.term.URIRef('http://www.w3.org/1999/02/22-rdf-syntax-ns#type')
604602
603+
Returns `None` if a namespace is not bound to the prefix.
605604
"""
606605
if not type(curie) is str:
607606
raise TypeError("Argument must be a string.")
608-
elif ":" not in curie or curie.split(":")[0] == "" or curie.split(":")[1] == "":
607+
parts = curie.split(":", 1)
608+
if len(parts) != 2 or len(parts[0]) < 1:
609609
raise ValueError(
610610
"Malformed curie argument, format should be e.g. “foaf:name”."
611611
)
612-
else:
613-
ns = self.store.namespace(curie.split(":")[0])
614-
if ns is not None:
615-
return URIRef(str(ns) + curie.split(":")[1])
612+
ns = self.store.namespace(parts[0])
613+
if ns is not None:
614+
return URIRef(f"{str(ns)}{parts[1]}")
616615
return None
617616

618617
def bind(

test/test_namespace/test_namespace.py

Lines changed: 40 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import unittest
2+
from contextlib import ExitStack
3+
from multiprocessing.sharedctypes import Value
4+
from typing import Any, Optional, Type, Union
25
from unittest.case import expectedFailure
36
from warnings import warn
47

@@ -261,46 +264,46 @@ def test_contains_method(self):
261264
ref = URIRef("http://www.w3.org/2002/07/owl#real")
262265
assert ref in OWL, "OWL does not include owl:real"
263266

264-
def test_expand_curie(self) -> None:
265-
g = Graph()
266-
267-
assert g.namespace_manager.expand_curie("rdf:type") == URIRef(
268-
"http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
269-
)
270-
271-
assert g.namespace_manager.expand_curie("rdf:type") == RDF.type
272-
273-
g.bind("ex", Namespace("urn:example:"))
274-
275-
assert g.namespace_manager.expand_curie("ex:tarek") == URIRef(
276-
"urn:example:tarek"
277-
)
278-
279267
@pytest.mark.parametrize(
280-
"invalid_curie",
268+
["curie", "expected_result"],
281269
[
270+
("ex:tarek", URIRef("urn:example:tarek")),
271+
("ex:", URIRef(f"urn:example:")),
272+
("ex:a", URIRef(f"urn:example:a")),
273+
("ex:a:b", URIRef(f"urn:example:a:b")),
274+
("ex:a:b:c", URIRef(f"urn:example:a:b:c")),
275+
("ex", ValueError),
282276
("em:tarek", None),
283-
("em:", "ValueError"),
284-
("em", "ValueError"),
285-
(":", "ValueError"),
286-
(":type", "ValueError"),
287-
("í", "ValueError"),
288-
(" :", "ValueError"),
289-
("", "ValueError"),
290-
("\n", "ValueError"),
291-
(None, "TypeError"),
292-
(99, "TypeError"),
293-
(URIRef("urn:example:"), "TypeError"),
277+
("em:", None),
278+
("em", ValueError),
279+
(":", ValueError),
280+
(":type", ValueError),
281+
("í", ValueError),
282+
(" :", None),
283+
("", ValueError),
284+
("\n", ValueError),
285+
(None, TypeError),
286+
(3, TypeError),
287+
(URIRef("urn:example:"), TypeError),
294288
],
295289
)
296-
def test_expand_curie_invalid_curie(self, invalid_curie: str) -> None:
297-
"""Test use of invalid CURIEs"""
298-
g = Graph()
299-
if invalid_curie[1] == "ValueError":
300-
with pytest.raises(ValueError):
301-
assert g.namespace_manager.expand_curie(invalid_curie[0])
302-
elif invalid_curie[1] == "TypeError":
303-
with pytest.raises(TypeError):
304-
assert g.namespace_manager.expand_curie(invalid_curie[0])
290+
def test_expand_curie(
291+
self, curie: Any, expected_result: Union[Type[Exception], URIRef, None]
292+
) -> None:
293+
g = Graph(bind_namespaces="none")
294+
nsm = g.namespace_manager
295+
nsm.bind("ex", "urn:example:")
296+
result: Optional[URIRef] = None
297+
catcher: Optional[pytest.ExceptionInfo[Exception]] = None
298+
with ExitStack() as xstack:
299+
if isinstance(expected_result, type) and issubclass(
300+
expected_result, Exception
301+
):
302+
catcher = xstack.enter_context(pytest.raises(expected_result))
303+
result = g.namespace_manager.expand_curie(curie)
304+
305+
if catcher is not None:
306+
assert result is None
307+
assert catcher.value is not None
305308
else:
306-
assert g.namespace_manager.expand_curie(invalid_curie[0]) is None
309+
assert expected_result == result

0 commit comments

Comments
 (0)