usse/scrape/venv/lib/python3.10/site-packages/cattrs/gen/_shared.py
2023-12-22 15:26:01 +01:00

52 lines
1.7 KiB
Python

from __future__ import annotations
from typing import TYPE_CHECKING, Any, Callable
from attrs import NOTHING, Attribute, Factory
from .._compat import is_bare_final
from ..fns import raise_error
if TYPE_CHECKING: # pragma: no cover
from cattr.converters import BaseConverter
def find_structure_handler(
a: Attribute, type: Any, c: BaseConverter, prefer_attrs_converters: bool = False
) -> Callable[[Any, Any], Any] | None:
"""Find the appropriate structure handler to use.
Return `None` if no handler should be used.
"""
if a.converter is not None and prefer_attrs_converters:
# If the user as requested to use attrib converters, use nothing
# so it falls back to that.
handler = None
elif a.converter is not None and not prefer_attrs_converters and type is not None:
handler = c._structure_func.dispatch(type)
if handler == raise_error:
handler = None
elif type is not None:
if (
is_bare_final(type)
and a.default is not NOTHING
and not isinstance(a.default, Factory)
):
# This is a special case where we can use the
# type of the default to dispatch on.
type = a.default.__class__
handler = c._structure_func.dispatch(type)
if handler == c._structure_call:
# Finals can't really be used with _structure_call, so
# we wrap it so the rest of the toolchain doesn't get
# confused.
def handler(v, _, _h=handler):
return _h(v, type)
else:
handler = c._structure_func.dispatch(type)
else:
handler = c.structure
return handler