# Source code for dataclass_wizard.bases

    from __future__ import annotations

    from abc import ABCMeta, abstractmethod
    from datetime import tzinfo
    from typing import (Callable, Type, Dict, Optional, ClassVar, Union,
                        TypeVar, Mapping, Sequence, TYPE_CHECKING, Any, Literal)

    from .constants import TAG
    from .decorators import cached_class_property
    from .enums import DateTimeTo, LetterCase, LetterCasePriority
    from .models import Condition

    if TYPE_CHECKING:
        from .v1.enums import KeyAction, KeyCase, DateTimeTo as V1DateTimeTo, EnvKeyStrategy, EnvPrecedence
        from .v1._path_util import EnvFilePaths, SecretsDirs
        from .bases_meta import ALLOWED_MODES, V1HookFn, V1PreDecoder
        from .type_def import FrozenKeys

        V1TypeToHook = Mapping[type, Union[tuple[ALLOWED_MODES, V1HookFn], V1HookFn, None]]

    # Create a generic variable that can be 'AbstractMeta', or any subclass.
    # Full word as `M` is already defined in another module
    META_ = TypeVar('META_', bound='AbstractMeta')
    # Use `type` here explicitly, because we will never have an `META_` object.
    META = type[META_]

    # Create a generic variable that can be 'AbstractMeta', or any subclass.
    # Full word as `M` is already defined in another module
    ENV_META_ = TypeVar('ENV_META_', bound='AbstractEnvMeta')
    # Use `type` here explicitly, because we will never have an `META_` object.
    ENV_META = type[ENV_META_]

    class ABCOrAndMeta(ABCMeta):
        """
        Metaclass to add class-level :meth:`__or__` and :meth:`__and__` methods
        to a base class of type :type:`M`.

        Ref:
          - https://stackoverflow.com/q/15008807/10237506
          - https://stackoverflow.com/a/57351066/10237506
        """

        def __or__(cls: META, other: META) -> META:
            """
            Merge two Meta configs. Priority will be given to the source config
            present in `cls`, e.g. the first operand in the '|' expression.

            Use case: Merge the Meta configs for two separate dataclasses into a
            single, unified Meta config.
            """
            src = cls
            src_dict = src.__dict__
            other_dict = other.__dict__

            base_dict = {'__slots__': ()}

            # Set meta attributes here.
            if src is AbstractMeta or src is AbstractEnvMeta:
                # Here we can't use `src` because the `bind_to` method isn't
                # defined on the abstract class. Use `other` instead, which
                # *will* be a concrete subclass of `AbstractMeta`.
                src = other
                # noinspection PyTypeChecker
                for k in src.fields_to_merge:
                    if k in other_dict:
                        base_dict[k] = other_dict[k]
            else:
                # noinspection PyTypeChecker
                for k in src.fields_to_merge:
                    if k in src_dict:
                        base_dict[k] = src_dict[k]
                    elif k in other_dict:
                        base_dict[k] = other_dict[k]

            # This mapping won't be updated. Use the src by default.
            for k in src.__special_attrs__:
                if k in src_dict:
                    base_dict[k] = src_dict[k]

            new_cls_name = src.__name__
            # Check if the type of the class we want to create is
            # `JSONWizard.Meta` or a subclass. If so, we want to avoid the
            # mandatory `__init_subclass__` call that gets invoked when creating
            # a new class, so use the superclass type instead.
            if src.__is_inner_meta__:
                # In a reversed MRO, the inheritance tree looks like this:
                #   |___ object -> AbstractMeta -> BaseJSONWizardMeta -> ...
                # So here, we want to choose the third-to-last class in the list.
                # noinspection PyUnresolvedReferences
                src = src.__mro__[-3]

            # noinspection PyTypeChecker
            return type(new_cls_name, (src, ), base_dict)

        def __and__(cls: META, other: META) -> META:
            """
            Merge the `other` Meta config into the first one, i.e. `cls`. This
            operation does not create a new class, but instead it modifies the
            source config `cls` in-place; the source will be the first operand in
            the '&' expression.

            Use case: Merge a separate Meta config (for a single dataclass) with
            the first config.
            """
            other_dict = other.__dict__

            # Set meta attributes here.
            # noinspection PyTypeChecker
            for k in cls.all_fields:
                if k in other_dict:
                    setattr(cls, k, other_dict[k])

            return cls

    class AbstractMeta(metaclass=ABCOrAndMeta):
        """
        Base class definition for the `JSONWizard.Meta` inner class.
        """
        __slots__ = ()

        # A list of class attributes that are exclusive to the Meta config.
        # When merging two Meta configs for a class, these are the only
        # attributes which will *not* be merged.
        __special_attrs__ = frozenset({
            'recursive',
            'json_key_to_field',
            'v1_field_to_alias',
            'v1_field_to_alias_dump',
            'v1_field_to_alias_load',
            'tag',
        })

        # Class attribute which enables us to detect a `JSONWizard.Meta` subclass.
        __is_inner_meta__ = False

        # Enable Debug mode for more verbose log output.
        #
        # This setting can be a `bool`, `int`, or `str`:
        # - `True` enables debug mode with default verbosity.
        # - A `str` or `int` specifies the minimum log level (e.g., 'DEBUG', 10).
        #
        # Debug mode provides additional helpful log messages, including:
        # - Logging unknown JSON keys encountered during `from_dict` or `from_json`.
        # - Detailed error messages for invalid types during unmarshalling.
        #
        # Note: Enabling Debug mode may have a minor performance impact.
        #
        # @deprecated and will be removed in V1 - Use `v1_debug` instead.
        debug_enabled: ClassVar['bool | int | str'] = False

        # When enabled, a specified Meta config for the main dataclass (i.e. the
        # class on which `from_dict` and `to_dict` is called) will cascade down
        # and be merged with the Meta config for each *nested* dataclass; note
        # that during a merge, priority is given to the Meta config specified on
        # each class.
        #
        # The default behavior is True, so the Meta config (if provided) will
        # apply in a recursive manner.
        recursive: ClassVar[bool] = True

        # True to support cyclic or self-referential dataclasses. For example,
        # the type of a dataclass field in class `A` refers to `A` itself.
        #
        # See https://github.com/rnag/dataclass-wizard/issues/62 for more details.
        recursive_classes: ClassVar[bool] = False

        # True to raise an class:`UnknownJSONKey` when an unmapped JSON key is
        # encountered when `from_dict` or `from_json` is called; an unknown key is
        # one that does not have a known mapping to a dataclass field.
        #
        # The default is to only log a "warning" for such cases, which is visible
        # when `v1_debug` is true and logging is properly configured.
        raise_on_unknown_json_key: ClassVar[bool] = False

        # A customized mapping of JSON keys to dataclass fields, that is used
        # whenever `from_dict` or `from_json` is called.
        #
        # Note: this is in addition to the implicit field transformations, like
        #   "myStr" -> "my_str"
        #
        # If the reverse mapping is also desired (i.e. dataclass field to JSON
        # key), then specify the "__all__" key as a truthy value. If multiple JSON
        # keys are specified for a dataclass field, only the first one provided is
        # used in this case.
        json_key_to_field: ClassVar[Dict[str, str]] = None

        # How should :class:`time` and :class:`datetime` objects be serialized
        # when converted to a Python dictionary object or a JSON string.
        marshal_date_time_as: ClassVar[Union[DateTimeTo, str]] = None

        # How JSON keys should be transformed to dataclass fields.
        #
        # Note that this only applies to keys which are to be set on dataclass
        # fields; other fields such as the ones for `TypedDict` or `NamedTuple`
        # sub-classes won't be similarly transformed.
        key_transform_with_load: ClassVar[Union[LetterCase, str]] = None

        # How dataclass fields should be transformed to JSON keys.
        #
        # Note that this only applies to dataclass fields; other fields such as
        # the ones for `TypedDict` or `NamedTuple` sub-classes won't be similarly
        # transformed.
        key_transform_with_dump: ClassVar[Union[LetterCase, str]] = None

        # The field name that identifies the tag for a class.
        #
        # When set to a value, an :attr:`TAG` field will be populated in the
        # dictionary object in the dump (serialization) process. When loading
        # (or de-serializing) a dictionary object, the :attr:`TAG` field will be
        # used to load the corresponding dataclass, assuming the dataclass field
        # is properly annotated as a Union type, ex.:
        #   my_data: Union[Data1, Data2, Data3]
        tag: ClassVar[str] = None

        # The dictionary key that identifies the tag field for a class. This is
        # only set when the `tag` field or the `auto_assign_tags` flag is enabled
        # in the `Meta` config for a dataclass.
        #
        # Defaults to '__tag__' if not specified.
        tag_key: ClassVar[str] = TAG

        # Auto-assign the class name as a dictionary "tag" key, for any dataclass
        # fields which are in a `Union` declaration, ex.:
        #   my_data: Union[Data1, Data2, Data3]
        auto_assign_tags: ClassVar[bool] = False

        # Determines whether we should we skip / omit fields with default values
        # (based on the `default` or `default_factory` argument specified for
        # the :func:`dataclasses.field`) in the serialization process.
        skip_defaults: ClassVar[bool] = False

        # Determines the :class:`Condition` to skip / omit dataclass
        # fields in the serialization process.
        skip_if: ClassVar[Condition] = None

        # Determines the condition to skip / omit fields with default values
        # (based on the `default` or `default_factory` argument specified for
        # the :func:`dataclasses.field`) in the serialization process.
        skip_defaults_if: ClassVar[Condition] = None

        # Enable opt-in to the "experimental" major release `v1` feature.
        # This feature offers optimized performance for de/serialization.
        # Defaults to False.
        v1: ClassVar[bool] = False

        # Enable Debug mode for more verbose log output.
        #
        # This setting can be a `bool`, `int`, or `str`:
        # - `True` enables debug mode with default verbosity.
        # - A `str` or `int` specifies the minimum log level (e.g., 'DEBUG', 10).
        #
        # Debug mode provides additional helpful log messages, including:
        # - Logging unknown JSON keys encountered during `from_dict` or `from_json`.
        # - Detailed error messages for invalid types during unmarshalling.
        #
        # Note: Enabling Debug mode may have a minor performance impact.
        v1_debug: ClassVar['bool | int | str'] = False

        # Custom load hooks for extending type support in the v1 engine.
        #
        # Mapping: {Type -> hook}
        #
        # A hook must accept either:
        #   - one positional argument (runtime hook): value -> object
        #   - two positional arguments (v1 hook): (TypeInfo, Extras) -> str | TypeInfo
        #
        # The hook is invoked when loading a value annotated with the given type.
        v1_type_to_load_hook: ClassVar[V1TypeToHook] = None

        # Custom dump hooks for extending type support in the v1 engine.
        #
        # Mapping: {Type -> hook}
        #
        # A hook must accept either:
        #   - one positional argument (runtime hook): object -> JSON-serializable value
        #   - two positional arguments (v1 hook): (TypeInfo, Extras) -> str | TypeInfo
        #
        # The hook is invoked when dumping a value whose runtime type matches
        # the given type.
        v1_type_to_dump_hook: ClassVar[V1TypeToHook] = None

        # ``v1_pre_decoder``: Optional hook called before ``v1`` type loading.
        # Receives the container type plus (cls, TypeInfo, Extras) and may return a
        # transformed ``TypeInfo`` (e.g., wrapped in a function which decodes
        # JSON/delimited strings into list/dict for env loading). Returning the
        # input value leaves behavior unchanged.
        #
        #  Pre-decoder signature:
        #   (cls, container_tp, tp, extras) -> new_tp
        v1_pre_decoder: ClassVar[V1PreDecoder] = None

        # Specifies the letter case to use for JSON keys when both loading and dumping.
        #
        # This is a convenience setting that applies the same key casing rule to
        # both deserialization (load) and serialization (dump).
        #
        # If set, it is used as the default for both `v1_load_case` and
        # `v1_dump_case`, unless either is explicitly specified.
        #
        # The setting is case-insensitive and supports shorthand assignment,
        # such as using the string 'C' instead of 'CAMEL'.
        v1_case: ClassVar[Union[KeyCase, str, None]] = None

        # Specifies the letter case used to match JSON keys when mapping them
        # to dataclass fields during deserialization.
        #
        # This setting determines how dataclass field names are transformed
        # when looking up corresponding keys in the input JSON object. It does
        # not affect keys in `TypedDict` or `NamedTuple` subclasses.
        #
        # By default, JSON keys are assumed to be in `snake_case`, and fields
        # are matched directly without transformation.
        #
        # The setting is case-insensitive and supports shorthand assignment,
        # such as using the string 'C' instead of 'CAMEL'.
        #
        # If set to `A` or `AUTO`, all supported key casing transforms are
        # attempted at runtime, and the resolved transform is cached for
        # subsequent lookups.
        #
        # If unset, this value defaults to `v1_case` when provided.
        v1_load_case: ClassVar[Union[KeyCase, str, None]] = None

        # Specifies the letter case used for JSON keys during serialization.
        #
        # This setting determines how dataclass field names are transformed
        # when generating keys in the output JSON object.
        #
        # By default, field names are emitted in `snake_case`.
        #
        # The setting is case-insensitive and supports shorthand assignment,
        # such as using the string 'P' instead of 'PASCAL'.
        #
        # If unset, this value defaults to `v1_case` when provided.
        v1_dump_case: ClassVar[Union[KeyCase, str, None]] = None

        # A custom mapping of dataclass fields to their JSON aliases (keys).
        #
        # Values may be a single alias string or a sequence of alias strings.
        #
        # - During deserialization (load), any listed alias for a field is accepted.
        # - During serialization (dump), the first alias is used by default.
        #
        # This mapping overrides default key casing and implicit field-to-key
        # transformations (e.g., "my_field" → "myField") for the affected fields.
        #
        # This setting applies to both load and dump unless explicitly overridden
        # by `v1_field_to_alias_load` or `v1_field_to_alias_dump`.
        v1_field_to_alias: ClassVar[
            Mapping[str, Union[str, Sequence[str]]]
        ] = None

        # A custom mapping of dataclass fields to their JSON aliases (keys) used
        # during deserialization only.
        #
        # Values may be a single alias string or a sequence of alias strings.
        # Any listed alias is accepted when mapping input JSON keys to
        # dataclass fields.
        #
        # When set, this mapping overrides `v1_field_to_alias` for load behavior
        # only.
        v1_field_to_alias_load: ClassVar[
            Mapping[str, Union[str, Sequence[str]]]
        ] = None

        # A custom mapping of dataclass fields to their JSON aliases (keys) used
        # during serialization only.
        #
        # Values may be a single alias string or a sequence of alias strings.
        # When a sequence is provided, the first alias is used as the output key.
        #
        # When set, this mapping overrides `v1_field_to_alias` for dump behavior
        # only.
        v1_field_to_alias_dump: ClassVar[
            Mapping[str, Union[str, Sequence[str]]]
        ] = None

        # Defines the action to take when an unknown JSON key is encountered during
        # `from_dict` or `from_json` calls. An unknown key is one that does not map
        # to any dataclass field.
        #
        # Valid options are:
        # - `"ignore"` (default): Silently ignore unknown keys.
        # - `"warn"`: Log a warning for each unknown key. Requires `v1_debug`
        #   to be `True` and properly configured logging.
        # - `"raise"`: Raise an `UnknownKeyError` for the first unknown key encountered.
        v1_on_unknown_key: ClassVar[KeyAction] = None

        # Unsafe: Enables parsing of dataclasses in unions without requiring
        # the presence of a `tag_key`, i.e., a dictionary key identifying the
        # tag field in the input. Defaults to False.
        v1_unsafe_parse_dataclass_in_union: ClassVar[bool] = False

        # Specifies how :class:`datetime` (and :class:`time`, where applicable)
        # objects are serialized during output.
        #
        # This setting controls how temporal values are emitted when converting
        # a dataclass to a Python dictionary (`to_dict`) or a JSON string
        # (`to_json`). It applies to serialization only and does not affect
        # deserialization.
        #
        # By default, values are serialized using ISO 8601 string format.
        #
        # Supported values are defined by :class:`DateTimeTo`.
        v1_dump_date_time_as: ClassVar[Union[V1DateTimeTo, str]] = None

        # Specifies the timezone to assume for naive :class:`datetime` values
        # during serialization.
        #
        # By default, naive datetimes are rejected to avoid ambiguous or
        # environment-dependent behavior.
        #
        # When set, naive datetimes are interpreted as being in the specified
        # timezone before conversion to a UTC epoch timestamp.
        #
        # Common usage:
        #     v1_assume_naive_datetime_tz = timezone.utc
        #
        # This setting applies to serialization only and does not affect
        # deserialization.
        v1_assume_naive_datetime_tz: ClassVar[tzinfo | None] = None

        # Controls how `typing.NamedTuple` and `collections.namedtuple`
        # fields are loaded and serialized.
        #
        # - False (DEFAULT): load from list/tuple and serialize
        #                     as a positional list.
        # - True: load from mapping and serialize as a dict
        #           keyed by field name.
        #
        # In strict mode, inputs that do not match the selected mode
        # raise TypeError.
        #
        # Note:
        #   This option enforces strict shape matching for performance reasons.
        v1_namedtuple_as_dict: ClassVar[bool] = None

        # If True (default: False), ``None`` is coerced to an empty string (``""``)
        # when loading ``str`` fields.
        #
        # When False, ``None`` is coerced using ``str(value)``, so ``None`` becomes
        # the literal string ``'None'`` for ``str`` fields.
        #
        # For ``Optional[str]`` fields, ``None`` is preserved by default.
        v1_coerce_none_to_empty_str: ClassVar[bool] = None

        # Controls how leaf (non-recursive) types are detected during serialization.
        #
        # - "exact" (DEFAULT): only exact built-in leaf types are treated as leaf values.
        # - "issubclass": subclasses of leaf types are also treated as leaf values.
        #
        # Leaf types are returned without recursive traversal. Bytes are still
        # handled separately according to their serialization rules.
        #
        # Note:
        #     The default "exact" mode avoids treating third-party scalar-like
        #     objects (e.g. NumPy scalars) as built-in leaf types.
        v1_leaf_handling: ClassVar[Literal['exact', 'issubclass']] = None

        # noinspection PyMethodParameters
        @cached_class_property
        def all_fields(cls) -> FrozenKeys:
            """Return a list of all class attributes"""
            return frozenset(AbstractMeta.__annotations__)

        # noinspection PyMethodParameters
        @cached_class_property
        def fields_to_merge(cls) -> FrozenKeys:
            """Return a list of class attributes, minus `__special_attrs__`"""
            return cls.all_fields - cls.__special_attrs__

        @classmethod
        @abstractmethod
        def bind_to(cls, dataclass: Type, create=True, is_default=True):
            """
            Initialize hook which applies the Meta config to `dataclass`, which is
            typically a subclass of :class:`JSONWizard`.

            :param dataclass: A class which has been decorated by the `@dataclass`
              decorator; typically this is a sub-class of :class:`JSONWizard`.
            :param create: When true, a separate loader/dumper will be created
              for the class. If disabled, this will access the root loader/dumper,
              so modifying this should affect global settings across all
              dataclasses that use the JSON load/dump process.
            :param is_default: When enabled, the Meta will be cached as the
              default Meta config for the dataclass. Defaults to true.

            """

    class AbstractEnvMeta(metaclass=ABCOrAndMeta):
        """
        Base class definition for the `EnvWizard.Meta` inner class.
        """
        __slots__ = ()

        # A list of class attributes that are exclusive to the Meta config.
        # When merging two Meta configs for a class, these are the only
        # attributes which will *not* be merged.
        __special_attrs__ = frozenset({
            'recursive',
            'debug_enabled',
            'env_var_to_field',
            'v1_field_to_env_load',
            'v1_field_to_alias_dump',
            'tag',
        })

        # Class attribute which enables us to detect a `EnvWizard.Meta` subclass.
        __is_inner_meta__ = False

        # True to enable Debug mode for additional (more verbose) log output.
        #
        # For example, a message is logged with the environment variable that is
        # mapped to each attribute.
        #
        # This also results in more helpful messages during error handling, which
        # can be useful when debugging the cause when values are an invalid type
        # (i.e. they don't match the annotation for the field) when unmarshalling
        # a environ variable values to attributes in an EnvWizard subclass.
        #
        # Note there is a minor performance impact when DEBUG mode is enabled.
        debug_enabled: ClassVar[bool] = False

        # When enabled, a specified Meta config for the main dataclass (i.e. the
        # class on which `from_dict` and `to_dict` is called) will cascade down
        # and be merged with the Meta config for each *nested* dataclass; note
        # that during a merge, priority is given to the Meta config specified on
        # each class.
        #
        # The default behavior is True, so the Meta config (if provided) will
        # apply in a recursive manner.
        recursive: ClassVar[bool] = True

        # `True` to load environment variables from an `.env` file, or a
        # list/tuple of dotenv files.
        #
        # This can also be set to a path to a custom dotenv file, for example:
        #   `path/to/.env.prod`
        #
        # Simply passing in a filename such as `.env.prod` will search the current
        # directory, as well as any parent folders (working backwards to the root
        # directory), until it locates the given file.
        #
        # If multiple files are passed in, later files in the list/tuple will take
        # priority over earlier files.
        #
        # For example, in below the '.env.last' file takes priority over '.env':
        #   env_file = '.env', '.env.last'
        env_file: ClassVar[EnvFilePaths] = None

        # Prefix for all environment variables. Defaults to `None`.
        env_prefix: ClassVar[str] = None

        # secrets_dir: The secret files directory or a sequence of directories. Defaults to `None`.
        secrets_dir: ClassVar[SecretsDirs] = None

        # -- BEGIN Deprecated Fields --

        # The nested env values delimiter. Defaults to `None`.
        # env_nested_delimiter: ClassVar[str] = None

        # A customized mapping of field in the `EnvWizard` subclass to its
        # corresponding environment variable to search for.
        #
        # Note: this is in addition to the implicit field transformations, like
        #   "myStr" -> "my_str"
        field_to_env_var: ClassVar[Dict[str, str]] = None

        # The letter casing priority to use when looking up Env Var Names.
        #
        # The default is `SCREAMING_SNAKE_CASE`.
        key_lookup_with_load: ClassVar[Union[LetterCasePriority, str]] = LetterCasePriority.SCREAMING_SNAKE

        # How `EnvWizard` fields (variables) should be transformed to JSON keys.
        #
        # The default is 'snake_case'.
        key_transform_with_dump: ClassVar[Union[LetterCase, str]] = LetterCase.SNAKE

        # -- END Deprecated Fields --

        # Determines whether we should we skip / omit fields with default values
        # in the serialization process.
        skip_defaults: ClassVar[bool] = False

        # Determines the :class:`Condition` to skip / omit dataclass
        # fields in the serialization process.
        skip_if: ClassVar[Condition] = None

        # Determines the condition to skip / omit fields with default values
        # (based on the `default` or `default_factory` argument specified for
        # the :func:`dataclasses.field`) in the serialization process.
        skip_defaults_if: ClassVar[Condition] = None

        # The field name that identifies the tag for a class.
        #
        # When set to a value, an :attr:`TAG` field will be populated in the
        # dictionary object in the dump (serialization) process. When loading
        # (or de-serializing) a dictionary object, the :attr:`TAG` field will be
        # used to load the corresponding dataclass, assuming the dataclass field
        # is properly annotated as a Union type, ex.:
        #   my_data: Union[Data1, Data2, Data3]
        tag: ClassVar[str] = None

        # The dictionary key that identifies the tag field for a class. This is
        # only set when the `tag` field or the `auto_assign_tags` flag is enabled
        # in the `Meta` config for a dataclass.
        #
        # Defaults to '__tag__' if not specified.
        tag_key: ClassVar[str] = TAG

        # Auto-assign the class name as a dictionary "tag" key, for any dataclass
        # fields which are in a `Union` declaration, ex.:
        #   my_data: Union[Data1, Data2, Data3]
        auto_assign_tags: ClassVar[bool] = False

        # Enable opt-in to the "experimental" major release `v1` feature.
        # This feature offers optimized performance for de/serialization.
        # Defaults to False.
        v1: ClassVar[bool] = False

        # Enable Debug mode for more verbose log output.
        #
        # This setting can be a `bool`, `int`, or `str`:
        # - `True` enables debug mode with default verbosity.
        # - A `str` or `int` specifies the minimum log level (e.g., 'DEBUG', 10).
        #
        # Debug mode provides additional helpful log messages, including:
        # - Logging unknown JSON keys encountered during `from_dict` or `from_json`.
        # - Detailed error messages for invalid types during unmarshalling.
        #
        # Note: Enabling Debug mode may have a minor performance impact.
        v1_debug: ClassVar['bool | int | str'] = False

        # Custom load hooks for extending type support in the v1 engine.
        #
        # Mapping: {Type -> hook}
        #
        # A hook must accept either:
        #   - one positional argument (runtime hook): value -> object
        #   - two positional arguments (v1 hook): (TypeInfo, Extras) -> str | TypeInfo
        #
        # The hook is invoked when loading a value annotated with the given type.
        v1_type_to_load_hook: ClassVar[V1TypeToHook] = None

        # Custom dump hooks for extending type support in the v1 engine.
        #
        # Mapping: {Type -> hook}
        #
        # A hook must accept either:
        #   - one positional argument (runtime hook): object -> JSON-serializable value
        #   - two positional arguments (v1 hook): (TypeInfo, Extras) -> str | TypeInfo
        #
        # The hook is invoked when dumping a value whose runtime type matches
        # the given type.
        v1_type_to_dump_hook: ClassVar[V1TypeToHook] = None

        # ``v1_pre_decoder``: Optional hook called before ``v1`` type loading.
        # Receives the container type plus (cls, TypeInfo, Extras) and may return a
        # transformed ``TypeInfo`` (e.g., wrapped in a function which decodes
        # JSON/delimited strings into list/dict for env loading). Returning the
        # input value leaves behavior unchanged.
        #
        #  Pre-decoder signature:
        #   (cls, container_tp, tp, extras) -> new_tp
        v1_pre_decoder: ClassVar[V1PreDecoder] = None

        # The key lookup strategy to use for Env Var Names.
        #
        # The default strategy is `SCREAMING_SNAKE_CASE` > `snake_case`.
        v1_load_case: ClassVar[Union[EnvKeyStrategy, str]] = None

        # How `EnvWizard` fields (variables) should be transformed to JSON keys.
        #
        # The default is 'snake_case'.
        v1_dump_case: ClassVar[Union[LetterCase, str]] = None

        # Environment Precedence (order) to search for values
        # Defaults to EnvPrecedence.SECRETS_ENV_DOTENV
        v1_env_precedence: EnvPrecedence = None

        # A custom mapping of dataclass fields to their env vars (keys) used
        # during deserialization only.
        #
        # Values may be a single alias string or a sequence of alias strings.
        # Any listed alias is accepted when mapping input env vars to
        # dataclass fields.
        v1_field_to_env_load: ClassVar[
            Mapping[str, Union[str, Sequence[str]]]
        ] = None

        # A custom mapping of dataclass fields to their JSON aliases (keys) used
        # during serialization only.
        #
        # Values may be a single alias string or a sequence of alias strings.
        # When a sequence is provided, the first alias is used as the output key.
        #
        # When set, this mapping overrides `v1_field_to_alias` for dump behavior
        # only.
        v1_field_to_alias_dump: ClassVar[
            Mapping[str, Union[str, Sequence[str]]]
        ] = None

        # Defines the action to take when an unknown JSON key is encountered during
        # `from_dict` or `from_json` calls. An unknown key is one that does not map
        # to any dataclass field.
        #
        # Valid options are:
        # - `"ignore"` (default): Silently ignore unknown keys.
        # - `"warn"`: Log a warning for each unknown key. Requires `v1_debug`
        #   to be `True` and properly configured logging.
        # - `"raise"`: Raise an `UnknownKeyError` for the first unknown key encountered.
        # v1_on_unknown_key: ClassVar[KeyAction] = None

        # Unsafe: Enables parsing of dataclasses in unions without requiring
        # the presence of a `tag_key`, i.e., a dictionary key identifying the
        # tag field in the input. Defaults to False.
        v1_unsafe_parse_dataclass_in_union: ClassVar[bool] = False

        # Specifies how :class:`datetime` (and :class:`time`, where applicable)
        # objects are serialized during output.
        #
        # This setting controls how temporal values are emitted when converting
        # a dataclass to a Python dictionary (`to_dict`) or a JSON string
        # (`to_json`). It applies to serialization only and does not affect
        # deserialization.
        #
        # By default, values are serialized using ISO 8601 string format.
        #
        # Supported values are defined by :class:`DateTimeTo`.
        v1_dump_date_time_as: ClassVar[Union[V1DateTimeTo, str]] = None

        # Specifies the timezone to assume for naive :class:`datetime` values
        # during serialization.
        #
        # By default, naive datetimes are rejected to avoid ambiguous or
        # environment-dependent behavior.
        #
        # When set, naive datetimes are interpreted as being in the specified
        # timezone before conversion to a UTC epoch timestamp.
        #
        # Common usage:
        #     v1_assume_naive_datetime_tz = timezone.utc
        #
        # This setting applies to serialization only and does not affect
        # deserialization.
        v1_assume_naive_datetime_tz: ClassVar[tzinfo | None] = None

        # Controls how `typing.NamedTuple` and `collections.namedtuple`
        # fields are loaded and serialized.
        #
        # - False (DEFAULT): load from list/tuple and serialize
        #                     as a positional list.
        # - True: load from mapping and serialize as a dict
        #           keyed by field name.
        #
        # In strict mode, inputs that do not match the selected mode
        # raise TypeError.
        #
        # Note:
        #   This option enforces strict shape matching for performance reasons.
        v1_namedtuple_as_dict: ClassVar[bool] = None

        # If True (default: False), ``None`` is coerced to an empty string (``""``)
        # when loading ``str`` fields.
        #
        # When False, ``None`` is coerced using ``str(value)``, so ``None`` becomes
        # the literal string ``'None'`` for ``str`` fields.
        #
        # For ``Optional[str]`` fields, ``None`` is preserved by default.
        v1_coerce_none_to_empty_str: ClassVar[bool] = None

        # Controls how leaf (non-recursive) types are detected during serialization.
        #
        # - "exact" (DEFAULT): only exact built-in leaf types are treated as leaf values.
        # - "issubclass": subclasses of leaf types are also treated as leaf values.
        #
        # Leaf types are returned without recursive traversal. Bytes are still
        # handled separately according to their serialization rules.
        #
        # Note:
        #     The default "exact" mode avoids treating third-party scalar-like
        #     objects (e.g. NumPy scalars) as built-in leaf types.
        v1_leaf_handling: ClassVar[Literal['exact', 'issubclass']] = None

        # noinspection PyMethodParameters
        @cached_class_property
        def all_fields(cls) -> FrozenKeys:
            """Return a list of all class attributes"""
            return frozenset(AbstractEnvMeta.__annotations__)

        # noinspection PyMethodParameters
        @cached_class_property
        def fields_to_merge(cls) -> FrozenKeys:
            """Return a list of class attributes, minus `__special_attrs__`"""
            return cls.all_fields - cls.__special_attrs__

        @classmethod
        @abstractmethod
        def bind_to(cls, env_class: Type, create=True, is_default=True):
            """
            Initialize hook which applies the Meta config to `env_class`, which is
            typically a subclass of :class:`EnvWizard`.

            :param env_class: A sub-class of :class:`EnvWizard`.
            :param create: When true, a separate loader/dumper will be created
              for the class. If disabled, this will access the root loader/dumper,
              so modifying this should affect global settings across all
              dataclasses that use the JSON load/dump process.
            :param is_default: When enabled, the Meta will be cached as the
              default Meta config for the dataclass. Defaults to true.

            """

    class BaseLoadHook:
        """
        Container class for type hooks.
        """
        __slots__ = ()

        __LOAD_HOOKS__: ClassVar[Dict[Type, Callable]] = None

        def __init_subclass__(cls):
            super().__init_subclass__()
            # (Re)assign the dict object so we have a fresh copy per class
            cls.__LOAD_HOOKS__ = {}

        @classmethod
        def register_load_hook(cls, typ: Type, func: Callable):
            """Registers the hook for a type, on the default loader by default."""
            cls.__LOAD_HOOKS__[typ] = func

        @classmethod
        def get_load_hook(cls, typ: Type) -> Optional[Callable]:
            """Retrieves the hook for a type, if one exists."""
            return cls.__LOAD_HOOKS__.get(typ)

    class BaseDumpHook:
        """
        Container class for type hooks.
        """
        __slots__ = ()

        __DUMP_HOOKS__: ClassVar[Dict[Type, Callable]] = None

        def __init_subclass__(cls):
            super().__init_subclass__()
            # (Re)assign the dict object so we have a fresh copy per class
            cls.__DUMP_HOOKS__ = {}

        @classmethod
        def register_dump_hook(cls, typ: Type, func: Callable):
            """Registers the hook for a type, on the default dumper by default."""
            cls.__DUMP_HOOKS__[typ] = func

        @classmethod
        def get_dump_hook(cls, typ: Type) -> Optional[Callable]:
            """Retrieves the hook for a type, if one exists."""
            return cls.__DUMP_HOOKS__.get(typ)