From a03f84360e4830ffa63883ba52f6b5958c6bd16a Mon Sep 17 00:00:00 2001 From: Carl Meyer Date: Fri, 16 Dec 2022 09:14:27 -0800 Subject: [PATCH] fix instance-only async attr --- Lib/test/test_unittest/testmock/testasync.py | 7 +++++++ Lib/unittest/mock.py | 5 ++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_unittest/testmock/testasync.py b/Lib/test/test_unittest/testmock/testasync.py index e05a22861d47bf..990b247e5ee975 100644 --- a/Lib/test/test_unittest/testmock/testasync.py +++ b/Lib/test/test_unittest/testmock/testasync.py @@ -300,6 +300,13 @@ def test_spec_normal_methods_on_class_with_mock(self): self.assertIsInstance(mock.async_method, AsyncMock) self.assertIsInstance(mock.normal_method, Mock) + def test_spec_async_attributes_instance(self): + async_instance = AsyncClass() + async_instance.async_func_attr = async_func + + mock_async_instance = Mock(async_instance) + self.assertIsInstance(mock_async_instance.async_func_attr, AsyncMock) + def test_spec_mock_type_kw(self): def inner_test(mock_type): async_mock = mock_type(spec=async_func) diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 50e9e5b287849a..e37d31dda201c0 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -506,8 +506,10 @@ def _mock_add_spec(self, spec, spec_set, _spec_as_instance=False, _spec_class = None _spec_signature = None + _spec_obj = None if spec is not None and not _is_list(spec): + _spec_obj = spec if isinstance(spec, type): _spec_class = spec else: @@ -520,6 +522,7 @@ def _mock_add_spec(self, spec, spec_set, _spec_as_instance=False, __dict__ = self.__dict__ __dict__['_spec_class'] = _spec_class + __dict__['_spec_obj'] = _spec_obj __dict__['_spec_set'] = spec_set __dict__['_spec_signature'] = _spec_signature __dict__['_mock_methods'] = spec @@ -1012,7 +1015,7 @@ def _get_child_mock(self, /, **kw): For non-callable mocks the callable variant will be used (rather than any custom subclass).""" _new_name = kw.get("_new_name") - _spec_val = getattr(self.__dict__["_spec_class"], _new_name, None) + _spec_val = getattr(self.__dict__["_spec_obj"], _new_name, None) if _spec_val is not None and asyncio.iscoroutinefunction(_spec_val): return AsyncMock(**kw)