1
1
"""Type checking of attribute access"""
2
2
3
- from typing import cast , Callable , List , Optional , TypeVar
3
+ from typing import cast , Callable , List , Optional , TypeVar , Union
4
4
5
5
from mypy .types import (
6
6
Type , Instance , AnyType , TupleType , TypedDictType , CallableType , FunctionLike , TypeVarDef ,
@@ -764,25 +764,32 @@ def type_object_type(info: TypeInfo, builtin_type: Callable[[str], Instance]) ->
764
764
765
765
# We take the type from whichever of __init__ and __new__ is first
766
766
# in the MRO, preferring __init__ if there is a tie.
767
- init_method = info .get_method ('__init__' )
768
- new_method = info .get_method ('__new__' )
769
- if not init_method :
767
+ init_method = info .get ('__init__' )
768
+ new_method = info .get ('__new__' )
769
+ if not init_method or not is_valid_constructor ( init_method . node ) :
770
770
# Must be an invalid class definition.
771
771
return AnyType (TypeOfAny .from_error )
772
772
# There *should* always be a __new__ method except the test stubs
773
773
# lack it, so just copy init_method in that situation
774
774
new_method = new_method or init_method
775
+ if not is_valid_constructor (new_method .node ):
776
+ # Must be an invalid class definition.
777
+ return AnyType (TypeOfAny .from_error )
778
+
779
+ # The two is_valid_constructor() checks ensure this.
780
+ assert isinstance (new_method .node , (FuncBase , Decorator ))
781
+ assert isinstance (init_method .node , (FuncBase , Decorator ))
775
782
776
- init_index = info .mro .index (init_method .info )
777
- new_index = info .mro .index (new_method .info )
783
+ init_index = info .mro .index (init_method .node . info )
784
+ new_index = info .mro .index (new_method .node . info )
778
785
779
786
fallback = info .metaclass_type or builtin_type ('builtins.type' )
780
787
if init_index < new_index :
781
- method = init_method
788
+ method = init_method . node # type: Union[FuncBase, Decorator]
782
789
elif init_index > new_index :
783
- method = new_method
790
+ method = new_method . node
784
791
else :
785
- if init_method .info .fullname () == 'builtins.object' :
792
+ if init_method .node . info .fullname () == 'builtins.object' :
786
793
# Both are defined by object. But if we've got a bogus
787
794
# base class, we can't know for sure, so check for that.
788
795
if info .fallback_to_any :
@@ -798,17 +805,34 @@ def type_object_type(info: TypeInfo, builtin_type: Callable[[str], Instance]) ->
798
805
# Otherwise prefer __init__ in a tie. It isn't clear that this
799
806
# is the right thing, but __new__ caused problems with
800
807
# typeshed (#5647).
801
- method = init_method
808
+ method = init_method . node
802
809
# Construct callable type based on signature of __init__. Adjust
803
810
# return type and insert type arguments.
804
- return type_object_type_from_function (method , info , fallback )
811
+ if isinstance (method , FuncBase ):
812
+ t = function_type (method , fallback )
813
+ else :
814
+ assert isinstance (method .type , FunctionLike ) # is_valid_constructor() ensures this
815
+ t = method .type
816
+ return type_object_type_from_function (t , info , method .info , fallback )
817
+
805
818
819
+ def is_valid_constructor (n : Optional [SymbolNode ]) -> bool :
820
+ """Does this node represents a valid constructor method?
806
821
807
- def type_object_type_from_function (init_or_new : FuncBase ,
822
+ This includes normal functions, overloaded functions, and decorators
823
+ that return a callable type.
824
+ """
825
+ if isinstance (n , FuncBase ):
826
+ return True
827
+ if isinstance (n , Decorator ):
828
+ return isinstance (n .type , FunctionLike )
829
+ return False
830
+
831
+
832
+ def type_object_type_from_function (signature : FunctionLike ,
808
833
info : TypeInfo ,
834
+ def_info : TypeInfo ,
809
835
fallback : Instance ) -> FunctionLike :
810
- signature = bind_self (function_type (init_or_new , fallback ))
811
-
812
836
# The __init__ method might come from a generic superclass
813
837
# (init_or_new.info) with type variables that do not map
814
838
# identically to the type variables of the class being constructed
@@ -818,10 +842,11 @@ def type_object_type_from_function(init_or_new: FuncBase,
818
842
# class B(A[List[T]], Generic[T]): pass
819
843
#
820
844
# We need to first map B's __init__ to the type (List[T]) -> None.
845
+ signature = bind_self (signature )
821
846
signature = cast (FunctionLike ,
822
- map_type_from_supertype (signature , info , init_or_new . info ))
847
+ map_type_from_supertype (signature , info , def_info ))
823
848
special_sig = None # type: Optional[str]
824
- if init_or_new . info .fullname () == 'builtins.dict' :
849
+ if def_info .fullname () == 'builtins.dict' :
825
850
# Special signature!
826
851
special_sig = 'dict'
827
852
0 commit comments