bpo-33668: Fix inspect.getmembers to traverse mro when object is class#8284
bpo-33668: Fix inspect.getmembers to traverse mro when object is class#8284corona10 wants to merge 1 commit intopython:masterfrom
Conversation
|
What is the purpose of iterating the instance attribute |
|
@serhiy-storchaka import inspect
import types
class Base(object):
@types.DynamicClassAttribute
def fried(self):
return self._x
_x = object()
class A(Base):
@types.DynamicClassAttribute
def eggs(self):
return self._x
_x = object()
inspect.getmembers(A) |
|
For reviewers,
I add the check the type of |
|
@serhiy-storchaka |
|
I found the case of the related to this code. "Lib/test/test_enum.py", line 2560, in test_inspect_getmembersI think that we can update this code into |
|
Current implementation returns dulplicated members, But with this PR It works well. |
|
Shouldn't this be executed only for classes? |
import enum
import inspect
class Color(enum.Enum):
red = 1
green = 2
blue = 3
values = dict((
('__class__', enum.EnumMeta),
('__doc__', 'An enumeration.'),
('__members__', Color.__members__),
('__module__', __name__),
('blue', Color.blue),
('green', Color.green),
('name', enum.Enum.__dict__['name']),
('red', Color.red),
('value', enum.Enum.__dict__['value']),
))
print(dict(inspect.getmembers(Color)).keys())
c = Color.red
print(c.value)Here is the case, |
|
In all your examples |
|
@serhiy-storchaka |
The comment above the loop over |
There was a problem hiding this comment.
I suggest to move the above comment inside the if branch. Seems :dd is a typo of Add.
This if isclass(object): can be merged with other if isclass(object): at the beginning of the function.
|
@serhiy-storchaka Thanks I've updated. |
There was a problem hiding this comment.
travering -> traversing
And I would add "only" before "traversing".
And maybe add a markup: :func:`inspect.getmembers`.
There was a problem hiding this comment.
I think it would be better to change the name (and perhaps the code) of the test. There is nothing specific for modules. Instead we need to test that the instance attribute __bases__ doesn't break inspect.getmembers().
|
@serhiy-storchaka |
|
Thank you for your review despite the busy situation. set colorcolumn=79
autocmd BufWritePre *.py :%s/\s\+$//eI 've reflected your review. |
Isn't this true for 3.6 and 3.7 as well, except for the "decade" part? IMO this should only go into 3.8, and have a "What's New" entry mentioning the change. This strikes me as being similar to bpo-33899, in that this is probably how it should have been to begin with, but changing it now in released versions would likely unexpectedly break existing code that uses it. |
|
This PR should be backported at least to 3.7, because a module-level But the bug can be encountered in older Python versions for classes with |
No, I don't. You're probably right about backporting this to 3.x. |
There was a problem hiding this comment.
Should not it iterate mro instead of object.__bases__? Or _static_getmro(object)?
There was a problem hiding this comment.
Indeed, it should apparently use one of those.
|
Thanks for the review! I've updated the PR. |
|
@1st1 |
|
Could you please add a test for your last change? I.e. the test that passed when iterate mro, but fails when iterate class A: # A DynamicClassAttribute should be defined here
class B(A): pass
class C(B): pass
# test inspect.getmembers(C) |
|
@serhiy-storchaka |
There was a problem hiding this comment.
Why not self.assertIn('ham', attrs)?
Add also test for inspect.getmembers(B).
There was a problem hiding this comment.
@serhiy-storchaka
Just checking self.assertIn('ham', attrs) does not fail when iterate __bases__.
|
I updated the unit test and to understand more deeply. import types
import inspect
class A:
@types.DynamicClassAttribute
def ham(self):
return 'eggs'
class B(A): pass
class C(B): pass
print([a for a in inspect.getmembers(A) if a[0] == 'ham'])
print([b for b in inspect.getmembers(B) if b[0] == 'ham'])
print([c for c in inspect.getmembers(C) if c[0] == 'ham'])AS-IS -> iterate
|
|
Should not Seems using mro instead of |
|
@serhiy-storchaka Maybe other good people will find the way. |
|
I removed the " needs backport to 3.6" label, the 3.6 branch no longer accept bugfixes (only security fixes are accepted): https://devguide.python.org/#status-of-python-branches |
|
@1st1 Can you take a look, please? |
|
@1st1 @serhiy-storchaka @vstinner @csabella Hi, this PR remains for a year. Thanks |
|
@1st1 @serhiy-storchaka @vstinner @csabella I close this PR due to no feedback.. Thanks! |
https://bugs.python.org/issue33668