Skip to content

Commit 0939d82

Browse files
committed
pythongh-91126: Docs and tests for slotted dataclasses with __init_subclass__
1 parent a1ddaae commit 0939d82

2 files changed

Lines changed: 42 additions & 4 deletions

File tree

‎Doc/library/dataclasses.rst‎

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,20 @@ Module contents
185185
- *slots*: If true (the default is ``False``), :attr:`~object.__slots__` attribute
186186
will be generated and new class will be returned instead of the original one.
187187
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+
Having a base class with :meth:`~object.__init_subclass__` with parameters
199+
when using ``slots=True`` will result in a :exc:`TypeError`.
200+
Either use ``__init_subclass__`` with no parameters or use default values.
201+
See :gh:`91126` for full details.
192202

193203
.. versionadded:: 3.10
194204

‎Lib/test/test_dataclasses/__init__.py‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3664,6 +3664,34 @@ class A(WithDictSlot): ...
36643664
self.assertEqual(A().__dict__, {})
36653665
A()
36663666

3667+
def test_slots_with_wrong_init_subclass(self):
3668+
class WrongSuper:
3669+
def __init_subclass__(cls, arg):
3670+
pass
3671+
3672+
with self.assertRaisesRegex(
3673+
TypeError,
3674+
"missing 1 required positional argument: 'arg'",
3675+
):
3676+
@dataclass(slots=True)
3677+
class WithWrongSuper(WrongSuper, arg=1):
3678+
pass
3679+
3680+
def test_slots_with_correct_init_subclass(self):
3681+
class CorrectSuper:
3682+
args = []
3683+
def __init_subclass__(cls, arg="default"):
3684+
cls.args.append(arg)
3685+
3686+
@dataclass(slots=True)
3687+
class WithCorrectSuper(CorrectSuper):
3688+
pass
3689+
3690+
# __init_subclass__ is called twice: once for `WithCorrectSuper`
3691+
# and once for `WithCorrectSuper__slots__` new class
3692+
# that we create internally.
3693+
self.assertEqual(CorrectSuper.args, ["default", "default"])
3694+
36673695

36683696
class TestDescriptors(unittest.TestCase):
36693697
def test_set_name(self):

0 commit comments

Comments
 (0)