classification
Title: mock.ANY doesn't match mock.MagicMock() object
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.6, Python 3.5
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: aplummer, berker.peksag, felixonmars, michael.foord, python-dev, serhiy.storchaka
Priority: normal Keywords: 3.5regression, patch

Created on 2015-09-20 10:27 by felixonmars, last changed 2016-03-27 21:30 by berker.peksag. This issue is now closed.

Files
File name Uploaded Description Edit
fix_mock_call_ne.patch aplummer, 2016-02-08 11:01 review
Messages (7)
msg251162 - (view) Author: Felix Yan (felixonmars) * Date: 2015-09-20 10:27
Since Python 3.5.0 mock.MagicMock() object seems not matched by mock.ANY. This behavior looks weird and breaks tests of boto.

Minimized example:

In Python 3.4.3:
>>> from unittest import mock
>>> m = mock.MagicMock()
>>> m(mock.MagicMock())
<MagicMock name='mock()' id='139728217270704'>
>>> m.assert_called_with(mock.ANY)
>>>

In Python 3.5.0:
>>> from unittest import mock
>>> m = mock.MagicMock()
>>> m(mock.MagicMock())
<MagicMock name='mock()' id='140093484276536'>
>>> m.assert_called_with(mock.ANY)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/unittest/mock.py", line 792, in assert_called_with
    raise AssertionError(_error_message()) from cause
AssertionError: Expected call: mock(<ANY>)
Actual call: mock(<MagicMock id='140093520206872'>)
msg259811 - (view) Author: Andrew Plummer (aplummer) * Date: 2016-02-08 00:02
I've had a look and I think this could be because the class _Call (also in unittest.mock) has lost its __ne__ method between 3.4 and 3.5.

Compare
https://hg.python.org/cpython/file/v3.4.4/Lib/unittest/mock.py#l2010
with
https://hg.python.org/cpython/file/v3.5.1/Lib/unittest/mock.py#l2028

This leads me to this changeset:
https://hg.python.org/cpython/rev/3603bae63c13


My failing test:

from unittest import mock

call1 = mock.call(mock.MagicMock())
call2 = mock.call(mock.ANY)

assert call1 == call2
assert not (call1 != call2)

This passes in 3.4 but fails in 3.5, but fails on the second assert, not the first. So they are equal, but they're not not-equal. I've added this as a test and reinstated __ne__ in my patch.
msg259814 - (view) Author: Berker Peksag (berker.peksag) * (Python committer) Date: 2016-02-08 04:36
Looks like _Call is a subclass of tuple. Checks in the test could be written as "self.assertIs(a == b, True)".
msg259822 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2016-02-08 06:54
It would be better to use just default implementation:

    __ne__ = object.__ne__

Interesting that while call1 == call2 is True, call2 == call1 is False. But this is different issue.
msg259835 - (view) Author: Andrew Plummer (aplummer) * Date: 2016-02-08 11:00
Have added a new diff to just use the default __ne__ implementation rather than tuple's.

Have also added a test that targets exactly the reported issue.
msg262538 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2016-03-27 21:28
New changeset dcd3b078ab84 by Berker Peksag in branch '3.5':
Issue #25195: Fix a regression in mock.MagicMock
https://hg.python.org/cpython/rev/dcd3b078ab84

New changeset 880d609b6664 by Berker Peksag in branch 'default':
Issue #25195: Fix a regression in mock.MagicMock
https://hg.python.org/cpython/rev/880d609b6664
msg262539 - (view) Author: Berker Peksag (berker.peksag) * (Python committer) Date: 2016-03-27 21:29
Thanks!
History
Date User Action Args
2016-03-27 21:30:10berker.peksagsetkeywords: + patch
2016-03-27 21:29:41berker.peksagsetstatus: open -> closed
messages: + msg262539

keywords: + 3.5regression, - patch
resolution: fixed
stage: patch review -> resolved
2016-03-27 21:28:48python-devsetnosy: + python-dev
messages: + msg262538
2016-02-08 11:01:34aplummersetfiles: - fix_mock_call_ne.patch
2016-02-08 11:01:19aplummersetfiles: + fix_mock_call_ne.patch
2016-02-08 11:01:06aplummersetfiles: - test_assert_called_with_any.diff
2016-02-08 11:00:02aplummersetfiles: + test_assert_called_with_any.diff

messages: + msg259835
2016-02-08 06:54:02serhiy.storchakasetmessages: + msg259822
2016-02-08 04:36:19berker.peksagsetversions: + Python 3.6
nosy: + berker.peksag

messages: + msg259814

stage: patch review
2016-02-08 04:10:21berker.peksagsetnosy: + serhiy.storchaka
2016-02-08 00:02:58aplummersetfiles: + fix_mock_call_ne.patch

nosy: + aplummer
messages: + msg259811

keywords: + patch
2016-02-07 05:36:42ned.deilysetnosy: + michael.foord
2015-09-20 10:27:28felixonmarssettype: behavior
2015-09-20 10:27:20felixonmarscreate