Skip to content

Commit 1290171

Browse files
committed
Do not invoke descriptors or metaclass __getattr__()
Add Python pseudo-code in the doc.
1 parent 01a141f commit 1290171

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

Doc/c-api/type.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,13 +311,30 @@ Type Objects
311311
312312
Look for a type attribute through the type
313313
:term:`MRO <method resolution order>`.
314+
Do not invoke descriptors or metaclass ``__getattr__``.
314315
315316
*name* must be a :class:`str`.
316317
317318
* If found, set *\*attr* to a :term:`strong reference` and return ``1``.
318319
* If not found, set *\*attr* to ``NULL`` and return ``0``.
319320
* On error, set an exception and return ``-1``.
320321
322+
Python pseudo-code (return :exc:`AttributeError` if not found instead of
323+
raising an exception)::
324+
325+
def PyType_Lookup(type, name):
326+
if not isinstance(name, str):
327+
raise TypeError
328+
329+
for klass in type.mro():
330+
try:
331+
return klass.__dict__[name]
332+
except KeyError:
333+
pass
334+
335+
# not found
336+
return AttributeError
337+
321338
.. versionadded:: next
322339
323340
.. seealso::

Lib/test/test_capi/test_type.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -278,14 +278,31 @@ def test_extension_managed_dict_type(self):
278278
def test_type_lookup(self):
279279
type_lookup = _testcapi.type_lookup
280280

281-
class Parent:
281+
class Meta(type):
282+
def __getattr__(self, name):
283+
if name == "meta_attr":
284+
return "meta attr"
285+
else:
286+
raise AttributeError
287+
288+
class Ten:
289+
def __get__(self, obj, objtype=None):
290+
return 10
291+
292+
class Parent(metaclass=Meta):
282293
parent_attr = "parent"
294+
attr = "parent"
283295

284296
class Child(Parent):
285-
child_attr = "child"
297+
attr = "child"
298+
descr = Ten()
286299

287300
self.assertEqual(type_lookup(Child, "parent_attr"), "parent")
288-
self.assertEqual(type_lookup(Child, "child_attr"), "child")
301+
self.assertEqual(type_lookup(Child, "attr"), "child")
302+
self.assertEqual(type_lookup(Child, "descr"), Child.__dict__['descr'])
303+
self.assertEqual(Child.descr, 10)
304+
self.assertEqual(type_lookup(Child, "meta_attr"), AttributeError)
305+
self.assertEqual(Child.meta_attr, "meta attr")
289306
self.assertEqual(type_lookup(Child, "xxx"), AttributeError)
290307

291308
# name parameter must be a str

0 commit comments

Comments
 (0)