65
65
SetComprehension , DictionaryComprehension , TYPE_ALIAS , TypeAliasExpr ,
66
66
YieldExpr , ExecStmt , Argument , BackquoteExpr , ImportBase , AwaitExpr ,
67
67
IntExpr , FloatExpr , UnicodeExpr , EllipsisExpr , TempNode ,
68
- COVARIANT , CONTRAVARIANT , INVARIANT , UNBOUND_IMPORTED , LITERAL_YES , nongen_builtins ,
68
+ COVARIANT , CONTRAVARIANT , INVARIANT , UNBOUND_IMPORTED , LITERAL_YES , ARG_OPT , nongen_builtins ,
69
69
collections_type_aliases , get_member_expr_fullname ,
70
70
)
71
71
from mypy .typevars import has_no_typevars , fill_typevars
@@ -588,27 +588,32 @@ def visit_class_def(self, defn: ClassDef) -> None:
588
588
if self .analyze_typeddict_classdef (defn ):
589
589
return
590
590
if self .analyze_namedtuple_classdef (defn ):
591
- return
592
- self .setup_class_def_analysis (defn )
591
+ # just analyze the class body so we catch type errors in default values
592
+ self .enter_class (defn )
593
+ defn .defs .accept (self )
594
+ self .leave_class ()
595
+ else :
596
+ self .setup_class_def_analysis (defn )
593
597
594
- self .bind_class_type_vars (defn )
598
+ self .bind_class_type_vars (defn )
595
599
596
- self .analyze_base_classes (defn )
597
- self .analyze_metaclass (defn )
600
+ self .analyze_base_classes (defn )
601
+ self .analyze_metaclass (defn )
598
602
599
- for decorator in defn .decorators :
600
- self .analyze_class_decorator (defn , decorator )
603
+ for decorator in defn .decorators :
604
+ self .analyze_class_decorator (defn , decorator )
601
605
602
- self .enter_class (defn )
606
+ self .enter_class (defn )
603
607
604
- # Analyze class body.
605
- defn .defs .accept (self )
608
+ # Analyze class body.
609
+ defn .defs .accept (self )
606
610
607
- self .calculate_abstract_status (defn .info )
608
- self .setup_type_promotion (defn )
611
+ self .calculate_abstract_status (defn .info )
612
+ self .setup_type_promotion (defn )
609
613
610
- self .leave_class ()
611
- self .unbind_class_type_vars ()
614
+ self .leave_class ()
615
+
616
+ self .unbind_class_type_vars ()
612
617
613
618
def enter_class (self , defn : ClassDef ) -> None :
614
619
# Remember previous active class
@@ -818,21 +823,24 @@ def analyze_namedtuple_classdef(self, defn: ClassDef) -> bool:
818
823
node = self .lookup (defn .name , defn )
819
824
if node is not None :
820
825
node .kind = GDEF # TODO in process_namedtuple_definition also applies here
821
- items , types = self .check_namedtuple_classdef (defn )
822
- node .node = self .build_namedtuple_typeinfo (defn .name , items , types )
826
+ items , types , default_items = self .check_namedtuple_classdef (defn )
827
+ node .node = self .build_namedtuple_typeinfo (
828
+ defn .name , items , types , default_items )
823
829
return True
824
830
return False
825
831
826
- def check_namedtuple_classdef (self , defn : ClassDef ) -> Tuple [List [str ], List [Type ]]:
832
+ def check_namedtuple_classdef (
833
+ self , defn : ClassDef ) -> Tuple [List [str ], List [Type ], Dict [str , Expression ]]:
827
834
NAMEDTUP_CLASS_ERROR = ('Invalid statement in NamedTuple definition; '
828
835
'expected "field_name: field_type"' )
829
836
if self .options .python_version < (3 , 6 ):
830
837
self .fail ('NamedTuple class syntax is only supported in Python 3.6' , defn )
831
- return [], []
838
+ return [], [], {}
832
839
if len (defn .base_type_exprs ) > 1 :
833
840
self .fail ('NamedTuple should be a single base' , defn )
834
841
items = [] # type: List[str]
835
842
types = [] # type: List[Type]
843
+ default_items = {} # type: Dict[str, Expression]
836
844
for stmt in defn .defs .body :
837
845
if not isinstance (stmt , AssignmentStmt ):
838
846
# Still allow pass or ... (for empty namedtuples).
@@ -854,10 +862,14 @@ def check_namedtuple_classdef(self, defn: ClassDef) -> Tuple[List[str], List[Typ
854
862
.format (name ), stmt )
855
863
if stmt .type is None or hasattr (stmt , 'new_syntax' ) and not stmt .new_syntax :
856
864
self .fail (NAMEDTUP_CLASS_ERROR , stmt )
857
- elif not isinstance (stmt .rvalue , TempNode ):
865
+ elif isinstance (stmt .rvalue , TempNode ):
858
866
# x: int assigns rvalue to TempNode(AnyType())
859
- self .fail ('Right hand side values are not supported in NamedTuple' , stmt )
860
- return items , types
867
+ if default_items :
868
+ self .fail ('Non-default NamedTuple fields cannot follow default fields' ,
869
+ stmt )
870
+ else :
871
+ default_items [name ] = stmt .rvalue
872
+ return items , types , default_items
861
873
862
874
def setup_class_def_analysis (self , defn : ClassDef ) -> None :
863
875
"""Prepare for the analysis of a class definition."""
@@ -1915,12 +1927,12 @@ def check_namedtuple(self, node: Expression, var_name: str = None) -> Optional[T
1915
1927
items , types , ok = self .parse_namedtuple_args (call , fullname )
1916
1928
if not ok :
1917
1929
# Error. Construct dummy return value.
1918
- return self .build_namedtuple_typeinfo ('namedtuple' , [], [])
1930
+ return self .build_namedtuple_typeinfo ('namedtuple' , [], [], {} )
1919
1931
name = cast (StrExpr , call .args [0 ]).value
1920
1932
if name != var_name or self .is_func_scope ():
1921
1933
# Give it a unique name derived from the line number.
1922
1934
name += '@' + str (call .line )
1923
- info = self .build_namedtuple_typeinfo (name , items , types )
1935
+ info = self .build_namedtuple_typeinfo (name , items , types , {} )
1924
1936
# Store it as a global just in case it would remain anonymous.
1925
1937
# (Or in the nearest class if there is one.)
1926
1938
stnode = SymbolTableNode (GDEF , info , self .cur_mod_id )
@@ -2013,8 +2025,8 @@ def basic_new_typeinfo(self, name: str, basetype_or_fallback: Instance) -> TypeI
2013
2025
info .bases = [basetype_or_fallback ]
2014
2026
return info
2015
2027
2016
- def build_namedtuple_typeinfo (self , name : str , items : List [str ],
2017
- types : List [ Type ]) -> TypeInfo :
2028
+ def build_namedtuple_typeinfo (self , name : str , items : List [str ], types : List [ Type ],
2029
+ default_items : Dict [ str , Expression ]) -> TypeInfo :
2018
2030
strtype = self .str_type ()
2019
2031
basetuple_type = self .named_type ('__builtins__.tuple' , [AnyType ()])
2020
2032
dictype = (self .named_type_or_none ('builtins.dict' , [strtype , AnyType ()])
@@ -2046,6 +2058,7 @@ def add_field(var: Var, is_initialized_in_class: bool = False,
2046
2058
tuple_of_strings = TupleType ([strtype for _ in items ], basetuple_type )
2047
2059
add_field (Var ('_fields' , tuple_of_strings ), is_initialized_in_class = True )
2048
2060
add_field (Var ('_field_types' , dictype ), is_initialized_in_class = True )
2061
+ add_field (Var ('_field_defaults' , dictype ), is_initialized_in_class = True )
2049
2062
add_field (Var ('_source' , strtype ), is_initialized_in_class = True )
2050
2063
2051
2064
tvd = TypeVarDef ('NT' , 1 , [], info .tuple_type )
@@ -2083,8 +2096,14 @@ def add_method(funcname: str,
2083
2096
2084
2097
add_method ('_replace' , ret = selftype ,
2085
2098
args = [Argument (var , var .type , EllipsisExpr (), ARG_NAMED_OPT ) for var in vars ])
2099
+
2100
+ def make_init_arg (var : Var ) -> Argument :
2101
+ default = default_items .get (var .name (), None )
2102
+ kind = ARG_POS if default is None else ARG_OPT
2103
+ return Argument (var , var .type , default , kind )
2104
+
2086
2105
add_method ('__init__' , ret = NoneTyp (), name = info .name (),
2087
- args = [Argument (var , var . type , None , ARG_POS ) for var in vars ])
2106
+ args = [make_init_arg (var ) for var in vars ])
2088
2107
add_method ('_asdict' , args = [], ret = ordereddictype )
2089
2108
add_method ('_make' , ret = selftype , is_classmethod = True ,
2090
2109
args = [Argument (Var ('iterable' , iterable_type ), iterable_type , None , ARG_POS ),
0 commit comments