-
-
Notifications
You must be signed in to change notification settings - Fork 374
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add PEP484 stubs #238
Merged
Merged
Add PEP484 stubs #238
Changes from 72 commits
Commits
Show all changes
74 commits
Select commit
Hold shift + click to select a range
e3d43a9
Add PEP484 stubs
chadrik a725e37
Deploy .pyi stubs alongside .py files.
chadrik c60d2f1
Add support for the new type argument.
chadrik 642ddb5
Add tests for stubs and address a few issues.
chadrik 0df5b9a
Improve declaration of private vs public objects in stubs
chadrik d0b9253
More stub tests
chadrik 9030de3
Separate the stub tests into their own tox env
chadrik cedf2c8
Update the manifest with stub files
chadrik a822cee
Remove mypy from the dev requirements
chadrik d58379e
Allow _CountingAttr to be instantiated, but not Attribute.
chadrik ec7d29c
Incorporate defaults into attr.ib typing
chadrik 8cb8000
Fix a bug with validators.and_
chadrik ebd6c17
Add more tests
chadrik 19857ec
Remove _CountingAttr from public interface
chadrik 7b953d2
Lie about return type of Factory
chadrik 102e21b
Merge branch 'master' into pyi_stubs
wsanchez b68657f
Add tox stubs env to travis
chadrik 4a2d589
used the wrong comment character in mypy tests
chadrik f254513
Improve overloads using PyCharm order-based approach
chadrik 121b742
Remove features not yet working in mypy. Document remaining issues.
chadrik c42bbd2
Test stubs against euresti fork of mypy with attrs plugin
chadrik db25517
Add some types and TypeVars to some types. Make tests pass
euresti ff72441
Suppress warnings about named attribute access from fields()
chadrik 4fe065b
Add WIP mypy-doctest plugin
chadrik 762d976
Deal with a few remaining type issues in the docs
chadrik 00b8e3e
Merge branch 'master' into pyi_stubs
chadrik ecc3484
sphinx doctest: don't turn warnings into errors.
chadrik 2cd9d53
Update "type: ignore" comments to reflect issues fixed in mypy plugin
chadrik 5bf1564
doctest2: improve output formatting
chadrik db2d269
Update manifest
chadrik 850a36d
static tests: use inline error declarations
chadrik 7e03c2f
More tests
chadrik 2293070
Tests passing (with notes about remaining issues)
chadrik 5ba0539
Attempt to get latest plugin from euresti working
chadrik 70e108f
Issues fixed.
chadrik c69ff42
Deal with a PyCharm bug
chadrik c9a975a
Minor test improvements
chadrik a900a74
Make tests prettier
chadrik cc4bbdc
Use 2 decorators instead of 3
euresti 7fcd7c8
doctest2: add support for skipping mypy tests
chadrik 7d97c44
Merge remote-tracking branch 'euresti/pyi_stubs' into pyi_stubs
chadrik a430345
Add tests for inheritance, eq, and cmp
chadrik f0900aa
Add fixmes and todos
chadrik 6e1c818
Merge branch 'master' into pyi_stubs
chadrik 7344ac4
Rename convert to converter
chadrik 11b47a0
Attribute.validator is always a single validator
chadrik d7e5783
Conform stubs to typeshed coding style
chadrik b745de6
backport style fixes from typeshed
chadrik 4863502
Add test cases to cover forward references and Any
chadrik 84d3eb4
Add fixes for forward references and Any
chadrik 0db6009
Address typeshed review notes
chadrik 7087828
Use Sequence instead of List/Tuple for validator arg
chadrik 201ad63
backports changes from typeshed #1914
chadrik e4461f4
backport changes from typeshed #1933
chadrik 3ce2503
Merge with master
chadrik 3fc633c
Prevent mypy tests from getting picked up
chadrik 175ad70
Merge branch 'master' into pyi_stubs
hynek 0ab6d5c
make our doctest extension compatible with latest sphinx
chadrik c95d5ae
Adjustments to the tests
chadrik 29c60d2
Merge remote-tracking branch 'upstream/master' into pyi_stubs
chadrik 0ddec13
Merge remote-tracking branch 'origin/pyi_stubs' into pyi_stubs
chadrik f33712d
Fix flake and manifest tests (hopefully)
chadrik 4ac5590
Fix tests on pypy3 (hopefully)
chadrik 2c77bca
Merge remote-tracking branch 'upstream/master' into pyi_stubs
chadrik e13612c
Update stubs from typeshed
chadrik 8c9ca24
Merge branch 'master' into pyi_stubs
chadrik af4dbcc
Make PEP 561-compliant
chadrik b922698
minor cleanup
chadrik 989cd88
Consolidate stub support files into stub directory
chadrik 875d2ac
Get tests passing
chadrik 60dd489
Revert stub test additions
chadrik 2b19c36
get pre-commit passing
chadrik 88fcd12
Address review feedback
chadrik 85862cb
Move typing test up in tox envlist
chadrik File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,8 @@ | |
.cache | ||
.coverage* | ||
.hypothesis | ||
.idea | ||
.mypy_cache | ||
.pytest_cache | ||
.tox | ||
build | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,240 @@ | ||
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] | ||
# 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 -- | ||
|
||
NOTHING: object | ||
|
||
# NOTE: Factory lies about its return type to make this possible: `x: List[int] = Factory(list)` | ||
# Work around mypy issue #4554 in the common case by using an overload. | ||
@overload | ||
def Factory(factory: Callable[[], _T]) -> _T: ... | ||
@overload | ||
def Factory( | ||
factory: Union[Callable[[Any], _T], Callable[[], _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 (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 | ||
# type arg. | ||
# We chose option #1 until either PyCharm adds support for attrs, or python 2 | ||
# reaches EOL. | ||
|
||
# `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) | ||
# | ||
# This form catches explicit None or no default but with no other arguments returns Any. | ||
@overload | ||
def attrib( | ||
default: None = ..., | ||
validator: None = ..., | ||
repr: bool = ..., | ||
cmp: bool = ..., | ||
hash: Optional[bool] = ..., | ||
init: bool = ..., | ||
convert: None = ..., | ||
metadata: Optional[Mapping[Any, Any]] = ..., | ||
type: None = ..., | ||
converter: None = ..., | ||
factory: None = ..., | ||
) -> Any: ... | ||
|
||
# This form catches an explicit None or no default and infers the type from the other arguments. | ||
@overload | ||
def attrib( | ||
default: None = ..., | ||
validator: Optional[_ValidatorArgType[_T]] = ..., | ||
repr: bool = ..., | ||
cmp: bool = ..., | ||
hash: Optional[bool] = ..., | ||
init: bool = ..., | ||
convert: Optional[_ConverterType[_T]] = ..., | ||
metadata: Optional[Mapping[Any, Any]] = ..., | ||
type: Optional[Type[_T]] = ..., | ||
converter: Optional[_ConverterType[_T]] = ..., | ||
factory: Optional[Callable[[], _T]] = ..., | ||
) -> _T: ... | ||
|
||
# This form catches an explicit default argument. | ||
@overload | ||
def attrib( | ||
default: _T, | ||
validator: Optional[_ValidatorArgType[_T]] = ..., | ||
repr: bool = ..., | ||
cmp: bool = ..., | ||
hash: Optional[bool] = ..., | ||
init: bool = ..., | ||
convert: Optional[_ConverterType[_T]] = ..., | ||
metadata: Optional[Mapping[Any, Any]] = ..., | ||
type: Optional[Type[_T]] = ..., | ||
converter: Optional[_ConverterType[_T]] = ..., | ||
factory: Optional[Callable[[], _T]] = ..., | ||
) -> _T: ... | ||
|
||
# This form covers type=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]] = ..., | ||
factory: Optional[Callable[[], _T]] = ..., | ||
) -> Any: ... | ||
@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 fields_dict(cls: type) -> Dict[str, Attribute]: ... | ||
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: 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 -- | ||
|
||
# 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[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 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) ;) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
from typing import TypeVar, Optional | ||
from . import _ConverterType | ||
|
||
_T = TypeVar("_T") | ||
|
||
def optional( | ||
converter: _ConverterType[_T] | ||
) -> _ConverterType[Optional[_T]]: ... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
class FrozenInstanceError(AttributeError): | ||
msg: str = ... | ||
|
||
class AttrsAttributeNotFoundError(ValueError): ... | ||
class NotAnAttrsClassError(ValueError): ... | ||
class DefaultAlreadySetError(RuntimeError): ... | ||
class UnannotatedAttributeError(RuntimeError): ... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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: ... |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from typing import Container, List, Union, TypeVar, Type, Any, Optional, Tuple | ||
from . import _ValidatorType | ||
|
||
_T = TypeVar("_T") | ||
|
||
def instance_of( | ||
type: Union[Tuple[Type[_T], ...], 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]: ... |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
Sorry, something went wrong.
This comment was marked as spam.
Sorry, something went wrong.