diff --git a/docs/changelog/fragments/+conversion.feature.rst b/docs/changelog/fragments/+conversion.feature.rst index 1997034a..f70593f4 100644 --- a/docs/changelog/fragments/+conversion.feature.rst +++ b/docs/changelog/fragments/+conversion.feature.rst @@ -1,2 +1,4 @@ New major feature is out! -Added support for model conversion! See :ref:`conversion tutorial ` for details. +Added support for model conversion! +Now, you can generate boilerplate converter function by adaptix. +See :ref:`conversion tutorial ` for details. diff --git a/docs/changelog/fragments/+load_error_rename.deprecation.rst b/docs/changelog/fragments/+load_error_rename.deprecation.rst new file mode 100644 index 00000000..68165ff7 --- /dev/null +++ b/docs/changelog/fragments/+load_error_rename.deprecation.rst @@ -0,0 +1,23 @@ +Standardize names inside :mod:`adaptix.load_error`. Import of old names will emit ``DeprecationWarning``. + +.. list-table:: + :header-rows: 1 + + * - Old name + - New name + * - ``MsgError`` + - ``MsgLoadError`` + * - ``ExtraFieldsError`` + - ``ExtraFieldsLoadError`` + * - ``ExtraItemsError`` + - ``ExtraItemsLoadError`` + * - ``NoRequiredFieldsError`` + - ``NoRequiredFieldsLoadError`` + * - ``NoRequiredItemsError`` + - ``NoRequiredItemsLoadError`` + * - ``ValidationError`` + - ``ValidationLoadError`` + * - ``BadVariantError`` + - ``BadVariantLoadError`` + * - ``DatetimeFormatMismatch`` + - ``FormatMismatchLoadError`` diff --git a/docs/examples/loading-and-dumping/extended_usage/unknown_fields_processing/on_loading_extra_forbid.py b/docs/examples/loading-and-dumping/extended_usage/unknown_fields_processing/on_loading_extra_forbid.py index 5057ef79..2613d5e7 100644 --- a/docs/examples/loading-and-dumping/extended_usage/unknown_fields_processing/on_loading_extra_forbid.py +++ b/docs/examples/loading-and-dumping/extended_usage/unknown_fields_processing/on_loading_extra_forbid.py @@ -1,7 +1,7 @@ from dataclasses import dataclass from adaptix import ExtraForbid, Retort, name_mapping -from adaptix.load_error import AggregateLoadError, ExtraFieldsError +from adaptix.load_error import AggregateLoadError, ExtraFieldsLoadError @dataclass @@ -27,5 +27,5 @@ class Book: retort.load(data, Book) except AggregateLoadError as e: assert len(e.exceptions) == 1 - assert isinstance(e.exceptions[0], ExtraFieldsError) + assert isinstance(e.exceptions[0], ExtraFieldsLoadError) assert set(e.exceptions[0].fields) == {"unknown1", "unknown2"} diff --git a/docs/examples/loading-and-dumping/tutorial/validators.py b/docs/examples/loading-and-dumping/tutorial/validators.py index 3dbd0f3c..045bbd2c 100644 --- a/docs/examples/loading-and-dumping/tutorial/validators.py +++ b/docs/examples/loading-and-dumping/tutorial/validators.py @@ -1,7 +1,7 @@ from dataclasses import dataclass from adaptix import P, Retort, validator -from adaptix.load_error import AggregateLoadError, LoadError, ValidationError +from adaptix.load_error import AggregateLoadError, LoadError, ValidationLoadError @dataclass @@ -25,7 +25,7 @@ class Book: retort.load(data, Book) except AggregateLoadError as e: assert len(e.exceptions) == 1 - assert isinstance(e.exceptions[0], ValidationError) + assert isinstance(e.exceptions[0], ValidationLoadError) assert e.exceptions[0].msg == "value must be greater or equal 0" diff --git a/examples/api_division/retort.py b/examples/api_division/retort.py index c5ef2f02..19cbdad9 100644 --- a/examples/api_division/retort.py +++ b/examples/api_division/retort.py @@ -5,7 +5,7 @@ from phonenumbers import PhoneNumber from adaptix import Chain, ExtraForbid, ExtraSkip, P, Retort, dumper, enum_by_name, loader, name_mapping, validator -from adaptix.load_error import ExtraFieldsError, ValueLoadError +from adaptix.load_error import ExtraFieldsLoadError, ValueLoadError from .models import Receipt, ReceiptType, RecItem from .money import Money, TooPreciseAmount @@ -51,7 +51,7 @@ def money_loader(data): def forbid_version_key(data): if isinstance(data, dict) and 'version' in data: - raise ExtraFieldsError(['version'], data) + raise ExtraFieldsLoadError(['version'], data) return data diff --git a/examples/api_division/test_example.py b/examples/api_division/test_example.py index 8b3ed6bc..6754a3ad 100644 --- a/examples/api_division/test_example.py +++ b/examples/api_division/test_example.py @@ -7,11 +7,11 @@ from adaptix.load_error import ( AggregateLoadError, - BadVariantError, - ExtraFieldsError, + BadVariantLoadError, + ExtraFieldsLoadError, TypeLoadError, UnionLoadError, - ValidationError, + ValidationLoadError, ValueLoadError, ) @@ -72,7 +72,7 @@ def test_outer_loading_no_rec_items(): f'while loading model {Receipt}', [ with_trail( - ValidationError('At least one item must be presented', []), + ValidationLoadError('At least one item must be presented', []), ['items'], ) ] @@ -119,7 +119,7 @@ def test_outer_loading_bad_phone(): f'while loading model {NotifyEmail}', [ with_trail( - BadVariantError({'email'}, 'phone'), + BadVariantLoadError({'email'}, 'phone'), ['type'] ) ] @@ -155,7 +155,7 @@ def test_outer_loading_bad_receipt_type(): raises_exc( AggregateLoadError( f'while loading model {Receipt}', - [with_trail(BadVariantError(['INCOME', 'INCOME_REFUND'], 'BAD_TYPE'), ['type'])] + [with_trail(BadVariantLoadError(['INCOME', 'INCOME_REFUND'], 'BAD_TYPE'), ['type'])] ), lambda: outer_receipt_loader(bad_receipt_type_data), ) @@ -165,7 +165,7 @@ def test_outer_loading_with_version_tag(): with_version_data = change(outer_sample_data, ["version"], 1) raises_exc( - ExtraFieldsError(['version'], with_version_data), + ExtraFieldsLoadError(['version'], with_version_data), lambda: outer_receipt_loader(with_version_data), ) @@ -186,7 +186,7 @@ def test_outer_loading_bad_item_quantity(): f'while loading model {RecItem!r}', [ with_trail( - ValidationError('Value must be > 0', 0), + ValidationLoadError('Value must be > 0', 0), ['quantity'], ), ] @@ -219,7 +219,7 @@ def test_outer_loading_bad_item_price(): f'while loading model {RecItem}', [ with_trail( - ValidationError('Value must be >= 0', rubles(-10)), + ValidationLoadError('Value must be >= 0', rubles(-10)), ['price'], ) ] diff --git a/src/adaptix/_internal/conversion/facade/retort.py b/src/adaptix/_internal/conversion/facade/retort.py index db89920a..8de3a164 100644 --- a/src/adaptix/_internal/conversion/facade/retort.py +++ b/src/adaptix/_internal/conversion/facade/retort.py @@ -43,7 +43,7 @@ class FilledConversionRetort(OperatingRetort): class AdornedConversionRetort(OperatingRetort): - def _calculate_derived(self): + def _calculate_derived(self) -> None: super()._calculate_derived() self._simple_converter_cache: Dict[Tuple[TypeHint, TypeHint, Optional[str]], Converter] = {} diff --git a/src/adaptix/_internal/morphing/concrete_provider.py b/src/adaptix/_internal/morphing/concrete_provider.py index 2207817f..7a3c8f69 100644 --- a/src/adaptix/_internal/morphing/concrete_provider.py +++ b/src/adaptix/_internal/morphing/concrete_provider.py @@ -16,7 +16,7 @@ from ..provider.request_cls import LocatedRequest, StrictCoercionRequest, TypeHintLoc, find_owner_with_field from ..provider.static_provider import static_provision_action from ..special_cases_optimization import as_is_stub -from .load_error import DatetimeFormatMismatch, TypeLoadError, ValueLoadError +from .load_error import FormatMismatchLoadError, TypeLoadError, ValueLoadError from .provider_template import DumperProvider, LoaderProvider, ProviderWithAttachableLSC from .request_cls import DumperRequest, LoaderRequest @@ -59,7 +59,7 @@ def datetime_format_loader(data): try: return datetime.strptime(data, fmt) except ValueError: - raise DatetimeFormatMismatch(fmt, data) + raise FormatMismatchLoadError(fmt, data) except TypeError: raise TypeLoadError(str, data) diff --git a/src/adaptix/_internal/morphing/constant_length_tuple_provider.py b/src/adaptix/_internal/morphing/constant_length_tuple_provider.py index 3b71f3f4..253dcc85 100644 --- a/src/adaptix/_internal/morphing/constant_length_tuple_provider.py +++ b/src/adaptix/_internal/morphing/constant_length_tuple_provider.py @@ -21,9 +21,9 @@ from .load_error import ( AggregateLoadError, ExcludedTypeLoadError, - ExtraItemsError, + ExtraItemsLoadError, LoadError, - NoRequiredItemsError, + NoRequiredItemsLoadError, TypeLoadError, ) from .provider_template import DumperProvider, LoaderProvider @@ -114,9 +114,9 @@ def dt_all_loader(data): # noqa: CCR001 if data_len != loaders_len: if data_len > loaders_len: - raise ExtraItemsError(loaders_len, data) + raise ExtraItemsLoadError(loaders_len, data) if loaders_len > data_len: - raise NoRequiredItemsError(loaders_len, data) + raise NoRequiredItemsLoadError(loaders_len, data) idx = 0 errors = [] @@ -156,9 +156,9 @@ def dt_first_loader(data): if data_len != loaders_len: if data_len > loaders_len: - raise ExtraItemsError(loaders_len, data) + raise ExtraItemsLoadError(loaders_len, data) if loaders_len > data_len: - raise NoRequiredItemsError(loaders_len, data) + raise NoRequiredItemsLoadError(loaders_len, data) idx = 0 for loader, field in zip(loaders, data): @@ -182,9 +182,9 @@ def dt_disable_non_sc_loader(data): if data_len != loaders_len: if data_len > loaders_len: - raise ExtraItemsError(loaders_len, data) + raise ExtraItemsLoadError(loaders_len, data) if loaders_len > data_len: - raise NoRequiredItemsError(loaders_len, data) + raise NoRequiredItemsLoadError(loaders_len, data) return tuple( loader(field) @@ -209,9 +209,9 @@ def dt_disable_sc_loader(data): if data_len != loaders_len: if data_len > loaders_len: - raise ExtraItemsError(loaders_len, data) + raise ExtraItemsLoadError(loaders_len, data) if loaders_len > data_len: - raise NoRequiredItemsError(loaders_len, data) + raise NoRequiredItemsLoadError(loaders_len, data) return tuple( loader(field) @@ -267,9 +267,9 @@ def dt_all_dumper(data): if data_len != dumpers_len: if data_len > dumpers_len: - raise ExtraItemsError(dumpers_len, data) + raise ExtraItemsLoadError(dumpers_len, data) if dumpers_len > data_len: - raise NoRequiredItemsError(dumpers_len, data) + raise NoRequiredItemsLoadError(dumpers_len, data) idx = 0 errors = [] @@ -300,9 +300,9 @@ def dt_first_dumper(data): if data_len != dumpers_len: if data_len > dumpers_len: - raise ExtraItemsError(dumpers_len, data) + raise ExtraItemsLoadError(dumpers_len, data) if dumpers_len > data_len: - raise NoRequiredItemsError(dumpers_len, data) + raise NoRequiredItemsLoadError(dumpers_len, data) idx = 0 for dumper, field in zip(dumpers, data): @@ -332,9 +332,9 @@ def tuple_dumper(data): if data_len != dumpers_len: if data_len > dumpers_len: - raise ExtraItemsError(dumpers_len, data) + raise ExtraItemsLoadError(dumpers_len, data) if dumpers_len > data_len: - raise NoRequiredItemsError(dumpers_len, data) + raise NoRequiredItemsLoadError(dumpers_len, data) return tuple( dumper(field) diff --git a/src/adaptix/_internal/morphing/enum_provider.py b/src/adaptix/_internal/morphing/enum_provider.py index a13f8213..1efc3ea4 100644 --- a/src/adaptix/_internal/morphing/enum_provider.py +++ b/src/adaptix/_internal/morphing/enum_provider.py @@ -15,12 +15,12 @@ from ..provider.request_cls import LocMap, StrictCoercionRequest, TypeHintLoc, get_type_from_request from ..type_tools import is_subclass_soft, normalize_type from .load_error import ( - BadVariantError, - DuplicatedValues, + BadVariantLoadError, + DuplicatedValuesLoadError, ExcludedTypeLoadError, - MsgError, - MultipleBadVariant, - OutOfRange, + MsgLoadError, + MultipleBadVariantLoadError, + OutOfRangeLoadError, TypeLoadError, ) from .request_cls import DumperRequest, LoaderRequest @@ -116,9 +116,9 @@ def enum_loader(data): try: return mapping[data] except KeyError: - raise BadVariantError(variants, data) from None + raise BadVariantLoadError(variants, data) from None except TypeError: - raise BadVariantError(variants, data) + raise BadVariantLoadError(variants, data) return enum_loader @@ -153,7 +153,7 @@ def enum_loader(data): try: return enum(loaded_value) except ValueError: - raise MsgError("Bad enum value", data) + raise MsgLoadError("Bad enum value", data) return enum_loader @@ -194,12 +194,12 @@ def _make_loader(self, enum): def enum_exact_loader(data): # since MyEnum(MyEnum.MY_CASE) == MyEnum.MY_CASE if type(data) is enum: # pylint: disable=unidiomatic-typecheck - raise BadVariantError(variants, data) + raise BadVariantLoadError(variants, data) try: return enum(data) except ValueError: - raise BadVariantError(variants, data) from None + raise BadVariantLoadError(variants, data) from None return enum_exact_loader @@ -207,9 +207,9 @@ def enum_exact_loader_v2m(data): try: return value_to_member[data] except KeyError: - raise BadVariantError(variants, data) from None + raise BadVariantLoadError(variants, data) from None except TypeError: - raise BadVariantError(variants, data) + raise BadVariantLoadError(variants, data) return enum_exact_loader_v2m @@ -254,7 +254,7 @@ def flag_loader(data): raise TypeLoadError(int, data) if data < 0 or data > flag_mask: - raise OutOfRange(0, flag_mask, data) + raise OutOfRangeLoadError(0, flag_mask, data) # data already has been validated for all edge cases # so enum lookup cannot raise an error @@ -318,7 +318,7 @@ def flag_loader(data) -> Flag: # noqa: CCR001 if not allow_duplicates: if len(process_data) != len(set(process_data)): - raise DuplicatedValues(data) + raise DuplicatedValuesLoadError(data) bad_variants = [] result = zero_case @@ -329,7 +329,7 @@ def flag_loader(data) -> Flag: # noqa: CCR001 result |= mapping[item] if bad_variants: - raise MultipleBadVariant( + raise MultipleBadVariantLoadError( allowed_values=variants, invalid_values=bad_variants, input_value=data, diff --git a/src/adaptix/_internal/morphing/facade/provider.py b/src/adaptix/_internal/morphing/facade/provider.py index 74bf8d80..4c59d012 100644 --- a/src/adaptix/_internal/morphing/facade/provider.py +++ b/src/adaptix/_internal/morphing/facade/provider.py @@ -33,7 +33,7 @@ FlagByExactValueProvider, FlagByListProvider, ) -from ..load_error import LoadError, ValidationError +from ..load_error import LoadError, ValidationLoadError from ..model.loader_provider import InlinedShapeModelLoaderProvider from ..name_layout.base import ExtraIn, ExtraOut from ..name_layout.component import ExtraMoveAndPoliciesOverlay, SievesOverlay, StructureOverlay @@ -389,7 +389,7 @@ def flag_by_member_names( :param allow_single_value: Allows calling the loader with a single value. If this is allowed, singlular values are treated as one element list. :param allow_duplicates: Allows calling the loader with a list containing non-unique elements. - Unless this is allowed, loader will raise :exc:`.DuplicatedValues` in that case. + Unless this is allowed, loader will raise :exc:`.DuplicatedValuesLoadError` in that case. :param allow_compound: Allows the loader to accept names of compound members (e.g. ``WHITE = RED | GREEN | BLUE``) and the dumper to return names of compound members. If this is allowed, dumper will use compound members names to serialize value. @@ -419,7 +419,7 @@ def validator( ) -> Provider: # pylint: disable=C3001 exception_factory = ( - (lambda x: ValidationError(error, x)) + (lambda x: ValidationLoadError(error, x)) if error is None or isinstance(error, str) else error ) diff --git a/src/adaptix/_internal/morphing/generic_provider.py b/src/adaptix/_internal/morphing/generic_provider.py index 934b5278..18bf683c 100644 --- a/src/adaptix/_internal/morphing/generic_provider.py +++ b/src/adaptix/_internal/morphing/generic_provider.py @@ -27,7 +27,7 @@ from ..special_cases_optimization import as_is_stub from ..type_tools import BaseNormType, NormTypeAlias, is_new_type, is_subclass_soft, strip_tags from ..type_tools.norm_utils import strip_annotated -from .load_error import BadVariantError, LoadError, TypeLoadError, UnionLoadError +from .load_error import BadVariantLoadError, LoadError, TypeLoadError, UnionLoadError from .provider_template import DumperProvider, LoaderProvider from .request_cls import DumperRequest, LoaderRequest @@ -209,7 +209,7 @@ def _provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader: def literal_loader_sc(data): if (type(data), data) in allowed_values_with_types: return data - raise BadVariantError(allowed_values_repr, data) + raise BadVariantLoadError(allowed_values_repr, data) return self._get_literal_loader_with_enum( literal_loader_sc, enum_loaders, allowed_values_with_types @@ -220,7 +220,7 @@ def literal_loader_sc(data): def literal_loader(data): if data in allowed_values: return data - raise BadVariantError(allowed_values_repr, data) + raise BadVariantLoadError(allowed_values_repr, data) return self._get_literal_loader_with_enum(literal_loader, enum_loaders, allowed_values) diff --git a/src/adaptix/_internal/morphing/load_error.py b/src/adaptix/_internal/morphing/load_error.py index ba785c18..6f7a7821 100644 --- a/src/adaptix/_internal/morphing/load_error.py +++ b/src/adaptix/_internal/morphing/load_error.py @@ -48,6 +48,10 @@ class LoadExceptionGroup(CompatExceptionGroup[LoadError], LoadError): message: str exceptions: VarTuple[LoadError] + # stub `__init__` is required for right introspection + def __init__(self, message: str, exceptions: VarTuple[LoadError]): + pass + @custom_exception(str_by_fields=False) @dataclass(eq=False, init=False) @@ -63,35 +67,35 @@ class UnionLoadError(LoadExceptionGroup): @custom_exception @dataclass(eq=False) -class MsgError(LoadError): +class MsgLoadError(LoadError): msg: Optional[str] input_value: Any @custom_exception @dataclass(eq=False) -class ExtraFieldsError(LoadError): +class ExtraFieldsLoadError(LoadError): fields: Iterable[str] input_value: Any @custom_exception @dataclass(eq=False) -class ExtraItemsError(LoadError): +class ExtraItemsLoadError(LoadError): expected_len: int input_value: Any @custom_exception @dataclass(eq=False) -class NoRequiredFieldsError(LoadError): +class NoRequiredFieldsLoadError(LoadError): fields: Iterable[str] input_value: Any @custom_exception @dataclass(eq=False) -class NoRequiredItemsError(LoadError): +class NoRequiredItemsLoadError(LoadError): expected_len: int input_value: Any @@ -113,26 +117,26 @@ class ExcludedTypeLoadError(TypeLoadError): @custom_exception(str_by_fields=False) @dataclass(eq=False) -class ValueLoadError(MsgError): +class ValueLoadError(MsgLoadError): pass @custom_exception(str_by_fields=False) @dataclass(eq=False) -class ValidationError(MsgError): +class ValidationLoadError(MsgLoadError): pass @custom_exception @dataclass(eq=False) -class BadVariantError(LoadError): +class BadVariantLoadError(LoadError): allowed_values: Iterable[Any] input_value: Any @custom_exception @dataclass(eq=False) -class MultipleBadVariant(LoadError): +class MultipleBadVariantLoadError(LoadError): allowed_values: Iterable[Any] invalid_values: Iterable[Any] input_value: Any @@ -140,20 +144,20 @@ class MultipleBadVariant(LoadError): @custom_exception @dataclass(eq=False) -class DatetimeFormatMismatch(LoadError): +class FormatMismatchLoadError(LoadError): format: str input_value: Any @custom_exception @dataclass(eq=False) -class DuplicatedValues(LoadError): +class DuplicatedValuesLoadError(LoadError): input_value: Any @custom_exception @dataclass(eq=False) -class OutOfRange(LoadError): +class OutOfRangeLoadError(LoadError): min_value: Optional[Union[int, float]] max_value: Optional[Union[int, float]] input_value: Any diff --git a/src/adaptix/_internal/morphing/model/loader_gen.py b/src/adaptix/_internal/morphing/model/loader_gen.py index 94f0d02d..5d85ef01 100644 --- a/src/adaptix/_internal/morphing/model/loader_gen.py +++ b/src/adaptix/_internal/morphing/model/loader_gen.py @@ -15,11 +15,11 @@ from ..load_error import ( AggregateLoadError, ExcludedTypeLoadError, - ExtraFieldsError, - ExtraItemsError, + ExtraFieldsLoadError, + ExtraItemsLoadError, LoadError, - NoRequiredFieldsError, - NoRequiredItemsError, + NoRequiredFieldsLoadError, + NoRequiredItemsLoadError, TypeLoadError, ) from .basic_gen import ModelLoaderGen @@ -237,8 +237,8 @@ def produce_code(self, closure_name: str) -> Tuple[str, Mapping[str, object]]: for named_value in ( append_trail, extend_trail, render_trail_as_note, - ExtraFieldsError, ExtraItemsError, - NoRequiredFieldsError, NoRequiredItemsError, + ExtraFieldsLoadError, ExtraItemsLoadError, + NoRequiredFieldsLoadError, NoRequiredItemsLoadError, TypeLoadError, ExcludedTypeLoadError, LoadError, AggregateLoadError, ): @@ -408,7 +408,7 @@ def _gen_assigment_from_parent_data( bad_type_error = '(TypeError, IndexError)' bad_type_load_error = f'TypeLoadError(CollectionsMapping, {state.parent.v_data})' not_found_error = ( - "NoRequiredFieldsError(" + "NoRequiredFieldsLoadError(" f"{state.parent.v_required_keys} - set({state.parent.v_data}), {state.parent.v_data}" ")" ) @@ -416,7 +416,7 @@ def _gen_assigment_from_parent_data( lookup_error = 'IndexError' bad_type_error = '(TypeError, KeyError)' bad_type_load_error = f'TypeLoadError(CollectionsSequence, {state.parent.v_data})' - not_found_error = f"NoRequiredItemsError({len(state.parent_crown.map)}, {state.parent.v_data})" + not_found_error = f"NoRequiredItemsLoadError({len(state.parent_crown.map)}, {state.parent.v_data})" with state.builder( f""" @@ -520,7 +520,7 @@ def _gen_dict_crown(self, state: GenState, crown: InpDictCrown): state.builder += f""" {state.v_extra}_set = set({state.v_data}) - {state.v_known_keys} if {state.v_extra}_set: - {state.emit_error(f"ExtraFieldsError({state.v_extra}_set, {state.v_data})")} + {state.emit_error(f"ExtraFieldsLoadError({state.v_extra}_set, {state.v_data})")} """ state.builder.empty_line() elif crown.extra_policy == ExtraCollect(): @@ -567,14 +567,14 @@ def _gen_list_crown(self, state: GenState, crown: InpListCrown): state.builder += f""" if len({state.v_data}) != {expected_len}: if len({state.v_data}) < {expected_len}: - {state.emit_error(f"NoRequiredItemsError({expected_len}, {state.v_data})")} + {state.emit_error(f"NoRequiredItemsLoadError({expected_len}, {state.v_data})")} else: - {state.emit_error(f"ExtraItemsError({expected_len}, {state.v_data})")} + {state.emit_error(f"ExtraItemsLoadError({expected_len}, {state.v_data})")} """ else: state.builder += f""" if len({state.v_data}) < {expected_len}: - {state.emit_error(f"NoRequiredItemsError({expected_len}, {state.v_data})")} + {state.emit_error(f"NoRequiredItemsLoadError({expected_len}, {state.v_data})")} """ if self._can_collect_extra: diff --git a/src/adaptix/_internal/retort/base_retort.py b/src/adaptix/_internal/retort/base_retort.py index 751a8885..00176e90 100644 --- a/src/adaptix/_internal/retort/base_retort.py +++ b/src/adaptix/_internal/retort/base_retort.py @@ -55,7 +55,7 @@ def _get_config_recipe(self) -> VarTuple[Provider]: def _get_full_recipe(self) -> Sequence[Provider]: return self._full_recipe - def _calculate_derived(self): + def _calculate_derived(self) -> None: super()._calculate_derived() self._full_recipe = ( self._inc_instance_recipe diff --git a/src/adaptix/_internal/utils.py b/src/adaptix/_internal/utils.py index 200a7b88..6fb9c378 100644 --- a/src/adaptix/_internal/utils.py +++ b/src/adaptix/_internal/utils.py @@ -1,4 +1,6 @@ import itertools +import sys +import warnings from abc import ABC, abstractmethod from contextlib import contextmanager from copy import copy @@ -204,3 +206,19 @@ def decorator(cls): return cls return decorator + + +def create_deprecated_alias_getter(module_name, old_name_to_new_name): + def __getattr__(name): + if name not in old_name_to_new_name: + raise AttributeError(f"module {module_name!r} has no attribute {name!r}") + + new_name = old_name_to_new_name[name] + warnings.warn( + f"Name {name!r} is deprecated, use {new_name!r} instead", + DeprecationWarning, + stacklevel=2, + ) + return getattr(sys.modules[module_name], new_name) + + return __getattr__ diff --git a/src/adaptix/load_error.py b/src/adaptix/load_error.py index 01ade039..af1907bb 100644 --- a/src/adaptix/load_error.py +++ b/src/adaptix/load_error.py @@ -1,41 +1,57 @@ from adaptix._internal.morphing.load_error import ( AggregateLoadError, - BadVariantError, - DatetimeFormatMismatch, - DuplicatedValues, + BadVariantLoadError, + DuplicatedValuesLoadError, ExcludedTypeLoadError, - ExtraFieldsError, - ExtraItemsError, + ExtraFieldsLoadError, + ExtraItemsLoadError, + FormatMismatchLoadError, LoadError, LoadExceptionGroup, - MsgError, - MultipleBadVariant, - NoRequiredFieldsError, - NoRequiredItemsError, - OutOfRange, + MsgLoadError, + MultipleBadVariantLoadError, + NoRequiredFieldsLoadError, + NoRequiredItemsLoadError, + OutOfRangeLoadError, TypeLoadError, UnionLoadError, - ValidationError, + ValidationLoadError, ValueLoadError, ) +from adaptix._internal.utils import create_deprecated_alias_getter __all__ = ( 'LoadError', 'LoadExceptionGroup', 'AggregateLoadError', 'UnionLoadError', - 'MsgError', - 'ExtraFieldsError', - 'ExtraItemsError', - 'NoRequiredFieldsError', - 'NoRequiredItemsError', + 'MsgLoadError', + 'ExtraFieldsLoadError', + 'ExtraItemsLoadError', + 'NoRequiredFieldsLoadError', + 'NoRequiredItemsLoadError', 'TypeLoadError', 'ExcludedTypeLoadError', 'ValueLoadError', - 'ValidationError', - 'BadVariantError', - 'DatetimeFormatMismatch', - 'DuplicatedValues', - 'OutOfRange', - 'MultipleBadVariant' + 'ValidationLoadError', + 'BadVariantLoadError', + 'FormatMismatchLoadError', + 'DuplicatedValuesLoadError', + 'OutOfRangeLoadError', + 'MultipleBadVariantLoadError' +) + + +__getattr__ = create_deprecated_alias_getter( + __name__, + { + 'MsgError': 'MsgLoadError', + 'ExtraFieldsError': 'ExtraFieldsLoadError', + 'ExtraItemsError': 'ExtraItemsLoadError', + 'NoRequiredFieldsError': 'NoRequiredFieldsLoadError', + 'NoRequiredItemsError': 'NoRequiredItemsLoadError', + 'ValidationError': 'ValidationLoadError', + 'BadVariantError': 'BadVariantLoadError', + 'DatetimeFormatMismatch': 'FormatMismatchLoadError', + }, ) diff --git a/tests/unit/morphing/generic_provider/test_literal_provider.py b/tests/unit/morphing/generic_provider/test_literal_provider.py index 860b719d..4a8cfdf4 100644 --- a/tests/unit/morphing/generic_provider/test_literal_provider.py +++ b/tests/unit/morphing/generic_provider/test_literal_provider.py @@ -7,7 +7,7 @@ from adaptix._internal.morphing.enum_provider import EnumExactValueProvider from adaptix._internal.morphing.generic_provider import LiteralProvider, UnionProvider -from adaptix._internal.morphing.load_error import BadVariantError +from adaptix._internal.morphing.load_error import BadVariantLoadError @pytest.fixture @@ -34,7 +34,7 @@ def test_loader_base(retort, strict_coercion, debug_trail): assert loader(10) == 10 raises_exc( - BadVariantError({'a', 'b', 10}, 'c'), + BadVariantLoadError({'a', 'b', 10}, 'c'), lambda: loader("c") ) @@ -65,11 +65,11 @@ def test_strict_coercion(retort, debug_trail): assert _is_exact_one(literal_loader(1)) raises_exc( - BadVariantError({0, 1, rnd_val1}, False), + BadVariantLoadError({0, 1, rnd_val1}, False), lambda: literal_loader(False) ) raises_exc( - BadVariantError({0, 1, rnd_val1}, True), + BadVariantLoadError({0, 1, rnd_val1}, True), lambda: literal_loader(True) ) @@ -85,11 +85,11 @@ def test_strict_coercion(retort, debug_trail): assert bool_loader(True) is True raises_exc( - BadVariantError({False, True, rnd_val2}, 0), + BadVariantLoadError({False, True, rnd_val2}, 0), lambda: bool_loader(0) ) raises_exc( - BadVariantError({False, True, rnd_val2}, 1), + BadVariantLoadError({False, True, rnd_val2}, 1), lambda: bool_loader(1) ) @@ -126,7 +126,7 @@ class Enum2(Enum): assert loader(10) == 10 raises_exc( - BadVariantError({Enum1.CASE1.value, Enum2.CASE2.value, 10}, 15), + BadVariantLoadError({Enum1.CASE1.value, Enum2.CASE2.value, 10}, 15), lambda: loader(15) ) diff --git a/tests/unit/morphing/generic_provider/test_union_provider.py b/tests/unit/morphing/generic_provider/test_union_provider.py index 493a9b39..b9bd46a9 100644 --- a/tests/unit/morphing/generic_provider/test_union_provider.py +++ b/tests/unit/morphing/generic_provider/test_union_provider.py @@ -7,7 +7,7 @@ from adaptix import CannotProvide, DebugTrail, NoSuitableProvider, Retort, dumper, loader from adaptix._internal.compat import CompatExceptionGroup from adaptix._internal.morphing.generic_provider import LiteralProvider, UnionProvider -from adaptix._internal.morphing.load_error import BadVariantError, LoadError, TypeLoadError, UnionLoadError +from adaptix._internal.morphing.load_error import BadVariantLoadError, LoadError, TypeLoadError, UnionLoadError @dataclass @@ -241,14 +241,14 @@ def test_literal(strict_coercion, debug_trail): if debug_trail == DebugTrail.DISABLE: raises_exc( - BadVariantError({'a'}, 'b'), + BadVariantLoadError({'a'}, 'b'), lambda: loader_('b'), ) elif debug_trail in (DebugTrail.FIRST, DebugTrail.ALL): raises_exc( UnionLoadError( f'while loading {Literal["a", None]}', - [TypeLoadError(None, 'b'), BadVariantError({'a'}, 'b')] + [TypeLoadError(None, 'b'), BadVariantLoadError({'a'}, 'b')] ), lambda: loader_('b'), ) diff --git a/tests/unit/morphing/model/test_loader_provider.py b/tests/unit/morphing/model/test_loader_provider.py index 3931dcd9..e616b318 100644 --- a/tests/unit/morphing/model/test_loader_provider.py +++ b/tests/unit/morphing/model/test_loader_provider.py @@ -37,11 +37,11 @@ from adaptix._internal.provider.provider_template import ValueProvider from adaptix._internal.provider.shape_provider import InputShapeRequest from adaptix.load_error import ( - ExtraFieldsError, - ExtraItemsError, + ExtraFieldsLoadError, + ExtraItemsLoadError, LoadError, - NoRequiredFieldsError, - NoRequiredItemsError, + NoRequiredFieldsLoadError, + NoRequiredItemsLoadError, TypeLoadError, ) @@ -175,11 +175,11 @@ def test_direct(debug_ctx, debug_trail, extra_policy, trail_select): data = {'a': 1, 'b': 2, 'c': 3} raises_exc( trail_select( - disable=ExtraFieldsError({'c'}, data), - first=ExtraFieldsError({'c'}, data), + disable=ExtraFieldsLoadError({'c'}, data), + first=ExtraFieldsLoadError({'c'}, data), all=AggregateLoadError( f'while loading model {Gauge}', - [ExtraFieldsError({'c'}, data)], + [ExtraFieldsLoadError({'c'}, data)], ), ), lambda: loader(data), @@ -200,11 +200,11 @@ def test_direct(debug_ctx, debug_trail, extra_policy, trail_select): data = {'a': 1} raises_exc( trail_select( - disable=NoRequiredFieldsError({'b'}, data), - first=NoRequiredFieldsError({'b'}, data), + disable=NoRequiredFieldsLoadError({'b'}, data), + first=NoRequiredFieldsLoadError({'b'}, data), all=AggregateLoadError( f'while loading model {Gauge}', - [NoRequiredFieldsError({'b'}, data)], + [NoRequiredFieldsLoadError({'b'}, data)], ), ), lambda: loader({'a': 1}), @@ -255,11 +255,11 @@ def test_direct_list(debug_ctx, debug_trail, extra_policy, trail_select, strict_ data = [1, 2, 3] raises_exc( trail_select( - disable=ExtraItemsError(2, data), - first=ExtraItemsError(2, data), + disable=ExtraItemsLoadError(2, data), + first=ExtraItemsLoadError(2, data), all=AggregateLoadError( f'while loading model {Gauge}', - [ExtraItemsError(2, data)], + [ExtraItemsLoadError(2, data)], ), ), lambda: loader(data), @@ -268,11 +268,11 @@ def test_direct_list(debug_ctx, debug_trail, extra_policy, trail_select, strict_ data = [10] raises_exc( trail_select( - disable=NoRequiredItemsError(2, data), - first=NoRequiredItemsError(2, data), + disable=NoRequiredItemsLoadError(2, data), + first=NoRequiredItemsLoadError(2, data), all=AggregateLoadError( f'while loading model {Gauge}', - [NoRequiredItemsError(2, data)], + [NoRequiredItemsLoadError(2, data)], ), ), lambda: loader(data), @@ -331,11 +331,11 @@ def test_extra_forbid(debug_ctx, debug_trail, trail_select): data = {'a': 1, 'b': 2, 'c': 3} raises_exc( trail_select( - disable=ExtraFieldsError({'c'}, data), - first=ExtraFieldsError({'c'}, data), + disable=ExtraFieldsLoadError({'c'}, data), + first=ExtraFieldsLoadError({'c'}, data), all=AggregateLoadError( f'while loading model {Gauge}', - [ExtraFieldsError({'c'}, data)], + [ExtraFieldsLoadError({'c'}, data)], ) ), lambda: loader(data), @@ -343,11 +343,11 @@ def test_extra_forbid(debug_ctx, debug_trail, trail_select): data = {'a': 1, 'b': 2, 'c': 3, 'd': 4} raises_exc( trail_select( - disable=ExtraFieldsError({'c', 'd'}, data), - first=ExtraFieldsError({'c', 'd'}, data), + disable=ExtraFieldsLoadError({'c', 'd'}, data), + first=ExtraFieldsLoadError({'c', 'd'}, data), all=AggregateLoadError( f'while loading model {Gauge}', - [ExtraFieldsError({'c', 'd'}, data)], + [ExtraFieldsLoadError({'c', 'd'}, data)], ) ), lambda: loader(data), @@ -536,9 +536,9 @@ def test_mapping_and_extra_kwargs(debug_ctx, debug_trail, trail_select): data = {'a': 1, 'b': 2} raises_exc( trail_select( - disable=NoRequiredFieldsError({'m_a'}, data), - first=NoRequiredFieldsError({'m_a'}, data), - all=AggregateLoadError(f'while loading model {Gauge}', [NoRequiredFieldsError({'m_a'}, data)]) + disable=NoRequiredFieldsLoadError({'m_a'}, data), + first=NoRequiredFieldsLoadError({'m_a'}, data), + all=AggregateLoadError(f'while loading model {Gauge}', [NoRequiredFieldsLoadError({'m_a'}, data)]) ), lambda: loader(data), ) @@ -686,9 +686,9 @@ def test_flat_mapping(debug_ctx, debug_trail, is_required, trail_select): data = {'a': 1, 'b': 2} raises_exc( trail_select( - disable=NoRequiredFieldsError({'m_a'}, data), - first=NoRequiredFieldsError({'m_a'}, data), - all=AggregateLoadError(f'while loading model {Gauge}', [NoRequiredFieldsError({'m_a'}, data)]) + disable=NoRequiredFieldsLoadError({'m_a'}, data), + first=NoRequiredFieldsLoadError({'m_a'}, data), + all=AggregateLoadError(f'while loading model {Gauge}', [NoRequiredFieldsLoadError({'m_a'}, data)]) ), lambda: loader(data), ) @@ -955,9 +955,9 @@ def test_none_crown_at_dict_crown(debug_ctx, debug_trail, extra_policy, trail_se data = {'a': 1, 'b': 2, 'c': 3} raises_exc( trail_select( - disable=ExtraFieldsError({'c'}, data), - first=ExtraFieldsError({'c'}, data), - all=AggregateLoadError(f'while loading model {Gauge}', [ExtraFieldsError({'c'}, data)]), + disable=ExtraFieldsLoadError({'c'}, data), + first=ExtraFieldsLoadError({'c'}, data), + all=AggregateLoadError(f'while loading model {Gauge}', [ExtraFieldsLoadError({'c'}, data)]), ), lambda: loader(data), ) @@ -990,9 +990,9 @@ def test_none_crown_at_list_crown(debug_ctx, debug_trail, extra_policy, trail_se data = [1, 2] raises_exc( trail_select( - disable=NoRequiredItemsError(3, data), - first=NoRequiredItemsError(3, data), - all=AggregateLoadError(f'while loading model {Gauge}', [NoRequiredItemsError(3, data)]), + disable=NoRequiredItemsLoadError(3, data), + first=NoRequiredItemsLoadError(3, data), + all=AggregateLoadError(f'while loading model {Gauge}', [NoRequiredItemsLoadError(3, data)]), ), lambda: loader(data), ) @@ -1004,9 +1004,9 @@ def test_none_crown_at_list_crown(debug_ctx, debug_trail, extra_policy, trail_se data = [1, 2, 3, 4] raises_exc( trail_select( - disable=ExtraItemsError(3, data), - first=ExtraItemsError(3, data), - all=AggregateLoadError(f'while loading model {Gauge}', [ExtraItemsError(3, data)]), + disable=ExtraItemsLoadError(3, data), + first=ExtraItemsLoadError(3, data), + all=AggregateLoadError(f'while loading model {Gauge}', [ExtraItemsLoadError(3, data)]), ), lambda: loader(data), ) @@ -1050,7 +1050,7 @@ def test_exception_collection(debug_ctx): f'while loading model {Gauge}', [ with_trail(ValueLoadError('error at a', ...), ['a']), - NoRequiredFieldsError({'b'}, data), + NoRequiredFieldsLoadError({'b'}, data), ] ), lambda: loader(data), @@ -1062,8 +1062,8 @@ def test_exception_collection(debug_ctx): f'while loading model {Gauge}', [ with_trail(ValueLoadError('error at a', ...), ['a']), - NoRequiredFieldsError({'b'}, data), - ExtraFieldsError({'c'}, data), + NoRequiredFieldsLoadError({'b'}, data), + ExtraFieldsLoadError({'c'}, data), ] ), lambda: loader(data), @@ -1169,9 +1169,9 @@ def test_empty_list(debug_ctx, debug_trail, extra_policy, trail_select, strict_c elif extra_policy == ExtraForbid(): raises_exc( trail_select( - disable=ExtraItemsError(0, 'abc'), - first=ExtraItemsError(0, 'abc'), - all=AggregateLoadError(f'while loading model {Gauge}', [ExtraItemsError(0, 'abc')]), + disable=ExtraItemsLoadError(0, 'abc'), + first=ExtraItemsLoadError(0, 'abc'), + all=AggregateLoadError(f'while loading model {Gauge}', [ExtraItemsLoadError(0, 'abc')]), ), lambda: loader('abc'), ) diff --git a/tests/unit/morphing/test_concrete_provider.py b/tests/unit/morphing/test_concrete_provider.py index 413435b2..bbd3fb31 100644 --- a/tests/unit/morphing/test_concrete_provider.py +++ b/tests/unit/morphing/test_concrete_provider.py @@ -11,7 +11,7 @@ from adaptix import Retort from adaptix._internal.feature_requirement import HAS_PY_311, IS_PYPY from adaptix._internal.morphing.concrete_provider import DatetimeFormatProvider -from adaptix.load_error import DatetimeFormatMismatch, TypeLoadError, ValueLoadError +from adaptix.load_error import FormatMismatchLoadError, TypeLoadError, ValueLoadError def check_any_dt(loader): @@ -119,7 +119,7 @@ def test_datetime_format_provider(strict_coercion, debug_trail): check_any_dt(loader) raises_exc( - DatetimeFormatMismatch("%Y-%m-%d", "some string"), + FormatMismatchLoadError("%Y-%m-%d", "some string"), lambda: loader("some string") ) diff --git a/tests/unit/morphing/test_constant_length_tuple_provider.py b/tests/unit/morphing/test_constant_length_tuple_provider.py index ada2d226..52e44e88 100644 --- a/tests/unit/morphing/test_constant_length_tuple_provider.py +++ b/tests/unit/morphing/test_constant_length_tuple_provider.py @@ -12,7 +12,7 @@ from adaptix._internal.morphing.concrete_provider import INT_LOADER_PROVIDER, STR_LOADER_PROVIDER from adaptix._internal.morphing.constant_length_tuple_provider import ConstantLengthTupleProvider from adaptix._internal.morphing.load_error import AggregateLoadError -from adaptix.load_error import ExcludedTypeLoadError, ExtraItemsError, NoRequiredItemsError, TypeLoadError +from adaptix.load_error import ExcludedTypeLoadError, ExtraItemsLoadError, NoRequiredItemsLoadError, TypeLoadError def string_dumper(data): @@ -227,11 +227,11 @@ def test_loading_not_enough_fields(retort): loader_ = retort.get_loader(Tuple[int, int]) raises_exc( - ExtraItemsError(2, (1, 2, 3)), + ExtraItemsLoadError(2, (1, 2, 3)), lambda: loader_([1, 2, 3]) ) raises_exc( - NoRequiredItemsError(2, (1,)), + NoRequiredItemsLoadError(2, (1,)), lambda: loader_([1]) ) @@ -245,11 +245,11 @@ def test_dumping_not_enough_fields(retort): dumper_ = retort.get_dumper(Tuple[int, int]) raises_exc( - ExtraItemsError(2, [1, 2, 3]), + ExtraItemsLoadError(2, [1, 2, 3]), lambda: dumper_([1, 2, 3]) ) raises_exc( - NoRequiredItemsError(2, [1]), + NoRequiredItemsLoadError(2, [1]), lambda: dumper_([1]) ) diff --git a/tests/unit/morphing/test_enum_provider.py b/tests/unit/morphing/test_enum_provider.py index a8323b25..49778875 100644 --- a/tests/unit/morphing/test_enum_provider.py +++ b/tests/unit/morphing/test_enum_provider.py @@ -17,13 +17,13 @@ ) from adaptix._internal.morphing.enum_provider import EnumExactValueProvider from adaptix._internal.morphing.load_error import ( - DuplicatedValues, + DuplicatedValuesLoadError, ExcludedTypeLoadError, - MultipleBadVariant, - OutOfRange, + MultipleBadVariantLoadError, + OutOfRangeLoadError, TypeLoadError, ) -from adaptix.load_error import BadVariantError, MsgError +from adaptix.load_error import BadVariantLoadError, MsgLoadError class MyEnum(Enum): @@ -72,17 +72,17 @@ def test_name_provider(strict_coercion, debug_trail): assert loader("V1") == MyEnum.V1 raises_exc( - BadVariantError(['V1'], '1'), + BadVariantLoadError(['V1'], '1'), lambda: loader("1") ) raises_exc( - BadVariantError(['V1'], 1), + BadVariantLoadError(['V1'], 1), lambda: loader(1) ) raises_exc( - BadVariantError(['V1'], MyEnum.V1), + BadVariantLoadError(['V1'], MyEnum.V1), lambda: loader(MyEnum.V1) ) @@ -105,7 +105,7 @@ def test_name_provider_with_mapping(strict_coercion, debug_trail, mapping_option assert loader("v1") == MyEnum.V1 raises_exc( - BadVariantError(["v1"], "V1"), + BadVariantLoadError(["v1"], "V1"), lambda: loader("V1") ) @@ -128,17 +128,17 @@ def test_exact_value_provider(strict_coercion, debug_trail, enum_cls): assert loader("1") == enum_cls.V1 raises_exc( - BadVariantError(['1'], 'V1'), + BadVariantLoadError(['1'], 'V1'), lambda: loader("V1") ) raises_exc( - BadVariantError(['1'], 1), + BadVariantLoadError(['1'], 1), lambda: loader(1) ) raises_exc( - BadVariantError(['1'], enum_cls.V1), + BadVariantLoadError(['1'], enum_cls.V1), lambda: loader(enum_cls.V1) ) @@ -160,12 +160,12 @@ def test_exact_value_provider_int_enum(strict_coercion, debug_trail): assert int_enum_loader(1) == MyIntEnum.V1 raises_exc( - BadVariantError([1], MyEnum.V1), + BadVariantLoadError([1], MyEnum.V1), lambda: int_enum_loader(MyEnum.V1), ) raises_exc( - BadVariantError([1], 'V1'), + BadVariantLoadError([1], 'V1'), lambda: int_enum_loader("V1") ) @@ -196,12 +196,12 @@ def test_value_provider(strict_coercion, debug_trail): assert enum_loader(1) == MyEnum.V1 raises_exc( - MsgError('Bad enum value', "V1"), + MsgLoadError('Bad enum value', "V1"), lambda: enum_loader("V1") ) raises_exc( - MsgError('Bad enum value', MyEnum.V1), + MsgLoadError('Bad enum value', MyEnum.V1), lambda: enum_loader(MyEnum.V1) ) @@ -226,10 +226,10 @@ def test_flag_by_exact_value(strict_coercion, debug_trail): assert dumper(FlagEnum.CASE_ONE | FlagEnum.CASE_FOUR) == 5 raises_exc( - OutOfRange(0, 15, 16), lambda: loader(16) + OutOfRangeLoadError(0, 15, 16), lambda: loader(16) ) raises_exc( - OutOfRange(0, 15, -1), lambda: loader(-1) + OutOfRangeLoadError(0, 15, -1), lambda: loader(-1) ) @@ -310,7 +310,7 @@ def test_flag_by_member_names( variants = ["CASE_ONE", "CASE_TWO", "CASE_FOUR", "CASE_EIGHT"] raises_exc( - MultipleBadVariant( + MultipleBadVariantLoadError( allowed_values=variants, invalid_values=["NOT_EXISTING_CASE_1", "NOT_EXISTING_CASE_2"], input_value=["CASE_ONE", "NOT_EXISTING_CASE_1", "NOT_EXISTING_CASE_2"], @@ -323,7 +323,7 @@ def test_flag_by_member_names( assert loader(data_with_compound) == FlagEnum.CASE_THREE else: raises_exc( - MultipleBadVariant(variants, ["CASE_THREE"], data_with_compound), + MultipleBadVariantLoadError(variants, ["CASE_THREE"], data_with_compound), lambda: loader(data_with_compound) ) @@ -332,7 +332,7 @@ def test_flag_by_member_names( assert loader(data_with_duplicates) == FlagEnum.CASE_ONE else: raises_exc( - DuplicatedValues(data_with_duplicates), + DuplicatedValuesLoadError(data_with_duplicates), lambda: loader(data_with_duplicates) ) @@ -424,7 +424,7 @@ def test_flag_by_member_names_with_mapping(strict_coercion, debug_trail): variants = ["caseFirst", "caseSecond", "caseThree", "caseFour", "caseEight"] raises_exc( - MultipleBadVariant( + MultipleBadVariantLoadError( allowed_values=variants, input_value=["caseThree", "CASE_TWO", "CASE_1"], invalid_values=["CASE_TWO", "CASE_1"]