Skip to content

Commit

Permalink
I hope this will be the last commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Eclips4 committed Aug 7, 2024
1 parent 033ecef commit 5e9f9c4
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 44 deletions.
14 changes: 7 additions & 7 deletions src/adaptix/_internal/morphing/concrete_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ class SecondsTimedeltaProvider(MorphingProvider):

def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
return mediator.cached_call(self._make_loader)

def _make_loader(self):
ok_types = self._OK_TYPES

Expand Down Expand Up @@ -244,13 +244,13 @@ def none_loader(data):
class NoneProvider(MorphingProvider):
def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
return mediator.cached_call(self._make_loader)

def _make_loader(self):
return none_loader

def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
return mediator.cached_call(self._make_dumper)

def _make_dumper(self):
return as_is_stub

Expand Down Expand Up @@ -279,7 +279,7 @@ def _generate_json_schema(self, mediator: Mediator, request: JSONSchemaRequest)
class BytesBase64Provider(_Base64DumperMixin, _Base64JSONSchemaMixin, MorphingProvider):
def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
return mediator.cached_call(self._make_loader)

def _make_loader(self):
def bytes_base64_loader(data):
try:
Expand Down Expand Up @@ -419,7 +419,7 @@ def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
strict_coercion=strict_coercion,
)

def _make_loader(self, strict_coercion: bool):
def _make_loader(self, *, strict_coercion: bool):
return self._strict_coercion_loader if strict_coercion else self._lax_coercion_loader

def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
Expand Down Expand Up @@ -646,11 +646,11 @@ class LiteralStringProvider(MorphingProvider):
def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
strict_coercion = mediator.mandatory_provide(StrictCoercionRequest(loc_stack=request.loc_stack))
return mediator.cached_call(
self._make_loader, # type: ignore[return-value]
self._make_loader,
strict_coercion=strict_coercion,
)

def _make_loader(self, strict_coercion: bool):
def _make_loader(self, *, strict_coercion: bool):
return str_strict_coercion_loader if strict_coercion else str

def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
Expand Down
88 changes: 68 additions & 20 deletions src/adaptix/_internal/morphing/enum_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,14 +108,13 @@ def __init__(self, mapping_generator: BaseEnumMappingGenerator):
self._mapping_generator = mapping_generator

def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
enum = request.last_loc.type
mapping = self._mapping_generator.generate_for_loading(enum.__members__.values())
return mediator.cached_call(
self._make_loader,
mapping=mapping,
enum=request.last_loc.type,
)

def _make_loader(self, mapping: Mapping):

def _make_loader(self, enum):
mapping = self._mapping_generator.generate_for_loading(enum.__members__.values())
variants = list(mapping.keys())

def enum_loader(data):
Expand All @@ -130,12 +129,19 @@ def enum_loader(data):

def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
enum = request.last_loc.type

return mediator.cached_call(
self._make_dumper,
enum=enum,
)

def _make_dumper(self, enum):
mapping = self._mapping_generator.generate_for_dumping(enum.__members__.values())

def enum_dumper(data: Enum) -> str:
return mapping[data]

return mediator.cached_call(lambda: enum_dumper)
return enum_dumper


class EnumValueProvider(BaseEnumProvider):
Expand All @@ -148,35 +154,51 @@ def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
request.append_loc(TypeHintLoc(type=self._value_type)),
)

return mediator.cached_call(
self._make_loader,
enum=enum,
value_loader=value_loader,
)

def _make_loader(self, enum: Enum, value_loader: Loader):
def enum_loader(data):
loaded_value = value_loader(data)
try:
return enum(loaded_value)
except ValueError:
raise MsgLoadError("Bad enum value", data)

return mediator.cached_call(lambda: enum_loader)
return enum_loader

def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
value_dumper = mediator.mandatory_provide(
request.append_loc(TypeHintLoc(type=self._value_type)),
)

return mediator.cached_call(
self._make_dumper,
value_dumper=value_dumper,
)

def _make_dumper(self, value_dumper: Dumper):
def enum_dumper(data):
return value_dumper(data.value)

return mediator.cached_call(lambda: enum_dumper)

return enum_dumper

class EnumExactValueProvider(BaseEnumProvider):
"""This provider represents enum members to the outside world
by their value without any processing
"""

def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
enum = request.last_loc.type
variants = [case.value for case in enum]
return mediator.cached_call(
self._make_loader,
enum=request.last_loc.type,
)

def _make_loader(self, enum):
variants = [case.value for case in enum]
value_to_member = self._get_exact_value_to_member(enum)
if value_to_member is None:
def enum_exact_loader(data):
Expand All @@ -199,7 +221,8 @@ def enum_exact_loader_v2m(data):
except TypeError:
raise BadVariantLoadError(variants, data)

return mediator.cached_call(lambda: enum_exact_loader_v2m)
return enum_exact_loader_v2m


def _get_exact_value_to_member(self, enum: Type[Enum]) -> Optional[Mapping[Any, Any]]:
try:
Expand All @@ -213,17 +236,28 @@ def _get_exact_value_to_member(self, enum: Type[Enum]) -> Optional[Mapping[Any,
return value_to_member

def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
member_to_value = {member: member.value for member in request.last_loc.type}
return mediator.cached_call(
self._make_dumper,
enum=request.last_loc.type,
)

def _make_dumper(self, enum):
member_to_value = {member: member.value for member in enum}

def enum_exact_value_dumper(data):
return member_to_value[data]

return mediator.cached_call(lambda: enum_exact_value_dumper)
return enum_exact_value_dumper


class FlagByExactValueProvider(BaseFlagProvider):
def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
enum = request.last_loc.type
return mediator.cached_call(
self._make_loader,
enum=request.last_loc.type,
)

def _make_loader(self, enum):
flag_mask = reduce(or_, enum.__members__.values()).value

if flag_mask < 0:
Expand Down Expand Up @@ -252,13 +286,16 @@ def flag_loader(data):
# so enum lookup cannot raise an error
return enum(data)

return mediator.cached_call(lambda: flag_loader)
return flag_loader

def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
return mediator.cached_call(self._make_dumper)

def _make_dumper(self):
def flag_exact_value_dumper(data):
return data.value

return mediator.cached_call(lambda: flag_exact_value_dumper)
return flag_exact_value_dumper


def _extract_non_compound_cases_from_flag(enum: Type[FlagT]) -> Sequence[FlagT]:
Expand Down Expand Up @@ -288,6 +325,13 @@ def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
enum = request.last_loc.type

strict_coercion = mediator.mandatory_provide(StrictCoercionRequest(loc_stack=request.loc_stack))
return mediator.cached_call(
self._make_loader,
enum=enum,
strict_coercion=strict_coercion,
)

def _make_loader(self, enum, *, strict_coercion: bool):
allow_single_value = self._allow_single_value
allow_duplicates = self._allow_duplicates

Expand Down Expand Up @@ -332,11 +376,15 @@ def flag_loader(data) -> Flag:

return result

return mediator.cached_call(lambda: flag_loader)
return flag_loader

def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
enum = request.last_loc.type
return mediator.cached_call(
self._make_dumper,
enum=request.last_loc.type,
)

def _make_dumper(self, enum):
cases = self._get_cases(enum)
need_to_reverse = self._allow_compound and cases != _extract_non_compound_cases_from_flag(enum)
if need_to_reverse:
Expand All @@ -355,4 +403,4 @@ def flag_dumper(value: Flag) -> Sequence[str]:
result.append(mapping[case])
return list(reversed(result)) if need_to_reverse else result

return mediator.cached_call(lambda: flag_dumper)
return flag_dumper
57 changes: 40 additions & 17 deletions src/adaptix/_internal/morphing/generic_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,14 @@ def literal_loader(data):

def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
norm = try_normalize_type(request.last_loc.type)
return mediator.cached_call(
self._make_dumper,
norm=norm,
mediator=mediator,
request=request,
)

def _make_dumper(self, norm: BaseNormType, mediator: Mediator, request: DumperRequest):
enum_cases = [arg for arg in norm.args if isinstance(arg, Enum)]

if not enum_cases:
Expand All @@ -213,15 +221,23 @@ def literal_dumper_with_enums(data):
return enum_dumpers[type(data)](data)
return data

return mediator.cached_call(lambda: literal_dumper_with_enums)

return literal_dumper_with_enums

@for_predicate(Union)
class UnionProvider(LoaderProvider, DumperProvider):
def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
norm = try_normalize_type(request.last_loc.type)
debug_trail = mediator.mandatory_provide(DebugTrailRequest(loc_stack=request.loc_stack))

return mediator.cached_call(
self._make_loader,
norm=norm,
debug_trail=debug_trail,
mediator=mediator,
request=request,
)

def _make_loader(self, norm: BaseNormType, debug_trail: DebugTrail, mediator: Mediator, request: LoaderRequest):
if self._is_single_optional(norm):
not_none = next(case for case in norm.args if case.origin is not None)
not_none_loader = mediator.mandatory_provide(
Expand All @@ -234,14 +250,12 @@ def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
lambda x: "Cannot create loader for union. Loaders for some union cases cannot be created",
)
if debug_trail in (DebugTrail.ALL, DebugTrail.FIRST):
return mediator.cached_call(
self._single_optional_dt_loader,
return self._single_optional_dt_loader(
tp=norm.source,
loader=not_none_loader,
)
if debug_trail == DebugTrail.DISABLE:
return mediator.cached_call(
self._single_optional_dt_disable_loader,
return self._single_optional_dt_disable_loader(
loader=not_none_loader,
)
raise ValueError
Expand All @@ -259,11 +273,11 @@ def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
lambda: "Cannot create loader for union. Loaders for some union cases cannot be created",
)
if debug_trail == DebugTrail.DISABLE:
return mediator.cached_call(self._get_loader_dt_disable, loader_iter=tuple(loaders))
return self._get_loader_dt_disable(loader_iter=tuple(loaders))
if debug_trail == DebugTrail.FIRST:
return mediator.cached_call(self._get_loader_dt_first, tp=norm.source, loader_iter=tuple(loaders))
return self._get_loader_dt_first(tp=norm.source, loader_iter=tuple(loaders))
if debug_trail == DebugTrail.ALL:
return mediator.cached_call(self._get_loader_dt_all, tp=norm.source, loader_iter=tuple(loaders))
return self._get_loader_dt_all(tp=norm.source, loader_iter=tuple(loaders))
raise ValueError

def _single_optional_dt_disable_loader(self, loader: Loader) -> Loader:
Expand Down Expand Up @@ -341,6 +355,14 @@ def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
request_type = request.last_loc.type
norm = try_normalize_type(request_type)

return mediator.cached_call(
self._make_dumper,
norm=norm,
mediator=mediator,
request=request,
)

def _make_dumper(self, norm: BaseNormType, mediator: Mediator, request: DumperRequest):
if self._is_single_optional(norm):
not_none = next(case for case in norm.args if case.origin is not None)
not_none_dumper = mediator.mandatory_provide(
Expand All @@ -353,9 +375,8 @@ def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
lambda x: "Cannot create dumper for union. Dumpers for some union cases cannot be created",
)
if not_none_dumper == as_is_stub:
return mediator.cached_call(lambda: as_is_stub)
return mediator.cached_call(
self._get_single_optional_dumper,
return as_is_stub
return self._get_single_optional_dumper(
dumper=not_none_dumper,
)

Expand Down Expand Up @@ -385,7 +406,7 @@ def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
lambda: "Cannot create dumper for union. Dumpers for some union cases cannot be created",
)
if all(dumper == as_is_stub for dumper in dumpers):
return mediator.cached_call(lambda: as_is_stub)
return as_is_stub

dumper_type_dispatcher = ClassDispatcher(
{type(None) if case.origin is None else case.origin: dumper for case, dumper in zip(norm.args, dumpers)},
Expand All @@ -394,10 +415,9 @@ def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
literal_dumper = self._get_dumper_for_literal(norm, dumpers, dumper_type_dispatcher)

if literal_dumper:
return mediator.cached_call(lambda: literal_dumper)
return literal_dumper

return mediator.cached_call(
self._produce_dumper,
return self._produce_dumper(
dumper_type_dispatcher=dumper_type_dispatcher,
)

Expand Down Expand Up @@ -464,4 +484,7 @@ def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
)

def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
return mediator.cached_call(lambda: path_like_dumper)
return mediator.cached_call(self._make_dumper)

def _make_dumper(self):
return path_like_dumper

0 comments on commit 5e9f9c4

Please sign in to comment.