[3.13] gh-91126: Docs and tests for slotted dataclasses with `__init_… · python/cpython@cfdf376 (original) (raw)
File tree
2 files changed
lines changed
- Lib/test/test_dataclasses
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): |