Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix --strict-equality for decorated and aliased __eq__ methods #7156

Merged
merged 2 commits into from Jul 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 6 additions & 4 deletions mypy/checkexpr.py
Expand Up @@ -28,7 +28,8 @@
DictionaryComprehension, ComplexExpr, EllipsisExpr, StarExpr, AwaitExpr, YieldExpr,
YieldFromExpr, TypedDictExpr, PromoteExpr, NewTypeExpr, NamedTupleExpr, TypeVarExpr,
TypeAliasExpr, BackquoteExpr, EnumCallExpr, TypeAlias, SymbolNode, PlaceholderNode,
ARG_POS, ARG_OPT, ARG_NAMED, ARG_STAR, ARG_STAR2, LITERAL_TYPE, REVEAL_TYPE
ARG_POS, ARG_OPT, ARG_NAMED, ARG_STAR, ARG_STAR2, LITERAL_TYPE, REVEAL_TYPE,
SYMBOL_FUNCBASE_TYPES
)
from mypy.literals import literal
from mypy import nodes
Expand Down Expand Up @@ -3931,9 +3932,10 @@ def is_expr_literal_type(node: Expression) -> bool:
def custom_equality_method(typ: Type) -> bool:
"""Does this type have a custom __eq__() method?"""
if isinstance(typ, Instance):
method = typ.type.get_method('__eq__')
if method and method.info:
return not method.info.fullname().startswith('builtins.')
method = typ.type.get('__eq__')
if method and isinstance(method.node, (SYMBOL_FUNCBASE_TYPES, Decorator, Var)):
if method.node.info:
return not method.node.info.fullname().startswith('builtins.')
return False
if isinstance(typ, UnionType):
return any(custom_equality_method(t) for t in typ.items)
Expand Down
24 changes: 24 additions & 0 deletions test-data/unit/check-expressions.test
Expand Up @@ -2217,6 +2217,30 @@ o in exp
[builtins fixtures/list.pyi]
[typing fixtures/typing-full.pyi]

[case testCustomEqDecoratedStrictEquality]
# flags: --strict-equality
from typing import TypeVar, Callable, Any

F = TypeVar('F', bound=Callable[..., Any])

def deco(f: F) -> F: ...

class Custom:
@deco
def __eq__(self, other: object) -> bool: ...

Custom() == int()
[builtins fixtures/bool.pyi]

[case testCustomEqVarStrictEquality]
# flags: --strict-equality

class Custom:
def compare(self, other: object) -> bool: ...
__eq__ = compare

Custom() == int()
[builtins fixtures/bool.pyi]

[case testUnimportedHintAny]
def f(x: Any) -> None: # E: Name 'Any' is not defined \
Expand Down