diff options
author | sobolevn <mail@sobolevn.me> | 2024-09-27 06:48:31 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-27 06:48:31 (GMT) |
commit | 3a0e7f57628466aedcaaf6c5ff7c8224f5155a2c (patch) | |
tree | 9b1cefec532fff95a3296bb09645beefef4a8647 /Lib/unittest/mock.py | |
parent | 08e1bbe4a329e5961716f030c6ccfe92c736bf28 (diff) | |
download | cpython-3a0e7f57628466aedcaaf6c5ff7c8224f5155a2c.zip cpython-3a0e7f57628466aedcaaf6c5ff7c8224f5155a2c.tar.gz cpython-3a0e7f57628466aedcaaf6c5ff7c8224f5155a2c.tar.bz2 |
gh-124176: Add special support for dataclasses to `create_autospec` (#124429)
Diffstat (limited to 'Lib/unittest/mock.py')
-rw-r--r-- | Lib/unittest/mock.py | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/Lib/unittest/mock.py b/Lib/unittest/mock.py index df3901f..21ca061 100644 --- a/Lib/unittest/mock.py +++ b/Lib/unittest/mock.py @@ -34,6 +34,7 @@ import builtins import pkgutil from inspect import iscoroutinefunction import threading +from dataclasses import fields, is_dataclass from types import CodeType, ModuleType, MethodType from unittest.util import safe_repr from functools import wraps, partial @@ -2756,7 +2757,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): + dataclass_fields = fields(spec) + entries.extend((f.name, f.type) for f in dataclass_fields) + _kwargs = {'spec': [f.name for f in dataclass_fields]} + else: + _kwargs = {'spec': spec} + if spec_set: _kwargs = {'spec_set': spec} elif spec is None: @@ -2813,7 +2822,7 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None, _name='()', _parent=mock, wraps=wrapped) - for entry in dir(spec): + for entry, original in entries: if _is_magic(entry): # MagicMock already does the useful magic methods for us continue @@ -2827,10 +2836,11 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None, # AttributeError on being fetched? # we could be resilient against it, or catch and propagate the # exception when the attribute is fetched from the mock - try: - original = getattr(spec, entry) - except AttributeError: - continue + if original is _missing: + try: + original = getattr(spec, entry) + except AttributeError: + continue child_kwargs = {'spec': original} # Wrap child attributes also. |