@@ -38,9 +38,11 @@ class FormatOp(Enum):
3838 For example, to mark a conversion from any object to string,
3939 ConversionSpecifier may have several representations, like '%s', '{}'
4040 or '{:{}}'. However, there would only exist one corresponding FormatOp.
41+ The ':s' format code is stricter and maps to STR_ONLY.
4142 """
4243
4344 STR = "s"
45+ STR_ONLY = "s_only"
4446 INT = "d"
4547 BYTES = "b"
4648
@@ -53,8 +55,10 @@ def generate_format_ops(specifiers: list[ConversionSpecifier]) -> list[FormatOp]
5355 format_ops = []
5456 for spec in specifiers :
5557 # TODO: Match specifiers instead of using whole_seq
56- if spec .whole_seq == "%s" or spec .whole_seq in ( "{:{}}" , ":s" ) :
58+ if spec .whole_seq == "%s" or spec .whole_seq == "{:{}}" :
5759 format_op = FormatOp .STR
60+ elif spec .whole_seq == ":s" :
61+ format_op = FormatOp .STR_ONLY
5862 elif spec .whole_seq in ("%d" , ":d" ):
5963 format_op = FormatOp .INT
6064 elif spec .whole_seq == "%b" :
@@ -152,6 +156,13 @@ def convert_format_expr_to_str(
152156 var_str = builder .primitive_op (int_to_str_op , [builder .accept (x )], line )
153157 else :
154158 var_str = builder .primitive_op (str_op , [builder .accept (x )], line )
159+ elif format_op == FormatOp .STR_ONLY :
160+ if isinstance (folded := constant_fold_expr (builder , x ), str ):
161+ var_str = builder .load_literal_value (folded )
162+ elif is_str_rprimitive (node_type ):
163+ var_str = builder .accept (x )
164+ else :
165+ return None
155166 elif format_op == FormatOp .INT :
156167 if isinstance (folded := constant_fold_expr (builder , x ), int ):
157168 var_str = builder .load_literal_value (str (folded ))
0 commit comments