Skip to content

Commit 8ba3a08

Browse files
hongweipenghongweipeng
authored and
hongweipeng
committed
Add function inspect.getmembers_static that does not call properties or dynamic
properties.
1 parent 2693132 commit 8ba3a08

File tree

3 files changed

+32
-2
lines changed

3 files changed

+32
-2
lines changed

Lib/inspect.py

+13-2
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ def isabstract(object):
441441
return True
442442
return False
443443

444-
def getmembers(object, predicate=None):
444+
def _getmembers(object, predicate=None, getter=None):
445445
"""Return all members of an object as (name, value) pairs sorted by name.
446446
Optionally, only return members that satisfy a given predicate."""
447447
if isclass(object):
@@ -466,7 +466,7 @@ def getmembers(object, predicate=None):
466466
# like calling their __get__ (see bug #1785), so fall back to
467467
# looking in the __dict__.
468468
try:
469-
value = getattr(object, key)
469+
value = getter(object, key)
470470
# handle the duplicate key
471471
if key in processed:
472472
raise AttributeError
@@ -485,6 +485,17 @@ def getmembers(object, predicate=None):
485485
results.sort(key=lambda pair: pair[0])
486486
return results
487487

488+
def getmembers(object, predicate=None):
489+
"""Return all members of an object as (name, value) pairs sorted by name.
490+
Optionally, only return members that satisfy a given predicate."""
491+
return _getmembers(object, predicate, getattr)
492+
493+
def getmembers_static(object, predicate=None):
494+
"""Return all members of an object as (name, value) pairs sorted by name
495+
without calling properties and other dynamic. Optionally, only return
496+
members that satisfy a given predicate."""
497+
return _getmembers(object, predicate, getattr_static)
498+
488499
Attribute = namedtuple('Attribute', 'name kind defining_class object')
489500

490501
def classify_class_attrs(cls):

Lib/test/test_inspect.py

+17
Original file line numberDiff line numberDiff line change
@@ -1275,6 +1275,23 @@ def eggs(self):
12751275
self.assertIn(('eggs', 'scrambled'), inspect.getmembers(A))
12761276
self.assertIn(('eggs', 'spam'), inspect.getmembers(A()))
12771277

1278+
def test_getmembers_static(self):
1279+
class A:
1280+
@property
1281+
def name(self):
1282+
raise NotImplementedError
1283+
@types.DynamicClassAttribute
1284+
def eggs(self):
1285+
raise NotImplementedError
1286+
1287+
a = A()
1288+
instance_members = inspect.getmembers_static(a)
1289+
class_members = inspect.getmembers_static(A)
1290+
self.assertIn(('name', inspect.getattr_static(a, 'name')), instance_members)
1291+
self.assertIn(('eggs', inspect.getattr_static(a, 'eggs')), instance_members)
1292+
self.assertIn(('name', inspect.getattr_static(A, 'name')), class_members)
1293+
self.assertIn(('eggs', inspect.getattr_static(A, 'eggs')), class_members)
1294+
12781295
def test_getmembers_with_buggy_dir(self):
12791296
class M(type):
12801297
def __dir__(cls):
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add :func:`inspect.getmembers_static` , it return all members without
2+
calling properties and other dynamic. Patch by Weipeng Hong.

0 commit comments

Comments
 (0)