File: 0005-Fix-defined-namespace-warnings-2964-2965.patch

package info (click to toggle)
rdflib 7.4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 77,852 kB
  • sloc: python: 59,555; sh: 153; makefile: 83; ruby: 74; xml: 45
file content (176 lines) | stat: -rw-r--r-- 6,762 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
From: Ashley Sommer <ashleysommer@gmail.com>
Date: Fri, 1 Nov 2024 14:24:41 +1000
Subject: Fix defined namespace warnings (#2964) (#2965)

* Fix defined namespace warnings

Current docs-generation tests are polluted by lots of warnings that occur when Sphinx tries to read various parts of DefinedNamespace.

* Fix tests that no longer need incorrect exceptions handled.

* fix black formatting in test file

* Undo typing changes, so this works on current pre-3.9 branch

* better handling for any/all double-underscore properties

* Don't include __slots__ in dir().
---
 rdflib/namespace/__init__.py                 | 44 ++++++++++++++++++----------
 test/test_namespace/test_definednamespace.py | 28 ++++++------------
 2 files changed, 38 insertions(+), 34 deletions(-)

diff --git a/rdflib/namespace/__init__.py b/rdflib/namespace/__init__.py
index 4077b0b..eb8e2ee 100644
--- a/rdflib/namespace/__init__.py
+++ b/rdflib/namespace/__init__.py
@@ -226,6 +226,7 @@ class URIPattern(str):
 # considered part of __dir__ results. These should be all annotations on
 # `DefinedNamespaceMeta`.
 _DFNS_RESERVED_ATTRS: Set[str] = {
+    "__slots__",
     "_NS",
     "_warn",
     "_fail",
@@ -244,6 +245,8 @@ _IGNORED_ATTR_LOOKUP: Set[str] = {
 class DefinedNamespaceMeta(type):
     """Utility metaclass for generating URIRefs with a common prefix."""
 
+    __slots__: Tuple[str, ...] = tuple()
+
     _NS: Namespace
     _warn: bool = True
     _fail: bool = False  # True means mimic ClosedNamespace
@@ -255,15 +258,11 @@ class DefinedNamespaceMeta(type):
         name = str(name)
 
         if name in _DFNS_RESERVED_ATTRS:
-            raise AttributeError(
-                f"DefinedNamespace like object has no attribute {name!r}"
+            raise KeyError(
+                f"DefinedNamespace like object has no access item named {name!r}"
             )
         elif name in _IGNORED_ATTR_LOOKUP:
             raise KeyError()
-        if str(name).startswith("__"):
-            # NOTE on type ignore: This seems to be a real bug, super() does not
-            # implement this method, it will fail if it is ever reached.
-            return super().__getitem__(name, default)  # type: ignore[misc] # undefined in superclass
         if (cls._warn or cls._fail) and name not in cls:
             if cls._fail:
                 raise AttributeError(f"term '{name}' not in namespace '{cls._NS}'")
@@ -277,26 +276,39 @@ class DefinedNamespaceMeta(type):
     def __getattr__(cls, name: str):
         if name in _IGNORED_ATTR_LOOKUP:
             raise AttributeError()
+        elif name in _DFNS_RESERVED_ATTRS:
+            raise AttributeError(
+                f"DefinedNamespace like object has no attribute {name!r}"
+            )
+        elif name.startswith("__"):
+            return super(DefinedNamespaceMeta, cls).__getattribute__(name)
         return cls.__getitem__(name)
 
     def __repr__(cls) -> str:
-        return f"Namespace({str(cls._NS)!r})"
+        try:
+            ns_repr = repr(cls._NS)
+        except AttributeError:
+            ns_repr = "<DefinedNamespace>"
+        return f"Namespace({ns_repr})"
 
     def __str__(cls) -> str:
-        return str(cls._NS)
+        try:
+            return str(cls._NS)
+        except AttributeError:
+            return "<DefinedNamespace>"
 
     def __add__(cls, other: str) -> URIRef:
         return cls.__getitem__(other)
 
     def __contains__(cls, item: str) -> bool:
         """Determine whether a URI or an individual item belongs to this namespace"""
+        try:
+            this_ns = cls._NS
+        except AttributeError:
+            return False
         item_str = str(item)
-        if item_str.startswith("__"):
-            # NOTE on type ignore: This seems to be a real bug, super() does not
-            # implement this method, it will fail if it is ever reached.
-            return super().__contains__(item)  # type: ignore[misc] # undefined in superclass
-        if item_str.startswith(str(cls._NS)):
-            item_str = item_str[len(str(cls._NS)) :]
+        if item_str.startswith(str(this_ns)):
+            item_str = item_str[len(str(this_ns)) :]
         return any(
             item_str in c.__annotations__
             or item_str in c._extras
@@ -313,7 +325,7 @@ class DefinedNamespaceMeta(type):
         return values
 
     def as_jsonld_context(self, pfx: str) -> dict:  # noqa: N804
-        """Returns this DefinedNamespace as a a JSON-LD 'context' object"""
+        """Returns this DefinedNamespace as a JSON-LD 'context' object"""
         terms = {pfx: str(self._NS)}
         for key, term in self.__annotations__.items():
             if issubclass(term, URIRef):
@@ -328,6 +340,8 @@ class DefinedNamespace(metaclass=DefinedNamespaceMeta):
     Warnings are emitted if unknown members are referenced if _warn is True
     """
 
+    __slots__: Tuple[str, ...] = tuple()
+
     def __init__(self):
         raise TypeError("namespace may not be instantiated")
 
diff --git a/test/test_namespace/test_definednamespace.py b/test/test_namespace/test_definednamespace.py
index ea8e129..5860e8e 100644
--- a/test/test_namespace/test_definednamespace.py
+++ b/test/test_namespace/test_definednamespace.py
@@ -299,14 +299,9 @@ def test_repr(dfns: Type[DefinedNamespace]) -> None:
     ns_uri = f"{prefix}{dfns_info.suffix}"
     logging.debug("ns_uri = %s", ns_uri)
 
-    repr_str: Optional[str] = None
-
-    with ExitStack() as xstack:
-        if dfns_info.suffix is None:
-            xstack.enter_context(pytest.raises(AttributeError))
-        repr_str = f"{dfns_info.dfns!r}"
+    repr_str: str = f"{dfns_info.dfns!r}"
     if dfns_info.suffix is None:
-        assert repr_str is None
+        assert "<DefinedNamespace>" in repr_str
     else:
         assert repr_str is not None
         repro = eval(repr_str)
@@ -368,20 +363,15 @@ def test_contains(
     dfns_info = get_dfns_info(dfns)
     if dfns_info.suffix is not None:
         logging.debug("dfns_info = %s", dfns_info)
-    if dfns_info.has_attrs is False:
+    if dfns_info.has_attrs is False or dfns_info.suffix is None:
         is_defined = False
-    does_contain: Optional[bool] = None
-    with ExitStack() as xstack:
-        if dfns_info.suffix is None:
-            xstack.enter_context(pytest.raises(AttributeError))
-        does_contain = attr_name in dfns
-    if dfns_info.suffix is not None:
-        if is_defined:
-            assert does_contain is True
-        else:
-            assert does_contain is False
+
+    does_contain: bool = attr_name in dfns
+
+    if is_defined:
+        assert does_contain is True
     else:
-        assert does_contain is None
+        assert does_contain is False
 
 
 @pytest.mark.parametrize(