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

Created on 2019-06-10 07:53 by xtreak, last changed 2019-09-09 11:42 by miss-islington. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 14310 merged xtreak, 2019-06-22 18:45
PR 15755 merged miss-islington, 2019-09-09 10:57
Messages (5)
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/
msg351426 - (view) Author: Zachary Ware (zach.ware) * (Python committer) Date: 2019-09-09 10:55
New changeset 9d607061c9c888913ae2c18543775cf360d55f27 by Zachary Ware (Xtreak) in branch 'master':
bpo-37212: Preserve keyword argument order in unittest.mock.call and error messages (GH-14310)
https://github.com/python/cpython/commit/9d607061c9c888913ae2c18543775cf360d55f27
msg351435 - (view) Author: miss-islington (miss-islington) Date: 2019-09-09 11:42
New changeset bee8bfe5f440c2dde7f5af189febdbf81b27abd5 by Miss Islington (bot) in branch '3.8':
bpo-37212: Preserve keyword argument order in unittest.mock.call and error messages (GH-14310)
https://github.com/python/cpython/commit/bee8bfe5f440c2dde7f5af189febdbf81b27abd5
History
Date User Action Args
2019-09-09 11:42:46miss-islingtonsetnosy: + miss-islington
messages: + msg351435
2019-09-09 10:59:38zach.waresetstatus: open -> closed
stage: patch review -> resolved
resolution: fixed
versions: + Python 3.8
2019-09-09 10:57:14miss-islingtonsetpull_requests: + pull_request15408
2019-09-09 10:55:25zach.waresetnosy: + zach.ware
messages: + msg351426
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