-
-
Notifications
You must be signed in to change notification settings - Fork 32k
reset_mock
resets MagicMock
's magic methods in an unexpected way
#123934
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
Comments
reset_mock
resets MagicMock
's magic methods in an unexpected way
Thank you for the report. I will take a look soon :) |
Yes, this is correct.
print(type(mock.Mock().__str__))
# <class 'method-wrapper'>
print(type(mock.MagicMock().__str__))
# <class 'unittest.mock.MagicMock'> But, I agree that retuning
|
…ues (pythonGH-124038) (cherry picked from commit 7628f67) Co-authored-by: sobolevn <[email protected]>
…ues (pythonGH-124038) (cherry picked from commit 7628f67) Co-authored-by: sobolevn <[email protected]>
I see that this test in mu-editor fails with infinite RecursionError: with mock.patch("builtins.super") as mock_super:
pm = PythonMode(editor, view)
pm.set_buttons = mock.MagicMock()
mock_super.reset_mock() I believe this is because it is calling reset_mock on a mock of super and after this PR reset_mock calls super. I think that mocking super is probably dangerous (and always has been), but I thought I should mention this here. |
Hm, I think that we can not use What do others think? Should we fix this? |
…sionError Starting with Python 3.12.7 or 3.13.0rc3, the reset_mock() method calls super(). python/cpython#123934 This lead to: __________________________ test_python_remove_plotter __________________________ def test_python_remove_plotter(): """ Ensure the button states are returned to normal before calling super method. """ editor = mock.MagicMock() view = mock.MagicMock() with mock.patch("builtins.super") as mock_super: pm = PythonMode(editor, view) pm.set_buttons = mock.MagicMock() > mock_super.reset_mock() tests/modes/test_python3.py:489: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib64/python3.13/unittest/mock.py:2232: in reset_mock super().reset_mock(*args, return_value=return_value, **kwargs) /usr/lib64/python3.13/unittest/mock.py:2232: in reset_mock super().reset_mock(*args, return_value=return_value, **kwargs) /usr/lib64/python3.13/unittest/mock.py:2232: in reset_mock super().reset_mock(*args, return_value=return_value, **kwargs) E RecursionError: maximum recursion depth exceeded !!! Recursion detected (same locals & position) We avoid the problem by not needlessly calling reset_mock() in this test at all.
FWIW this particular use case was simple enough to fix: mu-editor/mu#2528 |
…sionError (#2528) Starting with Python 3.12.7 or 3.13.0rc3, the reset_mock() method calls super(). python/cpython#123934 This lead to: __________________________ test_python_remove_plotter __________________________ def test_python_remove_plotter(): """ Ensure the button states are returned to normal before calling super method. """ editor = mock.MagicMock() view = mock.MagicMock() with mock.patch("builtins.super") as mock_super: pm = PythonMode(editor, view) pm.set_buttons = mock.MagicMock() > mock_super.reset_mock() tests/modes/test_python3.py:489: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/lib64/python3.13/unittest/mock.py:2232: in reset_mock super().reset_mock(*args, return_value=return_value, **kwargs) /usr/lib64/python3.13/unittest/mock.py:2232: in reset_mock super().reset_mock(*args, return_value=return_value, **kwargs) /usr/lib64/python3.13/unittest/mock.py:2232: in reset_mock super().reset_mock(*args, return_value=return_value, **kwargs) E RecursionError: maximum recursion depth exceeded !!! Recursion detected (same locals & position) We avoid the problem by not needlessly calling reset_mock() in this test at all.
Triage: PR merged and backported. The output on 3.12 and 3.14 is now as expected: <class 'str'>
<class 'str'>
<class 'int'>
<class 'int'> Please re-open if there's more to do. |
Uh oh!
There was an error while loading. Please reload this page.
Bug report
Bug description:
The
reset_mock(return_value=True)
method behaves in a wrong/inconsistent way.When used with
MagicMock
, the methodreset_mock(return_value=True)
does not reset the return values of the magic methods. Only if you call for example__str__
and then call the reset_mock function, the return value will be reset, but not to the default value.Output
Since Python 3.9 PR
reset_mock
now also resets child mocks. This explains the behaviour. Calling the__str__
method creates a childMagicMock
with a set return value. Since this child mock now exists, its return value is reset when reset_mock(return_value=True) is called.Although this can be logically explained, it's counter-intuitive and annoying as I'm never sure which values are being reset.
I would expect the same behaviour as
Mock
. The return value of__str__
and other magic methods should not be effected.Output
CPython versions tested on:
3.10
Operating systems tested on:
Linux
Linked PRs
MagicMock
not to reset magic method return values #124038MagicMock
not to reset magic method return values (GH-124038) #124231MagicMock
not to reset magic method return values (GH-124038) #124232The text was updated successfully, but these errors were encountered: