From c11de7d563b02340e26542d24087bd0d15119046 Mon Sep 17 00:00:00 2001 From: Iwan Aucamp Date: Thu, 8 Jul 2021 09:41:55 +0200 Subject: [PATCH 1/2] Fix infinite recursion when __repr__ is called Also add some more tests. --- rdflib/namespace.py | 7 +++-- test/test_namespace.py | 71 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 74 insertions(+), 4 deletions(-) diff --git a/rdflib/namespace.py b/rdflib/namespace.py index 084646c2d..8c083ca0a 100644 --- a/rdflib/namespace.py +++ b/rdflib/namespace.py @@ -141,7 +141,7 @@ def __getattr__(self, name): return self.term(name) def __repr__(self): - return f"Namespace({self!r})" + return f"Namespace({super().__repr__()})" def __contains__(self, ref): """Allows to check if a URI is within (starts with) this Namespace. @@ -187,7 +187,7 @@ def format(self, *args, **kwargs): return URIRef(super().format(*args, **kwargs)) def __repr__(self): - return f"URIPattern({self!r})" + return f"URIPattern({super().__repr__()})" class ClosedNamespace(Namespace): @@ -199,6 +199,7 @@ class ClosedNamespace(Namespace): def __new__(cls, uri, terms): rt = super().__new__(cls, uri) + rt.__terms = terms rt.__uris = {t: URIRef(rt + t) for t in terms} return rt @@ -225,7 +226,7 @@ def __getattr__(self, name): raise AttributeError(e) def __repr__(self): - return f"{self.__module__}.{self.__class__.__name__}({self!r})" + return f"{self.__module__}.{self.__class__.__name__}({str(self)!r})" def __dir__(self): return list(self.__uris) diff --git a/test/test_namespace.py b/test/test_namespace.py index 59ff0ecec..87b7f046a 100644 --- a/test/test_namespace.py +++ b/test/test_namespace.py @@ -1,11 +1,36 @@ import unittest +from unittest.case import expectedFailure from rdflib.graph import Graph -from rdflib.namespace import Namespace, FOAF, RDF, RDFS, SH, DCTERMS +from rdflib.namespace import ( + ClosedNamespace, + Namespace, + FOAF, + RDF, + RDFS, + SH, + DCTERMS, + URIPattern, +) from rdflib.term import URIRef class NamespaceTest(unittest.TestCase): + def setUp(self): + self.ns_str = "http://example.com/name/space/" + self.ns = Namespace(self.ns_str) + + def test_repr(self): + # NOTE: this assumes ns_str has no characthers that need escaping + self.assertIn(self.ns_str, f"{self.ns!r}") + self.assertEqual(self.ns, eval(f"{self.ns!r}")) + + def test_str(self): + self.assertEqual(self.ns_str, f"{self.ns}") + + def test_member(self): + self.assertEqual(f"{self.ns_str}a", f"{self.ns.a}") + def test_dcterms_title(self): self.assertEqual(DCTERMS.title, URIRef(DCTERMS + 'title')) @@ -16,6 +41,50 @@ def test_iri(self): self.assert_(ns[u'jörn'].startswith(ns)) +class ClosedNamespaceTest(unittest.TestCase): + def setUp(self): + self.ns_str = "http://example.com/name/space/" + self.ns = ClosedNamespace(self.ns_str, ["a", "b", "c"]) + + def test_repr(self): + # NOTE: this assumes ns_str has no characthers that need escaping + self.assertIn(self.ns_str, f"{self.ns!r}") + + @expectedFailure + def test_repr_ef(self): + """ + This fails because ClosedNamespace repr does not represent the second argument + """ + self.assertEqual(self.ns, eval(f"{self.ns!r}")) + + def test_str(self): + self.assertEqual(self.ns_str, f"{self.ns}") + + def test_member(self): + self.assertEqual(f"{self.ns_str}a", f"{self.ns.a}") + + def test_missing_member(self): + with self.assertRaises(AttributeError) as context: + f"{self.ns.missing}" + self.assertIn("missing", f"{context.exception}") + + +class URIPatternTest(unittest.TestCase): + def setUp(self): + self.pattern_str = "http://example.org/%s/%d/resource" + self.pattern = URIPattern(self.pattern_str) + + def test_repr(self): + # NOTE: this assumes pattern_str has no characthers that need escaping + self.assertIn(self.pattern_str, f"{self.pattern!r}") + self.assertEqual(self.pattern, eval(f"{self.pattern!r}")) + + def test_format(self): + self.assertEqual( + "http://example.org/foo/100/resource", str(self.pattern % ("foo", 100)) + ) + + class NamespacePrefixTest(unittest.TestCase): def test_compute_qname(self): """Test sequential assignment of unknown prefixes""" From bc42cd12eba18442b2f48885f5e906b1b315bfc5 Mon Sep 17 00:00:00 2001 From: Iwan Aucamp Date: Thu, 8 Jul 2021 11:40:01 +0200 Subject: [PATCH 2/2] Update rdflib/namespace.py Remove stray line Co-authored-by: kernc --- rdflib/namespace.py | 1 - 1 file changed, 1 deletion(-) diff --git a/rdflib/namespace.py b/rdflib/namespace.py index 8c083ca0a..c053c2fa1 100644 --- a/rdflib/namespace.py +++ b/rdflib/namespace.py @@ -199,7 +199,6 @@ class ClosedNamespace(Namespace): def __new__(cls, uri, terms): rt = super().__new__(cls, uri) - rt.__terms = terms rt.__uris = {t: URIRef(rt + t) for t in terms} return rt