From ea1f7da20d1cf3623d3beeab8e5603e95d8508a4 Mon Sep 17 00:00:00 2001 From: Ekin Dursun Date: Wed, 26 Sep 2018 12:32:51 +0300 Subject: [PATCH 1/8] Make return type implicitly None --- mypy/semanal.py | 7 +++++-- test-data/unit/check-classes.test | 2 -- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index a4174de03742..d0b02672a00d 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -68,8 +68,7 @@ from mypy.types import ( FunctionLike, UnboundType, TypeVarDef, TupleType, UnionType, StarType, function_type, CallableType, Overloaded, Instance, Type, AnyType, - TypeTranslator, TypeOfAny, TypeType, -) + TypeTranslator, TypeOfAny, TypeType, NoneTyp) from mypy.nodes import implicit_module_attrs from mypy.typeanal import ( TypeAnalyser, analyze_type_alias, no_subscript_builtin_alias, @@ -407,6 +406,10 @@ def _visit_func_def(self, defn: FuncDef) -> None: add_symbol = False if add_symbol: self.type.names[defn.name()] = SymbolTableNode(MDEF, defn) + if (defn.type is not None and + defn.name() in ('__init__', '__init_subclass__') and + isinstance(defn.type.ret_type, AnyType)): + defn.type = defn.type.copy_modified(ret_type=NoneTyp()) self.prepare_method_signature(defn, self.type) elif self.is_func_scope(): # Nested function diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 3e40c78be47b..99a5cbd1a998 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -577,7 +577,6 @@ import typing class A: def __init__(self, x: int): pass [out] -main:3: error: The return type of "__init__" must be None [case testInitSubclassWithReturnValueType] import typing @@ -591,7 +590,6 @@ import typing class A: def __init_subclass__(cls, x: int=1): pass [out] -main:3: error: The return type of "__init_subclass__" must be None [case testGlobalFunctionInitWithReturnType] import typing From dd0b7e6b40b7556e20f40b26b72553970f9f3f8d Mon Sep 17 00:00:00 2001 From: Ekin Dursun Date: Wed, 26 Sep 2018 13:12:32 +0300 Subject: [PATCH 2/8] Assert for type checking --- mypy/semanal.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index d0b02672a00d..76b754b5c55f 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -406,10 +406,10 @@ def _visit_func_def(self, defn: FuncDef) -> None: add_symbol = False if add_symbol: self.type.names[defn.name()] = SymbolTableNode(MDEF, defn) - if (defn.type is not None and - defn.name() in ('__init__', '__init_subclass__') and - isinstance(defn.type.ret_type, AnyType)): - defn.type = defn.type.copy_modified(ret_type=NoneTyp()) + if defn.type is not None and defn.name() in ('__init__', '__init_subclass__'): + assert isinstance(defn.type, CallableType) + if isinstance(defn.type.ret_type, AnyType): + defn.type = defn.type.copy_modified(ret_type=NoneTyp()) self.prepare_method_signature(defn, self.type) elif self.is_func_scope(): # Nested function From 5c6eaac2d7060ab7465d64988670795e0b2c2655 Mon Sep 17 00:00:00 2001 From: Ekin Dursun Date: Wed, 26 Sep 2018 20:56:43 +0300 Subject: [PATCH 3/8] Fix import style --- mypy/semanal.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mypy/semanal.py b/mypy/semanal.py index 76b754b5c55f..e94f0a56282c 100644 --- a/mypy/semanal.py +++ b/mypy/semanal.py @@ -68,7 +68,8 @@ from mypy.types import ( FunctionLike, UnboundType, TypeVarDef, TupleType, UnionType, StarType, function_type, CallableType, Overloaded, Instance, Type, AnyType, - TypeTranslator, TypeOfAny, TypeType, NoneTyp) + TypeTranslator, TypeOfAny, TypeType, NoneTyp, +) from mypy.nodes import implicit_module_attrs from mypy.typeanal import ( TypeAnalyser, analyze_type_alias, no_subscript_builtin_alias, From 2563c348c0bd15fb263cee95b15ef979a92b2b78 Mon Sep 17 00:00:00 2001 From: Ekin Dursun Date: Wed, 26 Sep 2018 23:20:00 +0300 Subject: [PATCH 4/8] Add decorated tests --- test-data/unit/check-classes.test | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index 99a5cbd1a998..613b919d4afc 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -578,6 +578,18 @@ class A: def __init__(self, x: int): pass [out] +[case testDecoratedConstructorWithImplicitReturnValueType] +import typing +from typing import Callable + +def deco(fn: Callable) -> Callable: + return fn + +class A: + @deco + def __init__(self, x: int): pass +[out] + [case testInitSubclassWithReturnValueType] import typing class A: @@ -591,6 +603,18 @@ class A: def __init_subclass__(cls, x: int=1): pass [out] +[case testDecoratedInitSubclassWithImplicitReturnValueType] +import typing +from typing import Callable + +def deco(fn: Callable) -> Callable: + return fn + +class A: + @deco + def __init_subclass__(self, x: int=1): pass +[out] + [case testGlobalFunctionInitWithReturnType] import typing a = __init__() # type: A From 7a82feb765f8f637ad0d0498c632d54382aa308e Mon Sep 17 00:00:00 2001 From: Ekin Dursun Date: Thu, 27 Sep 2018 01:37:06 +0300 Subject: [PATCH 5/8] Correct first parameter of __init_subclass__ --- 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 613b919d4afc..b4468b6ad196 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -612,7 +612,7 @@ def deco(fn: Callable) -> Callable: class A: @deco - def __init_subclass__(self, x: int=1): pass + def __init_subclass__(cls, x: int=1): pass [out] [case testGlobalFunctionInitWithReturnType] From d65bb747ff597bd9f3e5dc7312fa1530fbf0632f Mon Sep 17 00:00:00 2001 From: Ekin Dursun Date: Thu, 27 Sep 2018 01:44:46 +0300 Subject: [PATCH 6/8] Add overloaded tests --- test-data/unit/check-classes.test | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index b4468b6ad196..f3f259e212d6 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -590,6 +590,19 @@ class A: def __init__(self, x: int): pass [out] +[case testOverloadedConstructorWithImplicitReturnValueType] +from foo import * +[file foo.pyi] +from typing import overload +class Foo: + @overload + def __init__(self, a: int): + pass + + @overload + def __init__(self, a: str): + pass + [case testInitSubclassWithReturnValueType] import typing class A: @@ -615,6 +628,19 @@ class A: def __init_subclass__(cls, x: int=1): pass [out] +[case testOverloadedConstructorWithImplicitReturnValueType] +from foo import * +[file foo.pyi] +from typing import overload +class Foo: + @overload + def __init_subclass__(cls, a: int): + pass + + @overload + def __init_subclass__(cls, a: str): + pass + [case testGlobalFunctionInitWithReturnType] import typing a = __init__() # type: A From 3f84608e84b5fd2b53b2076feee31e2e48927ad9 Mon Sep 17 00:00:00 2001 From: Ekin Dursun Date: Thu, 27 Sep 2018 18:55:17 +0300 Subject: [PATCH 7/8] Correct test name --- 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 f3f259e212d6..bcc1909fd659 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -628,7 +628,7 @@ class A: def __init_subclass__(cls, x: int=1): pass [out] -[case testOverloadedConstructorWithImplicitReturnValueType] +[case testOverloadedInitSubclassWithImplicitReturnValueType] from foo import * [file foo.pyi] from typing import overload From 9becf45d20f77664efb4d099a0ac27b79f67cb25 Mon Sep 17 00:00:00 2001 From: Ekin Dursun Date: Thu, 27 Sep 2018 19:13:20 +0300 Subject: [PATCH 8/8] Add explicit Any return type tests --- test-data/unit/check-classes.test | 61 +++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/test-data/unit/check-classes.test b/test-data/unit/check-classes.test index bcc1909fd659..7784f26df4b2 100644 --- a/test-data/unit/check-classes.test +++ b/test-data/unit/check-classes.test @@ -603,6 +603,36 @@ class Foo: def __init__(self, a: str): pass +[case testConstructorWithAnyReturnValueType] +import typing +from typing import Any +class A: + def __init__(self) -> Any: pass # E: The return type of "__init__" must be None + +[case testDecoratedConstructorWithAnyReturnValueType] +import typing +from typing import Callable, Any + +def deco(fn: Callable) -> Callable: + return fn + +class A: + @deco + def __init__(self) -> Any: pass # E: The return type of "__init__" must be None + +[case testOverloadedConstructorWithAnyReturnValueType] +from foo import * +[file foo.pyi] +from typing import overload, Any +class Foo: + @overload + def __init__(self, a: int) -> Any: # E: The return type of "__init__" must be None + pass + + @overload + def __init__(self, a: str) -> Any: # E: The return type of "__init__" must be None + pass + [case testInitSubclassWithReturnValueType] import typing class A: @@ -641,6 +671,37 @@ class Foo: def __init_subclass__(cls, a: str): pass +[case testInitSubclassWithAnyReturnValueType] +import typing +from typing import Any +class A: + def __init_subclass__(cls) -> Any: pass # E: The return type of "__init_subclass__" must be None + +[case testDecoratedInitSubclassWithAnyReturnValueType] +import typing +from typing import Callable, Any + +def deco(fn: Callable) -> Callable: + return fn + +class A: + @deco + def __init_subclass__(cls) -> Any: pass # E: The return type of "__init_subclass__" must be None +[out] + +[case testOverloadedInitSubclassWithAnyReturnValueType] +from foo import * +[file foo.pyi] +from typing import overload, Any +class Foo: + @overload + def __init_subclass__(cls, a: int) -> Any: # E: The return type of "__init_subclass__" must be None + pass + + @overload + def __init_subclass__(cls, a: str) -> Any: # E: The return type of "__init_subclass__" must be None + pass + [case testGlobalFunctionInitWithReturnType] import typing a = __init__() # type: A