|
9 | 9 | from ..converters import BaseConverter |
10 | 10 | from ..gen import AttributeOverride, make_dict_structure_fn, make_dict_unstructure_fn |
11 | 11 | from ..gen._consts import already_generating |
| 12 | +from ..subclasses import subclasses |
12 | 13 |
|
13 | 14 |
|
14 | 15 | def _make_subclasses_tree(cl: type) -> list[type]: |
15 | 16 | # get class origin for accessing subclasses (see #648 for more info) |
16 | 17 | cls_origin = typing.get_origin(cl) or cl |
17 | 18 | return [cl] + [ |
18 | | - sscl |
19 | | - for scl in cls_origin.__subclasses__() |
20 | | - for sscl in _make_subclasses_tree(scl) |
| 19 | + sscl for scl in subclasses(cls_origin) for sscl in _make_subclasses_tree(scl) |
21 | 20 | ] |
22 | 21 |
|
23 | 22 |
|
24 | 23 | def _has_subclasses(cl: type, given_subclasses: tuple[type, ...]) -> bool: |
25 | 24 | """Whether the given class has subclasses from `given_subclasses`.""" |
26 | 25 | cls_origin = typing.get_origin(cl) or cl |
27 | | - actual = set(cls_origin.__subclasses__()) |
| 26 | + actual = set(subclasses(cls_origin.__subclasses__())) |
28 | 27 | given = set(given_subclasses) |
29 | 28 | return bool(actual & given) |
30 | 29 |
|
@@ -69,6 +68,9 @@ def include_subclasses( |
69 | 68 | .. versionchanged:: 24.1.0 |
70 | 69 | When overrides are not provided, hooks for individual classes are retrieved from |
71 | 70 | the converter instead of generated with no overrides, using converter defaults. |
| 71 | + .. versionchanged:: 25.2.0 |
| 72 | + Slotted dataclasses work on Python 3.14 via :func:`cattrs.subclasses.subclasses`, |
| 73 | + which filters out duplicate classes caused by slotting. |
72 | 74 | """ |
73 | 75 | # Due to https://github.com/python-attrs/attrs/issues/1047 |
74 | 76 | collect() |
|
0 commit comments