Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1b19bd1

Browse filesBrowse files
AlexWaygoodcarljm
andauthored
gh-103193: cache calls to inspect._shadowed_dict in inspect.getattr_static (#104267)
Co-authored-by: Carl Meyer <carl@oddbird.net>
1 parent 60f5884 commit 1b19bd1
Copy full SHA for 1b19bd1

File tree

3 files changed

+32
-5
lines changed
Filter options

3 files changed

+32
-5
lines changed

‎Doc/whatsnew/3.12.rst

Copy file name to clipboardExpand all lines: Doc/whatsnew/3.12.rst
+4-3Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,8 +342,9 @@ inspect
342342
(Contributed by Thomas Krennwallner in :issue:`35759`.)
343343

344344
* The performance of :func:`inspect.getattr_static` has been considerably
345-
improved. Most calls to the function should be around 2x faster than they
346-
were in Python 3.11. (Contributed by Alex Waygood in :gh:`103193`.)
345+
improved. Most calls to the function should be at least 2x faster than they
346+
were in Python 3.11, and some may be 6x faster or more. (Contributed by Alex
347+
Waygood in :gh:`103193`.)
347348

348349
pathlib
349350
-------
@@ -597,7 +598,7 @@ typing
597598
:func:`runtime-checkable protocols <typing.runtime_checkable>` has changed
598599
significantly. Most ``isinstance()`` checks against protocols with only a few
599600
members should be at least 2x faster than in 3.11, and some may be 20x
600-
faster or more. However, ``isinstance()`` checks against protocols with seven
601+
faster or more. However, ``isinstance()`` checks against protocols with fourteen
601602
or more members may be slower than in Python 3.11. (Contributed by Alex
602603
Waygood in :gh:`74690` and :gh:`103193`.)
603604

‎Lib/inspect.py

Copy file name to clipboardExpand all lines: Lib/inspect.py
+6-2Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,8 +1794,9 @@ def _check_class(klass, attr):
17941794
return entry.__dict__[attr]
17951795
return _sentinel
17961796

1797-
def _shadowed_dict(klass):
1798-
for entry in _static_getmro(klass):
1797+
@functools.lru_cache()
1798+
def _shadowed_dict_from_mro_tuple(mro):
1799+
for entry in mro:
17991800
dunder_dict = _get_dunder_dict_of_class(entry)
18001801
if '__dict__' in dunder_dict:
18011802
class_dict = dunder_dict['__dict__']
@@ -1805,6 +1806,9 @@ def _shadowed_dict(klass):
18051806
return class_dict
18061807
return _sentinel
18071808

1809+
def _shadowed_dict(klass):
1810+
return _shadowed_dict_from_mro_tuple(_static_getmro(klass))
1811+
18081812
def getattr_static(obj, attr, default=_sentinel):
18091813
"""Retrieve attributes without triggering dynamic lookup via the
18101814
descriptor protocol, __getattr__ or __getattribute__.

‎Lib/test/test_inspect.py

Copy file name to clipboardExpand all lines: Lib/test/test_inspect.py
+22Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2111,6 +2111,28 @@ def __dict__(self):
21112111
self.assertEqual(inspect.getattr_static(foo, 'a'), 3)
21122112
self.assertFalse(test.called)
21132113

2114+
def test_mutated_mro(self):
2115+
test = self
2116+
test.called = False
2117+
2118+
class Foo(dict):
2119+
a = 3
2120+
@property
2121+
def __dict__(self):
2122+
test.called = True
2123+
return {}
2124+
2125+
class Bar(dict):
2126+
a = 4
2127+
2128+
class Baz(Bar): pass
2129+
2130+
baz = Baz()
2131+
self.assertEqual(inspect.getattr_static(baz, 'a'), 4)
2132+
Baz.__bases__ = (Foo,)
2133+
self.assertEqual(inspect.getattr_static(baz, 'a'), 3)
2134+
self.assertFalse(test.called)
2135+
21142136
def test_custom_object_dict(self):
21152137
test = self
21162138
test.called = False

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.