Skip to content
Closed
Changes from 1 commit
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
Next Next commit
[3.8] bpo-38122: minor fixes to AsyncMock spec handling (GH-16099).
(cherry picked from commit 14fd925)

Co-authored-by: Michael Foord <voidspace@users.noreply.github.com>
  • Loading branch information
voidspace authored and matrixise committed Sep 14, 2019
commit 301d852a6ca9ea008e8ca7b61c29a92cd77a193f
35 changes: 24 additions & 11 deletions Lib/unittest/mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,18 +402,12 @@ def __new__(cls, /, *args, **kw):
# so we can create magic methods on the
# class without stomping on other mocks
bases = (cls,)
if not issubclass(cls, AsyncMock):
if not issubclass(cls, AsyncMockMixin):
# Check if spec is an async object or function
sig = inspect.signature(NonCallableMock.__init__)
bound_args = sig.bind_partial(cls, *args, **kw).arguments
spec_arg = [
arg for arg in bound_args.keys()
if arg.startswith('spec')
]
if spec_arg:
# what if spec_set is different than spec?
if _is_async_obj(bound_args[spec_arg[0]]):
bases = (AsyncMockMixin, cls,)
bound_args = _MOCK_SIG.bind_partial(cls, *args, **kw).arguments
spec_arg = bound_args.get('spec_set', bound_args.get('spec'))
if spec_arg and _is_async_obj(spec_arg):
bases = (AsyncMockMixin, cls)
new = type(cls.__name__, bases, {'__doc__': cls.__doc__})
instance = object.__new__(new)
return instance
Expand Down Expand Up @@ -1019,6 +1013,25 @@ def _calls_repr(self, prefix="Calls"):
return f"\n{prefix}: {safe_repr(self.mock_calls)}."


_MOCK_SIG = inspect.signature(NonCallableMock.__init__)


class _AnyComparer(list):
"""A list which checks if it contains a call which may have an
argument of ANY, flipping the components of item and self from
their traditional locations so that ANY is guaranteed to be on
the left."""
def __contains__(self, item):
for _call in self:
if len(item) != len(_call):
continue
if all([
expected == actual
for expected, actual in zip(item, _call)
]):
return True
return False


def _try_iter(obj):
if obj is None:
Expand Down