-
-
Notifications
You must be signed in to change notification settings - Fork 33k
Description
Bug report
Bug description:
Hi, I generated some code and experienced a difficulty generating the ast of template-strings.
ast.unparse uses the str
attribute of the Interpolation to unparse it and ignores the value
attribute.
from ast import *
tree = TemplateStr(
values=[
Interpolation(value=Name(id="test1", ctx=Load()), str="test2", conversion=-1)
]
)
print(unparse(tree))
output (Python 3.14.0rc2+):
t'{test2}'
I know that it is important to preserve the original code because the formatting might be important, but this makes it difficult to generate correct AST.
from ast import *
code=Lambda(args=arguments(args=[arg(arg='a')]), body=Name(id='a', ctx=Load()))
tree = TemplateStr(
values=[
Interpolation(value=code, str=unparse(code), conversion=-1)
]
)
compile(unparse(tree),"<string>","exec")
output (Python 3.14.0rc2+):
Traceback (most recent call last):
File "/home/frank/projects/pysource-playground/pysource-codegen/example.py", line 12, in <module>
compile(unparse(tree),"<string>","exec")
~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<string>", line 1
t'{lambda a: a}'
^^^^^^^^^
SyntaxError: t-string: lambda expressions are not allowed without parentheses
The solution here can be to add "()" around all interpolations.
Another problem can be that you use interpolations inside interpolations, which means that you have to process the childs first.
This is my current workaround which fixes these issues for me:
def walk_childs_first(node):
for e in ast.iter_child_nodes(node):
yield from walk_childs_first(e)
yield e
def fix_result(node):
if sys.version_info >= (3, 14):
for n in walk_childs_first(node):
if isinstance(n, ast.Interpolation):
f_str = ast.JoinedStr(
[ast.FormattedValue(value=n.value, conversion=-1, format_spec=None)]
)
f_str_repr = ast.unparse(f_str)
if f_str_repr.startswith(("f'''", 'f"""')):
n.str = ast.unparse(f_str)[5:-4] # strip f"""{...}"""
else:
n.str = ast.unparse(f_str)[3:-2] # strip f"{...}"
I'm using the unparsing code for f-strings here to generate the correct source code.
I would like to know if there is something which I missed, or if this problem was just overlooked untill now.
I experienced this problem during my work on pysoruce-codegen and pysource-minimize. This might be the reason why this examples could look like some edge cases, but I think it can also be problematic for other people who just want to change the AST and unparse the code, because unparse would use the old code from str
and ignore the changed value
.
I have no idea how this could be solved but I think it should at least be mentioned in the docs.
Being able to set Interpolation.str
to None
could help with the unparse use case (it should unparse Interpolation.value
in this case), but I don't know if this could cause other problems.
CPython versions tested on:
3.14
Operating systems tested on:
No response