3232 NameExpr ,
3333 PassStmt ,
3434 RefExpr ,
35+ Statement ,
3536 StrExpr ,
3637 SymbolTable ,
3738 SymbolTableNode ,
@@ -111,7 +112,7 @@ def analyze_namedtuple_classdef(
111112 if result is None :
112113 # This is a valid named tuple, but some types are incomplete.
113114 return True , None
114- items , types , default_items = result
115+ items , types , default_items , statements = result
115116 if is_func_scope and "@" not in defn .name :
116117 defn .name += "@" + str (defn .line )
117118 existing_info = None
@@ -123,31 +124,35 @@ def analyze_namedtuple_classdef(
123124 defn .analyzed = NamedTupleExpr (info , is_typed = True )
124125 defn .analyzed .line = defn .line
125126 defn .analyzed .column = defn .column
127+ defn .defs .body = statements
126128 # All done: this is a valid named tuple with all types known.
127129 return True , info
128130 # This can't be a valid named tuple.
129131 return False , None
130132
131133 def check_namedtuple_classdef (
132134 self , defn : ClassDef , is_stub_file : bool
133- ) -> tuple [list [str ], list [Type ], dict [str , Expression ]] | None :
135+ ) -> tuple [list [str ], list [Type ], dict [str , Expression ], list [ Statement ] ] | None :
134136 """Parse and validate fields in named tuple class definition.
135137
136- Return a three tuple:
138+ Return a four tuple:
137139 * field names
138140 * field types
139141 * field default values
142+ * valid statements
140143 or None, if any of the types are not ready.
141144 """
142145 if self .options .python_version < (3 , 6 ) and not is_stub_file :
143146 self .fail ("NamedTuple class syntax is only supported in Python 3.6" , defn )
144- return [], [], {}
147+ return [], [], {}, []
145148 if len (defn .base_type_exprs ) > 1 :
146149 self .fail ("NamedTuple should be a single base" , defn )
147150 items : list [str ] = []
148151 types : list [Type ] = []
149152 default_items : dict [str , Expression ] = {}
153+ statements : list [Statement ] = []
150154 for stmt in defn .defs .body :
155+ statements .append (stmt )
151156 if not isinstance (stmt , AssignmentStmt ):
152157 # Still allow pass or ... (for empty namedtuples).
153158 if isinstance (stmt , PassStmt ) or (
@@ -160,9 +165,13 @@ def check_namedtuple_classdef(
160165 # And docstrings.
161166 if isinstance (stmt , ExpressionStmt ) and isinstance (stmt .expr , StrExpr ):
162167 continue
168+ statements .pop ()
169+ defn .removed_statements .append (stmt )
163170 self .fail (NAMEDTUP_CLASS_ERROR , stmt )
164171 elif len (stmt .lvalues ) > 1 or not isinstance (stmt .lvalues [0 ], NameExpr ):
165172 # An assignment, but an invalid one.
173+ statements .pop ()
174+ defn .removed_statements .append (stmt )
166175 self .fail (NAMEDTUP_CLASS_ERROR , stmt )
167176 else :
168177 # Append name and type in this case...
@@ -199,7 +208,7 @@ def check_namedtuple_classdef(
199208 )
200209 else :
201210 default_items [name ] = stmt .rvalue
202- return items , types , default_items
211+ return items , types , default_items , statements
203212
204213 def check_namedtuple (
205214 self , node : Expression , var_name : str | None , is_func_scope : bool
0 commit comments