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 --