Skip to content

Commit

Permalink
New semantic analyzer: fix handling invalid attrs converters
Browse files Browse the repository at this point in the history
This is a hacky fix to better handle overloaded function during
semantic analysis. The original approach is not very clean so this
doesn't make this worse.

Fixes #6438.
  • Loading branch information
JukkaL committed Jun 28, 2019
1 parent 8030804 commit 2457b7d
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 5 deletions.
13 changes: 11 additions & 2 deletions mypy/plugins/attrs.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Plugin for supporting the attrs library (http://www.attrs.org)"""

from collections import OrderedDict

from typing import Optional, Dict, List, cast, Tuple, Iterable
Expand All @@ -9,7 +10,7 @@
from mypy.fixup import lookup_qualified_stnode
from mypy.nodes import (
Context, Argument, Var, ARG_OPT, ARG_POS, TypeInfo, AssignmentStmt,
TupleExpr, ListExpr, NameExpr, CallExpr, RefExpr, FuncBase,
TupleExpr, ListExpr, NameExpr, CallExpr, RefExpr, FuncDef,
is_class_var, TempNode, Decorator, MemberExpr, Expression,
SymbolTableNode, MDEF, JsonDict, OverloadedFuncDef, ARG_NAMED_OPT, ARG_NAMED,
TypeVarExpr
Expand Down Expand Up @@ -463,10 +464,13 @@ def _parse_converter(ctx: 'mypy.plugin.ClassDefContext',
# TODO: Support complex converters, e.g. lambdas, calls, etc.
if converter:
if isinstance(converter, RefExpr) and converter.node:
if (isinstance(converter.node, FuncBase)
if (isinstance(converter.node, FuncDef)
and converter.node.type
and isinstance(converter.node.type, FunctionLike)):
return Converter(converter.node.fullname())
elif (isinstance(converter.node, OverloadedFuncDef)
and is_valid_overloaded_converter(converter.node)):
return Converter(converter.node.fullname())
elif isinstance(converter.node, TypeInfo):
return Converter(converter.node.fullname())

Expand All @@ -490,6 +494,11 @@ def _parse_converter(ctx: 'mypy.plugin.ClassDefContext',
return Converter(None)


def is_valid_overloaded_converter(defn: OverloadedFuncDef) -> bool:
return all((not isinstance(item, Decorator) or isinstance(item.func.type, FunctionLike))
for item in defn.items)


def _parse_assignments(
lvalue: Expression,
stmt: AssignmentStmt) -> Tuple[List[NameExpr], List[Expression]]:
Expand Down
32 changes: 29 additions & 3 deletions test-data/unit/check-attr.test
Original file line number Diff line number Diff line change
Expand Up @@ -577,10 +577,8 @@ class C:

[builtins fixtures/list.pyi]

-- This is tricky with new analyzer:
-- We need to know the analyzed type of a function while still processing top-level.
[case testAttrsUsingBadConverter]
# flags: --no-new-semantic-analyzer --no-strict-optional
# flags: --no-strict-optional
import attr
from typing import overload
@overload
Expand All @@ -606,6 +604,34 @@ main:17: error: Argument "converter" has incompatible type overloaded function;
main:18: note: Revealed type is 'def (bad: Any, bad_overloaded: Any) -> __main__.A'
[builtins fixtures/list.pyi]

[case testAttrsUsingBadConverterReprocess]
# flags: --no-strict-optional
import attr
from typing import overload
forward: 'A'
@overload
def bad_overloaded_converter(x: int, y: int) -> int:
...
@overload
def bad_overloaded_converter(x: str, y: str) -> str:
...
def bad_overloaded_converter(x, y=7):
return x
def bad_converter() -> str:
return ''
@attr.dataclass
class A:
bad: str = attr.ib(converter=bad_converter)
bad_overloaded: int = attr.ib(converter=bad_overloaded_converter)
reveal_type(A)
[out]
main:17: error: Cannot determine __init__ type from converter
main:17: error: Argument "converter" has incompatible type "Callable[[], str]"; expected "Callable[[Any], str]"
main:18: error: Cannot determine __init__ type from converter
main:18: error: Argument "converter" has incompatible type overloaded function; expected "Callable[[Any], int]"
main:19: note: Revealed type is 'def (bad: Any, bad_overloaded: Any) -> __main__.A'
[builtins fixtures/list.pyi]

[case testAttrsUsingUnsupportedConverter]
import attr
class Thing:
Expand Down

0 comments on commit 2457b7d

Please sign in to comment.