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/customizing.md
+46-30
Original file line number
Diff line number
Diff line change
@@ -2,6 +2,20 @@
2
2
3
3
This section describes customizing the unstructuring and structuring processes in _cattrs_.
4
4
5
+
As you go about customizing converters by registering hooks and hook factories,
6
+
keep in mind that **the order of hook registration matters**.
7
+
8
+
Technically speaking, whether the order matters or not depends on the actual implementation of hook factories used.
9
+
In practice, the built-in _cattrs_ hooks are optimized to perform early resolution of hooks.
10
+
You will likely compose with these hook factories.
11
+
12
+
This means that **hooks for simpler types should be registered first**.
13
+
For example, to override hooks for structuring `int` and `list[int]`, the hook for `int`
14
+
must be registered first.
15
+
When the {meth}`list_structure_factory() <cattrs.cols.list_structure_factory>`
16
+
is applied to the `list[int]` type to produce a hook, it will retrieve and store
17
+
the hook for `int`, which should be already present.
18
+
5
19
## Custom (Un-)structuring Hooks
6
20
7
21
You can write your own structuring and unstructuring functions and register them for types using {meth}`Converter.register_structure_hook() <cattrs.BaseConverter.register_structure_hook>` and {meth}`Converter.register_unstructure_hook() <cattrs.BaseConverter.register_unstructure_hook>`.
@@ -11,13 +25,13 @@ This approach is the most flexible but also requires the most amount of boilerpl
11
25
_singledispatch_ is powerful and fast but comes with some limitations; namely that it performs checks using `issubclass()` which doesn't work with many Python types.
12
26
Some examples of this are:
13
27
14
-
* various generic collections (`list[int]` is not a _subclass_ of `list`)
15
-
* literals (`Literal[1]` is not a _subclass_ of `Literal[1]`)
16
-
* generics (`MyClass[int]` is not a _subclass_ of `MyClass`)
17
-
* protocols, unless they are `runtime_checkable`
18
-
* various modifiers, such as `Final` and `NotRequired`
19
-
* newtypes and 3.12 type aliases
20
-
*`typing.Annotated`
28
+
- various generic collections (`list[int]` is not a _subclass_ of `list`)
29
+
- literals (`Literal[1]` is not a _subclass_ of `Literal[1]`)
30
+
- generics (`MyClass[int]` is not a _subclass_ of `MyClass`)
31
+
- protocols, unless they are `runtime_checkable`
32
+
- various modifiers, such as `Final` and `NotRequired`
33
+
- newtypes and 3.12 type aliases
34
+
-`typing.Annotated`
21
35
22
36
... and many others. In these cases, predicate functions should be used instead.
The non-decorator approach is still recommended when dealing with lambdas, hooks produced elsewhere, unannotated hooks and situations where type introspection doesn't work.
50
64
51
65
```{versionadded} 24.1.0
66
+
52
67
```
53
68
54
69
### Predicate Hooks
@@ -87,7 +102,7 @@ D(a=2)
87
102
88
103
### Hook Factories
89
104
90
-
Hook factories are higher-order predicate hooks: they are functions that *produce* hooks.
105
+
Hook factories are higher-order predicate hooks: they are functions that _produce_ hooks.
91
106
Hook factories are commonly used to create very optimized hooks by offloading part of the work into a separate, earlier step.
92
107
93
108
Hook factories are registered using {meth}`Converter.register_unstructure_hook_factory() <cattrs.BaseConverter.register_unstructure_hook_factory>` and {meth}`Converter.register_structure_hook_factory() <cattrs.BaseConverter.register_structure_hook_factory>`.
@@ -251,7 +266,6 @@ This behavior can only be applied to classes or to the default for the {class}`C
251
266
The value for the `make_dict_structure_fn._cattrs_forbid_extra_keys` parameter is now taken from the given converter by default.
252
267
```
253
268
254
-
255
269
### `rename`
256
270
257
271
Using the rename override makes `cattrs` use the provided name instead of the real attribute name.
Additional predicates and hook factories will be added as requested.
423
440
@@ -460,9 +477,8 @@ ValueError: Not a list!
460
477
461
478
### Customizing Named Tuples
462
479
463
-
Named tuples can be un/structured using dictionaries using the {meth}`namedtuple_dict_structure_factory <cattrs.cols.namedtuple_dict_structure_factory>`
464
-
and {meth}`namedtuple_dict_unstructure_factory <cattrs.cols.namedtuple_dict_unstructure_factory>`
465
-
hook factories.
480
+
Named tuples can be un/structured using dictionaries using the {meth}`namedtuple_dict_structure_factory`
481
+
and {meth}`namedtuple_dict_unstructure_factory` hook factories.
466
482
467
483
To unstructure _all_ named tuples into dictionaries:
468
484
@@ -497,4 +513,4 @@ change the predicate function when registering the hook factory:
0 commit comments