Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 34k
gh-100690: Prevent prefix "called_" for attributes of safe mock objects#100691
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 and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Conversation
cklein commented Jan 2, 2023 • edited by AlexWaygood
Loading Uh oh!
There was an error while loading. Please reload this page.
edited by AlexWaygood
Uh oh!
There was an error while loading. Please reload this page.
bedevere-bot commented Jan 2, 2023
Most changes to Python require a NEWS entry. Please add it using the blurb_it web app or the blurb command-line tool. |
25e26d8 to 7bc8c46Compare
cjw296 left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm -0 on this change, feels like we're into the diminishing realms where someone out there is going to have a legitimate use case for called_name or some such and this then prevents them using a safe mock.
Who else is hitting this?
7bc8c46 to b84bc75Comparecklein commented Jan 2, 2023
@cjw296, the same applies to any of the forbidden prefixes. This could be solved by allowing those prefixes with a spec. Currently, even if the name appears in |
cklein commented Jan 2, 2023 • edited by AlexWaygood
Loading Uh oh!
There was an error while loading. Please reload this page.
edited by AlexWaygood
Uh oh!
There was an error while loading. Please reload this page.
I have been thinking a bit more about the whole problem. It seems the current behavior does not match the error message: >>> classFoo: ... defassert_bar(self): ... pass ... >>> from unittest.mock import Mock >>> m = Mock(spec=Foo) >>> m.assert_bar() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/opt/local/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/unittest/mock.py", line 648, in __getattr__ raise AttributeError( AttributeError: 'assert_bar' is not a valid assertion. Use a spec for the mock if 'assert_bar' is meant to be an attribute.The error message says "Use a spec for the mock if 'assert_bar' is meant to be an attribute.", but this example should pass according to the error message. There's a spec and the name With cklein@37aa291 applied, it behaves like described: >>> classFoo: ... defassert_bar(self): ... pass ... >>> from unittest.mock import Mock >>> m = Mock(spec=Foo) >>> m.assert_bar() <Mock name='mock.assert_bar()' id='4384202080'> >>> m.assert_frobnicated() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Users/cklein/github/cklein/cpython/Lib/unittest/mock.py", line 652, in __getattr__ raise AttributeError("Mock object has no attribute %r" % name) AttributeError: Mock object has no attribute 'assert_frobnicated' |
merwok commented Jan 3, 2023
The prefixes checked could be more specific like |
cjw296 commented Jan 3, 2023
@cklein - I think you're right about this being a complicated issue, perhaps a PR isn't the best place to discuss it? Could you maybe close this PR an open an issue explaining your concerns and some possible ways forward? |
AlexWaygood commented Jan 3, 2023
OP has already done so:
|
cklein commented Jan 3, 2023 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
I can also create another issue for my second branch about the spec not being properly checked, if that helps Edit: See https://discuss.python.org/t/check-for-assert-prefixes-doesnt-respect-spec/22388 |
… mode Raise an AttributeError when calling e.g. `mock_obj.called_once` instead of `mock_obj.assert_called_once`.
b84bc75 to 154012fComparecklein commented Jan 3, 2023
I'm aware that the documentation is now off. I'd like to get some feedback on the change first, if that's OK |
Uh oh!
There was an error while loading. Please reload this page.
| # gh-100690 Denylist for forbidden attribute names in safe mode | ||
| ATTRIB_DENY_LIST={name.removeprefix("assert_") fornameindir(NonCallableMock) ifname.startswith("assert_")} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Much prefer this approach! 🎉
cjw296 commented Jan 5, 2023
Approach is good, so once the docs are fixed up, should be good to land. |
cklein commented Jan 5, 2023
I'm struggling a bit with documentation. What about the following: |
Misc/NEWS.d/next/Library/2023-01-02-16-59-49.gh-issue-100690.2EgWPS.rst Outdated Show resolvedHide resolved
Uh oh!
There was an error while loading. Please reload this page.
cklein commented Jan 6, 2023
Personally I'd like to see it in earlier versions of Python. |
cjw296 commented Jan 6, 2023 • edited
Loading Uh oh!
There was an error while loading. Please reload this page.
edited
Uh oh!
There was an error while loading. Please reload this page.
@cklein - 3.10 and 3.11 are open for bug fixes so their next third point release would contain this once its landed. |
cjw296 commented Jan 6, 2023
The Azure Pipelines failure seems unrelated. |
AlexWaygood commented Jan 6, 2023
Yes, that failure happens intermittently on a lot of PRs |
bedevere-bot commented Jan 6, 2023
|
| # Denylist for forbidden attribute names in safe mode | ||
| ATTRIB_DENY_LIST={name.removeprefix("assert_") fornameindir(NonCallableMock) ifname.startswith("assert_")} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for being late to the party, but anyways :)
I think that ATTRIB_DENY_LIST is an implementation detail, so it should be _ATTRIB_DENY_LIST. And also, it is not suited for mutation, isn't it? So, it should be a frozenset instead :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this PR is already merged, I've opened #100819 with this proposal. Feel free to close if it should be public and mutable!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is already non-public by not being included in __all__, and the mutability is not really an issue.
Prevent prefix "called_" for mocks in safe mode