|
| 1 | +__all__ = ["t"] |
| 2 | + |
| 3 | + |
| 4 | +class Interpolation: |
| 5 | + def __init__(self, expr): |
| 6 | + self.expr = expr |
| 7 | + |
| 8 | + def __getattr__(self, name): |
| 9 | + expr = getattr(self, "expr") |
| 10 | + if name == "value": |
| 11 | + return eval(expr) |
| 12 | + if name == "expr": |
| 13 | + return expr |
| 14 | + if name == "conv": |
| 15 | + return None |
| 16 | + if name == "format_spec": |
| 17 | + return "" |
| 18 | + |
| 19 | + |
| 20 | +class Template: |
| 21 | + def __init__(self, args): |
| 22 | + self.args = tuple(args) |
| 23 | + |
| 24 | + def __getattr__(self, name): |
| 25 | + args = getattr(self, "args") |
| 26 | + if name == "args": |
| 27 | + return args |
| 28 | + if name == "strings": |
| 29 | + return args[::2] |
| 30 | + if name == "values": |
| 31 | + return [i.value for i in args[1::2]] |
| 32 | + if name == "interpolations": |
| 33 | + return args[1::2] |
| 34 | + |
| 35 | + def __str__(self): |
| 36 | + out = [] |
| 37 | + i = 0 |
| 38 | + for arg in getattr(self, "args"): |
| 39 | + out.append(i % 2 and str(arg.value) or arg) |
| 40 | + i += 1 |
| 41 | + return "".join(out) |
| 42 | + |
| 43 | + |
| 44 | +drop = lambda s: s.replace("{{", "\x01").replace("}}", "\x02") |
| 45 | +add = lambda s: s.replace("\x01", "{{").replace("\x02", "}}") |
| 46 | + |
| 47 | + |
| 48 | +# PEP750 shim as function for MicroPython or Pyodide until it lands |
| 49 | +def t(content): |
| 50 | + # sanitize brackets (drop double brackets) |
| 51 | + content = drop(content) |
| 52 | + # fail if the format string is not balanced |
| 53 | + if content.count("{") != content.count("}"): |
| 54 | + raise ValueError("single '{' or '}' encountered in format string") |
| 55 | + # find outer most interesting curly braces |
| 56 | + l = len(content) |
| 57 | + i = 0 |
| 58 | + j = 0 |
| 59 | + start = 0 |
| 60 | + opened = 0 |
| 61 | + args = [] |
| 62 | + for c in content: |
| 63 | + if c == "{": |
| 64 | + if opened == 0: |
| 65 | + j = i |
| 66 | + opened += 1 |
| 67 | + elif c == "}": |
| 68 | + opened -= 1 |
| 69 | + if opened == 0: |
| 70 | + args.append(add(content[start:j:])) |
| 71 | + args.append(Interpolation(add(content[j + 1 : i :]))) |
| 72 | + start = i + 1 |
| 73 | + i += 1 |
| 74 | + args.append(add(content[start::])) |
| 75 | + return Template(args) |
0 commit comments