Skip to content

Commit

Permalink
mypy: remove has_member (#8438)
Browse files Browse the repository at this point in the history
In particular:
- The test case mentioned in the code passes without it
- The test case changed seems to have more desirable behaviour now,
  consider:

```
from typing import Any

"""
class C:
    def __radd__(self, other) -> float:
        return 1.234
"""
C: Any
class D(C):
    pass

reveal_type("str" + D())
```
  • Loading branch information
hauntsaninja committed Feb 25, 2020
1 parent 7af3191 commit 09cdab4
Show file tree
Hide file tree
Showing 3 changed files with 2 additions and 48 deletions.
46 changes: 0 additions & 46 deletions mypy/checkexpr.py
Expand Up @@ -2410,15 +2410,6 @@ def lookup_operator(op_name: str, base_type: Type) -> Optional[Type]:
"""Looks up the given operator and returns the corresponding type,
if it exists."""
local_errors = make_local_errors()

# TODO: Remove this call and rely just on analyze_member_access
# Currently, it seems we still need this to correctly deal with
# things like metaclasses?
#
# E.g. see the pythoneval.testMetaclassOpAccessAny test case.
if not self.has_member(base_type, op_name):
return None

member = analyze_member_access(
name=op_name,
typ=base_type,
Expand Down Expand Up @@ -3799,43 +3790,6 @@ def is_valid_keyword_var_arg(self, typ: Type) -> bool:
[self.named_type('builtins.unicode'),
AnyType(TypeOfAny.special_form)])))

def has_member(self, typ: Type, member: str) -> bool:
"""Does type have member with the given name?"""
# TODO: refactor this to use checkmember.analyze_member_access, otherwise
# these two should be carefully kept in sync.
typ = get_proper_type(typ)

if isinstance(typ, TypeVarType):
typ = get_proper_type(typ.upper_bound)
if isinstance(typ, TupleType):
typ = tuple_fallback(typ)
if isinstance(typ, LiteralType):
typ = typ.fallback
if isinstance(typ, Instance):
return typ.type.has_readable_member(member)
if isinstance(typ, CallableType) and typ.is_type_obj():
return typ.fallback.type.has_readable_member(member)
elif isinstance(typ, AnyType):
return True
elif isinstance(typ, UnionType):
result = all(self.has_member(x, member) for x in typ.relevant_items())
return result
elif isinstance(typ, TypeType):
# Type[Union[X, ...]] is always normalized to Union[Type[X], ...],
# so we don't need to care about unions here.
item = typ.item
if isinstance(item, TypeVarType):
item = get_proper_type(item.upper_bound)
if isinstance(item, TupleType):
item = tuple_fallback(item)
if isinstance(item, Instance) and item.type.metaclass_type is not None:
return self.has_member(item.type.metaclass_type, member)
if isinstance(item, AnyType):
return True
return False
else:
return False

def not_ready_callback(self, name: str, context: Context) -> None:
"""Called when we can't infer the type of a variable because it's not ready yet.
Expand Down
2 changes: 1 addition & 1 deletion mypy/typeops.py
Expand Up @@ -719,5 +719,5 @@ def custom_special_method(typ: Type, name: str, check_all: bool = False) -> bool
if isinstance(typ, AnyType):
# Avoid false positives in uncertain cases.
return True
# TODO: support other types (see ExpressionChecker.has_member())?
# TODO: support other types (see analyze_member_access)?
return False
2 changes: 1 addition & 1 deletion test-data/unit/check-classes.test
Expand Up @@ -6650,7 +6650,7 @@ reveal_type(0.5 + C) # N: Revealed type is 'Any'

reveal_type(0.5 + D()) # N: Revealed type is 'Any'
reveal_type(D() + 0.5) # N: Revealed type is 'Any'
reveal_type("str" + D()) # N: Revealed type is 'builtins.str'
reveal_type("str" + D()) # N: Revealed type is 'Any'
reveal_type(D() + "str") # N: Revealed type is 'Any'


Expand Down

0 comments on commit 09cdab4

Please sign in to comment.