Skip to content

Commit

Permalink
First satisfactory attempt at refactoring the provider routing system
Browse files Browse the repository at this point in the history
  • Loading branch information
zhPavel committed Jun 18, 2024
1 parent 2e67d8e commit 3064682
Show file tree
Hide file tree
Showing 56 changed files with 1,066 additions and 1,042 deletions.
2 changes: 1 addition & 1 deletion src/adaptix/_internal/conversion/coercer_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
from typing import Any, Callable, Tuple, Union, final

from ..common import Coercer, OneArgCoercer, TypeHint
from ..morphing.utils import try_normalize_type
from ..provider.essential import CannotProvide, Mediator
from ..provider.loc_stack_filtering import LocStackChecker
from ..provider.location import GenericParamLoc
from ..provider.request_cls import try_normalize_type
from ..special_cases_optimization import as_is_stub, as_is_stub_with_ctx
from ..type_tools import BaseNormType, is_generic, is_parametrized, is_subclass_soft, normalize_type, strip_tags
from .provider_template import CoercerProvider
Expand Down
4 changes: 2 additions & 2 deletions src/adaptix/_internal/conversion/converter_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
from ..model_tools.definitions import DefaultValue, NoDefault
from ..morphing.model.basic_gen import compile_closure_with_globals_capturing, fetch_code_gen_hook
from ..provider.essential import CannotProvide, Mediator
from ..provider.location import FieldLoc
from ..provider.request_cls import LocStack, TypeHintLoc
from ..provider.loc_stack_filtering import LocStack
from ..provider.location import FieldLoc, TypeHintLoc
from .provider_template import ConverterProvider


Expand Down
2 changes: 1 addition & 1 deletion src/adaptix/_internal/conversion/linking_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from ..provider.essential import CannotProvide, Mediator, mandatory_apply_by_iterable
from ..provider.fields import input_field_to_loc
from ..provider.loc_stack_filtering import LocStackChecker
from ..provider.loc_stack_tools import format_loc_stack
from ..provider.location import FieldLoc
from ..provider.request_cls import format_loc_stack
from ..utils import add_note
from .provider_template import LinkingProvider
from .request_cls import (
Expand Down
2 changes: 1 addition & 1 deletion src/adaptix/_internal/conversion/model_coercer_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@
from ..morphing.model.basic_gen import compile_closure_with_globals_capturing, fetch_code_gen_hook
from ..provider.essential import CannotProvide, Mediator, mandatory_apply_by_iterable
from ..provider.fields import input_field_to_loc, output_field_to_loc
from ..provider.loc_stack_filtering import LocStack
from ..provider.location import AnyLoc, InputFieldLoc, InputFuncFieldLoc, OutputFieldLoc
from ..provider.request_cls import LocStack
from ..provider.shape_provider import InputShapeRequest, OutputShapeRequest, provide_generic_resolved_shape
from ..utils import add_note
from .provider_template import CoercerProvider
Expand Down
6 changes: 3 additions & 3 deletions src/adaptix/_internal/conversion/policy_provider.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
from ..provider.essential import Mediator
from ..provider.static_provider import StaticProvider, static_provision_action
from ..provider.methods_provider import MethodsProvider, method_handler
from .request_cls import UnlinkedOptionalPolicy, UnlinkedOptionalPolicyRequest


class UnlinkedOptionalPolicyProvider(StaticProvider):
class UnlinkedOptionalPolicyProvider(MethodsProvider):
def __init__(self, *, is_allowed: bool):
self._is_allowed = is_allowed

@static_provision_action
@method_handler
def _unlinked_optional_policy(
self,
mediator: Mediator,
Expand Down
14 changes: 7 additions & 7 deletions src/adaptix/_internal/conversion/provider_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@

from ..common import Coercer, Converter
from ..provider.essential import Mediator
from ..provider.static_provider import StaticProvider, static_provision_action
from ..provider.methods_provider import MethodsProvider, method_handler
from .request_cls import CoercerRequest, ConverterRequest, LinkingRequest, LinkingResult


class ConverterProvider(StaticProvider, ABC):
class ConverterProvider(MethodsProvider, ABC):
@final
@static_provision_action
@method_handler
def _outer_provide_converter(self, mediator: Mediator, request: ConverterRequest):
return self._provide_converter(mediator, request)

Expand All @@ -18,15 +18,15 @@ def _provide_converter(self, mediator: Mediator, request: ConverterRequest) -> C
...


class CoercerProvider(StaticProvider, ABC):
@static_provision_action
class CoercerProvider(MethodsProvider, ABC):
@method_handler
@abstractmethod
def _provide_coercer(self, mediator: Mediator, request: CoercerRequest) -> Coercer:
...


class LinkingProvider(StaticProvider, ABC):
@static_provision_action
class LinkingProvider(MethodsProvider, ABC):
@method_handler
@abstractmethod
def _provide_linking(self, mediator: Mediator, request: LinkingRequest) -> LinkingResult:
...
3 changes: 2 additions & 1 deletion src/adaptix/_internal/conversion/request_cls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
from ..common import Coercer, VarTuple
from ..model_tools.definitions import DefaultFactory, DefaultValue, InputField, ParamKind
from ..provider.essential import Request
from ..provider.loc_stack_basis import LocatedRequest
from ..provider.loc_stack_filtering import LocStack
from ..provider.location import FieldLoc, GenericParamLoc, InputFieldLoc, InputFuncFieldLoc, OutputFieldLoc, TypeHintLoc
from ..provider.request_cls import LocatedRequest, LocStack


@dataclass(frozen=True)
Expand Down
3 changes: 1 addition & 2 deletions src/adaptix/_internal/conversion/request_filtering.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from adaptix._internal.provider.loc_stack_filtering import DirectMediator, LocStackChecker
from adaptix._internal.provider.request_cls import LocStack
from adaptix._internal.provider.loc_stack_filtering import DirectMediator, LocStack, LocStackChecker


class FromCtxParam(LocStackChecker):
Expand Down
4 changes: 2 additions & 2 deletions src/adaptix/_internal/integrations/pydantic/native.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def __init__(
def _skip_omitted(self, mapping: Mapping[str, T]) -> Mapping[str, T]:
return {k: v for k, v in mapping.items() if v != Omitted()}

def _provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
validation_params = self._skip_omitted(self._validation_params)
validator = TypeAdapter(request.last_loc.type, config=self._config).validator.validate_python

Expand All @@ -54,7 +54,7 @@ def native_pydantic_loader(data):

return native_pydantic_loader

def _provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
serialization_params = self._skip_omitted(self._serialization_params)
serializer = TypeAdapter(request.last_loc.type, config=self._config).serializer.to_python

Expand Down
64 changes: 33 additions & 31 deletions src/adaptix/_internal/morphing/concrete_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,13 @@
from ..common import Dumper, Loader
from ..feature_requirement import HAS_PY_311, HAS_SELF_TYPE
from ..provider.essential import CannotProvide, Mediator
from ..provider.loc_stack_basis import LocatedRequest, for_predicate
from ..provider.loc_stack_filtering import P, create_loc_stack_checker
from ..provider.provider_template import for_predicate
from ..provider.request_cls import LocatedRequest, StrictCoercionRequest, find_owner_with_field
from ..provider.static_provider import static_provision_action
from ..provider.loc_stack_tools import find_owner_with_field
from ..special_cases_optimization import as_is_stub
from .load_error import FormatMismatchLoadError, TypeLoadError, ValueLoadError
from .provider_template import DumperProvider, LoaderProvider, ProviderWithAttachableLSC
from .request_cls import DumperRequest, LoaderRequest
from .provider_template import DumperProvider, LoaderProvider
from .request_cls import DumperRequest, LoaderRequest, StrictCoercionRequest

T = TypeVar("T")

Expand All @@ -31,7 +30,7 @@ class IsoFormatProvider(LoaderProvider, DumperProvider):
def __post_init__(self):
self._loc_stack_checker = create_loc_stack_checker(self.cls)

def _provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
raw_loader = self.cls.fromisoformat

def isoformat_loader(data):
Expand All @@ -44,7 +43,7 @@ def isoformat_loader(data):

return isoformat_loader

def _provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
return self.cls.isoformat


Expand All @@ -53,7 +52,7 @@ def _provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
class DatetimeFormatProvider(LoaderProvider, DumperProvider):
format: str

def _provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
fmt = self.format

def datetime_format_loader(data):
Expand All @@ -66,7 +65,7 @@ def datetime_format_loader(data):

return datetime_format_loader

def _provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
fmt = self.format

def datetime_format_dumper(data: datetime):
Expand All @@ -79,7 +78,7 @@ def datetime_format_dumper(data: datetime):
class SecondsTimedeltaProvider(LoaderProvider, DumperProvider):
_OK_TYPES = (int, float, Decimal)

def _provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
ok_types = self._OK_TYPES

def timedelta_loader(data):
Expand All @@ -89,7 +88,7 @@ def timedelta_loader(data):

return timedelta_loader

def _provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
return timedelta.total_seconds


Expand All @@ -101,15 +100,15 @@ def none_loader(data):

@for_predicate(None)
class NoneProvider(LoaderProvider, DumperProvider):
def _provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
return none_loader

def _provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
return as_is_stub


class Base64DumperMixin(DumperProvider):
def _provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
def bytes_base64_dumper(data):
return b2a_base64(data, newline=False).decode("ascii")

Expand All @@ -121,7 +120,7 @@ def bytes_base64_dumper(data):

@for_predicate(bytes)
class BytesBase64Provider(LoaderProvider, Base64DumperMixin):
def _provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
def bytes_base64_loader(data):
try:
encoded = data.encode("ascii")
Expand All @@ -141,15 +140,15 @@ def bytes_base64_loader(data):

@for_predicate(BytesIO)
class BytesIOBase64Provider(BytesBase64Provider):
def _provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
bytes_base64_loader = super()._provide_loader(mediator, request)
def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
bytes_base64_loader = super().provide_loader(mediator, request)

def bytes_io_base64_loader(data):
return BytesIO(bytes_base64_loader(data))

return bytes_io_base64_loader

def _provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
def bytes_io_base64_dumper(data: BytesIO):
return b2a_base64(data.getvalue(), newline=False).decode("ascii")

Expand All @@ -158,7 +157,7 @@ def bytes_io_base64_dumper(data: BytesIO):

@for_predicate(typing.IO[bytes])
class IOBytesBase64Provider(BytesIOBase64Provider):
def _provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
def io_bytes_base64_dumper(data: typing.IO[bytes]):
if data.seekable():
data.seek(0)
Expand All @@ -172,8 +171,8 @@ def io_bytes_base64_dumper(data: typing.IO[bytes]):
class BytearrayBase64Provider(LoaderProvider, Base64DumperMixin):
_BYTES_PROVIDER = BytesBase64Provider()

def _provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
bytes_loader = self._BYTES_PROVIDER.apply_provider(
def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
bytes_loader = self._BYTES_PROVIDER.provide_loader(
mediator,
replace(request, loc_stack=request.loc_stack.replace_last_type(bytes)),
)
Expand All @@ -193,7 +192,7 @@ class RegexPatternProvider(LoaderProvider, DumperProvider):
def __init__(self, flags: re.RegexFlag = re.RegexFlag(0)):
self.flags = flags

def _provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
flags = self.flags
re_compile = re.compile

Expand All @@ -208,7 +207,7 @@ def regex_loader(data):

return regex_loader

def _provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
return _regex_dumper


Expand All @@ -219,7 +218,7 @@ def __init__(self, pred: Type[T], strict_coercion_loader: Loader[T], lax_coercio
self._strict_coercion_loader = strict_coercion_loader
self._lax_coercion_loader = lax_coercion_loader

def _provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
strict_coercion = mediator.mandatory_provide(StrictCoercionRequest(loc_stack=request.loc_stack))
return self._strict_coercion_loader if strict_coercion else self._lax_coercion_loader

Expand Down Expand Up @@ -383,11 +382,8 @@ def complex_lax_coercion_loader(data):


@for_predicate(typing.Self if HAS_SELF_TYPE else ~P.ANY)
class SelfTypeProvider(ProviderWithAttachableLSC):
@static_provision_action
def _provide_substitute(self, mediator: Mediator, request: LocatedRequest) -> Loader:
self._apply_loc_stack_checker(mediator, request)

class SelfTypeProvider(LoaderProvider, DumperProvider):
def _substituting_provide(self, mediator: Mediator, request: LocatedRequest) -> Loader:
try:
owner_loc, _field_loc = find_owner_with_field(request.loc_stack)
except ValueError:
Expand All @@ -404,12 +400,18 @@ def _provide_substitute(self, mediator: Mediator, request: LocatedRequest) -> Lo
),
)

def provide_loader(self, mediator: Mediator[Loader], request: LoaderRequest) -> Loader:
return self._substituting_provide(mediator, request)

def provide_dumper(self, mediator: Mediator[Dumper], request: DumperRequest) -> Dumper:
return self._substituting_provide(mediator, request)


@for_predicate(typing.LiteralString if HAS_PY_311 else ~P.ANY)
class LiteralStringProvider(LoaderProvider, DumperProvider):
def _provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
strict_coercion = mediator.mandatory_provide(StrictCoercionRequest(loc_stack=request.loc_stack))
return str_strict_coercion_loader if strict_coercion else str # type: ignore[return-value]

def _provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
return as_is_stub
11 changes: 6 additions & 5 deletions src/adaptix/_internal/morphing/constant_length_tuple_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
from ..definitions import DebugTrail
from ..feature_requirement import HAS_UNPACK
from ..provider.essential import CannotProvide, Mediator
from ..provider.loc_stack_basis import for_predicate
from ..provider.loc_stack_tools import get_type_from_request
from ..provider.location import GenericParamLoc
from ..provider.provider_template import for_predicate
from ..provider.request_cls import DebugTrailRequest, StrictCoercionRequest, get_type_from_request, try_normalize_type
from ..struct_trail import append_trail, render_trail_as_note
from .load_error import (
AggregateLoadError,
Expand All @@ -21,14 +21,15 @@
TypeLoadError,
)
from .provider_template import DumperProvider, LoaderProvider
from .request_cls import DumperRequest, LoaderRequest
from .request_cls import DebugTrailRequest, DumperRequest, LoaderRequest, StrictCoercionRequest
from .utils import try_normalize_type

CollectionsMapping = collections.abc.Mapping


@for_predicate(Tuple)
class ConstantLengthTupleProvider(LoaderProvider, DumperProvider):
def _provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
def provide_loader(self, mediator: Mediator, request: LoaderRequest) -> Loader:
norm = try_normalize_type(get_type_from_request(request))
if len(norm.args) > 1 and norm.args[1] == Ellipsis:
raise CannotProvide
Expand Down Expand Up @@ -214,7 +215,7 @@ def dt_disable_sc_loader(data):

return dt_disable_sc_loader

def _provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
def provide_dumper(self, mediator: Mediator, request: DumperRequest) -> Dumper:
norm = try_normalize_type(get_type_from_request(request))
if len(norm.args) > 1 and norm.args[1] == Ellipsis:
raise CannotProvide
Expand Down
Loading

0 comments on commit 3064682

Please sign in to comment.