Skip to content

Commit 029b6e5

Browse files
eurestiilevkivskyi
authored andcommitted
Fix issues with attr code. (#4628)
More meesages, no unbound types, better tests. In response to comments in #4607
1 parent f384df8 commit 029b6e5

File tree

3 files changed

+66
-33
lines changed

3 files changed

+66
-33
lines changed

mypy/plugins/attrs.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,13 @@ def argument(self, ctx: 'mypy.plugin.ClassDefContext') -> Argument:
6464
and converter.type
6565
and isinstance(converter.type, CallableType)
6666
and converter.type.arg_types):
67-
init_type = converter.type.arg_types[0]
67+
init_type = ctx.api.anal_type(converter.type.arg_types[0])
6868
else:
69+
ctx.api.fail("Cannot determine type of converter function", self.context)
6970
init_type = AnyType(TypeOfAny.from_error)
7071
elif self.converter_name == '':
7172
# This means we had a converter but it's not of a type we can infer.
73+
# Error was shown in _get_converter_name
7274
init_type = AnyType(TypeOfAny.from_error)
7375

7476
if init_type is None:
@@ -317,12 +319,13 @@ def _attribute_from_attrib_maker(ctx: 'mypy.plugin.ClassDefContext',
317319
elif convert:
318320
ctx.api.fail("convert is deprecated, use converter", rvalue)
319321
converter = convert
320-
converter_name = _get_converter_name(converter)
322+
converter_name = _get_converter_name(ctx, converter)
321323

322324
return Attribute(lhs.name, ctx.cls.info, attr_has_default, init, converter_name, stmt)
323325

324326

325-
def _get_converter_name(converter: Optional[Expression]) -> Optional[str]:
327+
def _get_converter_name(ctx: 'mypy.plugin.ClassDefContext',
328+
converter: Optional[Expression]) -> Optional[str]:
326329
"""Return the full name of the converter if it exists and is a simple function."""
327330
# TODO: Support complex converters, e.g. lambdas, calls, etc.
328331
if converter:
@@ -334,6 +337,10 @@ def _get_converter_name(converter: Optional[Expression]) -> Optional[str]:
334337
and converter.node.type.arg_types):
335338
return converter.node.fullname()
336339
# Signal that we have an unsupported converter.
340+
ctx.api.fail(
341+
"Unsupported converter function, only named functions are currently supported",
342+
converter
343+
)
337344
return ''
338345
return None
339346

test-data/unit/check-attr.test

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -542,9 +542,9 @@ def factory(default: int):
542542
...
543543
@attr.s
544544
class C:
545-
x: str = attr.ib(converter=thing.do_it)
546-
y: str = attr.ib(converter=lambda x: x)
547-
z: str = attr.ib(converter=factory(8))
545+
x: str = attr.ib(converter=thing.do_it) # E: Unsupported converter function, only named functions are currently supported
546+
y: str = attr.ib(converter=lambda x: x) # E: Unsupported converter function, only named functions are currently supported
547+
z: str = attr.ib(converter=factory(8)) # E: Unsupported converter function, only named functions are currently supported
548548
reveal_type(C) # E: Revealed type is 'def (x: Any, y: Any, z: Any) -> __main__.C'
549549
[builtins fixtures/list.pyi]
550550

test-data/unit/check-incremental.test

Lines changed: 53 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3766,19 +3766,53 @@ main:2: error: Revealed type is 'def (x: Union[builtins.int, builtins.None]) ->
37663766
main:2: error: Revealed type is 'def (x: Union[builtins.int, builtins.None]) -> a.a.A'
37673767

37683768
[case testAttrsIncrementalConverterManyStyles]
3769+
import a
3770+
[file a.py]
37693771
from base import Base
3770-
reveal_type(Base)
3772+
Base(1, 'str', True)
3773+
Base(None, None, None)
3774+
37713775
from subclass import A, B
3772-
reveal_type(A)
3773-
reveal_type(B)
3776+
A(1, 'str', True)
3777+
A(None, None, None)
3778+
B(1, 'str', True, 1, 'str', True)
3779+
B(None, None, None, None, None, None)
3780+
3781+
from submodule.base import SubBase
3782+
SubBase(1, 'str', True)
3783+
SubBase(None, None, None)
3784+
3785+
from submodule.subclass import AA, BB
3786+
AA(1, 'str', True)
3787+
AA(None, None, None)
3788+
BB(1, 'str', True, 1, 'str', True)
3789+
BB(None, None, None, None, None, None)
3790+
3791+
from submodule.subsubclass import SubAA, SubBB
3792+
SubAA(1, 'str', True)
3793+
SubAA(None, None, None)
3794+
SubBB(1, 'str', True, 1, 'str', True)
3795+
SubBB(None, None, None, None, None, None)
3796+
3797+
[file a.py.2]
3798+
# Now with errors.
3799+
from base import Base
3800+
Base(1, 1, True)
3801+
3802+
from subclass import A, B
3803+
A(1, 1, True)
3804+
B(1, 'str', True, 1, 1, True)
3805+
37743806
from submodule.base import SubBase
3775-
reveal_type(SubBase)
3807+
SubBase(1, 1, True)
3808+
37763809
from submodule.subclass import AA, BB
3777-
reveal_type(AA)
3778-
reveal_type(BB)
3810+
AA(1, 1, True)
3811+
BB(1, 'str', True, 1, 1, True)
3812+
37793813
from submodule.subsubclass import SubAA, SubBB
3780-
reveal_type(SubAA)
3781-
reveal_type(SubBB)
3814+
SubAA(1, 1, True)
3815+
SubBB(1, 'str', True, 1, 1, True)
37823816

37833817
[file foo.py]
37843818
from typing import Optional
@@ -3866,23 +3900,15 @@ class SubBB(SubBase):
38663900
zz: bool = attr.ib(converter=bar.maybe_bool)
38673901
[builtins fixtures/list.pyi]
38683902
[out1]
3869-
main:2: error: Revealed type is 'def (x: Union[builtins.int, builtins.None], y: Union[builtins.str, builtins.None], z: Union[builtins.bool, builtins.None]) -> base.Base'
3870-
main:4: error: Revealed type is 'def (x: Union[builtins.int, builtins.None], y: Union[builtins.str, builtins.None], z: Union[builtins.bool, builtins.None]) -> subclass.A'
3871-
main:5: error: Revealed type is 'def (x: Union[builtins.int, builtins.None], y: Union[builtins.str, builtins.None], z: Union[builtins.bool, builtins.None], xx: Union[builtins.int, builtins.None], yy: Union[builtins.str, builtins.None], zz: Union[builtins.bool, builtins.None]) -> subclass.B'
3872-
main:7: error: Revealed type is 'def (x: Union[builtins.int, builtins.None], y: Union[builtins.str, builtins.None], z: Union[builtins.bool, builtins.None]) -> submodule.base.SubBase'
3873-
main:9: error: Revealed type is 'def (x: Union[builtins.int, builtins.None], y: Union[builtins.str, builtins.None], z: Union[builtins.bool, builtins.None]) -> submodule.subclass.AA'
3874-
main:10: error: Revealed type is 'def (x: Union[builtins.int, builtins.None], y: Union[builtins.str, builtins.None], z: Union[builtins.bool, builtins.None], xx: Union[builtins.int, builtins.None], yy: Union[builtins.str, builtins.None], zz: Union[builtins.bool, builtins.None]) -> submodule.subclass.BB'
3875-
main:12: error: Revealed type is 'def (x: Union[builtins.int, builtins.None], y: Union[builtins.str, builtins.None], z: Union[builtins.bool, builtins.None]) -> submodule.subsubclass.SubAA'
3876-
main:13: error: Revealed type is 'def (x: Union[builtins.int, builtins.None], y: Union[builtins.str, builtins.None], z: Union[builtins.bool, builtins.None], xx: Union[builtins.int, builtins.None], yy: Union[builtins.str, builtins.None], zz: Union[builtins.bool, builtins.None]) -> submodule.subsubclass.SubBB'
3877-
[out2]
3878-
main:2: error: Revealed type is 'def (x: Union[builtins.int, builtins.None], y: Union[builtins.str, builtins.None], z: Union[builtins.bool, builtins.None]) -> base.Base'
3879-
main:4: error: Revealed type is 'def (x: Union[builtins.int, builtins.None], y: Union[builtins.str, builtins.None], z: Union[builtins.bool, builtins.None]) -> subclass.A'
3880-
main:5: error: Revealed type is 'def (x: Union[builtins.int, builtins.None], y: Union[builtins.str, builtins.None], z: Union[builtins.bool, builtins.None], xx: Union[builtins.int, builtins.None], yy: Union[builtins.str, builtins.None], zz: Union[builtins.bool, builtins.None]) -> subclass.B'
3881-
main:7: error: Revealed type is 'def (x: Union[builtins.int, builtins.None], y: Union[builtins.str, builtins.None], z: Union[builtins.bool, builtins.None]) -> submodule.base.SubBase'
3882-
main:9: error: Revealed type is 'def (x: Union[builtins.int, builtins.None], y: Union[builtins.str, builtins.None], z: Union[builtins.bool, builtins.None]) -> submodule.subclass.AA'
3883-
main:10: error: Revealed type is 'def (x: Union[builtins.int, builtins.None], y: Union[builtins.str, builtins.None], z: Union[builtins.bool, builtins.None], xx: Union[builtins.int, builtins.None], yy: Union[builtins.str, builtins.None], zz: Union[builtins.bool, builtins.None]) -> submodule.subclass.BB'
3884-
main:12: error: Revealed type is 'def (x: Union[builtins.int, builtins.None], y: Union[builtins.str, builtins.None], z: Union[builtins.bool, builtins.None]) -> submodule.subsubclass.SubAA'
3885-
main:13: error: Revealed type is 'def (x: Union[builtins.int, builtins.None], y: Union[builtins.str, builtins.None], z: Union[builtins.bool, builtins.None], xx: Union[builtins.int, builtins.None], yy: Union[builtins.str, builtins.None], zz: Union[builtins.bool, builtins.None]) -> submodule.subsubclass.SubBB'
3903+
[out2]
3904+
tmp/a.py:3: error: Argument 2 to "Base" has incompatible type "int"; expected "Optional[str]"
3905+
tmp/a.py:6: error: Argument 2 to "A" has incompatible type "int"; expected "Optional[str]"
3906+
tmp/a.py:7: error: Argument 5 to "B" has incompatible type "int"; expected "Optional[str]"
3907+
tmp/a.py:10: error: Argument 2 to "SubBase" has incompatible type "int"; expected "Optional[str]"
3908+
tmp/a.py:13: error: Argument 2 to "AA" has incompatible type "int"; expected "Optional[str]"
3909+
tmp/a.py:14: error: Argument 5 to "BB" has incompatible type "int"; expected "Optional[str]"
3910+
tmp/a.py:17: error: Argument 2 to "SubAA" has incompatible type "int"; expected "Optional[str]"
3911+
tmp/a.py:18: error: Argument 5 to "SubBB" has incompatible type "int"; expected "Optional[str]"
38863912

38873913
[case testAttrsIncrementalConverterInFunction]
38883914
import attr
@@ -3895,9 +3921,9 @@ def foo() -> None:
38953921
reveal_type(A)
38963922
[builtins fixtures/list.pyi]
38973923
[out1]
3898-
main:8: error: Revealed type is 'def (x: str?) -> __main__.A@5'
3924+
main:8: error: Revealed type is 'def (x: builtins.str) -> __main__.A@5'
38993925
[out2]
3900-
main:8: error: Revealed type is 'def (x: str?) -> __main__.A@5'
3926+
main:8: error: Revealed type is 'def (x: builtins.str) -> __main__.A@5'
39013927

39023928
[case testAttrsIncrementalConverterInSubmoduleForwardRef]
39033929
from a.a import A

0 commit comments

Comments
 (0)