From 0a3b1737f58d7c66157dedf91dc6869d28e9c7e3 Mon Sep 17 00:00:00 2001 From: Andrey Tikhonov <17@itishka.org> Date: Sun, 29 Sep 2024 20:27:23 +0200 Subject: [PATCH] bump adaptix to v3.0.0b8 --- src/dishka/_adaptix/common.py | 6 +- src/dishka/_adaptix/feature_requirement.py | 13 ++--- src/dishka/_adaptix/type_tools/__init__.py | 1 + src/dishka/_adaptix/type_tools/basic_utils.py | 24 +++----- src/dishka/_adaptix/type_tools/constants.py | 3 +- .../_adaptix/type_tools/fundamentals.py | 9 +-- .../_adaptix/type_tools/generic_resolver.py | 7 ++- .../_adaptix/type_tools/implicit_params.py | 4 +- src/dishka/_adaptix/type_tools/norm_utils.py | 15 +---- .../_adaptix/type_tools/normalize_type.py | 56 ++++++++----------- 10 files changed, 55 insertions(+), 83 deletions(-) diff --git a/src/dishka/_adaptix/common.py b/src/dishka/_adaptix/common.py index bae88ea4..ee3be802 100644 --- a/src/dishka/_adaptix/common.py +++ b/src/dishka/_adaptix/common.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, Any, Callable, Tuple, Type, TypeVar, Union +from typing import TYPE_CHECKING, Any, Callable, TypeVar, Union K_contra = TypeVar("K_contra", contravariant=True) V_co = TypeVar("V_co", covariant=True) @@ -12,9 +12,9 @@ TypeHint = Any -VarTuple = Tuple[T, ...] +VarTuple = tuple[T, ...] -Catchable = Union[Type[BaseException], VarTuple[Type[BaseException]]] +Catchable = Union[type[BaseException], VarTuple[type[BaseException]]] # https://github.com/python/typing/issues/684#issuecomment-548203158 if TYPE_CHECKING: diff --git a/src/dishka/_adaptix/feature_requirement.py b/src/dishka/_adaptix/feature_requirement.py index ea10c9cb..613f06e8 100644 --- a/src/dishka/_adaptix/feature_requirement.py +++ b/src/dishka/_adaptix/feature_requirement.py @@ -3,7 +3,8 @@ import re import sys from abc import ABC, abstractmethod -from typing import Any, Iterable +from collections.abc import Iterable +from typing import Any from .common import VarTuple @@ -17,11 +18,11 @@ def _false(): class Requirement(ABC): - __slots__ = ("is_meet", "__bool__", "__dict__") + __slots__ = ("is_met", "__bool__", "__dict__") def __init__(self): - self.is_meet = self._evaluate() - self.__bool__ = _true if self.is_meet else _false + self.is_met = self._evaluate() + self.__bool__ = _true if self.is_met else _false @abstractmethod def _evaluate(self) -> bool: @@ -148,10 +149,6 @@ def fail_reason(self) -> str: return f"{self.implementation_name} is required" -HAS_PY_39 = PythonVersionRequirement((3, 9)) -HAS_ANNOTATED = HAS_PY_39 -HAS_STD_CLASSES_GENERICS = HAS_PY_39 - HAS_PY_310 = PythonVersionRequirement((3, 10)) HAS_TYPE_UNION_OP = HAS_PY_310 HAS_TYPE_GUARD = HAS_PY_310 diff --git a/src/dishka/_adaptix/type_tools/__init__.py b/src/dishka/_adaptix/type_tools/__init__.py index 79d25e62..989ebf70 100644 --- a/src/dishka/_adaptix/type_tools/__init__.py +++ b/src/dishka/_adaptix/type_tools/__init__.py @@ -23,3 +23,4 @@ make_norm_type, normalize_type, ) +from .type_evaler import exec_type_checking, make_fragments_collector diff --git a/src/dishka/_adaptix/type_tools/basic_utils.py b/src/dishka/_adaptix/type_tools/basic_utils.py index 198b8aca..beedeedb 100644 --- a/src/dishka/_adaptix/type_tools/basic_utils.py +++ b/src/dishka/_adaptix/type_tools/basic_utils.py @@ -1,9 +1,9 @@ import types import typing -from typing import Any, Dict, ForwardRef, Generic, NewType, Protocol, TypedDict, TypeVar, Union +from typing import Annotated, Any, ForwardRef, Generic, NewType, Protocol, TypedDict, TypeVar, Union from ..common import TypeHint, VarTuple -from ..feature_requirement import HAS_ANNOTATED, HAS_PY_39, HAS_PY_312, HAS_STD_CLASSES_GENERICS +from ..feature_requirement import HAS_PY_312 from .constants import BUILTIN_ORIGIN_TO_TYPEVARS from .fundamentals import get_generic_args, get_type_vars, strip_alias @@ -81,16 +81,12 @@ def is_generic(tp: TypeHint) -> bool: bool(get_type_vars(tp)) or ( strip_alias(tp) in BUILTIN_ORIGIN_TO_TYPEVARS - and tp != type + and tp is not type and not is_parametrized(tp) - and ( - bool(HAS_STD_CLASSES_GENERICS) or not isinstance(tp, type) - ) ) or ( - bool(HAS_ANNOTATED) - and strip_alias(tp) == typing.Annotated - and tp != typing.Annotated + strip_alias(tp) == Annotated + and tp != Annotated and is_generic(tp.__origin__) ) ) @@ -129,7 +125,7 @@ def get_type_vars_of_parametrized(tp: TypeHint) -> VarTuple[TypeVar]: if not params: return () if isinstance(tp, type): - if HAS_STD_CLASSES_GENERICS and isinstance(tp, types.GenericAlias): + if isinstance(tp, types.GenericAlias): return params return () if strip_alias(tp) != tp and get_generic_args(tp) == (): @@ -137,9 +133,5 @@ def get_type_vars_of_parametrized(tp: TypeHint) -> VarTuple[TypeVar]: return params -if HAS_PY_39: - def eval_forward_ref(namespace: Dict[str, Any], forward_ref: ForwardRef): - return forward_ref._evaluate(namespace, None, frozenset()) -else: - def eval_forward_ref(namespace: Dict[str, Any], forward_ref: ForwardRef): - return forward_ref._evaluate(namespace, None) # type: ignore[call-arg] +def eval_forward_ref(namespace: dict[str, Any], forward_ref: ForwardRef): + return forward_ref._evaluate(namespace, None, recursive_guard=frozenset()) diff --git a/src/dishka/_adaptix/type_tools/constants.py b/src/dishka/_adaptix/type_tools/constants.py index e2963997..b6a13ebf 100644 --- a/src/dishka/_adaptix/type_tools/constants.py +++ b/src/dishka/_adaptix/type_tools/constants.py @@ -3,8 +3,9 @@ import concurrent.futures import queue import re +from collections.abc import Mapping from os import PathLike -from typing import Mapping, TypeVar +from typing import TypeVar from ..common import VarTuple diff --git a/src/dishka/_adaptix/type_tools/fundamentals.py b/src/dishka/_adaptix/type_tools/fundamentals.py index f83bfc3b..0a403805 100644 --- a/src/dishka/_adaptix/type_tools/fundamentals.py +++ b/src/dishka/_adaptix/type_tools/fundamentals.py @@ -2,7 +2,7 @@ from typing import TypeVar, get_args, get_origin, get_type_hints from ..common import TypeHint, VarTuple -from ..feature_requirement import HAS_ANNOTATED, HAS_SUPPORTED_PYDANTIC_PKG +from ..feature_requirement import HAS_SUPPORTED_PYDANTIC_PKG __all__ = ("is_pydantic_class", "strip_alias", "get_type_vars", "get_generic_args", "get_all_type_hints") @@ -41,8 +41,5 @@ def get_generic_args(tp: TypeHint) -> VarTuple[TypeHint]: return get_args(tp) -if HAS_ANNOTATED: - def get_all_type_hints(obj, globalns=None, localns=None): - return get_type_hints(obj, globalns, localns, include_extras=True) -else: - get_all_type_hints = get_type_hints +def get_all_type_hints(obj, globalns=None, localns=None): + return get_type_hints(obj, globalns, localns, include_extras=True) diff --git a/src/dishka/_adaptix/type_tools/generic_resolver.py b/src/dishka/_adaptix/type_tools/generic_resolver.py index 90233a31..3f8c7347 100644 --- a/src/dishka/_adaptix/type_tools/generic_resolver.py +++ b/src/dishka/_adaptix/type_tools/generic_resolver.py @@ -1,12 +1,13 @@ import typing +from collections.abc import Collection, Hashable, Mapping from dataclasses import dataclass, replace from itertools import chain -from typing import Callable, Collection, Dict, Generic, Hashable, Mapping, TypeVar +from typing import Callable, Generic, TypeVar from ..common import TypeHint from ..feature_requirement import HAS_TV_TUPLE, HAS_UNPACK -from . import get_generic_args from .basic_utils import get_type_vars, get_type_vars_of_parametrized, is_generic, is_parametrized, strip_alias +from .fundamentals import get_generic_args from .implicit_params import fill_implicit_params from .normalize_type import normalize_type @@ -85,7 +86,7 @@ def _get_members_by_parents(self, tp) -> MembersStorage[K, M]: if not hasattr(tp, "__orig_bases__"): return members_storage - bases_members: Dict[K, TypeHint] = {} + bases_members: dict[K, TypeHint] = {} for base in reversed(tp.__orig_bases__): bases_members.update(self.get_resolved_members(base).members) diff --git a/src/dishka/_adaptix/type_tools/implicit_params.py b/src/dishka/_adaptix/type_tools/implicit_params.py index 99f4fff5..34c45e96 100644 --- a/src/dishka/_adaptix/type_tools/implicit_params.py +++ b/src/dishka/_adaptix/type_tools/implicit_params.py @@ -1,6 +1,6 @@ import sys import typing -from typing import Any, ForwardRef, Tuple, TypeVar +from typing import Any, ForwardRef, TypeVar from ..common import TypeHint, VarTuple from ..feature_requirement import HAS_PARAM_SPEC, HAS_TV_TUPLE @@ -18,7 +18,7 @@ def _process_type_var(self, type_var) -> TypeHint: if HAS_PARAM_SPEC and isinstance(type_var, typing.ParamSpec): return ... if HAS_TV_TUPLE and isinstance(type_var, typing.TypeVarTuple): - return typing.Unpack[Tuple[Any, ...]] + return typing.Unpack[tuple[Any, ...]] if type_var.__constraints__: return create_union( tuple( diff --git a/src/dishka/_adaptix/type_tools/norm_utils.py b/src/dishka/_adaptix/type_tools/norm_utils.py index 4a414439..a3aeaa5d 100644 --- a/src/dishka/_adaptix/type_tools/norm_utils.py +++ b/src/dishka/_adaptix/type_tools/norm_utils.py @@ -1,14 +1,11 @@ import typing from dataclasses import InitVar -from typing import ClassVar, Final, TypeVar +from typing import Annotated, ClassVar, Final, TypeVar -from ..feature_requirement import HAS_ANNOTATED, HAS_TYPED_DICT_REQUIRED +from ..feature_requirement import HAS_TYPED_DICT_REQUIRED from .normalize_type import BaseNormType -_TYPE_TAGS = [Final, ClassVar, InitVar] - -if HAS_ANNOTATED: - _TYPE_TAGS.append(typing.Annotated) +_TYPE_TAGS = [Final, ClassVar, InitVar, Annotated] if HAS_TYPED_DICT_REQUIRED: _TYPE_TAGS.extend([typing.Required, typing.NotRequired]) @@ -26,12 +23,6 @@ def strip_tags(norm: BaseNormType) -> BaseNormType: N = TypeVar("N", bound=BaseNormType) -def strip_annotated(value: N) -> N: - if HAS_ANNOTATED and isinstance(value, BaseNormType) and value.origin == typing.Annotated: - return strip_annotated(value) - return value - - def is_class_var(norm: BaseNormType) -> bool: if norm.origin == ClassVar: return True diff --git a/src/dishka/_adaptix/type_tools/normalize_type.py b/src/dishka/_adaptix/type_tools/normalize_type.py index 34e8b142..201dae0c 100644 --- a/src/dishka/_adaptix/type_tools/normalize_type.py +++ b/src/dishka/_adaptix/type_tools/normalize_type.py @@ -1,32 +1,26 @@ -# ruff: noqa: RET503 +# ruff: noqa: RET503, UP006 import dataclasses import sys import types import typing from abc import ABC, abstractmethod from collections import abc as c_abc, defaultdict +from collections.abc import Hashable, Iterable, Sequence from copy import copy from dataclasses import InitVar, dataclass from enum import Enum, EnumMeta from functools import lru_cache, partial from typing import ( + Annotated, Any, Callable, ClassVar, - DefaultDict, - Dict, Final, ForwardRef, - Hashable, - Iterable, - List, Literal, NewType, NoReturn, Optional, - Sequence, - Tuple, - Type, TypeVar, Union, overload, @@ -34,7 +28,6 @@ from ..common import TypeHint, VarTuple from ..feature_requirement import ( - HAS_ANNOTATED, HAS_PARAM_SPEC, HAS_PY_310, HAS_PY_311, @@ -175,7 +168,7 @@ def __eq__(self, other): class _AnnotatedNormType(_BasicNormType): @property def origin(self) -> Any: - return typing.Annotated + return Annotated __slots__ = (*_BasicNormType.__slots__, "_hash") @@ -243,7 +236,7 @@ def origin(self) -> Any: return self._var @property - def args(self) -> Tuple[()]: + def args(self) -> tuple[()]: return () @property @@ -288,7 +281,7 @@ def origin(self) -> Any: return self._var @property - def args(self) -> Tuple[()]: + def args(self) -> tuple[()]: return () @property @@ -325,7 +318,7 @@ def param_spec(self) -> NormTV: return self._param_spec @property - def args(self) -> Tuple[()]: + def args(self) -> tuple[()]: return () @property @@ -418,7 +411,7 @@ def make_norm_type( if not all(type(arg) in [int, bool, str, bytes] or isinstance(type(arg), EnumMeta) for arg in args): raise TypeError return _LiteralNormType(args, source=source) - if HAS_ANNOTATED and origin == typing.Annotated: + if origin == Annotated: return _AnnotatedNormType(args, source=source) if isinstance(origin, TypeVar): raise TypeError @@ -471,7 +464,7 @@ def _replace_source_with_union(norm: BaseNormType, sources: list) -> BaseNormTyp NormAspect = Callable[["TypeNormalizer", Any, Any, tuple], Optional[BaseNormType]] -class AspectStorage(List[str]): +class AspectStorage(list[str]): @overload def add(self, *, condition: object = True) -> Callable[[NormAspect], NormAspect]: ... @@ -503,9 +496,9 @@ class NotSubscribedError(ValueError): class TypeNormalizer: def __init__(self, implicit_params_getter: ImplicitParamsGetter): self.implicit_params_getter = implicit_params_getter - self._namespace: Optional[Dict[str, Any]] = None + self._namespace: Optional[dict[str, Any]] = None - def _with_namespace(self: TN, namespace: Dict[str, Any]) -> TN: + def _with_namespace(self: TN, namespace: dict[str, Any]) -> TN: self_copy = copy(self) self_copy._namespace = namespace return self_copy @@ -563,9 +556,8 @@ def _norm_iter(self, tps: Iterable[Any]) -> VarTuple[BaseNormType]: MUST_SUBSCRIBED_ORIGINS = [ ClassVar, Final, Literal, Union, Optional, InitVar, + Annotated, ] - if HAS_ANNOTATED: - MUST_SUBSCRIBED_ORIGINS.append(typing.Annotated) if HAS_TYPE_GUARD: MUST_SUBSCRIBED_ORIGINS.append(typing.TypeGuard) if HAS_TYPED_DICT_REQUIRED: @@ -584,9 +576,9 @@ def _norm_none(self, tp, origin, args): if origin is None or origin is NoneType: return _NormType(None, (), source=tp) - @_aspect_storage.add(condition=HAS_ANNOTATED) + @_aspect_storage.add def _norm_annotated(self, tp, origin, args): - if origin == typing.Annotated: + if origin == Annotated: return _AnnotatedNormType( (self.normalize(args[0]), *args[1:]), source=tp, @@ -663,8 +655,8 @@ def _norm_new_type(self, tp, origin, args): @_aspect_storage.add def _norm_tuple(self, tp, origin, args): - if origin == tuple: - if tp in (tuple, Tuple): # not subscribed values + if origin is tuple: + if tp in (tuple, typing.Tuple): # not subscribed values return _NormType( tuple, (ANY_NT, ...), @@ -691,7 +683,7 @@ def _unpack_tuple_elements(self, args: VarTuple[BaseNormType]) -> VarTuple[BaseN # it is necessary to unpack the variable-length tuple as well if len(args) == 1 and args[0].origin == typing.Unpack: inner_tp = args[0].args[0] - if inner_tp.origin == tuple: + if inner_tp.origin is tuple: return inner_tp.args return self._unpack_generic_elements(args) @@ -706,7 +698,7 @@ def _unpack_generic_elements(self, args: VarTuple[Any]) -> VarTuple[BaseNormType return tuple(result) def _is_fixed_size_tuple(self, tp: BaseNormType) -> bool: - return tp.origin == tuple and (not tp.args or tp.args[-1] is not Ellipsis) + return tp.origin is tuple and (not tp.args or tp.args[-1] is not Ellipsis) @_aspect_storage.add def _norm_callable(self, tp, origin, args): @@ -749,7 +741,7 @@ def _norm_literal(self, tp, origin, args): return _LiteralNormType(args, source=tp) def _unfold_union_args(self, norm_args: Iterable[N]) -> Iterable[N]: - result: List[N] = [] + result: list[N] = [] for norm in norm_args: if norm.origin == Union: result.extend(norm.args) @@ -758,7 +750,7 @@ def _unfold_union_args(self, norm_args: Iterable[N]) -> Iterable[N]: return result def _dedup_union_args(self, args: Iterable[BaseNormType]) -> Iterable[BaseNormType]: - args_to_sources: DefaultDict[BaseNormType, List[Any]] = defaultdict(list) + args_to_sources: defaultdict[BaseNormType, list[Any]] = defaultdict(list) for arg in args: args_to_sources[arg].append(arg.source) @@ -772,7 +764,7 @@ def _dedup_union_args(self, args: Iterable[BaseNormType]) -> Iterable[BaseNormTy def _merge_literals(self, args: Iterable[N]) -> Sequence[N]: result = [] - lit_args: List[N] = [] + lit_args: list[N] = [] for norm in args: if norm.origin == Literal: lit_args.extend(norm.args) @@ -783,7 +775,7 @@ def _merge_literals(self, args: Iterable[N]) -> Sequence[N]: result.append(_create_norm_literal(lit_args)) return result - _UNION_ORIGINS: List[Any] = [Union] + _UNION_ORIGINS: list[Any] = [Union] if HAS_TYPE_UNION_OP: _UNION_ORIGINS.append(types.UnionType) @@ -808,13 +800,13 @@ def _norm_type(self, tp, origin, args): if norm.origin == Union: return _UnionNormType( tuple( - _NormType(type, (arg,), source=Type[arg.source]) + _NormType(type, (arg,), source=type[arg.source]) for arg in norm.args ), source=tp, ) - ALLOWED_ZERO_PARAMS_ORIGINS = {Any, NoReturn} + ALLOWED_ZERO_PARAMS_ORIGINS: set[Any] = {Any, NoReturn} if HAS_TYPE_ALIAS: ALLOWED_ZERO_PARAMS_ORIGINS.add(typing.TypeAlias) if HAS_PY_310: