# Source code for dataclass_wizard.abstractions

    """
    Contains implementations for Abstract Base Classes
    """
    from __future__ import annotations
    import json

    from abc import ABC, abstractmethod
    from dataclasses import dataclass, InitVar, Field
    from typing import Type, TypeVar, Dict, Generic, TYPE_CHECKING

    from .models import Extras

    from .type_def import T, TT

    # Create a generic variable that can be 'AbstractJSONWizard', or any subclass.
    W = TypeVar('W', bound='AbstractJSONWizard')

    if TYPE_CHECKING:
        from .v1.models import Extras as V1Extras, TypeInfo

    class AbstractEnvWizard(ABC):
        """
        Abstract class that defines the methods a sub-class must implement at a
        minimum to be considered a "true" Environment Wizard.
        """
        __slots__ = ()

        # Extends the `__annotations__` attribute to return only the fields
        # (variables) of the `EnvWizard` subclass.
        #
        # .. NOTE::
        #    This excludes fields marked as ``ClassVar``, or ones which are
        #    not type-annotated.
        __fields__: dict[str, Field]

        def dict(self):
            ...

        @abstractmethod
        def to_dict(self):
            ...

        @abstractmethod
        def to_json(self, indent=None):
            ...

    class AbstractJSONWizard(ABC):

        __slots__ = ()

        @classmethod
        @abstractmethod
        def from_json(cls, string):
            ...

        @classmethod
        @abstractmethod
        def from_list(cls, o):
            ...

        @classmethod
        @abstractmethod
        def from_dict(cls, o):
            ...

        @abstractmethod
        def to_dict(self):
            ...

        @abstractmethod
        def to_json(self, *,
                    encoder=json.dumps,
                    indent=None,
                    **encoder_kwargs):
            ...

        @classmethod
        @abstractmethod
        def list_to_json(cls,
                         instances,
                         encoder=json.dumps,
                         indent=None,
                         **encoder_kwargs):
            ...

    @dataclass
    class AbstractParser(ABC, Generic[T, TT]):

        __slots__ = ('base_type', )

        # Please see `abstractions.pyi` for documentation on each field.

        cls: InitVar[Type]
        extras: InitVar[Extras]
        base_type: type[T]

        def __contains__(self, item):
            return type(item) is self.base_type

        @abstractmethod
        def __call__(self, o) -> TT:
            ...

    class AbstractLoader(ABC):

        __slots__ = ()

        @staticmethod
        @abstractmethod
        def transform_json_field(string):
            ...

        @staticmethod
        @abstractmethod
        def default_load_to(o, _):
            ...

        @staticmethod
        @abstractmethod
        def load_after_type_check(o, base_type):
            ...

        @staticmethod
        @abstractmethod
        def load_to_str(o, base_type):
            ...

        @staticmethod
        @abstractmethod
        def load_to_int(o, base_type):
            ...

        @staticmethod
        @abstractmethod
        def load_to_float(o, base_type):
            ...

        @staticmethod
        @abstractmethod
        def load_to_bool(o, _):
            ...

        @staticmethod
        @abstractmethod
        def load_to_enum(o, base_type):
            ...

        @staticmethod
        @abstractmethod
        def load_to_uuid(o, base_type):
            ...

        @staticmethod
        @abstractmethod
        def load_to_iterable(
                o, base_type,
                elem_parser):
            ...

        @staticmethod
        @abstractmethod
        def load_to_tuple(
                o, base_type,
                elem_parsers):
            ...

        @staticmethod
        @abstractmethod
        def load_to_named_tuple(
                o, base_type,
                field_to_parser,
                field_parsers):
            ...

        @staticmethod
        @abstractmethod
        def load_to_named_tuple_untyped(
                o, base_type,
                dict_parser, list_parser):
            ...

        @staticmethod
        @abstractmethod
        def load_to_dict(
                o, base_type,
                key_parser,
                val_parser):
            ...

        @staticmethod
        @abstractmethod
        def load_to_defaultdict(
                o, base_type,
                default_factory,
                key_parser,
                val_parser):
            ...

        @staticmethod
        @abstractmethod
        def load_to_typed_dict(
                o, base_type,
                key_to_parser,
                required_keys,
                optional_keys):
            ...

        @staticmethod
        @abstractmethod
        def load_to_decimal(o, base_type):
            ...

        @staticmethod
        @abstractmethod
        def load_to_datetime(o, base_type):
            ...

        @staticmethod
        @abstractmethod
        def load_to_time(o, base_type):
            ...

        @staticmethod
        @abstractmethod
        def load_to_date(o, base_type):
            ...

        @staticmethod
        @abstractmethod
        def load_to_timedelta(o, base_type):
            ...

        # @staticmethod
        # @abstractmethod
        # def load_func_for_dataclass(
        #     cls: Type[T],
        #     config: Optional[META],
        # ) -> Callable[[JSONObject], T]:
        #     """
        #     Generate and return the load function for a (nested) dataclass of
        #     type `cls`.
        #     """

        @classmethod
        @abstractmethod
        def get_parser_for_annotation(cls, ann_type,
                                      base_cls=None,
                                      extras=None):
            ...

    class AbstractDumper(ABC):
        __slots__ = ()

    class AbstractLoaderGenerator(ABC):
        """
        Abstract code generator which defines helper methods to generate the
        code for deserializing an object `o` of a given annotated type into
        the corresponding dataclass field during dynamic function construction.
        """
        __slots__ = ()

        @staticmethod
        @abstractmethod
        def transform_json_field(string: str) -> str:
            """
            Transform a JSON field name (which will typically be camel-cased)
            into the conventional format for a dataclass field name
            (which will ideally be snake-cased).
            """

        @staticmethod
        @abstractmethod
        def is_none(tp: TypeInfo, extras: V1Extras) -> str:
            """
            Generate the condition to determine if a value is None.
            """

        @staticmethod
        @abstractmethod
        def load_fallback(tp: TypeInfo, extras: V1Extras) -> str:
            """
            Generate code for the fallback load handler when no specialized type matches.

            The default fallback implementation is typically an identity / passthrough,
            but subclasses may override this behavior.
            """

        @staticmethod
        @abstractmethod
        def load_to_str(tp: TypeInfo, extras: V1Extras) -> str:
            """
            Generate code to load a value into a string field.
            """

        @staticmethod
        @abstractmethod
        def load_to_int(tp: TypeInfo, extras: V1Extras) -> str:
            """
            Generate code to load a value into an integer field.
            """

        @staticmethod
        @abstractmethod
        def load_to_float(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to load a value into a float field.
            """

        @staticmethod
        @abstractmethod
        def load_to_bool(_: str, extras: V1Extras) -> str:
            """
            Generate code to load a value into a boolean field.
            Adds a helper function `as_bool` to the local context.
            """

        @staticmethod
        @abstractmethod
        def load_to_bytes(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to load a value into a bytes field.
            """

        @staticmethod
        @abstractmethod
        def load_to_bytearray(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to load a value into a bytearray field.
            """

        @staticmethod
        @abstractmethod
        def load_to_none(tp: TypeInfo, extras: V1Extras) -> str:
            """
            Generate code to load a value into a None.
            """

        @staticmethod
        @abstractmethod
        def load_to_literal(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to confirm a value is equivalent to one
            of the provided literals.
            """

        @classmethod
        @abstractmethod
        def load_to_union(cls, tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to load a value into a `Union[X, Y, ...]` (one of [X, Y, ...] possible types)
            """

        @staticmethod
        @abstractmethod
        def load_to_enum(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to load a value into an Enum field.
            """

        @staticmethod
        @abstractmethod
        def load_to_uuid(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to load a value into a UUID field.
            """

        @staticmethod
        @abstractmethod
        def load_to_iterable(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to load a value into an iterable field (list, set, etc.).
            """

        @staticmethod
        @abstractmethod
        def load_to_tuple(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to load a value into a tuple field.
            """

        @staticmethod
        @abstractmethod
        def load_to_named_tuple(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to load a value into a named tuple field.
            """

        @classmethod
        @abstractmethod
        def load_to_named_tuple_untyped(cls, tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to load a value into an untyped named tuple.
            """

        @staticmethod
        @abstractmethod
        def load_to_dict(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to load a value into a dictionary field.
            """

        @staticmethod
        @abstractmethod
        def load_to_defaultdict(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to load a value into a defaultdict field.
            """

        @staticmethod
        @abstractmethod
        def load_to_typed_dict(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to load a value into a typed dictionary field.
            """

        @staticmethod
        @abstractmethod
        def load_to_decimal(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to load a value into a Decimal field.
            """

        @staticmethod
        @abstractmethod
        def load_to_path(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to load a value into a Decimal field.
            """

        @staticmethod
        @abstractmethod
        def load_to_datetime(tp: TypeInfo, extras: V1Extras) -> str:
            """
            Generate code to load a value into a datetime field.
            """

        @staticmethod
        @abstractmethod
        def load_to_time(tp: TypeInfo, extras: V1Extras) -> str:
            """
            Generate code to load a value into a time field.
            """

        @staticmethod
        @abstractmethod
        def load_to_date(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to load a value into a date field.
            """

        @staticmethod
        @abstractmethod
        def load_to_timedelta(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to load a value into a timedelta field.
            """

        @staticmethod
        def load_to_dataclass(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to load a value into a `dataclass` type field.
            """

        @classmethod
        @abstractmethod
        def load_dispatcher_for_annotation(cls,
                                           tp: TypeInfo,
                                           extras: V1Extras) -> 'str | TypeInfo':
            """
            Resolve the load dispatcher for a given annotation type.

            Returns either a string reference to a dispatcher or a TypeInfo object,
            depending on how the annotation is handled.

            `base_cls` is the original class object, useful when the annotated
            type is a :class:`typing.ForwardRef` object.
            """

    class AbstractDumperGenerator(ABC):
        """
        Abstract code generator which defines helper methods to generate the
        code for deserializing an object `o` of a given annotated type into
        the corresponding dataclass field during dynamic function construction.
        """
        __slots__ = ()

        @staticmethod
        @abstractmethod
        def transform_dataclass_field(string: str) -> str:
            """
            Transform a dataclass field name (which will ideally be snake-cased)
            into the conventional format for a JSON field name.
            """

        @staticmethod
        @abstractmethod
        def dump_fallback(tp: TypeInfo, extras: V1Extras) -> str:
            """
            Generate code for the fallback dump handler when no specialized type matches.

            The default fallback implementation is typically an identity / passthrough,
            but subclasses may override this behavior.
            """

        @staticmethod
        @abstractmethod
        def dump_from_str(tp: TypeInfo, extras: V1Extras) -> str:
            """
            Generate code to dump a value from a string field.
            """

        @staticmethod
        @abstractmethod
        def dump_from_int(tp: TypeInfo, extras: V1Extras) -> str:
            """
            Generate code to dump a value from an integer field.
            """

        @staticmethod
        @abstractmethod
        def dump_from_float(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a value from a float field.
            """

        @staticmethod
        @abstractmethod
        def dump_from_bool(_: str, extras: V1Extras) -> str:
            """
            Generate code to dump a value from a boolean field.
            """

        @staticmethod
        @abstractmethod
        def dump_from_bytes(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a value from a bytes field.
            """

        @staticmethod
        @abstractmethod
        def dump_from_bytearray(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a value from a bytearray field.
            """

        @staticmethod
        @abstractmethod
        def dump_from_none(tp: TypeInfo, extras: V1Extras) -> str:
            """
            Generate code to dump a value from a None.
            """

        @staticmethod
        @abstractmethod
        def dump_from_literal(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a literal.
            """

        @classmethod
        @abstractmethod
        def dump_from_union(cls, tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a value from a `Union[X, Y, ...]` (one of [X, Y, ...] possible types)
            """

        @staticmethod
        @abstractmethod
        def dump_from_enum(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a value from an Enum field.
            """

        @staticmethod
        @abstractmethod
        def dump_from_uuid(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a value from a UUID field.
            """

        @staticmethod
        @abstractmethod
        def dump_from_iterable(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a value from an iterable field (list, set, etc.).
            """

        @staticmethod
        @abstractmethod
        def dump_from_tuple(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a value from a tuple field.
            """

        @staticmethod
        @abstractmethod
        def dump_from_named_tuple(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a value from a named tuple field.
            """

        @classmethod
        @abstractmethod
        def dump_from_named_tuple_untyped(cls, tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a value from an untyped named tuple.
            """

        @staticmethod
        @abstractmethod
        def dump_from_dict(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a value from a dictionary field.
            """

        @staticmethod
        @abstractmethod
        def dump_from_defaultdict(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a value from a defaultdict field.
            """

        @staticmethod
        @abstractmethod
        def dump_from_typed_dict(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a value from a typed dictionary field.
            """

        @staticmethod
        @abstractmethod
        def dump_from_decimal(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a value from a Decimal field.
            """

        @staticmethod
        @abstractmethod
        def dump_from_path(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a value from a Decimal field.
            """

        @staticmethod
        @abstractmethod
        def dump_from_datetime(tp: TypeInfo, extras: V1Extras) -> str:
            """
            Generate code to dump a value from a datetime field.
            """

        @staticmethod
        @abstractmethod
        def dump_from_time(tp: TypeInfo, extras: V1Extras) -> str:
            """
            Generate code to dump a value from a time field.
            """

        @staticmethod
        @abstractmethod
        def dump_from_date(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a value from a date field.
            """

        @staticmethod
        @abstractmethod
        def dump_from_timedelta(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a value from a timedelta field.
            """

        @staticmethod
        def dump_from_dataclass(tp: TypeInfo, extras: V1Extras) -> 'str | TypeInfo':
            """
            Generate code to dump a value from a `dataclass` type field.
            """

        @classmethod
        @abstractmethod
        def dump_dispatcher_for_annotation(cls,
                                           tp: TypeInfo,
                                           extras: V1Extras) -> 'str | TypeInfo':
            """
            Resolve the dump dispatcher for a given annotation type.

            Returns either a string reference to a dispatcher or a TypeInfo object,
            depending on how the annotation is handled.

            `base_cls` is the original class object, useful when the annotated
            type is a :class:`typing.ForwardRef` object.
            """