bpo-37251: Removes __code__ check from _is_async_obj. (GH-15830) Backports: f1a297acb60b88917712450ebd3cfa707e6efd6b Signed-off-by: Chris Withers <[email protected]>
diff --git a/NEWS.d/2019-09-10-10-59-50.bpo-37251.8zn2o3.rst b/NEWS.d/2019-09-10-10-59-50.bpo-37251.8zn2o3.rst new file mode 100644 index 0000000..27fd1e4 --- /dev/null +++ b/NEWS.d/2019-09-10-10-59-50.bpo-37251.8zn2o3.rst
@@ -0,0 +1,3 @@ +Remove `__code__` check in AsyncMock that incorrectly +evaluated function specs as async objects but failed to evaluate classes +with `__await__` but no `__code__` attribute defined as async objects.
diff --git a/mock/mock.py b/mock/mock.py index 2d4d89e..8a9fc9d 100644 --- a/mock/mock.py +++ b/mock/mock.py
@@ -47,10 +47,9 @@ _safe_super = super def _is_async_obj(obj): - if getattr(obj, '__code__', None): - return asyncio.iscoroutinefunction(obj) or inspect.isawaitable(obj) - else: + if _is_instance_mock(obj) and not isinstance(obj, AsyncMock): return False + return asyncio.iscoroutinefunction(obj) or inspect.isawaitable(obj) def _is_async_func(func):
diff --git a/mock/tests/testasync.py b/mock/tests/testasync.py index 9e0d322..e6f923e 100644 --- a/mock/tests/testasync.py +++ b/mock/tests/testasync.py
@@ -31,6 +31,10 @@ def normal_method(self): pass +class AwaitableClass: + def __await__(self): + yield + async def async_func(): pass @@ -173,6 +177,10 @@ with self.assertRaises(RuntimeError): create_autospec(async_func, instance=True) + def test_create_autospec_awaitable_class(self): + awaitable_mock = create_autospec(spec=AwaitableClass()) + self.assertIsInstance(create_autospec(awaitable_mock), AsyncMock) + def test_create_autospec(self): spec = create_autospec(async_func_args) awaitable = spec(1, 2, c=3) @@ -334,6 +342,13 @@ self.assertIsInstance(mock.normal_method, MagicMock) self.assertIsInstance(mock, MagicMock) + def test_magicmock_lambda_spec(self): + mock_obj = MagicMock() + mock_obj.mock_func = MagicMock(spec=lambda x: x) + + with patch.object(mock_obj, "mock_func") as cm: + self.assertIsInstance(cm, MagicMock) + class AsyncArguments(unittest.TestCase): def test_add_return_value(self):