@@ -715,14 +715,14 @@ def read_class_def(state: State, data: ReadBuffer) -> ClassDef:
715715 keywords .append ((key , value ))
716716
717717 metaclass = dict (keywords ).get ("metaclass" ) if keywords else None
718- filtered_keywords = [(k , v ) for k , v in keywords if k != "metaclass" ] if keywords else None
719718
720719 class_def = ClassDef (
721720 name ,
722721 body ,
723722 base_type_exprs = base_type_exprs if base_type_exprs else None ,
724723 metaclass = metaclass ,
725- keywords = filtered_keywords ,
724+ # Note we keep metaclass in keywords as well, to match the old parser.
725+ keywords = keywords if keywords else None ,
726726 type_args = type_params ,
727727 )
728728 class_def .decorators = decorators
@@ -1329,15 +1329,16 @@ def read_expression(state: State, data: ReadBuffer) -> Expression:
13291329 op = bool_ops [read_int (data )]
13301330 values = read_expression_list (state , data )
13311331 # Convert list of values to nested OpExpr nodes
1332- # E.g., [a, b, c] with "and" becomes OpExpr("and", OpExpr("and", a, b), c)
1332+ # E.g., [a, b, c] with "and" becomes OpExpr("and", a, OpExpr("and", b, c))
1333+ # This matches the old parser behavior, on which we may implicitly rely.
13331334 assert len (values ) >= 2
1334- result = values [0 ]
1335- for val in values [1 : ]:
1336- result = OpExpr (op , result , val )
1337- result .line = values [ 0 ] .line
1338- result .column = values [ 0 ] .column
1339- result .end_line = val .end_line
1340- result .end_column = val .end_column
1335+ result = last = values [- 1 ]
1336+ for val in values [- 2 :: - 1 ]:
1337+ result = OpExpr (op , val , result )
1338+ result .line = val .line
1339+ result .column = val .column
1340+ result .end_line = last .end_line
1341+ result .end_column = last .end_column
13411342 read_loc (data , result )
13421343 expect_end_tag (data )
13431344 return result
@@ -1375,7 +1376,7 @@ def read_expression(state: State, data: ReadBuffer) -> Expression:
13751376 s = StrExpr (read_str (data ))
13761377 read_loc (data , s )
13771378 fitems .append (s )
1378- expr = build_fstring_join (state , data , fitems )
1379+ expr = build_fstring_join (data , fitems )
13791380 expect_end_tag (data )
13801381 return expr
13811382 elif tag == nodes .LIST_COMPREHENSION :
@@ -1576,22 +1577,17 @@ def read_expression(state: State, data: ReadBuffer) -> Expression:
15761577
15771578
15781579def read_fstring_items (state : State , data : ReadBuffer ) -> Expression :
1579- items = []
15801580 n = read_int (data )
1581- items = [read_fstring_item (state , data ) for i in range (n )]
1582- return build_fstring_join (state , data , items )
1581+ items = [read_fstring_item (state , data ) for _ in range (n )]
1582+ return build_fstring_join (data , items )
15831583
15841584
1585- def build_fstring_join (state : State , data : ReadBuffer , items : list [Expression ]) -> Expression :
1585+ def build_fstring_join (data : ReadBuffer , items : list [Expression ]) -> Expression :
1586+ items = collapse_consecutive_str_items (items )
15861587 if len (items ) == 1 :
15871588 expr = items [0 ]
15881589 read_loc (data , expr )
15891590 return expr
1590- if all (isinstance (item , StrExpr ) for item in items ):
1591- s = "" .join ([cast (StrExpr , item ).value for item in items ])
1592- expr = StrExpr (s )
1593- read_loc (data , expr )
1594- return expr
15951591 args = ListExpr (items )
15961592 str_expr = StrExpr ("" )
15971593 member = MemberExpr (str_expr , "join" )
@@ -1603,6 +1599,22 @@ def build_fstring_join(state: State, data: ReadBuffer, items: list[Expression])
16031599 return call
16041600
16051601
1602+ def collapse_consecutive_str_items (items : list [Expression ]) -> list [Expression ]:
1603+ if len (items ) <= 1 :
1604+ return items
1605+ last = items [0 ]
1606+ new_items = [last ]
1607+ for item in items [1 :]:
1608+ if isinstance (last , StrExpr ) and isinstance (item , StrExpr ):
1609+ last .value += item .value
1610+ last .end_line = item .end_line
1611+ last .end_column = item .end_column
1612+ else :
1613+ new_items .append (item )
1614+ last = item
1615+ return new_items
1616+
1617+
16061618def read_fstring_item (state : State , data : ReadBuffer ) -> Expression :
16071619 t = read_tag (data )
16081620 if t == LITERAL_STR :
0 commit comments