Skip to content

Commit bb69123

Browse files
committed
Fix :s format handling and tests
1 parent 841641d commit bb69123

2 files changed

Lines changed: 14 additions & 3 deletions

File tree

mypyc/irbuild/format_str_tokenizer.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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))

mypyc/test-data/irbuild-constant-fold.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ def f() -> str:
200200
def g() -> str:
201201
return FMT_D.format(400 + 20, "roll" + "up")
202202
def h() -> str:
203-
return FMT_S.format(400 + 20, "roll" + "up")
203+
return FMT_S.format("4" + "20", "roll" + "up")
204204

205205
[out]
206206
def f():
@@ -222,7 +222,7 @@ L0:
222222
def h():
223223
r0, r1, r2, r3 :: str
224224
L0:
225-
r0 = CPyTagged_Str(840)
225+
r0 = '420'
226226
r1 = 'rollup'
227227
r2 = ' '
228228
r3 = CPyStr_Build(3, r0, r2, r1)

0 commit comments

Comments
 (0)