diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 1f0baec5b906..422a0f5c100e 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -704,8 +704,8 @@ def check_call(self, elif isinstance(callee, UnionType): return self.check_union_call(callee, args, arg_kinds, arg_names, context, arg_messages) elif isinstance(callee, Instance): - call_function = analyze_member_access('__call__', callee, context, - False, False, False, self.msg, + call_function = analyze_member_access('__call__', callee, context, is_lvalue=False, + is_super=False, is_operator=True, msg=self.msg, original_type=callee, chk=self.chk, in_literal_context=self.is_literal_context()) callable_name = callee.type.fullname() + ".__call__" diff --git a/mypy/checkmember.py b/mypy/checkmember.py index 2117194e7fba..2f4139d80a42 100644 --- a/mypy/checkmember.py +++ b/mypy/checkmember.py @@ -332,7 +332,8 @@ def analyze_member_var_access(name: str, return analyze_var(name, v, itype, info, mx, implicit=implicit) elif isinstance(v, FuncDef): assert False, "Did not expect a function" - elif not v and name not in ['__getattr__', '__setattr__', '__getattribute__']: + elif (not v and name not in ['__getattr__', '__setattr__', '__getattribute__'] and + not mx.is_operator): if not mx.is_lvalue: for method_name in ('__getattribute__', '__getattr__'): method = info.get_method(method_name) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 8710a7ee6b3c..511404e0fec0 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -2494,6 +2494,22 @@ b = a.bar [out] main:9: error: Incompatible types in assignment (expression has type "A", variable has type "B") +[case testGetattrWithGetitem] +class A: + def __getattr__(self, x: str) -> 'A': + return A() + +a = A() +a[0] # E: Value of type "A" is not indexable + +[case testGetattrWithCall] +class A: + def __getattr__(self, x: str) -> 'A': + return A() + +a = A() +a.y() # E: "A" not callable + [case testNestedGetattr] def foo() -> object: def __getattr__() -> None: # no error because not in a class
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: