[3.13] gh-91126: Docs and tests for slotted dataclasses with `__init_… · python/cpython@cfdf376 (original) (raw)

File tree

2 files changed

lines changed

2 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -185,10 +185,21 @@ Module contents
185 185 - *slots*: If true (the default is ``False``), :attr:`~object.__slots__` attribute
186 186 will be generated and new class will be returned instead of the original one.
187 187 If :attr:`!__slots__` is already defined in the class, then :exc:`TypeError`
188 - is raised. Calling no-arg :func:`super` in dataclasses using ``slots=True`` will result in
189 - the following exception being raised:
190 - ``TypeError: super(type, obj): obj must be an instance or subtype of type``.
191 - The two-arg :func:`super` is a valid workaround. See :gh:`90562` for full details.
188 + is raised.
189 +
190 + .. warning::
191 + Calling no-arg :func:`super` in dataclasses using ``slots=True``
192 + will result in the following exception being raised:
193 + ``TypeError: super(type, obj): obj must be an instance or subtype of type``.
194 + The two-arg :func:`super` is a valid workaround.
195 + See :gh:`90562` for full details.
196 +
197 + .. warning::
198 + Passing parameters to a base class :meth:`~object.__init_subclass__`
199 + when using ``slots=True`` will result in a :exc:`TypeError`.
200 + Either use ``__init_subclass__`` with no parameters
201 + or use default values as a workaround.
202 + See :gh:`91126` for full details.
192 203
193 204 .. versionadded:: 3.10
194 205
Original file line number Diff line number Diff line change
@@ -3664,6 +3664,38 @@ class A(WithDictSlot): ...
3664 3664 self.assertEqual(A().__dict__, {})
3665 3665 A()
3666 3666
3667 +@support.cpython_only
3668 +def test_slots_with_wrong_init_subclass(self):
3669 +# TODO: This test is for a kinda-buggy behavior.
3670 +# Ideally, it should be fixed and `__init_subclass__`
3671 +# should be fully supported in the future versions.
3672 +# See https://github.com/python/cpython/issues/91126
3673 +class WrongSuper:
3674 +def __init_subclass__(cls, arg):
3675 +pass
3676 +
3677 +with self.assertRaisesRegex(
3678 +TypeError,
3679 +"missing 1 required positional argument: 'arg'",
3680 + ):
3681 +@dataclass(slots=True)
3682 +class WithWrongSuper(WrongSuper, arg=1):
3683 +pass
3684 +
3685 +class CorrectSuper:
3686 +args = []
3687 +def __init_subclass__(cls, arg="default"):
3688 +cls.args.append(arg)
3689 +
3690 +@dataclass(slots=True)
3691 +class WithCorrectSuper(CorrectSuper):
3692 +pass
3693 +
3694 +# __init_subclass__ is called twice: once for `WithCorrectSuper`
3695 +# and once for `WithCorrectSuper__slots__` new class
3696 +# that we create internally.
3697 +self.assertEqual(CorrectSuper.args, ["default", "default"])
3698 +
3667 3699
3668 3700 class TestDescriptors(unittest.TestCase):
3669 3701 def test_set_name(self):