Files
micropython/tests/basics/string_tstring_basic1.py
Koudai Aono bdef10a92b tests: Add full feature and coverage tests for PEP 750 template strings.
Includes corresponding .exp files because this feature is only available in
Python 3.14+.

Tests for `!a` conversion specifier and space after `!` are not included
because they are not supported by MicroPython.

Signed-off-by: Koudai Aono <koxudaxi@gmail.com>
Signed-off-by: Damien George <damien@micropython.org>
2026-03-09 23:47:33 +11:00

132 lines
3.7 KiB
Python

print("=== Parser error tests ===")
try:
exec('t_empty = t"{}"')
print(f"Empty expr: {t_empty.interpolations[0].value}")
except SyntaxError as e:
print(f"Empty expr: SyntaxError - {e}")
# Whitespace in expression (Python semantics are to strip trailing)
t_ws = t"{ 42 }"
print(f"Whitespace: {str(t_ws)}")
print("\n=== Error cases ===")
try:
exec('t"{@}"')
except SyntaxError:
print("Invalid syntax: SyntaxError")
try:
long_expr = "x" * 10001
exec(f't"{{{long_expr}}}"')
except (ValueError, SyntaxError, RuntimeError, NameError):
print("Long expr: Error")
try:
exec('t"hello" "world"')
except SyntaxError:
print("Mixed concat: SyntaxError")
try:
exec('bt"test"')
except SyntaxError:
print("bt prefix: SyntaxError")
print("\n=== Escape sequence coverage tests ===")
def expect_invalid_escape(label, expr):
try:
eval(expr)
except SyntaxError:
print(f"{label}: SyntaxError")
else:
print(f"{label}: ERROR (expected SyntaxError)")
# Deprecated escape sequences (CPython warns, MicroPython accepts as literal)
print(repr(t"\8"))
print(repr(t"\9"))
# Unknown escape chars
print(repr(t"\z"))
print(repr(t"\k"))
# Invalid escapes
expect_invalid_escape("Invalid \\x escape", 't"\\xGG"')
expect_invalid_escape("Invalid \\u escape", 't"\\uGGGG"')
expect_invalid_escape("Invalid \\U escape", 't"\\UGGGGGGGG"')
# Unicode escapes (display format differs)
print(repr(t"\x00\x01\xFF"))
print(repr(t"\u0041"))
print(repr(t"\u03B1"))
print(repr(t"\u2764"))
print(repr(t"\U00000041"))
print(repr(t"\U0001F600"))
print(repr(t"\x41\u0042\103"))
# Unicode in triple-quoted strings
unicode_test = t"""Unicode test:
Emoji: {'\U0001f40d'}
Special: {'\u03b1 \u03b2 \u03b3'}"""
print(f"Unicode: {str(unicode_test)}")
print("\n=== Trailing whitespace preservation (PEP 750) ===")
x = 42
tmpl_trail = t"{x }"
expr = tmpl_trail.interpolations[0].expression
print(f"Expression with trailing spaces: |{expr}|")
assert expr == "x", f"Expected 'x' but got '{expr}'"
assert len(expr) == 1, f"Expected length 1 but got {len(expr)}"
tmpl_both = t"{ x }"
expr2 = tmpl_both.interpolations[0].expression
print(f"Expression with both spaces: |{expr2}|")
assert expr2 == " x", f"Expected ' x' but got '{expr2}'"
assert len(expr2) == 4, f"Expected length 4 but got {len(expr2)}"
tmpl_lead = t"{ x}"
expr3 = tmpl_lead.interpolations[0].expression
print(f"Expression with leading spaces: |{expr3}|")
assert expr3 == " x", f"Expected ' x' but got '{expr3}'"
# Debug specifiers: leading space preserved, trailing space stripped from expression
# PEP 750: "Whitespace is preserved in the debug specifier" (in strings part)
z = 99
t_debug4 = t"{z =}"
assert t_debug4.strings == ("z =", "")
assert t_debug4.interpolations[0].expression == "z" # Trailing space stripped
assert t_debug4.interpolations[0].conversion == "r"
t_debug5 = t"{ z=}"
assert t_debug5.strings == (" z=", "")
assert t_debug5.interpolations[0].expression == " z" # Leading space preserved
assert t_debug5.interpolations[0].conversion == "r"
t_debug6 = t"{ z =}"
assert t_debug6.strings == (" z =", "")
assert t_debug6.interpolations[0].expression == " z" # Leading preserved, trailing stripped
assert t_debug6.interpolations[0].conversion == "r"
print("Trailing whitespace: PASS")
print("\n=== Error message tests ===")
try:
exec('t"}"')
except SyntaxError:
print("Lone }} rejected (correct)")
try:
exec('t"{"')
except SyntaxError:
print("Unterminated {{ rejected (correct)")
print("\n=== Triple quote empty interpolation ===")
try:
exec('''empty_interp = t"""Start
{}
End"""''')
print(f"Empty interpolation: {str(empty_interp)}")
except Exception as e:
print(f"Empty interpolation error: {type(e).__name__}: {e}")
print("\nIncompatible tests completed!")