From c78c447c676e5fa2fdaf5d266e6863bcce7e695c Mon Sep 17 00:00:00 2001 From: elazar Date: Tue, 7 Feb 2017 16:47:23 +0200 Subject: [PATCH 1/2] check for member in fallback --- mypy/checkexpr.py | 2 ++ test-data/unit/check-classes.test | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index a5679f016060..e9097519062c 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -2054,6 +2054,8 @@ def has_member(self, typ: Type, member: str) -> bool: # TODO TupleType => also consider tuple attributes if isinstance(typ, Instance): return typ.type.has_readable_member(member) + if isinstance(typ, CallableType): + return typ.fallback.type.has_readable_member(member) elif isinstance(typ, AnyType): return True elif isinstance(typ, UnionType): diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index b8a7e19c5f0c..a2062f9b49f8 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -2822,4 +2822,17 @@ from typing import Tuple class M(Tuple[int]): pass class C(metaclass=M): pass # E: Invalid metaclass 'M' -[builtins fixtures/tuple.pyi] \ No newline at end of file +[builtins fixtures/tuple.pyi] + +[case testMetaclassOperatorBeforeReversed] +class X: + def __radd__(self, x: int) -> int: ... + +class Meta(type): + def __add__(cls, x: X) -> str: ... + +class Concrete(metaclass=Meta): + pass + +reveal_type(Concrete + X()) # E: Revealed type is 'builtins.str' +Concrete + "hello" # E: Unsupported operand types for + ("Meta" and "str") From 45be745825ce725281dfc46d1408835028ce8bc4 Mon Sep 17 00:00:00 2001 From: elazar Date: Tue, 7 Feb 2017 17:06:06 +0200 Subject: [PATCH 2/2] check for fallback only for type objects --- mypy/checkexpr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index e9097519062c..58bc705d9474 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -2054,7 +2054,7 @@ def has_member(self, typ: Type, member: str) -> bool: # TODO TupleType => also consider tuple attributes if isinstance(typ, Instance): return typ.type.has_readable_member(member) - if isinstance(typ, CallableType): + if isinstance(typ, CallableType) and typ.is_type_obj(): return typ.fallback.type.has_readable_member(member) elif isinstance(typ, AnyType): return True