from string.templatelib import Template, Interpolation print("\n=== Edge cases ===") t_empty = Template() print(f"Empty template: '{t_empty}'") t_empty_strs = Template("", Interpolation(1, "a"), "", Interpolation(2, "b"), "") print(f"Empty strings: {list(t_empty_strs)}") t_adj = t"{1}{2}{3}" print(f"Adjacent: '{t_adj}'") t_single = Template("only") print(f"Single iter: {list(t_single)}") t_self = t"test" print(f"Self+self: '{(t_self + t_self)}'") print("\n=== Additional coverage tests ===") t_str_literal = t"{'hello'}" print(f"String literal: {t_str_literal}") path = "/usr/local/bin" count = 42 raw_path = rt"Path: {path}\n" print(f"Raw path strings: {raw_path.strings}, value={raw_path.interpolations[0].value}") raw_regex = rt"Regex: \\d+{count}" print(f"Raw regex strings: {raw_regex.strings}, value={raw_regex.interpolations[0].value}") try: t_str_expr = t'{"test"}' print(f"String expr: '{t_str_expr}'") except Exception as e: print(f"String expr error: {e}") def raise_error(): raise ValueError("Special error") try: t_exc = t"{raise_error()}" print(t_exc) except ValueError as e: print(f"Re-raised exception: {e}") try: large_str = "x" * 100000 exec(f'very_long_name_{large_str} = t"test"') except (ValueError, MemoryError, SyntaxError, RuntimeError) as e: print("Large template: SyntaxError") try: exec('''t_triple = t"""Triple "quoted" string"""''') print(f"Triple quoted: '{t_triple}'") except Exception as e: print(f"Triple quoted error: {e}") try: exec(r'''t_raw_triple = rt"""Raw triple\n{42}"""''') print(f"Raw triple: '{t_raw_triple}'") except Exception as e: print(f"Raw triple error: {e}") t_concat1 = t"a{1}b" t_concat2 = t"c{2}d{3}e" t_concat3 = t_concat1 + t_concat2 print(f"Complex concat: strings={t_concat3.strings}, values={t_concat3.values}") t_empty = Template() t_nonempty = t"test{42}" t_concat_empty = t_empty + t_nonempty print(f"Empty concat: '{t_concat_empty}'") t_self_interp = t"x{1}y" t_self_concat = t_self_interp + t_self_interp print(f"Self interp concat: values={t_self_concat.values}") try: exec('t"unterminated') except SyntaxError as e: print(f"Lonely string: {type(e).__name__}") try: t_edge = t"" print(f"Empty t-string: '{t_edge}'") except Exception as e: print(f"Empty t-string error: {e}") print("\n=== High byte handling ===") try: result = t'\x7F\x80\x81\xFE\xFF' first_str = result.strings[0] print(f"High bytes: len={len(first_str)}, first=0x{ord(first_str[0]):02x}, last=0x{ord(first_str[-1]):02x}") except Exception as e: print(f"High bytes error: {e}") try: result = t'\200\201\377' print(f"Octal high bytes: OK, len={len(result.strings[0])}") except Exception as e: print(f"Octal high bytes error: {e}") print("\n=== Deep nesting test ===") try: nested = "1" + " + 1" * 150 code = f't"{{{nested}}}"' exec(code) print("Deep nesting: OK") except Exception as e: print(f"Deep nesting error: {type(e).__name__}") print("\n=== Trailing whitespace in expression ===") try: x = 42 code = 't"{x }"' result = eval(code) print(f"Trailing whitespace: OK") except Exception as e: print(f"Trailing whitespace error: {e}") print("\n=== Single closing brace ===") try: exec('t"test }"') print("ERROR: Single } should have raised SyntaxError") except SyntaxError as e: print(f"Single }}: SyntaxError - {e}") print("\n=== Escape in string within interpolation ===") try: compile('x = 1; t"{x=:"', '', 'exec') except SyntaxError: print('Debug unclosed colon: SyntaxError') try: compile('x = 1; t"{x=!"', '', 'exec') except SyntaxError: print('Debug unclosed exclaim: SyntaxError') try: compile('t"prefix{incomplete"', '', 'exec') except SyntaxError as e: print('Unclosed brace literal: SyntaxError') try: import sys if hasattr(sys.implementation, '_mpy'): compile('f"{x!invalid}"', '', 'exec') except SyntaxError: print('Malformed f-string: SyntaxError') # NOTE: Error messages are shortened in MicroPython to avoid stack overflow # during ROM compression on constrained platforms (Windows x86, ASan). # CPython 3.14 message: "Template.__new__ *args need to be of type 'str' or 'Interpolation', got int" # MicroPython message: "Template.__new__ args must be str or Interpolation, got 'int'" try: t = Template("string", 123) except TypeError as e: print('Type error int:', e) try: t = Template("a", "b", 3.14) except TypeError: print('Type error float: TypeError') try: compile('t"text { more text"', '', 'exec') except SyntaxError as e: print('Unmatched brace:', e) try: compile('x=1; t"{x= {nested}}"', '', 'exec') except SyntaxError: print('Nested debug braces: SyntaxError') try: compile('t"{x!}"', '', 'exec') except SyntaxError: print('Missing conversion: SyntaxError') try: compile('t"{x!z}"', '', 'exec') except SyntaxError as e: print('Invalid conversion:', e) try: compile('t"{x!r' + chr(0x0b) + ':10}"', '', 'exec') except SyntaxError as e: print('Vertical tab:', e) try: compile('t"{x!r@:10}"', '', 'exec') except SyntaxError as e: print('Invalid char after conversion:', e) # MicroPython doesn't allow space after conversion. # try: # x = 'test' # exec('result = t"{x!r :10}"') # print('Space after conversion: OK') # except Exception as e: # print(f'Unexpected error: {e}') try: x = 'test' exec('result = t"{x!s\\t:10}"') print('Tab after conversion: OK') except Exception as e: print(f'Unexpected error: {e}') try: x = 'test' exec('result = t"{x!r\\n:10}"') print('Newline after conversion: OK') except Exception as e: print(f'Unexpected error: {e}') try: x = 'test' exec('result = t"{x!r\\r:10}"') print('CR after conversion: OK') except Exception as e: print(f'Unexpected error: {e}') try: x = 'test' exec('result = t"{x!s\\f:10}"') print('Form-feed after conversion: OK') except Exception as e: print(f'Unexpected error: {e}') print("\n=== Mixed prefixes ===") for src in ('ft"{x}"', 'tf"{x}"', 'frt"{x}"', 'rtf"{x}"', 'trf"{x}"'): try: exec(src) print(src.split('"')[0] + ": OK (BUG!)") except SyntaxError as e: prefix = src.split('"')[0] # Check if we get the specific error message or generic one if "'f' and 't' prefixes are incompatible" in str(e): print(f"{prefix}: incompatible prefixes") else: print(f"{prefix}: invalid syntax")