From ee3259a1325c8d9c2c746dc2a97e85ca037e3884 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Thu, 12 Jun 2025 19:35:31 +0200 Subject: [PATCH] Extend dataclass mock_methods --- Lib/test/test_unittest/testmock/testhelpers.py | 2 ++ Lib/unittest/mock.py | 15 +++++++++------ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Lib/test/test_unittest/testmock/testhelpers.py b/Lib/test/test_unittest/testmock/testhelpers.py index 7dab2e05679ab7..0e82c723ec3eaa 100644 --- a/Lib/test/test_unittest/testmock/testhelpers.py +++ b/Lib/test/test_unittest/testmock/testhelpers.py @@ -1125,6 +1125,8 @@ class Description: self.assertIs(mock.__class__, Description) self.assertIsInstance(mock.__dataclass_fields__, MagicMock) self.assertIsInstance(mock.__dataclass_params__, MagicMock) + self.assertIsInstance(mock.__match_args__, MagicMock) + self.assertIsInstance(mock.__hash__, MagicMock) class TestCallList(unittest.TestCase): diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index 560ff56815a379..e370aa48b7c703 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -569,6 +569,11 @@ def _mock_add_spec(self, spec, spec_set, _spec_as_instance=False, __dict__['_mock_methods'] = spec __dict__['_spec_asyncs'] = _spec_asyncs + def _mock_extend_spec_methods(self, spec_methods): + methods = self.__dict__.get('_mock_methods') or [] + methods.extend(spec_methods) + self.__dict__['_mock_methods'] = methods + def __get_return_value(self): ret = self._mock_return_value if self._mock_delegate is not None: @@ -2766,17 +2771,15 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None, raise InvalidSpecError(f'Cannot autospec a Mock object. ' f'[object={spec!r}]') is_async_func = _is_async_func(spec) + _kwargs = {'spec': spec} entries = [(entry, _missing) for entry in dir(spec)] if is_type and instance and is_dataclass(spec): + is_dataclass_spec = True dataclass_fields = fields(spec) entries.extend((f.name, f.type) for f in dataclass_fields) - spec_list = [f.name for f in dataclass_fields] - spec_list.extend(['__dataclass_fields__', '__dataclass_params__']) - _kwargs = {'spec': spec_list} # we set `__class__` further - is_dataclass_spec = True + dataclass_spec_list = [f.name for f in dataclass_fields] else: - _kwargs = {'spec': spec} is_dataclass_spec = False if spec_set: @@ -2815,7 +2818,7 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None, mock = Klass(parent=_parent, _new_parent=_parent, _new_name=_new_name, name=_name, **_kwargs) if is_dataclass_spec: - mock.__class__ = spec # we need this for `isinstance` to work + mock._mock_extend_spec_methods(dataclass_spec_list) if isinstance(spec, FunctionTypes): # should only happen at the top level because we don't