Skip to content

Commit bd73cda

Browse files
committed
pythongh-124176: create_autospec must not change how dataclass defaults are mocked
1 parent 165ed68 commit bd73cda

File tree

2 files changed

+20
-3
lines changed

2 files changed

+20
-3
lines changed

Lib/test/test_unittest/testmock/testhelpers.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1107,6 +1107,21 @@ class WithNonFields:
11071107
with self.assertRaisesRegex(AttributeError, msg):
11081108
mock.b
11091109

1110+
def test_dataclass_with_wider_default(self):
1111+
# If field defines an actual default, we don't need to change
1112+
# the default type. Since this is how it used to work before #124176
1113+
@dataclass
1114+
class WithWiderDefault:
1115+
narrow_default: int | None = field(default=30)
1116+
1117+
for mock in [
1118+
create_autospec(WithWiderDefault, instance=True),
1119+
create_autospec(WithWiderDefault()),
1120+
]:
1121+
with self.subTest(mock=mock):
1122+
self.assertIs(mock.narrow_default.__class__, int)
1123+
1124+
11101125
class TestCallList(unittest.TestCase):
11111126

11121127
def test_args_list_contains_call_list(self):

Lib/unittest/mock.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2758,13 +2758,15 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None,
27582758
f'[object={spec!r}]')
27592759
is_async_func = _is_async_func(spec)
27602760

2761-
entries = [(entry, _missing) for entry in dir(spec)]
2761+
base_entries = {entry: _missing for entry in dir(spec)}
27622762
if is_type and instance and is_dataclass(spec):
27632763
dataclass_fields = fields(spec)
2764-
entries.extend((f.name, f.type) for f in dataclass_fields)
2764+
entries = {f.name: f.type for f in dataclass_fields}
2765+
entries.update(base_entries)
27652766
_kwargs = {'spec': [f.name for f in dataclass_fields]}
27662767
else:
27672768
_kwargs = {'spec': spec}
2769+
entries = base_entries
27682770

27692771
if spec_set:
27702772
_kwargs = {'spec_set': spec}
@@ -2822,7 +2824,7 @@ def create_autospec(spec, spec_set=False, instance=False, _parent=None,
28222824
_name='()', _parent=mock,
28232825
wraps=wrapped)
28242826

2825-
for entry, original in entries:
2827+
for entry, original in entries.items():
28262828
if _is_magic(entry):
28272829
# MagicMock already does the useful magic methods for us
28282830
continue

0 commit comments

Comments
 (0)