Skip to content

Commit 85c173b

Browse files
onlinedroot
authored and
root
committed
Make return type implicitly None for type checked __init__ and __init_subclass__ (python#5677)
Implements python#604 (comment).
1 parent 29152c1 commit 85c173b

File tree

2 files changed

+116
-3
lines changed

2 files changed

+116
-3
lines changed

mypy/semanal.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
from mypy.types import (
6969
FunctionLike, UnboundType, TypeVarDef, TupleType, UnionType, StarType, function_type,
7070
CallableType, Overloaded, Instance, Type, AnyType,
71-
TypeTranslator, TypeOfAny, TypeType,
71+
TypeTranslator, TypeOfAny, TypeType, NoneTyp,
7272
)
7373
from mypy.nodes import implicit_module_attrs
7474
from mypy.typeanal import (
@@ -407,6 +407,10 @@ def _visit_func_def(self, defn: FuncDef) -> None:
407407
add_symbol = False
408408
if add_symbol:
409409
self.type.names[defn.name()] = SymbolTableNode(MDEF, defn)
410+
if defn.type is not None and defn.name() in ('__init__', '__init_subclass__'):
411+
assert isinstance(defn.type, CallableType)
412+
if isinstance(defn.type.ret_type, AnyType):
413+
defn.type = defn.type.copy_modified(ret_type=NoneTyp())
410414
self.prepare_method_signature(defn, self.type)
411415
elif self.is_func_scope():
412416
# Nested function

test-data/unit/check-classes.test

+111-2
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,61 @@ import typing
577577
class A:
578578
def __init__(self, x: int): pass
579579
[out]
580-
main:3: error: The return type of "__init__" must be None
580+
581+
[case testDecoratedConstructorWithImplicitReturnValueType]
582+
import typing
583+
from typing import Callable
584+
585+
def deco(fn: Callable) -> Callable:
586+
return fn
587+
588+
class A:
589+
@deco
590+
def __init__(self, x: int): pass
591+
[out]
592+
593+
[case testOverloadedConstructorWithImplicitReturnValueType]
594+
from foo import *
595+
[file foo.pyi]
596+
from typing import overload
597+
class Foo:
598+
@overload
599+
def __init__(self, a: int):
600+
pass
601+
602+
@overload
603+
def __init__(self, a: str):
604+
pass
605+
606+
[case testConstructorWithAnyReturnValueType]
607+
import typing
608+
from typing import Any
609+
class A:
610+
def __init__(self) -> Any: pass # E: The return type of "__init__" must be None
611+
612+
[case testDecoratedConstructorWithAnyReturnValueType]
613+
import typing
614+
from typing import Callable, Any
615+
616+
def deco(fn: Callable) -> Callable:
617+
return fn
618+
619+
class A:
620+
@deco
621+
def __init__(self) -> Any: pass # E: The return type of "__init__" must be None
622+
623+
[case testOverloadedConstructorWithAnyReturnValueType]
624+
from foo import *
625+
[file foo.pyi]
626+
from typing import overload, Any
627+
class Foo:
628+
@overload
629+
def __init__(self, a: int) -> Any: # E: The return type of "__init__" must be None
630+
pass
631+
632+
@overload
633+
def __init__(self, a: str) -> Any: # E: The return type of "__init__" must be None
634+
pass
581635

582636
[case testInitSubclassWithReturnValueType]
583637
import typing
@@ -591,7 +645,62 @@ import typing
591645
class A:
592646
def __init_subclass__(cls, x: int=1): pass
593647
[out]
594-
main:3: error: The return type of "__init_subclass__" must be None
648+
649+
[case testDecoratedInitSubclassWithImplicitReturnValueType]
650+
import typing
651+
from typing import Callable
652+
653+
def deco(fn: Callable) -> Callable:
654+
return fn
655+
656+
class A:
657+
@deco
658+
def __init_subclass__(cls, x: int=1): pass
659+
[out]
660+
661+
[case testOverloadedInitSubclassWithImplicitReturnValueType]
662+
from foo import *
663+
[file foo.pyi]
664+
from typing import overload
665+
class Foo:
666+
@overload
667+
def __init_subclass__(cls, a: int):
668+
pass
669+
670+
@overload
671+
def __init_subclass__(cls, a: str):
672+
pass
673+
674+
[case testInitSubclassWithAnyReturnValueType]
675+
import typing
676+
from typing import Any
677+
class A:
678+
def __init_subclass__(cls) -> Any: pass # E: The return type of "__init_subclass__" must be None
679+
680+
[case testDecoratedInitSubclassWithAnyReturnValueType]
681+
import typing
682+
from typing import Callable, Any
683+
684+
def deco(fn: Callable) -> Callable:
685+
return fn
686+
687+
class A:
688+
@deco
689+
def __init_subclass__(cls) -> Any: pass # E: The return type of "__init_subclass__" must be None
690+
[out]
691+
692+
[case testOverloadedInitSubclassWithAnyReturnValueType]
693+
from foo import *
694+
[file foo.pyi]
695+
from typing import overload, Any
696+
class Foo:
697+
@overload
698+
def __init_subclass__(cls, a: int) -> Any: # E: The return type of "__init_subclass__" must be None
699+
pass
700+
701+
@overload
702+
def __init_subclass__(cls, a: str) -> Any: # E: The return type of "__init_subclass__" must be None
703+
pass
595704

596705
[case testGlobalFunctionInitWithReturnType]
597706
import typing

0 commit comments

Comments
 (0)