I have this code that parses and processes normal "f-string" template strings (See the usage part below for an example):
from string import Formatter
import sys
_conversions = {'a': ascii, 'r': repr, 's': str}
def z(template, locals_=None):
if locals_ is None:
previous_frame = sys._getframe(1)
previous_frame_locals = previous_frame.f_locals
locals_ = previous_frame_locals
# locals_ = globals()
result = []
parts = Formatter().parse(template)
for part in parts:
literal_text, field_name, format_spec, conversion = part
if literal_text:
result.append(literal_text)
if not field_name:
continue
value = eval(field_name, locals_) #.__format__()
if conversion:
value = _conversions[conversion](value)
if format_spec:
value = format(value, format_spec)
else:
value = str(value)
result.append(value)
res = ''.join(result)
return res
Usage:
a = 'World'
b = 10
z('Hello {a} --- {a:^30} --- {67+b} --- {a!r}')
# "Hello World --- World --- 77 --- 'World'"
But it doesn't work if the template string is something like this:
z('''
echo monkey {z("curl -s https://www.poemist.com/api/v1/randompoems | jq --raw-output '.[0].content'")} end | sed -e 's/monkey/start/'
echo --------------
''')
It gives this error:
File "<string>", line 1
z("curl -s https
^
SyntaxError: EOL while scanning string literal
I am willing to even copy code from Python's source code to get this to work, if it's not possible normally.
ast
module. It allows you to parse your string as if it were a regular f-string:ast.parse('f"Hello, {a} --- {67+b}"')
. Then you want the generated tree and process it the way you want – Twoway{}
in format strings. You need to pull thecurl
part out into a separate variable instead of nesting calls toz()
. – Rabbitfish:
is quoted in them.) – Photoflashast
? For example_ast.FormattedValue
to astring
? – Photoflashast.dump(tree_node)
to see what attributes each node has. Then walk the tree with a subclass ofast.NodeVisitor
and check the attributes of each node. Forf"{a}"
you can retrieve the stringa
like this:FormattedValue_node.value.id
. For more details, see Python's grammar. – Twoway