Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/cattrs/gen/_shared.py: 28%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from __future__ import annotations
3from typing import TYPE_CHECKING, Any
5from attrs import NOTHING, Attribute, Factory
7from .._compat import get_args, is_annotated, is_bare_final
8from ..dispatch import StructureHook
9from ..errors import StructureHandlerNotFoundError
10from ..fns import raise_error
11from ._consts import AttributeOverride
13if TYPE_CHECKING:
14 from ..converters import BaseConverter
17def _annotated_override_or_default(
18 type: Any, default: AttributeOverride
19) -> AttributeOverride:
20 """
21 If the type is Annotated containing an AttributeOverride, return it.
22 Otherwise, return the default.
23 """
24 if is_annotated(type):
25 for arg in get_args(type):
26 if isinstance(arg, AttributeOverride):
27 return arg
29 return default
32def find_structure_handler(
33 a: Attribute, type: Any, c: BaseConverter, prefer_attrs_converters: bool = False
34) -> StructureHook | None:
35 """Find the appropriate structure handler to use.
37 Return `None` if no handler should be used.
38 """
39 try:
40 if a.converter is not None and prefer_attrs_converters:
41 # If the user as requested to use attrib converters, use nothing
42 # so it falls back to that.
43 handler = None
44 elif (
45 a.converter is not None and not prefer_attrs_converters and type is not None
46 ):
47 try:
48 handler = c.get_structure_hook(type, cache_result=False)
49 except StructureHandlerNotFoundError:
50 handler = None
51 else:
52 # The legacy way, should still work.
53 if handler == raise_error:
54 handler = None
55 elif type is not None:
56 if (
57 is_bare_final(type)
58 and a.default is not NOTHING
59 and not isinstance(a.default, Factory)
60 ):
61 # This is a special case where we can use the
62 # type of the default to dispatch on.
63 type = a.default.__class__
64 handler = c.get_structure_hook(type, cache_result=False)
65 if handler == c._structure_call:
66 # Finals can't really be used with _structure_call, so
67 # we wrap it so the rest of the toolchain doesn't get
68 # confused.
70 def handler(v, _, _h=handler):
71 return _h(v, type)
73 else:
74 handler = c.get_structure_hook(type, cache_result=False)
75 else:
76 handler = c.structure
77 return handler
78 except RecursionError:
79 # This means we're dealing with a reference cycle, so use late binding.
80 return c.structure