From 3c83ce9c3f465f46d42e2346014b336fdbc3af07 Mon Sep 17 00:00:00 2001 From: Peter Ludemann Date: Thu, 4 Jul 2019 20:04:25 -0700 Subject: [PATCH 1/5] Add missing magic methods. --- mypy/sharedparse.py | 30 +++++++- test-data/unit/check-classes.test | 84 ++++++++++++++++++++++ test-data/unit/fixtures/notimplemented.pyi | 10 ++- 3 files changed, 121 insertions(+), 3 deletions(-) diff --git a/mypy/sharedparse.py b/mypy/sharedparse.py index 202c46701435..991a53f4c9dc 100644 --- a/mypy/sharedparse.py +++ b/mypy/sharedparse.py @@ -6,36 +6,52 @@ _NON_BINARY_MAGIC_METHODS = { "__abs__", + "__bool__" "__call__", + "__ceil__", "__complex__", - "__contains__", "__del__", "__delattr__", + "__delete__", "__delitem__", + "__dir__", "__enter__", "__exit__", "__float__", + "__floor__", + # "__get__", # breaks testAccessingGenericDescriptorFromClassBadOverload "__getattr__", "__getattribute__", "__getitem__", + "__hash__", "__hex__", + "__index__", "__init__", "__init_subclass__", + "__instancecheck__", "__int__", "__invert__", "__iter__", "__len__", + "__length_hint__", "__long__", + "__missing__", "__neg__", "__new__", + "__not__", "__nonzero__", "__oct__", "__pos__", "__repr__", "__reversed__", + "__round__", + "__set__", + "__set_name__", "__setattr__", "__setitem__", "__str__", + "__subclasscheck__", + "__trunc__", "__unicode__", } # type: Final @@ -50,27 +66,33 @@ "__add__", "__and__", "__cmp__", - "__divmod__", + "__concat__", + "__contains__", "__div__", + "__divmod__", "__eq__", "__floordiv__", "__ge__", "__gt__", "__iadd__", "__iand__", + "__iconcat__", "__idiv__", "__ifloordiv__", "__ilshift__", + "__imatmul__", "__imod__", "__imul__", "__ior__", "__ipow__", "__irshift__", "__isub__", + "__itruediv__", "__ixor__", "__le__", "__lshift__", "__lt__", + "__matmul__", "__mod__", "__mul__", "__ne__", @@ -79,8 +101,10 @@ "__radd__", "__rand__", "__rdiv__", + "__rdivmod__", "__rfloordiv__", "__rlshift__", + "__rmatmul__", "__rmod__", "__rmul__", "__ror__", @@ -88,8 +112,10 @@ "__rrshift__", "__rshift__", "__rsub__", + "__rtruediv__", "__rxor__", "__sub__", + "__truediv__", "__xor__", } # type: Final diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 563149956ea1..54fe5c0e19b0 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -5925,3 +5925,87 @@ class B: class C(A, B): pass [out] + +[case testBinaryMagicMethods] +# flags: --warn-return-any +# See also check-warnings.test [case testReturnAnyForNotImplementedInBinaryMagicMethods] +from typing import Any +class A: + def __init__(self, x: Any) -> None: + self.x = x + def __abs__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __bool__(self) -> bool: return NotImplemented # E: Returning Any from function declared to return "bool" + def __call__(self, *args, **kwargs) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __ceil__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __complex__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __del__(self) -> None: return NotImplemented # E: Returning Any from function declared to return "None" + def __delattr__(self, other: Any) -> None: return NotImplemented # E: Returning Any from function declared to return "None" + def __delete__(self, other: Any) -> None: return NotImplemented # E: Returning Any from function declared to return "None" + def __delitem__(self, other: Any) -> None: return NotImplemented # E: Returning Any from function declared to return "None" + def __dir__(self, other: Any) -> Sequence_str: return NotImplemented # E: Returning Any from function declared to return "Sequence_str" + def __enter__(self, other: Any) -> None: return NotImplemented # E: Returning Any from function declared to return "None" + def __exit__(self, other: Any) -> None: return NotImplemented # E: Returning Any from function declared to return "None" + def __float__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __floor__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __get__(self, instance: Any, other: Any) -> str: return NotImplemented # E: Returning Any from function declared to return "str" + def __getitem__(self, other: Any) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __int__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __index__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __inv__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __invert__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __neg__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __not__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __pos__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __setitem__(self, other: Any) -> None: return NotImplemented # E: Returning Any from function declared to return "None" + + def __add__(self, other: Any) -> 'A': return NotImplemented + def __and__(self, other: Any) -> 'A': return NotImplemented + def __concat__(self, other: Any) -> 'A': return NotImplemented + def __contains__(self, other: Any) -> 'A': return NotImplemented + def __eq__(self, other: Any) -> bool: return NotImplemented + def __floordiv__(self, other: Any) -> 'A': return NotImplemented + def __ge__(self, other: Any) -> bool: return NotImplemented + def __gt__(self, other: Any) -> bool: return NotImplemented + def __iadd__(self, other: Any) -> 'A': return NotImplemented + def __iand__(self, other: Any) -> 'A': return NotImplemented + def __iconcat__(self, other: Any) -> 'A': return NotImplemented + def __ifloordiv__(self, other: Any) -> 'A': return NotImplemented + def __ilshift__(self, other: Any) -> 'A': return NotImplemented + def __imatmul__(self, other: Any) -> 'A': return NotImplemented + def __imod__(self, other: Any) -> 'A': return NotImplemented + def __imul__(self, other: Any) -> 'A': return NotImplemented + def __ior__(self, other: Any) -> 'A': return NotImplemented + def __ipow__(self, other: Any) -> 'A': return NotImplemented + def __irshift__(self, other: Any) -> 'A': return NotImplemented + def __isub__(self, other: Any) -> 'A': return NotImplemented + def __itruediv__(self, other: Any) -> 'A': return NotImplemented + def __ixor__(self, other: Any) -> 'A': return NotImplemented + def __le__(self, other: Any) -> bool: return NotImplemented + def __lshift__(self, other: Any) -> 'A': return NotImplemented + def __lt__(self, other: Any) -> bool: return NotImplemented + def __matmul__(self, other: Any) -> 'A': return NotImplemented + def __mod__(self, other: Any) -> 'A': return NotImplemented + def __mul__(self, other: Any) -> 'A': return NotImplemented + def __ne__(self, other: Any) -> bool: return NotImplemented + def __or__(self, other: Any) -> 'A': return NotImplemented + def __pow__(self, other: Any) -> 'A': return NotImplemented + def __rshift__(self, other: Any) -> 'A': return NotImplemented + def __sub__(self, other: Any) -> 'A': return NotImplemented + def __truediv__(self, other: Any) -> 'A': return NotImplemented + def __xor__(self, other: Any) -> 'A': return NotImplemented + # The "reverse" methods: + def __radd__(self, other: Any) -> 'A': return NotImplemented + def __rsub__(self, other: Any) -> 'A': return NotImplemented + def __rmul__(self, other: Any) -> 'A': return NotImplemented + def __rmatmul__(self, other: Any) -> 'A': return NotImplemented + def __rtruediv__(self, other: Any) -> 'A': return NotImplemented + def __rfloordiv__(self, other: Any) -> 'A': return NotImplemented + def __rmod__(self, other: Any) -> 'A': return NotImplemented + def __rdivmod__(self, other: Any) -> 'A': return NotImplemented + def __rpow__(self, other: Any) -> 'A': return NotImplemented + def __rlshift__(self, other: Any) -> 'A': return NotImplemented + def __rrshift__(self, other: Any) -> 'A': return NotImplemented + def __rand__(self, other: Any) -> 'A': return NotImplemented + def __rxor__(self, other: Any) -> 'A': return NotImplemented + def __ror__(self, other: Any) -> 'A': return NotImplemented +[builtins fixtures/notimplemented.pyi] diff --git a/test-data/unit/fixtures/notimplemented.pyi b/test-data/unit/fixtures/notimplemented.pyi index e619a6c5ad85..f1a2874c8bc4 100644 --- a/test-data/unit/fixtures/notimplemented.pyi +++ b/test-data/unit/fixtures/notimplemented.pyi @@ -1,13 +1,21 @@ # builtins stub used in NotImplemented related cases. -from typing import Any, cast +from typing import Any, Iterable, Mapping, Generic, TypeVar, cast +Tco = TypeVar('Tco', covariant=True) +T = TypeVar('T') +S = TypeVar('S') class object: def __init__(self) -> None: pass + def __eq__(self, o: object) -> bool: pass + def __ne__(self, o: object) -> bool: pass +class dict(Iterable[T], Mapping[T, S], Generic[T, S]): pass +class tuple(Iterable[Tco], Generic[Tco]): pass class type: pass class function: pass class bool: pass class int: pass class str: pass +class Sequence_str: pass # Sequence[str] for testing __dir__ NotImplemented = cast(Any, None) From 9bdd78abfe714eaa9515b7f70ade074e804faa5c Mon Sep 17 00:00:00 2001 From: Peter Ludemann Date: Thu, 4 Jul 2019 20:04:25 -0700 Subject: [PATCH 2/5] Add missing magic methods. --- mypy/sharedparse.py | 30 +++++++- test-data/unit/check-classes.test | 84 ++++++++++++++++++++++ test-data/unit/fixtures/notimplemented.pyi | 10 ++- 3 files changed, 121 insertions(+), 3 deletions(-) diff --git a/mypy/sharedparse.py b/mypy/sharedparse.py index 202c46701435..3d5fd972d50a 100644 --- a/mypy/sharedparse.py +++ b/mypy/sharedparse.py @@ -6,36 +6,52 @@ _NON_BINARY_MAGIC_METHODS = { "__abs__", + "__bool__" "__call__", + "__ceil__", "__complex__", - "__contains__", "__del__", "__delattr__", + "__delete__", "__delitem__", + "__dir__", "__enter__", "__exit__", "__float__", + "__floor__", + # "__get__", # TODO: breaks testAccessingGenericDescriptorFromClassBadOverload "__getattr__", "__getattribute__", "__getitem__", + "__hash__", "__hex__", + "__index__", "__init__", "__init_subclass__", + "__instancecheck__", "__int__", "__invert__", "__iter__", "__len__", + "__length_hint__", "__long__", + "__missing__", "__neg__", "__new__", + "__not__", "__nonzero__", "__oct__", "__pos__", "__repr__", "__reversed__", + "__round__", + "__set__", + "__set_name__", "__setattr__", "__setitem__", "__str__", + "__subclasscheck__", + "__trunc__", "__unicode__", } # type: Final @@ -50,27 +66,33 @@ "__add__", "__and__", "__cmp__", - "__divmod__", + "__concat__", + "__contains__", "__div__", + "__divmod__", "__eq__", "__floordiv__", "__ge__", "__gt__", "__iadd__", "__iand__", + "__iconcat__", "__idiv__", "__ifloordiv__", "__ilshift__", + "__imatmul__", "__imod__", "__imul__", "__ior__", "__ipow__", "__irshift__", "__isub__", + "__itruediv__", "__ixor__", "__le__", "__lshift__", "__lt__", + "__matmul__", "__mod__", "__mul__", "__ne__", @@ -79,8 +101,10 @@ "__radd__", "__rand__", "__rdiv__", + "__rdivmod__", "__rfloordiv__", "__rlshift__", + "__rmatmul__", "__rmod__", "__rmul__", "__ror__", @@ -88,8 +112,10 @@ "__rrshift__", "__rshift__", "__rsub__", + "__rtruediv__", "__rxor__", "__sub__", + "__truediv__", "__xor__", } # type: Final diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 563149956ea1..54fe5c0e19b0 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -5925,3 +5925,87 @@ class B: class C(A, B): pass [out] + +[case testBinaryMagicMethods] +# flags: --warn-return-any +# See also check-warnings.test [case testReturnAnyForNotImplementedInBinaryMagicMethods] +from typing import Any +class A: + def __init__(self, x: Any) -> None: + self.x = x + def __abs__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __bool__(self) -> bool: return NotImplemented # E: Returning Any from function declared to return "bool" + def __call__(self, *args, **kwargs) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __ceil__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __complex__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __del__(self) -> None: return NotImplemented # E: Returning Any from function declared to return "None" + def __delattr__(self, other: Any) -> None: return NotImplemented # E: Returning Any from function declared to return "None" + def __delete__(self, other: Any) -> None: return NotImplemented # E: Returning Any from function declared to return "None" + def __delitem__(self, other: Any) -> None: return NotImplemented # E: Returning Any from function declared to return "None" + def __dir__(self, other: Any) -> Sequence_str: return NotImplemented # E: Returning Any from function declared to return "Sequence_str" + def __enter__(self, other: Any) -> None: return NotImplemented # E: Returning Any from function declared to return "None" + def __exit__(self, other: Any) -> None: return NotImplemented # E: Returning Any from function declared to return "None" + def __float__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __floor__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __get__(self, instance: Any, other: Any) -> str: return NotImplemented # E: Returning Any from function declared to return "str" + def __getitem__(self, other: Any) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __int__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __index__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __inv__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __invert__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __neg__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __not__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __pos__(self) -> 'A': return NotImplemented # E: Returning Any from function declared to return "A" + def __setitem__(self, other: Any) -> None: return NotImplemented # E: Returning Any from function declared to return "None" + + def __add__(self, other: Any) -> 'A': return NotImplemented + def __and__(self, other: Any) -> 'A': return NotImplemented + def __concat__(self, other: Any) -> 'A': return NotImplemented + def __contains__(self, other: Any) -> 'A': return NotImplemented + def __eq__(self, other: Any) -> bool: return NotImplemented + def __floordiv__(self, other: Any) -> 'A': return NotImplemented + def __ge__(self, other: Any) -> bool: return NotImplemented + def __gt__(self, other: Any) -> bool: return NotImplemented + def __iadd__(self, other: Any) -> 'A': return NotImplemented + def __iand__(self, other: Any) -> 'A': return NotImplemented + def __iconcat__(self, other: Any) -> 'A': return NotImplemented + def __ifloordiv__(self, other: Any) -> 'A': return NotImplemented + def __ilshift__(self, other: Any) -> 'A': return NotImplemented + def __imatmul__(self, other: Any) -> 'A': return NotImplemented + def __imod__(self, other: Any) -> 'A': return NotImplemented + def __imul__(self, other: Any) -> 'A': return NotImplemented + def __ior__(self, other: Any) -> 'A': return NotImplemented + def __ipow__(self, other: Any) -> 'A': return NotImplemented + def __irshift__(self, other: Any) -> 'A': return NotImplemented + def __isub__(self, other: Any) -> 'A': return NotImplemented + def __itruediv__(self, other: Any) -> 'A': return NotImplemented + def __ixor__(self, other: Any) -> 'A': return NotImplemented + def __le__(self, other: Any) -> bool: return NotImplemented + def __lshift__(self, other: Any) -> 'A': return NotImplemented + def __lt__(self, other: Any) -> bool: return NotImplemented + def __matmul__(self, other: Any) -> 'A': return NotImplemented + def __mod__(self, other: Any) -> 'A': return NotImplemented + def __mul__(self, other: Any) -> 'A': return NotImplemented + def __ne__(self, other: Any) -> bool: return NotImplemented + def __or__(self, other: Any) -> 'A': return NotImplemented + def __pow__(self, other: Any) -> 'A': return NotImplemented + def __rshift__(self, other: Any) -> 'A': return NotImplemented + def __sub__(self, other: Any) -> 'A': return NotImplemented + def __truediv__(self, other: Any) -> 'A': return NotImplemented + def __xor__(self, other: Any) -> 'A': return NotImplemented + # The "reverse" methods: + def __radd__(self, other: Any) -> 'A': return NotImplemented + def __rsub__(self, other: Any) -> 'A': return NotImplemented + def __rmul__(self, other: Any) -> 'A': return NotImplemented + def __rmatmul__(self, other: Any) -> 'A': return NotImplemented + def __rtruediv__(self, other: Any) -> 'A': return NotImplemented + def __rfloordiv__(self, other: Any) -> 'A': return NotImplemented + def __rmod__(self, other: Any) -> 'A': return NotImplemented + def __rdivmod__(self, other: Any) -> 'A': return NotImplemented + def __rpow__(self, other: Any) -> 'A': return NotImplemented + def __rlshift__(self, other: Any) -> 'A': return NotImplemented + def __rrshift__(self, other: Any) -> 'A': return NotImplemented + def __rand__(self, other: Any) -> 'A': return NotImplemented + def __rxor__(self, other: Any) -> 'A': return NotImplemented + def __ror__(self, other: Any) -> 'A': return NotImplemented +[builtins fixtures/notimplemented.pyi] diff --git a/test-data/unit/fixtures/notimplemented.pyi b/test-data/unit/fixtures/notimplemented.pyi index e619a6c5ad85..f1a2874c8bc4 100644 --- a/test-data/unit/fixtures/notimplemented.pyi +++ b/test-data/unit/fixtures/notimplemented.pyi @@ -1,13 +1,21 @@ # builtins stub used in NotImplemented related cases. -from typing import Any, cast +from typing import Any, Iterable, Mapping, Generic, TypeVar, cast +Tco = TypeVar('Tco', covariant=True) +T = TypeVar('T') +S = TypeVar('S') class object: def __init__(self) -> None: pass + def __eq__(self, o: object) -> bool: pass + def __ne__(self, o: object) -> bool: pass +class dict(Iterable[T], Mapping[T, S], Generic[T, S]): pass +class tuple(Iterable[Tco], Generic[Tco]): pass class type: pass class function: pass class bool: pass class int: pass class str: pass +class Sequence_str: pass # Sequence[str] for testing __dir__ NotImplemented = cast(Any, None) From 71d95bb20993b95e03ff9fccad05a986eef333a4 Mon Sep 17 00:00:00 2001 From: Peter Ludemann Date: Wed, 24 Jul 2019 22:13:49 -0700 Subject: [PATCH 3/5] __not__ is not magical --- mypy/sharedparse.py | 2 +- mypy/typeshed | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mypy/sharedparse.py b/mypy/sharedparse.py index 3d5fd972d50a..97524591a671 100644 --- a/mypy/sharedparse.py +++ b/mypy/sharedparse.py @@ -38,7 +38,7 @@ "__missing__", "__neg__", "__new__", - "__not__", + # "__not__", # Not magic -- `not` calls `__bool__` or `__len__`. "__nonzero__", "__oct__", "__pos__", diff --git a/mypy/typeshed b/mypy/typeshed index f5c107cacd7c..668d050476e6 160000 --- a/mypy/typeshed +++ b/mypy/typeshed @@ -1 +1 @@ -Subproject commit f5c107cacd7c17ef541278bf228ca411fdeaa11b +Subproject commit 668d050476e6e02332d7d8f8557f368e5bc8bd37 From 55c44ee38c41d99170bac05adcda74f7bacd120e Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Sun, 18 Oct 2020 13:59:55 -0700 Subject: [PATCH 4/5] fix typeshed version --- mypy/typeshed | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/typeshed b/mypy/typeshed index 668d050476e6..86ca46fa0abc 160000 --- a/mypy/typeshed +++ b/mypy/typeshed @@ -1 +1 @@ -Subproject commit 668d050476e6e02332d7d8f8557f368e5bc8bd37 +Subproject commit 86ca46fa0abcbbbb1a02b92969e3ef8b3f926e65 From 4b8ce55aee784828dfaa8f8a1ac31b6d9b0eb8f1 Mon Sep 17 00:00:00 2001 From: hauntsaninja <> Date: Sun, 18 Oct 2020 14:03:29 -0700 Subject: [PATCH 5/5] use a new line --- test-data/unit/check-classes.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index c2910bcbf312..b596ce0d0ec5 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -6225,7 +6225,7 @@ class A: def __rxor__(self, other: Any) -> 'A': return NotImplemented def __ror__(self, other: Any) -> 'A': return NotImplemented [builtins fixtures/notimplemented.pyi] -======= + [case testAttributeDefOrder1] import a