classification
Title: ordered keyword arguments in unittest.mock.call repr and error messages
Type: behavior Stage: patch review
Components: Library (Lib) Versions: Python 3.9
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: cjw296, dhilst, mariocj89, michael.foord, xtreak
Priority: normal Keywords: patch

Created on 2019-06-10 07:53 by xtreak, last changed 2019-06-22 18:45 by xtreak.

Pull Requests
URL Status Linked Edit
PR 14310 open xtreak, 2019-06-22 18:45
Messages (3)
msg345106 - (view) Author: Karthikeyan Singaravelan (xtreak) * (Python triager) Date: 2019-06-10 07:53
With PEP 468 implemented in Python 3.6 the order of keyword arguments are preserved. In mock.call the arguments are sorted [0]. This makes the output different from the expectation that order should be same as the one passed. This was implemented in issue21256 where ordered kwargs was suggested but I guess it was not implemented and hence sort was used for deterministic output. The PEP also links to the discussion where ordered kwargs was discussed [1] in 2009 before ordered dict implementation.

Given that keyword argument dictionary is now deterministic is it okay to drop sorting in 3.9? This is backwards incompatible with 3.8 where code might have depended upon the sorted output so if this requires a python-dev discussion I would be happy to start one.


# (b=1, a=2) is the actual call but "actual" in error message is noted as (a=2, b=1)

>>> from unittest.mock import call, Mock
>>> call(b=1, a=2)
call(a=2, b=1)
>>> m = Mock()
>>> m(b=1, a=2)
<Mock name='mock()' id='4477750800'>
>>> m.assert_called_with(c=3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/unittest/mock.py", line 870, in assert_called_with
    raise AssertionError(_error_message()) from cause
AssertionError: expected call not found.
Expected: mock(c=3)
Actual: mock(a=2, b=1)

# With proposed change removing sorting

>>> from unittest.mock import call, Mock
>>> call(b=1, a=2)
call(b=1, a=2)
>>> m = Mock()
>>> m(b=1, a=2)
<Mock name='mock()' id='4419010880'>
>>> m.assert_called_with(c=3)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/unittest/mock.py", line 870, in assert_called_with
    raise AssertionError(_error_message()) from cause
AssertionError: expected call not found.
Expected: mock(c=3)
Actual: mock(b=1, a=2)

[0] https://github.com/python/cpython/blob/c879ff247ae1b67a790ff98d2d59145302cd4e4e/Lib/unittest/mock.py#L2284
[1] https://mail.python.org/pipermail/python-ideas/2009-April/004163.html
msg346270 - (view) Author: Karthikeyan Singaravelan (xtreak) * (Python triager) Date: 2019-06-22 07:17
I created a python-dev thread for discussion : https://mail.python.org/archives/list/python-dev@python.org/thread/6F2NGCERZLZ2CDGYIAR5QOHMGAAE5VHE/
msg346281 - (view) Author: Karthikeyan Singaravelan (xtreak) * (Python triager) Date: 2019-06-22 14:28
I will create a PR for this as per mailing list discussion : https://mail.python.org/archives/list/python-dev@python.org/message/JWPDLKNM5X27FRWJG7UOAFXHNRUGH44S/
History
Date User Action Args
2019-06-22 18:45:43xtreaksetkeywords: + patch
stage: patch review
pull_requests: + pull_request14132
2019-06-22 14:28:15xtreaksetmessages: + msg346281
2019-06-22 14:26:05dhilstsetnosy: + dhilst
2019-06-22 07:17:21xtreaksetmessages: + msg346270
2019-06-10 07:53:37xtreakcreate