Skip to content

Commit

Permalink
Fix infinite recursion when __repr__ is called
Browse files Browse the repository at this point in the history
Also add some more tests.
  • Loading branch information
aucampia committed Jul 8, 2021
1 parent cb0c346 commit c11de7d
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 4 deletions.
7 changes: 4 additions & 3 deletions rdflib/namespace.py
Expand Up @@ -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.
Expand Down Expand Up @@ -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):
Expand All @@ -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

Expand All @@ -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)
Expand Down
71 changes: 70 additions & 1 deletion 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'))

Expand All @@ -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"""
Expand Down

0 comments on commit c11de7d

Please sign in to comment.