| 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]] |
| kw_only: bool |
| 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 = ..., |
| kw_only: bool = ..., |
| ) -> 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]] = ..., |
| kw_only: bool = ..., |
| ) -> _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]] = ..., |
| kw_only: bool = ..., |
| ) -> _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]] = ..., |
| kw_only: bool = ..., |
| ) -> 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 = ..., |
| kw_only: 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 = ..., |
| kw_only: 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 = ..., |
| kw_only: 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) ;) |