Fix some typing issues (#581)

* Typecheck stubs in CI and fix type errors.  Fixes #578

* Add overloads to instance_of definition.

Improves #576
This commit is contained in:
David Euresti 2019-09-25 21:49:15 -07:00 committed by Hynek Schlawack
parent d381f49fc2
commit 08bbaabaca
3 changed files with 42 additions and 9 deletions

View File

@ -10,18 +10,37 @@ from typing import (
Iterable, Iterable,
Mapping, Mapping,
Callable, Callable,
Match,
AnyStr,
overload,
) )
from . import _ValidatorType from . import _ValidatorType
_T = TypeVar("_T") _T = TypeVar("_T")
_I = TypeVar("_I", bound=Iterable[_T]) _T1 = TypeVar("_T1")
_T2 = TypeVar("_T2")
_T3 = TypeVar("_T3")
_I = TypeVar("_I", bound=Iterable)
_K = TypeVar("_K") _K = TypeVar("_K")
_V = TypeVar("_V") _V = TypeVar("_V")
_M = TypeVar("_V", bound=Mapping[_K, _V]) _M = TypeVar("_M", bound=Mapping)
# 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]: ...
@overload
def instance_of(type: Tuple[Type[_T]]) -> _ValidatorType[_T]: ...
@overload
def instance_of( def instance_of(
type: Union[Tuple[Type[_T], ...], Type[_T]] type: Tuple[Type[_T1], Type[_T2]]
) -> _ValidatorType[_T]: ... ) -> _ValidatorType[Union[_T1, _T2]]: ...
@overload
def instance_of(
type: Tuple[Type[_T1], Type[_T2], Type[_T3]]
) -> _ValidatorType[Union[_T1, _T2, _T3]]: ...
@overload
def instance_of(type: Tuple[type, ...]) -> _ValidatorType[Any]: ...
def provides(interface: Any) -> _ValidatorType[Any]: ... def provides(interface: Any) -> _ValidatorType[Any]: ...
def optional( def optional(
validator: Union[_ValidatorType[_T], List[_ValidatorType[_T]]] validator: Union[_ValidatorType[_T], List[_ValidatorType[_T]]]
@ -29,10 +48,12 @@ def optional(
def in_(options: Container[_T]) -> _ValidatorType[_T]: ... def in_(options: Container[_T]) -> _ValidatorType[_T]: ...
def and_(*validators: _ValidatorType[_T]) -> _ValidatorType[_T]: ... def and_(*validators: _ValidatorType[_T]) -> _ValidatorType[_T]: ...
def matches_re( def matches_re(
regex: str, regex: AnyStr,
flags: int = ..., flags: int = ...,
func: Optional[Callable[[str, str, int], ...]] = ..., func: Optional[
): ... Callable[[AnyStr, AnyStr, int], Optional[Match[AnyStr]]]
] = ...,
) -> _ValidatorType[AnyStr]: ...
def deep_iterable( def deep_iterable(
member_validator: _ValidatorType[_T], member_validator: _ValidatorType[_T],
iterable_validator: Optional[_ValidatorType[_I]] = ..., iterable_validator: Optional[_ValidatorType[_I]] = ...,

View File

@ -1,6 +1,6 @@
import re import re
from typing import Any, Dict, List, Tuple from typing import Any, Dict, List, Tuple, Union
import attr import attr
@ -158,6 +158,16 @@ class Validated:
validator=attr.validators.matches_re(r"foo", flags=42, func=re.search) validator=attr.validators.matches_re(r"foo", flags=42, func=re.search)
) )
# Test different forms of instance_of
g: int = attr.ib(validator=attr.validators.instance_of(int))
h: int = attr.ib(validator=attr.validators.instance_of((int,)))
j: Union[int, str] = attr.ib(
validator=attr.validators.instance_of((int, str))
)
k: Union[int, str, C] = attr.ib(
validator=attr.validators.instance_of((int, C, str))
)
# Custom repr() # Custom repr()
@attr.s @attr.s

View File

@ -92,4 +92,6 @@ commands = towncrier --draft
[testenv:typing] [testenv:typing]
basepython = python3.7 basepython = python3.7
deps = mypy deps = mypy
commands = mypy tests/typing_example.py commands =
mypy src/attr/__init__.pyi src/attr/converters.pyi src/attr/exceptions.pyi src/attr/filters.pyi src/attr/validators.pyi
mypy tests/typing_example.py