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

39 statements  

1from __future__ import annotations 

2 

3from typing import TYPE_CHECKING, Any 

4 

5from attrs import NOTHING, Attribute, Factory 

6 

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 

12 

13if TYPE_CHECKING: 

14 from ..converters import BaseConverter 

15 

16 

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 

28 

29 return default 

30 

31 

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. 

36 

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. 

69 

70 def handler(v, _, _h=handler): 

71 return _h(v, type) 

72 

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