From fc3a8dd1640b7e7b8285bde883e0f8c9db3a2697 Mon Sep 17 00:00:00 2001 From: Chad Dombrova <chadrik@gmail.com> Date: Sat, 20 Jan 2018 21:55:40 -0800 Subject: [PATCH 1/5] Add stubs for attrs library --- third_party/2and3/attr/__init__.pyi | 142 ++++++++++++++++++++++++++ third_party/2and3/attr/converters.pyi | 6 ++ third_party/2and3/attr/exceptions.pyi | 6 ++ third_party/2and3/attr/filters.pyi | 5 + third_party/2and3/attr/validators.pyi | 10 ++ 5 files changed, 169 insertions(+) create mode 100644 third_party/2and3/attr/__init__.pyi create mode 100644 third_party/2and3/attr/converters.pyi create mode 100644 third_party/2and3/attr/exceptions.pyi create mode 100644 third_party/2and3/attr/filters.pyi create mode 100644 third_party/2and3/attr/validators.pyi diff --git a/third_party/2and3/attr/__init__.pyi b/third_party/2and3/attr/__init__.pyi new file mode 100644 index 000000000000..166136ae19d6 --- /dev/null +++ b/third_party/2and3/attr/__init__.pyi @@ -0,0 +1,142 @@ +from typing import Any, Callable, Dict, Generic, List, Optional, Sequence, Mapping, Tuple, Type, TypeVar, Union, overload +# `import X as X` is required to make these public +from . import exceptions as exceptions +from . import filters as filters +from . import converters as converters +from . import validators as validators + +_T = TypeVar('_T') +_C = TypeVar('_C', bound=type) + +_ValidatorType = Callable[[Any, Attribute, _T], Any] +_ConverterType = Callable[[Any], _T] +_FilterType = Callable[[Attribute, Any], bool] +_ValidatorArgType = Union[_ValidatorType[_T], List[_ValidatorType[_T]], Tuple[_ValidatorType[_T], ...]] + +# _make -- + +NOTHING : object + +# NOTE: Factory lies about its return type to make this possible: `x: List[int] = Factory(list)` +def Factory(factory: Union[Callable[[], _T], Callable[[Any], _T]], takes_self: bool = ...) -> _T: ... + +class Attribute(Generic[_T]): + name: str + default: Optional[_T] + validator: Optional[_ValidatorType[_T]] + repr: bool + cmp: bool + hash: Optional[bool] + init: bool + converter: Optional[_ConverterType[_T]] + metadata: Dict[Any, Any] + type: Optional[Type[_T]] + def __lt__(self, x: Attribute) -> bool: ... + def __le__(self, x: Attribute) -> bool: ... + def __gt__(self, x: Attribute) -> bool: ... + def __ge__(self, x: Attribute) -> bool: ... + + +# NOTE: We had several choices for the annotation to use for type arg: +# 1) Type[_T] +# - Pros: works in PyCharm without plugin support +# - Cons: produces less informative error in the case of conflicting TypeVars +# e.g. `attr.ib(default='bad', type=int)` +# 2) Callable[..., _T] +# - Pros: more informative errors than #1 +# - Cons: validator tests results in confusing error. +# e.g. `attr.ib(type=int, validator=validate_str)` +# 3) type +# - Pros: in mypy, the behavior of type argument is exactly the same as with +# annotations. +# - Cons: completely disables type inspections in PyCharm when using the +# type arg. +# We chose option #1 until either PyCharm adds support for attrs, or python 2 +# reaches EOL. + +# NOTE: If you update these, update `ib` and `attr` below. + +# `attr` lies about its return type to make the following possible: +# attr() -> Any +# attr(8) -> int +# attr(validator=<some callable>) -> Whatever the callable expects. +# This makes this type of assignments possible: +# x: int = attr(8) + +# 1st form catches _T set. +@overload +def attrib(default: Optional[_T] = ..., validator: Optional[_ValidatorArgType[_T]] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Mapping = ..., type: Optional[Type[_T]] = ..., converter: Optional[_ConverterType[_T]] = ...) -> _T: ... +# 2nd form no _T , so returns Any. +@overload +def attrib(default: None = ..., validator: None = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Mapping = ..., type: None = ..., converter: None = ...) -> Any: ... + +# NOTE: If you update these, update `s` and `attributes` below. +@overload +def attrs(maybe_cls: _C, these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., str: bool = ..., auto_attribs: bool = ...) -> _C: ... +@overload +def attrs(maybe_cls: None = ..., these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., str: bool = ..., auto_attribs: bool = ...) -> Callable[[_C], _C]: ... + + +# TODO: add support for returning NamedTuple from the mypy plugin +class _Fields(Tuple[Attribute, ...]): + def __getattr__(self, name: str) -> Attribute: ... + +def fields(cls: type) -> _Fields: ... +def validate(inst: Any) -> None: ... + +# TODO: add support for returning a proper attrs class from the mypy plugin +# we use Any instead of _CountingAttr so that e.g. `make_class('Foo', [attr.ib()])` is valid +def make_class(name, attrs: Union[List[str], Dict[str, Any]], bases: Tuple[type, ...] = ..., **attributes_arguments) -> type: ... + +# _funcs -- + +# TODO: add support for returning TypedDict from the mypy plugin +# FIXME: asdict/astuple do not honor their factory args. waiting on one of these: +# https://github.com/python/mypy/issues/4236 +# https://github.com/python/typing/issues/253 +def asdict(inst: Any, recurse: bool = ..., filter: Optional[_FilterType] = ..., dict_factory: Type[Mapping] = ..., retain_collection_types: bool = ...) -> Dict[str, Any]: ... +# TODO: add support for returning NamedTuple from the mypy plugin +def astuple(inst: Any, recurse: bool = ..., filter: Optional[_FilterType] = ..., tuple_factory: Type[Sequence] = ..., retain_collection_types: bool = ...) -> Tuple[Any, ...]: ... +def has(cls: type) -> bool: ... +def assoc(inst: _T, **changes: Any) -> _T: ... +def evolve(inst: _T, **changes: Any) -> _T: ... + +# _config -- + +def set_run_validators(run: bool) -> None: ... +def get_run_validators() -> bool: ... + +# aliases -- +# s = attributes = attrs +# ib = attr = attrib +# dataclass = attrs # Technically, partial(attrs, auto_attribs=True) ;) + +# FIXME: there is a bug in PyCharm with creating aliases to overloads. +# Remove these when the bug is fixed: +# https://youtrack.jetbrains.com/issue/PY-27788 + +@overload +def ib(default: Optional[_T] = ..., validator: Optional[_ValidatorArgType[_T]] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Mapping = ..., type: Optional[Type[_T]] = ..., converter: Optional[_ConverterType[_T]] = ...) -> _T: ... +@overload +def ib(default: None = ..., validator: None = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Mapping = ..., type: None = ..., converter: None = ...) -> Any: ... + +@overload +def attr(default: Optional[_T] = ..., validator: Optional[_ValidatorArgType[_T]] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Mapping = ..., type: Optional[Type[_T]] = ..., converter: Optional[_ConverterType[_T]] = ...) -> _T: ... +@overload +def attr(default: None = ..., validator: None = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Mapping = ..., type: None = ..., converter: None = ...) -> Any: ... + +@overload +def attributes(maybe_cls: _C, these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., str: bool = ..., auto_attribs: bool = ...) -> _C: ... +@overload +def attributes(maybe_cls: None = ..., these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., str: bool = ..., auto_attribs: bool = ...) -> Callable[[_C], _C]: ... + +@overload +def s(maybe_cls: _C, these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., str: bool = ..., auto_attribs: bool = ...) -> _C: ... +@overload +def s(maybe_cls: None = ..., these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., str: bool = ..., auto_attribs: bool = ...) -> Callable[[_C], _C]: ... + +# same as above, but with auto_attrib=True +@overload +def dataclass(maybe_cls: _C, these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., str: bool = ...) -> _C: ... +@overload +def dataclass(maybe_cls: None = ..., these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., str: bool = ...) -> Callable[[_C], _C]: ... diff --git a/third_party/2and3/attr/converters.pyi b/third_party/2and3/attr/converters.pyi new file mode 100644 index 000000000000..9e31677e79c3 --- /dev/null +++ b/third_party/2and3/attr/converters.pyi @@ -0,0 +1,6 @@ +from typing import TypeVar, Optional +from . import _ConverterType + +_T = TypeVar('_T') + +def optional(converter: _ConverterType[_T]) -> _ConverterType[Optional[_T]]: ... diff --git a/third_party/2and3/attr/exceptions.pyi b/third_party/2and3/attr/exceptions.pyi new file mode 100644 index 000000000000..4a2904fc25b1 --- /dev/null +++ b/third_party/2and3/attr/exceptions.pyi @@ -0,0 +1,6 @@ +class FrozenInstanceError(AttributeError): + msg: str = ... +class AttrsAttributeNotFoundError(ValueError): ... +class NotAnAttrsClassError(ValueError): ... +class DefaultAlreadySetError(RuntimeError): ... +class UnannotatedAttributeError(RuntimeError): ... diff --git a/third_party/2and3/attr/filters.pyi b/third_party/2and3/attr/filters.pyi new file mode 100644 index 000000000000..a618140c2d1b --- /dev/null +++ b/third_party/2and3/attr/filters.pyi @@ -0,0 +1,5 @@ +from typing import Union +from . import Attribute, _FilterType + +def include(*what: Union[type, Attribute]) -> _FilterType: ... +def exclude(*what: Union[type, Attribute]) -> _FilterType: ... diff --git a/third_party/2and3/attr/validators.pyi b/third_party/2and3/attr/validators.pyi new file mode 100644 index 000000000000..477bac91c39b --- /dev/null +++ b/third_party/2and3/attr/validators.pyi @@ -0,0 +1,10 @@ +from typing import Container, List, Union, TypeVar, Type, Any, Optional +from . import _ValidatorType + +_T = TypeVar('_T') + +def instance_of(type: Type[_T]) -> _ValidatorType[_T]: ... +def provides(interface: Any) -> _ValidatorType[Any]: ... +def optional(validator: Union[_ValidatorType[_T], List[_ValidatorType[_T]]]) -> _ValidatorType[Optional[_T]]: ... +def in_(options: Container[_T]) -> _ValidatorType[_T]: ... +def and_(*validators: _ValidatorType[_T]) -> _ValidatorType[_T]: ... From 567e4849df1fcfa01378ae7be3df0a0dcb3e07c9 Mon Sep 17 00:00:00 2001 From: Chad Dombrova <chadrik@gmail.com> Date: Sun, 21 Jan 2018 10:30:40 -0800 Subject: [PATCH 2/5] Address code review notes about style --- third_party/2and3/attr/__init__.pyi | 154 +++++++++++++++++++++++++--- 1 file changed, 140 insertions(+), 14 deletions(-) diff --git a/third_party/2and3/attr/__init__.pyi b/third_party/2and3/attr/__init__.pyi index 166136ae19d6..9b5d80006891 100644 --- a/third_party/2and3/attr/__init__.pyi +++ b/third_party/2and3/attr/__init__.pyi @@ -65,16 +65,52 @@ class Attribute(Generic[_T]): # 1st form catches _T set. @overload -def attrib(default: Optional[_T] = ..., validator: Optional[_ValidatorArgType[_T]] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Mapping = ..., type: Optional[Type[_T]] = ..., converter: Optional[_ConverterType[_T]] = ...) -> _T: ... +def attrib(default: Optional[_T] = ..., + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: bool = ..., + cmp: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Mapping = ..., + type: Optional[Type[_T]] = ..., + converter: Optional[_ConverterType[_T]] = ...) -> _T: ... # 2nd form no _T , so returns Any. @overload -def attrib(default: None = ..., validator: None = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Mapping = ..., type: None = ..., converter: None = ...) -> Any: ... +def attrib(default: None = ..., + validator: None = ..., + repr: bool = ..., + cmp: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Mapping = ..., + type: None = ..., + converter: None = ...) -> Any: ... # NOTE: If you update these, update `s` and `attributes` below. @overload -def attrs(maybe_cls: _C, these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., str: bool = ..., auto_attribs: bool = ...) -> _C: ... +def attrs(maybe_cls: _C, + these: Optional[Dict[str, Any]] = ..., + repr_ns: Optional[str] = ..., + repr: bool = ..., + cmp: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + str: bool = ..., + auto_attribs: bool = ...) -> _C: ... @overload -def attrs(maybe_cls: None = ..., these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., str: bool = ..., auto_attribs: bool = ...) -> Callable[[_C], _C]: ... +def attrs(maybe_cls: None = ..., + these: Optional[Dict[str, Any]] = ..., + repr_ns: Optional[str] = ..., + repr: bool = ..., + cmp: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + str: bool = ..., + auto_attribs: bool = ...) -> Callable[[_C], _C]: ... # TODO: add support for returning NamedTuple from the mypy plugin @@ -116,27 +152,117 @@ def get_run_validators() -> bool: ... # https://youtrack.jetbrains.com/issue/PY-27788 @overload -def ib(default: Optional[_T] = ..., validator: Optional[_ValidatorArgType[_T]] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Mapping = ..., type: Optional[Type[_T]] = ..., converter: Optional[_ConverterType[_T]] = ...) -> _T: ... +def ib(default: Optional[_T] = ..., + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: bool = ..., + cmp: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Mapping = ..., + type: Optional[Type[_T]] = ..., + converter: Optional[_ConverterType[_T]] = ...) -> _T: ... @overload -def ib(default: None = ..., validator: None = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Mapping = ..., type: None = ..., converter: None = ...) -> Any: ... +def ib(default: None = ..., + validator: None = ..., + repr: bool = ..., + cmp: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Mapping = ..., + type: None = ..., + converter: None = ...) -> Any: ... @overload -def attr(default: Optional[_T] = ..., validator: Optional[_ValidatorArgType[_T]] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Mapping = ..., type: Optional[Type[_T]] = ..., converter: Optional[_ConverterType[_T]] = ...) -> _T: ... +def attr(default: Optional[_T] = ..., + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: bool = ..., + cmp: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Mapping = ..., + type: Optional[Type[_T]] = ..., + converter: Optional[_ConverterType[_T]] = ...) -> _T: ... @overload -def attr(default: None = ..., validator: None = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., metadata: Mapping = ..., type: None = ..., converter: None = ...) -> Any: ... +def attr(default: None = ..., + validator: None = ..., + repr: bool = ..., + cmp: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + metadata: Mapping = ..., + type: None = ..., + converter: None = ...) -> Any: ... @overload -def attributes(maybe_cls: _C, these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., str: bool = ..., auto_attribs: bool = ...) -> _C: ... +def attributes(maybe_cls: _C, + these: Optional[Dict[str, Any]] = ..., + repr_ns: Optional[str] = ..., + repr: bool = ..., + cmp: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + str: bool = ..., + auto_attribs: bool = ...) -> _C: ... @overload -def attributes(maybe_cls: None = ..., these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., str: bool = ..., auto_attribs: bool = ...) -> Callable[[_C], _C]: ... +def attributes(maybe_cls: None = ..., + these: Optional[Dict[str, Any]] = ..., + repr_ns: Optional[str] = ..., + repr: bool = ..., + cmp: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + str: bool = ..., + auto_attribs: bool = ...) -> Callable[[_C], _C]: ... @overload -def s(maybe_cls: _C, these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., str: bool = ..., auto_attribs: bool = ...) -> _C: ... +def s(maybe_cls: _C, + these: Optional[Dict[str, Any]] = ..., + repr_ns: Optional[str] = ..., + repr: bool = ..., + cmp: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + str: bool = ..., + auto_attribs: bool = ...) -> _C: ... @overload -def s(maybe_cls: None = ..., these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., str: bool = ..., auto_attribs: bool = ...) -> Callable[[_C], _C]: ... +def s(maybe_cls: None = ..., + these: Optional[Dict[str, Any]] = ..., + repr_ns: Optional[str] = ..., + repr: bool = ..., + cmp: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + str: bool = ..., + auto_attribs: bool = ...) -> Callable[[_C], _C]: ... # same as above, but with auto_attrib=True @overload -def dataclass(maybe_cls: _C, these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., str: bool = ...) -> _C: ... +def dataclass(maybe_cls: _C, + these: Optional[Dict[str, Any]] = ..., + repr_ns: Optional[str] = ..., + repr: bool = ..., + cmp: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + str: bool = ...) -> _C: ... @overload -def dataclass(maybe_cls: None = ..., these: Optional[Dict[str, Any]] = ..., repr_ns: Optional[str] = ..., repr: bool = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., slots: bool = ..., frozen: bool = ..., str: bool = ...) -> Callable[[_C], _C]: ... +def dataclass(maybe_cls: None = ..., + these: Optional[Dict[str, Any]] = ..., + repr_ns: Optional[str] = ..., + repr: bool = ..., + cmp: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + str: bool = ...) -> Callable[[_C], _C]: ... From c8361cf96139d8480c1e3f80a14d5ec3062e7e8d Mon Sep 17 00:00:00 2001 From: Chad Dombrova <chadrik@gmail.com> Date: Sun, 21 Jan 2018 10:46:07 -0800 Subject: [PATCH 3/5] Forgot one --- third_party/2and3/attr/__init__.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/2and3/attr/__init__.pyi b/third_party/2and3/attr/__init__.pyi index 9b5d80006891..e1f2f9275cdb 100644 --- a/third_party/2and3/attr/__init__.pyi +++ b/third_party/2and3/attr/__init__.pyi @@ -15,7 +15,7 @@ _ValidatorArgType = Union[_ValidatorType[_T], List[_ValidatorType[_T]], Tuple[_V # _make -- -NOTHING : object +NOTHING: object # NOTE: Factory lies about its return type to make this possible: `x: List[int] = Factory(list)` def Factory(factory: Union[Callable[[], _T], Callable[[Any], _T]], takes_self: bool = ...) -> _T: ... From 916bbb24241e7a6ed11e2b1fa136226895fa6166 Mon Sep 17 00:00:00 2001 From: Chad Dombrova <chadrik@gmail.com> Date: Fri, 2 Feb 2018 12:02:45 -0800 Subject: [PATCH 4/5] Address review notes - add attrib(convert) - replace Mapping with Optional[Mapping[Any, Any]] - add make_class arg types - deal properly with sequences of validator types - fix a bug with forward references --- third_party/2and3/attr/__init__.pyi | 94 ++++++++++++++++++++++++----- 1 file changed, 80 insertions(+), 14 deletions(-) diff --git a/third_party/2and3/attr/__init__.pyi b/third_party/2and3/attr/__init__.pyi index e1f2f9275cdb..8e328a162c6a 100644 --- a/third_party/2and3/attr/__init__.pyi +++ b/third_party/2and3/attr/__init__.pyi @@ -11,7 +11,10 @@ _C = TypeVar('_C', bound=type) _ValidatorType = Callable[[Any, Attribute, _T], Any] _ConverterType = Callable[[Any], _T] _FilterType = Callable[[Attribute, Any], bool] -_ValidatorArgType = Union[_ValidatorType[_T], List[_ValidatorType[_T]], Tuple[_ValidatorType[_T], ...]] +# 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]]] # _make -- @@ -46,7 +49,7 @@ class Attribute(Generic[_T]): # - Pros: more informative errors than #1 # - Cons: validator tests results in confusing error. # e.g. `attr.ib(type=int, validator=validate_str)` -# 3) type +# 3) type (and do all of the work in the mypy plugin) # - Pros: in mypy, the behavior of type argument is exactly the same as with # annotations. # - Cons: completely disables type inspections in PyCharm when using the @@ -71,7 +74,8 @@ def attrib(default: Optional[_T] = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., - metadata: Mapping = ..., + convert: Optional[_ConverterType[_T]] = ..., + metadata: Optional[Mapping[Any, Any]] = ..., type: Optional[Type[_T]] = ..., converter: Optional[_ConverterType[_T]] = ...) -> _T: ... # 2nd form no _T , so returns Any. @@ -82,9 +86,23 @@ def attrib(default: None = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., - metadata: Mapping = ..., + convert: Optional[_ConverterType[_T]] = ..., + metadata: Optional[Mapping[Any, Any]] = ..., type: None = ..., converter: None = ...) -> Any: ... +# 3rd form covers non-Type: e.g. forward references (str), Any +@overload +def attrib(default: Optional[_T] = ..., + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: bool = ..., + cmp: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + convert: Optional[_ConverterType[_T]] = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + type: object = ..., + converter: Optional[_ConverterType[_T]] = ...) -> Any: ... + # NOTE: If you update these, update `s` and `attributes` below. @overload @@ -122,7 +140,18 @@ def validate(inst: Any) -> None: ... # TODO: add support for returning a proper attrs class from the mypy plugin # we use Any instead of _CountingAttr so that e.g. `make_class('Foo', [attr.ib()])` is valid -def make_class(name, attrs: Union[List[str], Dict[str, Any]], bases: Tuple[type, ...] = ..., **attributes_arguments) -> type: ... +def make_class(name: str, + attrs: Union[List[str], Tuple[str, ...], Dict[str, Any]], + bases: Tuple[type, ...] = ..., + repr_ns: Optional[str] = ..., + repr: bool = ..., + cmp: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + slots: bool = ..., + frozen: bool = ..., + str: bool = ..., + auto_attribs: bool = ...) -> type: ... # _funcs -- @@ -130,9 +159,17 @@ def make_class(name, attrs: Union[List[str], Dict[str, Any]], bases: Tuple[type, # FIXME: asdict/astuple do not honor their factory args. waiting on one of these: # https://github.com/python/mypy/issues/4236 # https://github.com/python/typing/issues/253 -def asdict(inst: Any, recurse: bool = ..., filter: Optional[_FilterType] = ..., dict_factory: Type[Mapping] = ..., retain_collection_types: bool = ...) -> Dict[str, Any]: ... +def asdict(inst: Any, + recurse: bool = ..., + filter: Optional[_FilterType] = ..., + dict_factory: Type[Mapping[Any, Any]] = ..., + retain_collection_types: bool = ...) -> Dict[str, Any]: ... # TODO: add support for returning NamedTuple from the mypy plugin -def astuple(inst: Any, recurse: bool = ..., filter: Optional[_FilterType] = ..., tuple_factory: Type[Sequence] = ..., retain_collection_types: bool = ...) -> Tuple[Any, ...]: ... +def astuple(inst: Any, + recurse: bool = ..., + filter: Optional[_FilterType] = ..., + tuple_factory: Type[Sequence] = ..., + retain_collection_types: bool = ...) -> Tuple[Any, ...]: ... def has(cls: type) -> bool: ... def assoc(inst: _T, **changes: Any) -> _T: ... def evolve(inst: _T, **changes: Any) -> _T: ... @@ -142,14 +179,17 @@ def evolve(inst: _T, **changes: Any) -> _T: ... def set_run_validators(run: bool) -> None: ... def get_run_validators() -> bool: ... + # aliases -- + +# FIXME: there is a bug in PyCharm with creating aliases to overloads. +# Use the aliases instead of the duplicated overloads when the bug is fixed: +# https://youtrack.jetbrains.com/issue/PY-27788 + # s = attributes = attrs # ib = attr = attrib # dataclass = attrs # Technically, partial(attrs, auto_attribs=True) ;) -# FIXME: there is a bug in PyCharm with creating aliases to overloads. -# Remove these when the bug is fixed: -# https://youtrack.jetbrains.com/issue/PY-27788 @overload def ib(default: Optional[_T] = ..., @@ -158,7 +198,8 @@ def ib(default: Optional[_T] = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., - metadata: Mapping = ..., + convert: Optional[_ConverterType[_T]] = ..., + metadata: Optional[Mapping[Any, Any]] = ..., type: Optional[Type[_T]] = ..., converter: Optional[_ConverterType[_T]] = ...) -> _T: ... @overload @@ -168,9 +209,21 @@ def ib(default: None = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., - metadata: Mapping = ..., + convert: Optional[_ConverterType[_T]] = ..., + metadata: Optional[Mapping[Any, Any]] = ..., type: None = ..., converter: None = ...) -> Any: ... +@overload +def ib(default: Optional[_T] = ..., + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: bool = ..., + cmp: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + convert: Optional[_ConverterType[_T]] = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + type: object = ..., + converter: Optional[_ConverterType[_T]] = ...) -> Any: ... @overload def attr(default: Optional[_T] = ..., @@ -179,7 +232,8 @@ def attr(default: Optional[_T] = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., - metadata: Mapping = ..., + convert: Optional[_ConverterType[_T]] = ..., + metadata: Optional[Mapping[Any, Any]] = ..., type: Optional[Type[_T]] = ..., converter: Optional[_ConverterType[_T]] = ...) -> _T: ... @overload @@ -189,9 +243,21 @@ def attr(default: None = ..., cmp: bool = ..., hash: Optional[bool] = ..., init: bool = ..., - metadata: Mapping = ..., + convert: Optional[_ConverterType[_T]] = ..., + metadata: Optional[Mapping[Any, Any]] = ..., type: None = ..., converter: None = ...) -> Any: ... +@overload +def attr(default: Optional[_T] = ..., + validator: Optional[_ValidatorArgType[_T]] = ..., + repr: bool = ..., + cmp: bool = ..., + hash: Optional[bool] = ..., + init: bool = ..., + convert: Optional[_ConverterType[_T]] = ..., + metadata: Optional[Mapping[Any, Any]] = ..., + type: object = ..., + converter: Optional[_ConverterType[_T]] = ...) -> Any: ... @overload def attributes(maybe_cls: _C, From 43abb307d2051def6fb2248b507da774d34e0738 Mon Sep 17 00:00:00 2001 From: Chad Dombrova <chadrik@gmail.com> Date: Fri, 2 Feb 2018 15:19:30 -0800 Subject: [PATCH 5/5] fix flakes failure --- third_party/2and3/attr/__init__.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/2and3/attr/__init__.pyi b/third_party/2and3/attr/__init__.pyi index 8e328a162c6a..903c6135043a 100644 --- a/third_party/2and3/attr/__init__.pyi +++ b/third_party/2and3/attr/__init__.pyi @@ -150,7 +150,7 @@ def make_class(name: str, init: bool = ..., slots: bool = ..., frozen: bool = ..., - str: bool = ..., + str: bool = ..., auto_attribs: bool = ...) -> type: ... # _funcs --