Skip to content
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

gh-123934: Fix MagicMock not to reset magic method return values #124038

Merged
merged 3 commits into from
Sep 19, 2024

Conversation

sobolevn
Copy link
Member

@sobolevn sobolevn commented Sep 13, 2024

@sobolevn
Copy link
Member Author

I consider this a bug fix, so I propose to backport this to 3.12 and 3.13
@cjw296 what do you think? :)

Lib/unittest/mock.py Outdated Show resolved Hide resolved
Lib/unittest/mock.py Outdated Show resolved Hide resolved

def test_magic_mock_resets_manual_mocks(self):
mm = MagicMock()
mm.__iter__ = MagicMock(return_value=iter([1]))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, okay, things I didn't know about MagicMock and I'm not sure I like ;-) :

>>> m = MagicMock()
>>> list(iter(m))
[]

However, what happens if you change the above line to:

Suggested change
mm.__iter__ = MagicMock(return_value=iter([1]))
mm.__iter__ = MagicMock(return_value=[])

I'm not sure it makes any difference, but mainly 'cos of the weird behaviour I started with an example of ;-)

Here's some playing around in a Python 3.12 interpreter that might give more of a feel for what I'm trying to communicate:

>>> from unittest.mock import MagicMock
>>> m = MagicMock()
>>> m.__iter__
<MagicMock name='mock.__iter__' id='4307758752'>
>>> m.__iter__.return_value = []
>>> iter(m)
<list_iterator object at 0x10088f8b0>
>>> list(iter(m))
[]
>>> list(iter(m)) is m.__iter__.return_value
False
>>> m.__iter__.return_value = [1, 2, 3]
>>> list(iter(m))
[1, 2, 3]

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added one more test with the behavior you are showing here. I executed these two tests

    def test_magic_mock_resets_manual_mocks(self):
        mm = MagicMock()
        mm.__iter__ = MagicMock(return_value=iter([1]))
        mm.custom = MagicMock(return_value=2)
        self.assertEqual(list(iter(mm)), [1])
        self.assertEqual(mm.custom(), 2)

        mm.reset_mock(return_value=True)
        self.assertEqual(list(iter(mm)), [])
        self.assertIsInstance(mm.custom(), MagicMock)

    def test_magic_mock_resets_manual_mocks_empty_iter(self):
        mm = MagicMock()
        mm.__iter__.return_value = []
        self.assertEqual(list(iter(mm)), [])

        mm.reset_mock(return_value=True)
        self.assertEqual(list(iter(mm)), [])

on main (with no changes from this PR) and it was also successful.

Should I cover anything else?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I think this is where I got confused; the docs aren't great here. I believe the intention may be that return_value is only a boolean, or it may be that it's intended as a way to provide a new value.

If you feel inclined, it'd be good to clarify the docs on this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure!

Copy link
Contributor

@cjw296 cjw296 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I said inline, the docs aren't great. Any reason not to just add a type annotation of : bool to that parameter?

Anyway, I think this is good to land, thanks for the attention to detail here!


def test_magic_mock_resets_manual_mocks(self):
mm = MagicMock()
mm.__iter__ = MagicMock(return_value=iter([1]))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I think this is where I got confused; the docs aren't great here. I believe the intention may be that return_value is only a boolean, or it may be that it's intended as a way to provide a new value.

If you feel inclined, it'd be good to clarify the docs on this.

Lib/unittest/mock.py Show resolved Hide resolved
@cjw296 cjw296 added needs backport to 3.12 bug and security fixes needs backport to 3.13 bugs and security fixes labels Sep 19, 2024
@sobolevn sobolevn merged commit 7628f67 into python:main Sep 19, 2024
38 checks passed
@miss-islington-app
Copy link

Thanks @sobolevn for the PR 🌮🎉.. I'm working now to backport this PR to: 3.12, 3.13.
🐍🍒⛏🤖

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Sep 19, 2024
…ues (pythonGH-124038)

(cherry picked from commit 7628f67)

Co-authored-by: sobolevn <mail@sobolevn.me>
@sobolevn
Copy link
Member Author

sobolevn commented Sep 19, 2024

Thanks a lot for the helpful reviews! I would prefer to work on docs in a separate PR, because it is unrelated to this problem. Working on it now! 👍

#124234

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Sep 19, 2024
…ues (pythonGH-124038)

(cherry picked from commit 7628f67)

Co-authored-by: sobolevn <mail@sobolevn.me>
@bedevere-app
Copy link

bedevere-app bot commented Sep 19, 2024

GH-124231 is a backport of this pull request to the 3.13 branch.

@bedevere-app bedevere-app bot removed the needs backport to 3.13 bugs and security fixes label Sep 19, 2024
@bedevere-app
Copy link

bedevere-app bot commented Sep 19, 2024

GH-124232 is a backport of this pull request to the 3.12 branch.

@bedevere-app bedevere-app bot removed the needs backport to 3.12 bug and security fixes label Sep 19, 2024
sobolevn added a commit that referenced this pull request Sep 19, 2024
…lues (GH-124038) (#124232)

gh-123934: Fix `MagicMock` not to reset magic method return values (GH-124038)
(cherry picked from commit 7628f67)

Co-authored-by: sobolevn <mail@sobolevn.me>
savannahostrowski pushed a commit to savannahostrowski/cpython that referenced this pull request Sep 22, 2024
Yhg1s pushed a commit that referenced this pull request Sep 30, 2024
…lues (GH-124038) (#124231)

gh-123934: Fix `MagicMock` not to reset magic method return values (GH-124038)
(cherry picked from commit 7628f67)

Co-authored-by: sobolevn <mail@sobolevn.me>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants