bpo-34995: Maintain func.isabstractmethod in functools.cached_property by mwilbz · Pull Request #9904 · python/cpython (original) (raw)
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Conversation19 Commits6 Checks0 Files changed
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
[ Show hidden characters]({{ revealButtonHref }})
Hello, and thanks for your contribution!
I'm a bot set up to make sure that the project can legally accept your contribution by verifying you have signed the PSF contributor agreement (CLA).
Unfortunately our records indicate you have not signed the CLA. For legal reasons we need you to sign this before we can look at your contribution. Please follow the steps outlined in the CPython devguide to rectify this issue.
You can check yourself to see if the CLA has been received.
Thanks again for your contribution, we look forward to reviewing it!
@@ -882,6 +882,7 @@ def __init__(self, func): |
---|
self.func = func |
self.attrname = None |
self.__doc__ = func.__doc__ |
self.__isabstractmethod__ = getattr(func, '__isabstractmethod__', False) |
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to only set the attribute (on self) if the attribute exists on func?
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure! Updated the implementation
def calculate(self): |
---|
pass |
with self.assertRaises(TypeError): |
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to (also) directly check the isabstractmethod attribute?
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good suggestion, added an assertion for that
@@ -882,6 +882,9 @@ def __init__(self, func): |
---|
self.func = func |
self.attrname = None |
self.__doc__ = func.__doc__ |
func_isabstractmethod = getattr(func, '__isabstractmethod__') |
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Used like that, getattr() raises an exception if the attribute doesn't exist.
You can use:
try: self.__isabstractmethod__ = func.__isabstractmethod__
except AttributeError: pass
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, thank you. I opened the implementation in my IDE and it said default=None
so I was mislead. Pushing the version you're suggesting
def calculate(self): |
---|
pass |
self.assertTrue(getattr(AbstractExpensiveCalculator.calculate, '__isabstractmethod__', False)) |
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.assertTrue(AbstractExpensiveCalculator.calculate.isabstractmethod) is enough.
self.assertTrue(getattr(AbstractExpensiveCalculator.calculate, '__isabstractmethod__', False)) |
---|
with self.assertRaises(TypeError): |
AbstractExpensiveCalculator() |
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add a test on a method which doesn't have the __isabstractmethod__
attribute? I expect such test:
self.assertFalse(hasattr(AbstractExpensiveCalculator.calculate, '__isabstractmethod__'))
@@ -0,0 +1 @@ |
---|
Maintain wrapped method's __isabstractmethod__ in functools.cached_property |
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest:
:func:`functools.cached_property` now also copies the wrapped method's ``__isabstractmethod__`` attribute.
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.
Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again
. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.
I have made the requested changes; please review again
Thank you for your comments @vstinner ! Good suggestions around better test coverage + documentation. :)
Thanks for making the requested changes!
@vstinner: please review the changes made to this pull request.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think that it is better to use @property
instead of @cached_property
in abstract classes, but I have no strong objections. What would say ABC experts?
def calculate(self): |
---|
pass |
self.assertTrue(AbstractExpensiveCalculator.calculate.__isabstractmethod__) |
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Too long line. Maybe make the class or property name a little shorter?
Possibly outside the scope of this change, but I noticed that update_wrapper
in functools
is a common way to inherit various standard fields in a wrapped method. For example, it's used here: https://github.com/python/cpython/blob/master/Lib/functools.py#L906 This example also happens to maintain __isabstractmethod__
in its own way, slightly different from this PR's current implementation.
Is it worth considering more generally modifying the standard fields to update via update_wrapper
to include __isabstractmethod__
as well? https://github.com/python/cpython/blob/master/Lib/functools.py#L30 Then cached_property
can simply reuse update_wrapper
to be consistent with other wrappers in functools
.
Regardless of my previous comment, what are the next steps to move forward with this PR? Anything I can do? Thanks again for the reviews up until now =)
It sounds like there isn't interest from core contributors in merging this change, so I'll close the PR. Thanks reviewers for your time and feedback!