diff --git a/changelog.d/1234.change.md b/changelog.d/1234.change.md new file mode 100644 index 000000000..0fbb078f0 --- /dev/null +++ b/changelog.d/1234.change.md @@ -0,0 +1 @@ +Our type stubs now use modern type notation and are organized such that VS Code's quick-fix prefers the `attrs` namespace. diff --git a/src/attr/__init__.pyi b/src/attr/__init__.pyi index 37a208732..14e53a8d2 100644 --- a/src/attr/__init__.pyi +++ b/src/attr/__init__.pyi @@ -4,17 +4,11 @@ import sys from typing import ( Any, Callable, - Dict, Generic, - List, Mapping, - Optional, Protocol, Sequence, - Tuple, - Type, TypeVar, - Union, overload, ) @@ -27,6 +21,20 @@ from . import validators as validators from ._cmp import cmp_using as cmp_using from ._typing_compat import AttrsInstance_ from ._version_info import VersionInfo +from attrs import ( + define as define, + field as field, + mutable as mutable, + frozen as frozen, + _EqOrderType, + _ValidatorType, + _ConverterType, + _ReprArgType, + _OnSetAttrType, + _OnSetAttrArgType, + _FieldTransformer, + _ValidatorArgType, +) if sys.version_info >= (3, 10): from typing import TypeGuard @@ -52,23 +60,7 @@ __copyright__: str _T = TypeVar("_T") _C = TypeVar("_C", bound=type) -_EqOrderType = Union[bool, Callable[[Any], Any]] -_ValidatorType = Callable[[Any, "Attribute[_T]", _T], Any] -_ConverterType = Callable[[Any], Any] _FilterType = Callable[["Attribute[_T]", _T], bool] -_ReprType = Callable[[Any], str] -_ReprArgType = Union[bool, _ReprType] -_OnSetAttrType = Callable[[Any, "Attribute[Any]", Any], Any] -_OnSetAttrArgType = Union[ - _OnSetAttrType, List[_OnSetAttrType], setters._NoOpType -] -_FieldTransformer = Callable[ - [type, List["Attribute[Any]"]], List["Attribute[Any]"] -] -# FIXME: in reality, if multiple validators are passed they must be in a list -# or tuple, but those are invariant and so would prevent subtypes of -# _ValidatorType from working when passed in a list or tuple. -_ValidatorArgType = Union[_ValidatorType[_T], Sequence[_ValidatorType[_T]]] # We subclass this here to keep the protocol's qualified name clean. class AttrsInstance(AttrsInstance_, Protocol): @@ -110,20 +102,20 @@ else: class Attribute(Generic[_T]): name: str - default: Optional[_T] - validator: Optional[_ValidatorType[_T]] + default: _T | None + validator: _ValidatorType[_T] | None repr: _ReprArgType cmp: _EqOrderType eq: _EqOrderType order: _EqOrderType - hash: Optional[bool] + hash: bool | None init: bool - converter: Optional[_ConverterType] - metadata: Dict[Any, Any] - type: Optional[Type[_T]] + converter: _ConverterType | None + metadata: dict[Any, Any] + type: type[_T] | None kw_only: bool on_setattr: _OnSetAttrType - alias: Optional[str] + alias: str | None def evolve(self, **changes: Any) -> "Attribute[Any]": ... @@ -156,18 +148,18 @@ def attrib( default: None = ..., validator: None = ..., repr: _ReprArgType = ..., - cmp: Optional[_EqOrderType] = ..., - hash: Optional[bool] = ..., + cmp: _EqOrderType | None = ..., + hash: bool | None = ..., init: bool = ..., - metadata: Optional[Mapping[Any, Any]] = ..., + metadata: Mapping[Any, Any] | None = ..., type: None = ..., converter: None = ..., factory: None = ..., kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - alias: Optional[str] = ..., + eq: _EqOrderType | None = ..., + order: _EqOrderType | None = ..., + on_setattr: _OnSetAttrArgType | None = ..., + alias: str | None = ..., ) -> Any: ... # This form catches an explicit None or no default and infers the type from the @@ -175,149 +167,70 @@ def attrib( @overload def attrib( default: None = ..., - validator: Optional[_ValidatorArgType[_T]] = ..., + validator: _ValidatorArgType[_T] | None = ..., repr: _ReprArgType = ..., - cmp: Optional[_EqOrderType] = ..., - hash: Optional[bool] = ..., + cmp: _EqOrderType | None = ..., + hash: bool | None = ..., init: bool = ..., - metadata: Optional[Mapping[Any, Any]] = ..., - type: Optional[Type[_T]] = ..., - converter: Optional[_ConverterType] = ..., - factory: Optional[Callable[[], _T]] = ..., + metadata: Mapping[Any, Any] | None = ..., + type: type[_T] | None = ..., + converter: _ConverterType | None = ..., + factory: Callable[[], _T] | None = ..., kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - alias: Optional[str] = ..., + eq: _EqOrderType | None = ..., + order: _EqOrderType | None = ..., + on_setattr: _OnSetAttrArgType | None = ..., + alias: str | None = ..., ) -> _T: ... # This form catches an explicit default argument. @overload def attrib( default: _T, - validator: Optional[_ValidatorArgType[_T]] = ..., + validator: _ValidatorArgType[_T] | None = ..., repr: _ReprArgType = ..., - cmp: Optional[_EqOrderType] = ..., - hash: Optional[bool] = ..., + cmp: _EqOrderType | None = ..., + hash: bool | None = ..., init: bool = ..., - metadata: Optional[Mapping[Any, Any]] = ..., - type: Optional[Type[_T]] = ..., - converter: Optional[_ConverterType] = ..., - factory: Optional[Callable[[], _T]] = ..., + metadata: Mapping[Any, Any] | None = ..., + type: type[_T] | None = ..., + converter: _ConverterType | None = ..., + factory: Callable[[], _T] | None = ..., kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - alias: Optional[str] = ..., + eq: _EqOrderType | None = ..., + order: _EqOrderType | None = ..., + on_setattr: _OnSetAttrArgType | None = ..., + alias: str | None = ..., ) -> _T: ... # This form covers type=non-Type: e.g. forward references (str), Any @overload def attrib( - default: Optional[_T] = ..., - validator: Optional[_ValidatorArgType[_T]] = ..., + default: _T | None = ..., + validator: _ValidatorArgType[_T] | None = ..., repr: _ReprArgType = ..., - cmp: Optional[_EqOrderType] = ..., - hash: Optional[bool] = ..., + cmp: _EqOrderType | None = ..., + hash: bool | None = ..., init: bool = ..., - metadata: Optional[Mapping[Any, Any]] = ..., + metadata: Mapping[Any, Any] | None = ..., type: object = ..., - converter: Optional[_ConverterType] = ..., - factory: Optional[Callable[[], _T]] = ..., - kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - alias: Optional[str] = ..., -) -> Any: ... -@overload -def field( - *, - default: None = ..., - validator: None = ..., - repr: _ReprArgType = ..., - hash: Optional[bool] = ..., - init: bool = ..., - metadata: Optional[Mapping[Any, Any]] = ..., - converter: None = ..., - factory: None = ..., - kw_only: bool = ..., - eq: Optional[bool] = ..., - order: Optional[bool] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - alias: Optional[str] = ..., - type: Optional[type] = ..., -) -> Any: ... - -# This form catches an explicit None or no default and infers the type from the -# other arguments. -@overload -def field( - *, - default: None = ..., - validator: Optional[_ValidatorArgType[_T]] = ..., - repr: _ReprArgType = ..., - hash: Optional[bool] = ..., - init: bool = ..., - metadata: Optional[Mapping[Any, Any]] = ..., - converter: Optional[_ConverterType] = ..., - factory: Optional[Callable[[], _T]] = ..., - kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - alias: Optional[str] = ..., - type: Optional[type] = ..., -) -> _T: ... - -# This form catches an explicit default argument. -@overload -def field( - *, - default: _T, - validator: Optional[_ValidatorArgType[_T]] = ..., - repr: _ReprArgType = ..., - hash: Optional[bool] = ..., - init: bool = ..., - metadata: Optional[Mapping[Any, Any]] = ..., - converter: Optional[_ConverterType] = ..., - factory: Optional[Callable[[], _T]] = ..., - kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - alias: Optional[str] = ..., - type: Optional[type] = ..., -) -> _T: ... - -# This form covers type=non-Type: e.g. forward references (str), Any -@overload -def field( - *, - default: Optional[_T] = ..., - validator: Optional[_ValidatorArgType[_T]] = ..., - repr: _ReprArgType = ..., - hash: Optional[bool] = ..., - init: bool = ..., - metadata: Optional[Mapping[Any, Any]] = ..., - converter: Optional[_ConverterType] = ..., - factory: Optional[Callable[[], _T]] = ..., + converter: _ConverterType | None = ..., + factory: Callable[[], _T] | None = ..., kw_only: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - alias: Optional[str] = ..., - type: Optional[type] = ..., + eq: _EqOrderType | None = ..., + order: _EqOrderType | None = ..., + on_setattr: _OnSetAttrArgType | None = ..., + alias: str | None = ..., ) -> Any: ... @overload @dataclass_transform(order_default=True, field_specifiers=(attrib, field)) def attrs( maybe_cls: _C, - these: Optional[Dict[str, Any]] = ..., - repr_ns: Optional[str] = ..., + these: dict[str, Any] | None = ..., + repr_ns: str | None = ..., repr: bool = ..., - cmp: Optional[_EqOrderType] = ..., - hash: Optional[bool] = ..., + cmp: _EqOrderType | None = ..., + hash: bool | None = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., @@ -327,25 +240,25 @@ def attrs( kw_only: bool = ..., cache_hash: bool = ..., auto_exc: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., + eq: _EqOrderType | None = ..., + order: _EqOrderType | None = ..., auto_detect: bool = ..., collect_by_mro: bool = ..., - getstate_setstate: Optional[bool] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - field_transformer: Optional[_FieldTransformer] = ..., + getstate_setstate: bool | None = ..., + on_setattr: _OnSetAttrArgType | None = ..., + field_transformer: _FieldTransformer | None = ..., match_args: bool = ..., - unsafe_hash: Optional[bool] = ..., + unsafe_hash: bool | None = ..., ) -> _C: ... @overload @dataclass_transform(order_default=True, field_specifiers=(attrib, field)) def attrs( maybe_cls: None = ..., - these: Optional[Dict[str, Any]] = ..., - repr_ns: Optional[str] = ..., + these: dict[str, Any] | None = ..., + repr_ns: str | None = ..., repr: bool = ..., - cmp: Optional[_EqOrderType] = ..., - hash: Optional[bool] = ..., + cmp: _EqOrderType | None = ..., + hash: bool | None = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., @@ -355,131 +268,24 @@ def attrs( kw_only: bool = ..., cache_hash: bool = ..., auto_exc: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., + eq: _EqOrderType | None = ..., + order: _EqOrderType | None = ..., auto_detect: bool = ..., collect_by_mro: bool = ..., - getstate_setstate: Optional[bool] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - field_transformer: Optional[_FieldTransformer] = ..., - match_args: bool = ..., - unsafe_hash: Optional[bool] = ..., -) -> Callable[[_C], _C]: ... -@overload -@dataclass_transform(field_specifiers=(attrib, field)) -def define( - maybe_cls: _C, - *, - these: Optional[Dict[str, Any]] = ..., - repr: bool = ..., - unsafe_hash: Optional[bool] = ..., - hash: Optional[bool] = ..., - init: bool = ..., - slots: bool = ..., - frozen: bool = ..., - weakref_slot: bool = ..., - str: bool = ..., - auto_attribs: bool = ..., - kw_only: bool = ..., - cache_hash: bool = ..., - auto_exc: bool = ..., - eq: Optional[bool] = ..., - order: Optional[bool] = ..., - auto_detect: bool = ..., - getstate_setstate: Optional[bool] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - field_transformer: Optional[_FieldTransformer] = ..., - match_args: bool = ..., -) -> _C: ... -@overload -@dataclass_transform(field_specifiers=(attrib, field)) -def define( - maybe_cls: None = ..., - *, - these: Optional[Dict[str, Any]] = ..., - repr: bool = ..., - unsafe_hash: Optional[bool] = ..., - hash: Optional[bool] = ..., - init: bool = ..., - slots: bool = ..., - frozen: bool = ..., - weakref_slot: bool = ..., - str: bool = ..., - auto_attribs: bool = ..., - kw_only: bool = ..., - cache_hash: bool = ..., - auto_exc: bool = ..., - eq: Optional[bool] = ..., - order: Optional[bool] = ..., - auto_detect: bool = ..., - getstate_setstate: Optional[bool] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - field_transformer: Optional[_FieldTransformer] = ..., - match_args: bool = ..., -) -> Callable[[_C], _C]: ... - -mutable = define - -@overload -@dataclass_transform(frozen_default=True, field_specifiers=(attrib, field)) -def frozen( - maybe_cls: _C, - *, - these: Optional[Dict[str, Any]] = ..., - repr: bool = ..., - unsafe_hash: Optional[bool] = ..., - hash: Optional[bool] = ..., - init: bool = ..., - slots: bool = ..., - frozen: bool = ..., - weakref_slot: bool = ..., - str: bool = ..., - auto_attribs: bool = ..., - kw_only: bool = ..., - cache_hash: bool = ..., - auto_exc: bool = ..., - eq: Optional[bool] = ..., - order: Optional[bool] = ..., - auto_detect: bool = ..., - getstate_setstate: Optional[bool] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - field_transformer: Optional[_FieldTransformer] = ..., - match_args: bool = ..., -) -> _C: ... -@overload -@dataclass_transform(frozen_default=True, field_specifiers=(attrib, field)) -def frozen( - maybe_cls: None = ..., - *, - these: Optional[Dict[str, Any]] = ..., - repr: bool = ..., - unsafe_hash: Optional[bool] = ..., - hash: Optional[bool] = ..., - init: bool = ..., - slots: bool = ..., - frozen: bool = ..., - weakref_slot: bool = ..., - str: bool = ..., - auto_attribs: bool = ..., - kw_only: bool = ..., - cache_hash: bool = ..., - auto_exc: bool = ..., - eq: Optional[bool] = ..., - order: Optional[bool] = ..., - auto_detect: bool = ..., - getstate_setstate: Optional[bool] = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - field_transformer: Optional[_FieldTransformer] = ..., + getstate_setstate: bool | None = ..., + on_setattr: _OnSetAttrArgType | None = ..., + field_transformer: _FieldTransformer | None = ..., match_args: bool = ..., + unsafe_hash: bool | None = ..., ) -> Callable[[_C], _C]: ... -def fields(cls: Type[AttrsInstance]) -> Any: ... -def fields_dict(cls: Type[AttrsInstance]) -> Dict[str, Attribute[Any]]: ... +def fields(cls: type[AttrsInstance]) -> Any: ... +def fields_dict(cls: type[AttrsInstance]) -> dict[str, Attribute[Any]]: ... def validate(inst: AttrsInstance) -> None: ... def resolve_types( cls: _A, - globalns: Optional[Dict[str, Any]] = ..., - localns: Optional[Dict[str, Any]] = ..., - attribs: Optional[List[Attribute[Any]]] = ..., + globalns: dict[str, Any] | None = ..., + localns: dict[str, Any] | None = ..., + attribs: list[Attribute[Any]] | None = ..., include_extras: bool = ..., ) -> _A: ... @@ -488,13 +294,13 @@ def resolve_types( # [attr.ib()])` is valid def make_class( name: str, - attrs: Union[List[str], Tuple[str, ...], Dict[str, Any]], - bases: Tuple[type, ...] = ..., - class_body: Optional[Dict[str, Any]] = ..., - repr_ns: Optional[str] = ..., + attrs: list[str] | tuple[str, ...] | dict[str, Any], + bases: tuple[type, ...] = ..., + class_body: dict[str, Any] | None = ..., + repr_ns: str | None = ..., repr: bool = ..., - cmp: Optional[_EqOrderType] = ..., - hash: Optional[bool] = ..., + cmp: _EqOrderType | None = ..., + hash: bool | None = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., @@ -504,11 +310,11 @@ def make_class( kw_only: bool = ..., cache_hash: bool = ..., auto_exc: bool = ..., - eq: Optional[_EqOrderType] = ..., - order: Optional[_EqOrderType] = ..., + eq: _EqOrderType | None = ..., + order: _EqOrderType | None = ..., collect_by_mro: bool = ..., - on_setattr: Optional[_OnSetAttrArgType] = ..., - field_transformer: Optional[_FieldTransformer] = ..., + on_setattr: _OnSetAttrArgType | None = ..., + field_transformer: _FieldTransformer | None = ..., ) -> type: ... # _funcs -- @@ -522,24 +328,22 @@ def make_class( def asdict( inst: AttrsInstance, recurse: bool = ..., - filter: Optional[_FilterType[Any]] = ..., - dict_factory: Type[Mapping[Any, Any]] = ..., + filter: _FilterType[Any] | None = ..., + dict_factory: type[Mapping[Any, Any]] = ..., retain_collection_types: bool = ..., - value_serializer: Optional[ - Callable[[type, Attribute[Any], Any], Any] - ] = ..., - tuple_keys: Optional[bool] = ..., -) -> Dict[str, Any]: ... + value_serializer: Callable[[type, Attribute[Any], Any], Any] | None = ..., + tuple_keys: bool | None = ..., +) -> dict[str, Any]: ... # TODO: add support for returning NamedTuple from the mypy plugin def astuple( inst: AttrsInstance, recurse: bool = ..., - filter: Optional[_FilterType[Any]] = ..., - tuple_factory: Type[Sequence[Any]] = ..., + filter: _FilterType[Any] | None = ..., + tuple_factory: type[Sequence[Any]] = ..., retain_collection_types: bool = ..., -) -> Tuple[Any, ...]: ... -def has(cls: type) -> TypeGuard[Type[AttrsInstance]]: ... +) -> tuple[Any, ...]: ... +def has(cls: type) -> TypeGuard[type[AttrsInstance]]: ... def assoc(inst: _T, **changes: Any) -> _T: ... def evolve(inst: _T, **changes: Any) -> _T: ... diff --git a/src/attr/_cmp.pyi b/src/attr/_cmp.pyi index f3dcdc1a7..cc7893b04 100644 --- a/src/attr/_cmp.pyi +++ b/src/attr/_cmp.pyi @@ -1,13 +1,13 @@ -from typing import Any, Callable, Optional, Type +from typing import Any, Callable _CompareWithType = Callable[[Any, Any], bool] def cmp_using( - eq: Optional[_CompareWithType] = ..., - lt: Optional[_CompareWithType] = ..., - le: Optional[_CompareWithType] = ..., - gt: Optional[_CompareWithType] = ..., - ge: Optional[_CompareWithType] = ..., + eq: _CompareWithType | None = ..., + lt: _CompareWithType | None = ..., + le: _CompareWithType | None = ..., + gt: _CompareWithType | None = ..., + ge: _CompareWithType | None = ..., require_same_type: bool = ..., class_name: str = ..., -) -> Type: ... +) -> type: ... diff --git a/src/attr/converters.pyi b/src/attr/converters.pyi index 5abb49f6d..9ef478f21 100644 --- a/src/attr/converters.pyi +++ b/src/attr/converters.pyi @@ -1,6 +1,6 @@ from typing import Callable, TypeVar, overload -from . import _ConverterType +from attrs import _ConverterType _T = TypeVar("_T") diff --git a/src/attr/filters.pyi b/src/attr/filters.pyi index 8a02fa0fc..974abdcdb 100644 --- a/src/attr/filters.pyi +++ b/src/attr/filters.pyi @@ -1,6 +1,6 @@ -from typing import Any, Union +from typing import Any from . import Attribute, _FilterType -def include(*what: Union[type, str, Attribute[Any]]) -> _FilterType[Any]: ... -def exclude(*what: Union[type, str, Attribute[Any]]) -> _FilterType[Any]: ... +def include(*what: type | str | Attribute[Any]) -> _FilterType[Any]: ... +def exclude(*what: type | str | Attribute[Any]) -> _FilterType[Any]: ... diff --git a/src/attr/setters.pyi b/src/attr/setters.pyi index 72f7ce476..73abf36e7 100644 --- a/src/attr/setters.pyi +++ b/src/attr/setters.pyi @@ -1,6 +1,7 @@ from typing import Any, NewType, NoReturn, TypeVar -from . import Attribute, _OnSetAttrType +from . import Attribute +from attrs import _OnSetAttrType _T = TypeVar("_T") diff --git a/src/attr/validators.pyi b/src/attr/validators.pyi index d194a75ab..caca56c68 100644 --- a/src/attr/validators.pyi +++ b/src/attr/validators.pyi @@ -5,20 +5,15 @@ from typing import ( Container, ContextManager, Iterable, - List, Mapping, Match, - Optional, Pattern, - Tuple, - Type, TypeVar, - Union, overload, ) -from . import _ValidatorType -from . import _ValidatorArgType +from attrs import _ValidatorType +from attrs import _ValidatorArgType _T = TypeVar("_T") _T1 = TypeVar("_T1") @@ -36,42 +31,42 @@ def disabled() -> ContextManager[None]: ... # To be more precise on instance_of use some overloads. # If there are more than 3 items in the tuple then we fall back to Any @overload -def instance_of(type: Type[_T]) -> _ValidatorType[_T]: ... +def instance_of(type: type[_T]) -> _ValidatorType[_T]: ... @overload -def instance_of(type: Tuple[Type[_T]]) -> _ValidatorType[_T]: ... +def instance_of(type: tuple[type[_T]]) -> _ValidatorType[_T]: ... @overload def instance_of( - type: Tuple[Type[_T1], Type[_T2]] -) -> _ValidatorType[Union[_T1, _T2]]: ... + type: tuple[type[_T1], type[_T2]] +) -> _ValidatorType[_T1 | _T2]: ... @overload def instance_of( - type: Tuple[Type[_T1], Type[_T2], Type[_T3]] -) -> _ValidatorType[Union[_T1, _T2, _T3]]: ... + type: tuple[type[_T1], type[_T2], type[_T3]] +) -> _ValidatorType[_T1 | _T2 | _T3]: ... @overload -def instance_of(type: Tuple[type, ...]) -> _ValidatorType[Any]: ... +def instance_of(type: tuple[type, ...]) -> _ValidatorType[Any]: ... def provides(interface: Any) -> _ValidatorType[Any]: ... def optional( - validator: Union[ - _ValidatorType[_T], List[_ValidatorType[_T]], Tuple[_ValidatorType[_T]] - ] -) -> _ValidatorType[Optional[_T]]: ... + validator: ( + _ValidatorType[_T] + | list[_ValidatorType[_T]] + | tuple[_ValidatorType[_T]] + ), +) -> _ValidatorType[_T | None]: ... def in_(options: Container[_T]) -> _ValidatorType[_T]: ... def and_(*validators: _ValidatorType[_T]) -> _ValidatorType[_T]: ... def matches_re( - regex: Union[Pattern[AnyStr], AnyStr], + regex: Pattern[AnyStr] | AnyStr, flags: int = ..., - func: Optional[ - Callable[[AnyStr, AnyStr, int], Optional[Match[AnyStr]]] - ] = ..., + func: Callable[[AnyStr, AnyStr, int], Match[AnyStr] | None] | None = ..., ) -> _ValidatorType[AnyStr]: ... def deep_iterable( member_validator: _ValidatorArgType[_T], - iterable_validator: Optional[_ValidatorType[_I]] = ..., + iterable_validator: _ValidatorType[_I] | None = ..., ) -> _ValidatorType[_I]: ... def deep_mapping( key_validator: _ValidatorType[_K], value_validator: _ValidatorType[_V], - mapping_validator: Optional[_ValidatorType[_M]] = ..., + mapping_validator: _ValidatorType[_M] | None = ..., ) -> _ValidatorType[_M]: ... def is_callable() -> _ValidatorType[_T]: ... def lt(val: _T) -> _ValidatorType[_T]: ... @@ -83,6 +78,6 @@ def min_len(length: int) -> _ValidatorType[_T]: ... def not_( validator: _ValidatorType[_T], *, - msg: Optional[str] = None, - exc_types: Union[Type[Exception], Iterable[Type[Exception]]] = ..., + msg: str | None = None, + exc_types: type[Exception] | Iterable[type[Exception]] = ..., ) -> _ValidatorType[_T]: ... diff --git a/src/attrs/__init__.pyi b/src/attrs/__init__.pyi index 9372cfea1..33624666c 100644 --- a/src/attrs/__init__.pyi +++ b/src/attrs/__init__.pyi @@ -1,12 +1,12 @@ +import sys + from typing import ( Any, Callable, - Dict, Mapping, - Optional, Sequence, - Tuple, - Type, + overload, + TypeVar, ) # Because we need to type our own stuff, we have to make everything from @@ -20,48 +20,232 @@ from attr import __title__ as __title__ from attr import __url__ as __url__ from attr import __version__ as __version__ from attr import __version_info__ as __version_info__ -from attr import _FilterType from attr import assoc as assoc from attr import Attribute as Attribute from attr import AttrsInstance as AttrsInstance from attr import cmp_using as cmp_using from attr import converters as converters -from attr import define as define from attr import evolve as evolve from attr import exceptions as exceptions from attr import Factory as Factory -from attr import field as field from attr import fields as fields from attr import fields_dict as fields_dict from attr import filters as filters -from attr import frozen as frozen from attr import has as has from attr import make_class as make_class -from attr import mutable as mutable from attr import NOTHING as NOTHING from attr import resolve_types as resolve_types from attr import setters as setters from attr import validate as validate from attr import validators as validators +from attr import attrib, asdict as asdict, astuple as astuple + +if sys.version_info >= (3, 11): + from typing import dataclass_transform +else: + from typing_extensions import dataclass_transform + +_T = TypeVar("_T") +_C = TypeVar("_C", bound=type) + +_EqOrderType = bool | Callable[[Any], Any] +_ValidatorType = Callable[[Any, "Attribute[_T]", _T], Any] +_ConverterType = Callable[[Any], Any] +_ReprType = Callable[[Any], str] +_ReprArgType = bool | _ReprType +_OnSetAttrType = Callable[[Any, "Attribute[Any]", Any], Any] +_OnSetAttrArgType = _OnSetAttrType | list[_OnSetAttrType] | setters._NoOpType +_FieldTransformer = Callable[ + [type, list["Attribute[Any]"]], list["Attribute[Any]"] +] +# FIXME: in reality, if multiple validators are passed they must be in a list +# or tuple, but those are invariant and so would prevent subtypes of +# _ValidatorType from working when passed in a list or tuple. +_ValidatorArgType = _ValidatorType[_T] | Sequence[_ValidatorType[_T]] + +@overload +def field( + *, + default: None = ..., + validator: None = ..., + repr: _ReprArgType = ..., + hash: bool | None = ..., + init: bool = ..., + metadata: Mapping[Any, Any] | None = ..., + converter: None = ..., + factory: None = ..., + kw_only: bool = ..., + eq: bool | None = ..., + order: bool | None = ..., + on_setattr: _OnSetAttrArgType | None = ..., + alias: str | None = ..., + type: type | None = ..., +) -> Any: ... + +# This form catches an explicit None or no default and infers the type from the +# other arguments. +@overload +def field( + *, + default: None = ..., + validator: _ValidatorArgType[_T] | None = ..., + repr: _ReprArgType = ..., + hash: bool | None = ..., + init: bool = ..., + metadata: Mapping[Any, Any] | None = ..., + converter: _ConverterType | None = ..., + factory: Callable[[], _T] | None = ..., + kw_only: bool = ..., + eq: _EqOrderType | None = ..., + order: _EqOrderType | None = ..., + on_setattr: _OnSetAttrArgType | None = ..., + alias: str | None = ..., + type: type | None = ..., +) -> _T: ... + +# This form catches an explicit default argument. +@overload +def field( + *, + default: _T, + validator: _ValidatorArgType[_T] | None = ..., + repr: _ReprArgType = ..., + hash: bool | None = ..., + init: bool = ..., + metadata: Mapping[Any, Any] | None = ..., + converter: _ConverterType | None = ..., + factory: Callable[[], _T] | None = ..., + kw_only: bool = ..., + eq: _EqOrderType | None = ..., + order: _EqOrderType | None = ..., + on_setattr: _OnSetAttrArgType | None = ..., + alias: str | None = ..., + type: type | None = ..., +) -> _T: ... + +# This form covers type=non-Type: e.g. forward references (str), Any +@overload +def field( + *, + default: _T | None = ..., + validator: _ValidatorArgType[_T] | None = ..., + repr: _ReprArgType = ..., + hash: bool | None = ..., + init: bool = ..., + metadata: Mapping[Any, Any] | None = ..., + converter: _ConverterType | None = ..., + factory: Callable[[], _T] | None = ..., + kw_only: bool = ..., + eq: _EqOrderType | None = ..., + order: _EqOrderType | None = ..., + on_setattr: _OnSetAttrArgType | None = ..., + alias: str | None = ..., + type: type | None = ..., +) -> Any: ... +@overload +@dataclass_transform(field_specifiers=(attrib, field)) +def define( + maybe_cls: _C, + *, + these: dict[str, Any] | None = ..., + repr: bool = ..., + unsafe_hash: bool | None = ..., + hash: bool | None = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + weakref_slot: bool = ..., + str: bool = ..., + auto_attribs: bool = ..., + kw_only: bool = ..., + cache_hash: bool = ..., + auto_exc: bool = ..., + eq: bool | None = ..., + order: bool | None = ..., + auto_detect: bool = ..., + getstate_setstate: bool | None = ..., + on_setattr: _OnSetAttrArgType | None = ..., + field_transformer: _FieldTransformer | None = ..., + match_args: bool = ..., +) -> _C: ... +@overload +@dataclass_transform(field_specifiers=(attrib, field)) +def define( + maybe_cls: None = ..., + *, + these: dict[str, Any] | None = ..., + repr: bool = ..., + unsafe_hash: bool | None = ..., + hash: bool | None = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + weakref_slot: bool = ..., + str: bool = ..., + auto_attribs: bool = ..., + kw_only: bool = ..., + cache_hash: bool = ..., + auto_exc: bool = ..., + eq: bool | None = ..., + order: bool | None = ..., + auto_detect: bool = ..., + getstate_setstate: bool | None = ..., + on_setattr: _OnSetAttrArgType | None = ..., + field_transformer: _FieldTransformer | None = ..., + match_args: bool = ..., +) -> Callable[[_C], _C]: ... -# TODO: see definition of attr.asdict/astuple -def asdict( - inst: AttrsInstance, - recurse: bool = ..., - filter: Optional[_FilterType[Any]] = ..., - dict_factory: Type[Mapping[Any, Any]] = ..., - retain_collection_types: bool = ..., - value_serializer: Optional[ - Callable[[type, Attribute[Any], Any], Any] - ] = ..., - tuple_keys: bool = ..., -) -> Dict[str, Any]: ... +mutable = define -# TODO: add support for returning NamedTuple from the mypy plugin -def astuple( - inst: AttrsInstance, - recurse: bool = ..., - filter: Optional[_FilterType[Any]] = ..., - tuple_factory: Type[Sequence[Any]] = ..., - retain_collection_types: bool = ..., -) -> Tuple[Any, ...]: ... +@overload +@dataclass_transform(frozen_default=True, field_specifiers=(attrib, field)) +def frozen( + maybe_cls: _C, + *, + these: dict[str, Any] | None = ..., + repr: bool = ..., + unsafe_hash: bool | None = ..., + hash: bool | None = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + weakref_slot: bool = ..., + str: bool = ..., + auto_attribs: bool = ..., + kw_only: bool = ..., + cache_hash: bool = ..., + auto_exc: bool = ..., + eq: bool | None = ..., + order: bool | None = ..., + auto_detect: bool = ..., + getstate_setstate: bool | None = ..., + on_setattr: _OnSetAttrArgType | None = ..., + field_transformer: _FieldTransformer | None = ..., + match_args: bool = ..., +) -> _C: ... +@overload +@dataclass_transform(frozen_default=True, field_specifiers=(attrib, field)) +def frozen( + maybe_cls: None = ..., + *, + these: dict[str, Any] | None = ..., + repr: bool = ..., + unsafe_hash: bool | None = ..., + hash: bool | None = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + weakref_slot: bool = ..., + str: bool = ..., + auto_attribs: bool = ..., + kw_only: bool = ..., + cache_hash: bool = ..., + auto_exc: bool = ..., + eq: bool | None = ..., + order: bool | None = ..., + auto_detect: bool = ..., + getstate_setstate: bool | None = ..., + on_setattr: _OnSetAttrArgType | None = ..., + field_transformer: _FieldTransformer | None = ..., + match_args: bool = ..., +) -> Callable[[_C], _C]: ...