Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
bpo-37972: unittest.mock._Call now passes on __getitem__ to the __get…
…attr__ chaining so that call() can be subscriptable (GH-15565)

* bpo-37972: unittest.mock._Call now passes on __getitem__ to the __getattr__ chaining so that call() can be subscriptable

* 📜🤖 Added by blurb_it.

* Update 2019-08-28-21-40-12.bpo-37972.kP-n4L.rst

added name of the contributor

* bpo-37972: made all dunder methods chainable for _Call

* bpo-37972: delegate only attributes of tuple instead to __getattr__
(cherry picked from commit 72c3599)

Co-authored-by: blhsing <github@ydooby.com>
  • Loading branch information
blhsing authored and miss-islington committed Sep 11, 2019
commit 3fad9a059a3185174ba3bf3044a31a0f681157d8
6 changes: 6 additions & 0 deletions Lib/unittest/mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -2464,6 +2464,12 @@ def __getattr__(self, attr):
return _Call(name=name, parent=self, from_kall=False)


def __getattribute__(self, attr):
if attr in tuple.__dict__:
raise AttributeError
return tuple.__getattribute__(self, attr)


def count(self, /, *args, **kwargs):
return self.__getattr__('count')(*args, **kwargs)

Expand Down
20 changes: 20 additions & 0 deletions Lib/unittest/test/testmock/testhelpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,26 @@ def test_call_with_name(self):
self.assertEqual(_Call((('bar', 'barz'),),)[0], '')
self.assertEqual(_Call((('bar', 'barz'), {'hello': 'world'}),)[0], '')

def test_dunder_call(self):
m = MagicMock()
m().foo()['bar']()
self.assertEqual(
m.mock_calls,
[call(), call().foo(), call().foo().__getitem__('bar'), call().foo().__getitem__()()]
)
m = MagicMock()
m().foo()['bar'] = 1
self.assertEqual(
m.mock_calls,
[call(), call().foo(), call().foo().__setitem__('bar', 1)]
)
m = MagicMock()
iter(m().foo())
self.assertEqual(
m.mock_calls,
[call(), call().foo(), call().foo().__iter__()]
)


class SpecSignatureTest(unittest.TestCase):

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Subscripts to the `unittest.mock.call` objects now receive the same chaining mechanism as any other custom attributes, so that the following usage no longer raises a `TypeError`:

call().foo().__getitem__('bar')

Patch by blhsing