From ee19aedc2fb8dd9f9d2268c0b04008b78ac712a4 Mon Sep 17 00:00:00 2001 From: David Euresti Date: Thu, 22 Mar 2018 10:02:37 -0700 Subject: [PATCH] Support factory= in attr plugin. It works pretty much like default= --- mypy/plugins/attrs.py | 6 ++++++ test-data/unit/check-attr.test | 12 ++++++++++++ test-data/unit/lib-stub/attr.pyi | 8 ++++++-- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/mypy/plugins/attrs.py b/mypy/plugins/attrs.py index 04b63e196ecb7..7ef56ae731a80 100644 --- a/mypy/plugins/attrs.py +++ b/mypy/plugins/attrs.py @@ -318,6 +318,12 @@ def _attribute_from_attrib_maker(ctx: 'mypy.plugin.ClassDefContext', init = _get_bool_argument(ctx, rvalue, 'init', True) # TODO: Check for attr.NOTHING attr_has_default = bool(_get_argument(rvalue, 'default')) + attr_has_factory = bool(_get_argument(rvalue, 'factory')) + + if attr_has_default and attr_has_factory: + ctx.api.fail("Can't pass both `default` and `factory`.", rvalue) + elif attr_has_factory: + attr_has_default = attr_has_factory # If the type isn't set through annotation but is passed through `type=` use that. type_arg = _get_argument(rvalue, 'type') diff --git a/test-data/unit/check-attr.test b/test-data/unit/check-attr.test index 45a23ab56373f..73f86ffadbd4c 100644 --- a/test-data/unit/check-attr.test +++ b/test-data/unit/check-attr.test @@ -771,3 +771,15 @@ class FFrozen(F): def bar(self) -> bool: return self._cb(5, 6) [builtins fixtures/callable.pyi] + +[case testAttrsWithFactory] +from typing import List +import attr +def my_factory() -> int: + return 7 +@attr.s +class A: + x: List[int] = attr.ib(factory=list) + y: int = attr.ib(factory=my_factory) +A() +[builtins fixtures/list.pyi] diff --git a/test-data/unit/lib-stub/attr.pyi b/test-data/unit/lib-stub/attr.pyi index d62a99a685eb8..2f648b21c986b 100644 --- a/test-data/unit/lib-stub/attr.pyi +++ b/test-data/unit/lib-stub/attr.pyi @@ -13,7 +13,9 @@ def attr(default: Optional[_T] = ..., convert: Optional[Callable[[Any], _T]] = ..., metadata: Any = ..., type: Optional[Type[_T]] = ..., - converter: Optional[Callable[[Any], _T]] = ...) -> _T: ... + converter: Optional[Callable[[Any], _T]] = ..., + factory: Optional[Callable[[], _T]] = ..., + ) -> _T: ... @overload def attr(default: None = ..., validator: None = ..., @@ -24,7 +26,9 @@ def attr(default: None = ..., convert: Optional[Callable[[Any], _T]] = ..., metadata: Any = ..., type: None = ..., - converter: None = ...) -> Any: ... + converter: None = ..., + factory: Optional[Callable[[], _T]] = ..., + ) -> Any: ... @overload def attributes(maybe_cls: _C,