You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardexpand all lines: docs/strategies.md
+132-1
Original file line number
Diff line number
Diff line change
@@ -4,7 +4,7 @@ _cattrs_ ships with a number of _strategies_ for customizing un/structuring beha
4
4
5
5
Strategies are prepackaged, high-level patterns for quickly and easily applying complex customizations to a converter.
6
6
7
-
## Tagged Unions
7
+
## Tagged Unions Strategy
8
8
9
9
_Found at {py:func}`cattrs.strategies.configure_tagged_union`._
10
10
@@ -119,3 +119,134 @@ The converter is now ready to start structuring Apple notifications.
119
119
...print("Can't handle this yet")
120
120
121
121
```
122
+
123
+
## Include Subclasses Strategy
124
+
125
+
_Found at {py:func}`cattrs.strategies.include_subclasses`._
126
+
127
+
The _include subclass_ strategy allows the un/structuring of a base class to an instance of itself or one of its descendants.
128
+
Conceptually with this strategy, each time an un/structure operation for the base class is asked, `cattrs` machinery replaces that operation as if the union of the base class and its descendants had been asked instead.
129
+
130
+
```{doctest} include_subclass
131
+
132
+
>>> from attrs import define
133
+
>>> from cattrs.strategies import include_subclasses
In the example above, we asked to unstructure then structure a `Child` instance as the `Parent` class and in both cases we correctly obtained back the unstructured and structured versions of the `Child` instance.
155
+
If we did not apply the `include_subclasses` strategy, this is what we would have obtained:
Without the application of the strategy, in both unstructure and structure operations, we received a `Parent` instance.
168
+
169
+
```{note}
170
+
The handling of subclasses is an opt-in feature for two main reasons:
171
+
- Performance. While small and probably negligeable in most cases the subclass handling incurs more function calls and has a performance impact.
172
+
- Customization. The specific handling of subclasses can be different from one situation to the other. In particular there is not apparent universal good defaults for disambiguating the union type. Consequently The decision is left to the `cattrs` user.
173
+
```
174
+
175
+
```{warning}
176
+
To work properly, all subclasses must be defined when the `include_subclasses` strategy is applied to a `converter`. If subclasses types are defined later, for instance in the context of a plug-in mechanism using inheritance, then those late defined subclasses will not be part of the subclasses union type and will not be un/structured as expected.
177
+
```
178
+
179
+
### Customization
180
+
181
+
In the example shown in the previous section, the default options for `include_subclasses` work well because the `Child` class has an attribute that do not exist in the `Parent` class (the `b` attribute).
182
+
The automatic union type disambiguation function which is based on finding unique fields for each type of the union works as intended.
183
+
184
+
Sometimes, more disambiguation customization is required.
185
+
For instance, the unstructuring operation would have failed if `Child` did not have an extra attribute or if a sibling of `Child` had also a `b` attribute.
186
+
For those cases, a callable of 2 positional arguments (a union type and a converter) defining a [tagged union strategy](strategies.md#tagged-unions-strategy) can be passed to the `include_subclasses` strategy.
187
+
{py:func}`configure_tagged_union()<cattrs.strategies.configure_tagged_union>` can be used as-is, but if you want to change its defaults, the [partial](https://docs.python.org/3/library/functools.html#functools.partial) function from the `functools` module in the standard library can come in handy.
Copy file name to clipboardexpand all lines: docs/structuring.md
+3-1
Original file line number
Diff line number
Diff line change
@@ -280,7 +280,7 @@ the first time an appropriate union is structured.
280
280
To support arbitrary unions, register a custom structuring hook for the union
281
281
(see [Registering custom structuring hooks](structuring.md#registering-custom-structuring-hooks)).
282
282
283
-
Another option is to use a custom tagged union strategy (see [Strategies - Tagged Unions](strategies.md#tagged-unions)).
283
+
Another option is to use a custom tagged union strategy (see [Strategies - Tagged Unions](strategies.md#tagged-unions-strategy)).
284
284
285
285
### `typing.Final`
286
286
@@ -456,6 +456,8 @@ attributes holding `attrs` classes and dataclasses.
456
456
B(b=A(a=1))
457
457
```
458
458
459
+
Finally, if an `attrs`or`dataclass`class uses inheritance andas such has one or several subclasses, it can be structured automatically to its exact subtype by using the [include subclasses](strategies.md#include-subclasses-strategy) strategy.
460
+
459
461
## Registering Custom Structuring Hooks
460
462
461
463
_cattrs_ doesn't know how to structure non-_attrs_ classes by default,
0 commit comments