|
| 1 | +# A silly idea by Andrea Giammarchi |
| 2 | +from string import Template as _Template |
| 3 | + |
| 4 | +# The goal of this utility is to create a JS |
| 5 | +# Template Literal Tag like function that accepts |
| 6 | +# an immutable template as tuple and zero or more ordered |
| 7 | +# interpolated values per each gap between chunks. |
| 8 | +# If a cache dictionary is passed, it never parses the same |
| 9 | +# template string more than once, improving performance |
| 10 | +# for more complex scenarios / use cases. |
| 11 | +def tag(fn, cache=None): |
| 12 | + return lambda tpl, **kw: _tag(tpl, cache)(fn, **kw) |
| 13 | + |
| 14 | +def _create(tpl): |
| 15 | + i = 0 |
| 16 | + d = {} |
| 17 | + u = chr(0) |
| 18 | + template = _Template(tpl) |
| 19 | + identifiers = template.get_identifiers() |
| 20 | + # map all identifiers as chunks that |
| 21 | + # can be split without losing details |
| 22 | + for k in identifiers: |
| 23 | + d[k] = f"{u}{i}." |
| 24 | + i += 1 |
| 25 | + s = template.substitute(d) |
| 26 | + a = s.split(u) |
| 27 | + i = 1 |
| 28 | + keys = [] |
| 29 | + # create a template after removing chunks |
| 30 | + # leftovers, placing back ordered expected fields |
| 31 | + for k in a[1:]: |
| 32 | + d = k.index(".") |
| 33 | + x = k[0:d] |
| 34 | + keys.append(identifiers[int(x)]) |
| 35 | + a[i] = k[(d+1):] |
| 36 | + i += 1 |
| 37 | + # make the template immutable |
| 38 | + t = tuple(a) |
| 39 | + return lambda fn, **kw: fn(t, *[kw[k] for k in keys]) |
| 40 | + |
| 41 | +# given a template string, maps all non interpolated |
| 42 | +# parts as tuple and orchestrate ordered values to send |
| 43 | +def _tag(tpl, tags): |
| 44 | + if tags == None: return _create(tpl) |
| 45 | + if not tpl in tags: tags[tpl] = _create(tpl) |
| 46 | + return tags[tpl] |
0 commit comments