Skip to content

Commit

Permalink
facades for flag provider
Browse files Browse the repository at this point in the history
  • Loading branch information
daler-sz committed Jan 22, 2024
1 parent 2f515d3 commit 95b53bd
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 4 deletions.
4 changes: 4 additions & 0 deletions src/adaptix/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
enum_by_exact_value,
enum_by_name,
enum_by_value,
flag_by_list_using_exact_value,
flag_by_list_using_name,
loader,
name_mapping,
validator,
Expand Down Expand Up @@ -60,6 +62,8 @@
'enum_by_value',
'name_mapping',
'AdornedRetort',
'flag_by_list_using_name',
'flag_by_list_using_exact_value',
'FilledRetort',
'Retort',
'TypedDictAt38Warning',
Expand Down
8 changes: 7 additions & 1 deletion src/adaptix/_internal/morphing/enum_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from ..common import Dumper, Loader, TypeHint
from ..morphing.provider_template import DumperProvider, LoaderProvider
from ..name_style import NameStyle, convert_snake_style
from ..provider.essential import Mediator
from ..provider.essential import CannotProvide, Mediator
from ..provider.loc_stack_filtering import DirectMediator, LastLocMapChecker
from ..provider.provider_template import for_predicate
from ..provider.request_cls import LocMap, TypeHintLoc, get_type_from_request
Expand Down Expand Up @@ -262,6 +262,9 @@ def _get_loader_process_data(self, data, enum):
def _provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
enum = get_type_from_request(request)

if not issubclass(enum, Flag):
raise CannotProvide

def _flag_loader(data: Union[int, Iterable[int], Iterable[str]]) -> Flag:
process_data = self._get_loader_process_data(data, enum)
cases = self._get_cases(enum)
Expand Down Expand Up @@ -289,6 +292,9 @@ def _flag_loader(data: Union[int, Iterable[int], Iterable[str]]) -> Flag:
def _provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
enum = get_type_from_request(request)

if not issubclass(enum, Flag):
raise CannotProvide

def flag_dumper(value: Flag) -> Iterable[Hashable]:
cases = self._get_cases(enum)
mapping = self._mapping_generator.generate_for_dumping(cases)
Expand Down
76 changes: 75 additions & 1 deletion src/adaptix/_internal/morphing/facade/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,14 @@
from ...provider.shape_provider import PropertyExtender
from ...special_cases_optimization import as_is_stub
from ...utils import Omittable, Omitted
from ..enum_provider import EnumExactValueProvider, EnumNameProvider, EnumValueProvider
from ..enum_provider import (
EnumExactValueProvider,
EnumNameProvider,
EnumValueProvider,
ExactValueEnumMappingGenerator,
FlagProvider,
NameEnumMappingGenerator,
)
from ..load_error import LoadError, ValidationError
from ..model.loader_provider import InlinedShapeModelLoaderProvider
from ..name_layout.base import ExtraIn, ExtraOut
Expand Down Expand Up @@ -349,6 +356,73 @@ def enum_by_value(first_pred: EnumPred, /, *preds: EnumPred, tp: TypeHint) -> Pr
return _wrap_enum_provider([first_pred, *preds], EnumValueProvider(tp))


def flag_by_list_using_name(
*preds: EnumPred,
allow_single_value: bool = False,
allow_duplicates: bool = True,
allow_compound: bool = True,
name_style: Optional[NameStyle] = None,
map: Optional[Mapping[Union[str, Enum], str]] = None # noqa: A002
) -> Provider:
"""Provider that represents flag members to the outside world by their name.
:param preds: Predicates specifying where the provider should be used.
The provider will be applied if any predicates meet the conditions,
if no predicates are passed, the provider will be used for all Flags.
See :ref:`predicate-system` for details.
:param allow_single_value: Specifies if it is allowed to call loader by single value.
If it is allowed and loader called by single value, it will be interpreted as a list with single element.
:param allow_duplicates: Specifies if it is allowed to call loader by list with non-unique elements.
If it is not allowed and loader by list with non-unique elements, ValueError will be raised.
:param allow_compound: Specifies if it is allowed for loader to accept compound values and
if it is allowed for dumper to return compound values.
:param name_style: Name style that represents values to the outside world
:param map: Mapping for values to represent them to the outside world
:return: desired provider
"""
return _wrap_enum_provider(
preds,
FlagProvider(
NameEnumMappingGenerator(name_style=name_style, map=map),
allow_single_value,
allow_duplicates,
allow_compound
),
)


def flag_by_list_using_exact_value(
*preds: EnumPred,
allow_single_value: bool = False,
allow_duplicates: bool = True,
allow_compound: bool = True,
) -> Provider:
"""Provider that represents flag members to the outside world by their exact values.
:param preds: Predicates specifying where the provider should be used.
The provider will be applied if any predicates meet the conditions,
if no predicates are passed, the provider will be used for all Flags.
See :ref:`predicate-system` for details.
:param allow_single_value: Specifies if it is allowed to call loader by single value.
If it is allowed and loader called by single value, it will be interpreted as a list with single element,
otherwise TypeLoadError will be raised
:param allow_duplicates: Specifies if it is allowed to call loader by list with non-unique elements.
If it is not allowed and loader by list with non-unique elements, ValueError will be raised.
:param allow_compound: Specifies if it is allowed for loader to accept compound values and
allowed for dumper to return compound values.
:return: desired provider
"""
return _wrap_enum_provider(
preds,
FlagProvider(
ExactValueEnumMappingGenerator(),
allow_single_value,
allow_duplicates,
allow_compound
),
)


def validator(
pred: Pred,
func: Callable[[Any], bool],
Expand Down
3 changes: 1 addition & 2 deletions src/adaptix/_internal/morphing/facade/retort.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
)
from ..constant_length_tuple_provider import ConstantLengthTupleProvider
from ..dict_provider import DictProvider
from ..enum_provider import EnumExactValueProvider, FlagProvider, NameEnumMappingGenerator
from ..enum_provider import EnumExactValueProvider
from ..generic_provider import (
LiteralProvider,
NewTypeUnwrappingProvider,
Expand Down Expand Up @@ -80,7 +80,6 @@ class FilledRetort(OperatingRetort, ABC):
SecondsTimedeltaProvider(),

EnumExactValueProvider(), # it has higher priority than scalar types for Enum with mixins
FlagProvider(NameEnumMappingGenerator()),

INT_LOADER_PROVIDER,
as_is_dumper(int),
Expand Down

0 comments on commit 95b53bd

Please sign in to comment.