classification
Title: ast.FormattedValue.format_spec unnecessarily wrapped in JoinedStr
Type: behavior Stage:
Components: Library (Lib) Versions: Python 3.9
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: BTaskaya, Ilya Kamenshchikov, eric.smith, serhiy.storchaka
Priority: normal Keywords:

Created on 2020-02-26 12:43 by Ilya Kamenshchikov, last changed 2020-03-04 19:58 by BTaskaya.

Messages (4)
msg362691 - (view) Author: Ilya Kamenshchikov (Ilya Kamenshchikov) * Date: 2020-02-26 12:43
Most usual usecase for format_spec is to specify it as a constant, that would be logical to represent as ast.Constant. However, ast.parse wraps value of ast.FormattedValue.format_spec into a JoinedStr with a single constant value, as can be seen from example below:


import ast

code = '''f"is {x:d}"'''
tree = ast.parse(code)

for n in ast.walk(tree):
    if isinstance(n, ast.FormattedValue):
        print(
            type(n.format_spec),
            len(n.format_spec.values),
            set(type(v) for v in n.format_spec.values),
        )

This is confusing for programmatically analyzing the ast, and likely creates some overhead in any modules using ast and FormattedValue.

Proposal: represent ast.FormattedValue.format_spec as ast.Constant in most cases.
msg362696 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2020-02-26 15:22
I agree that could probably be simplified, if the format_spec is constant (which it need not be).

>>> ast.dump(ast.parse('f"is {x:d}"'))

"Module(body=[Expr(value=JoinedStr(values=[Str(s='is '), FormattedValue(value=Name(id='x', ctx=Load()), conversion=-1, format_spec=JoinedStr(values=[Str(s='d')]))]))])"

But:

ast.dump(ast.parse('f"is {x:{length+1}d}"'))

"Module(body=[Expr(value=JoinedStr(values=[Str(s='is '), FormattedValue(value=Name(id='x', ctx=Load()), conversion=-1, format_spec=JoinedStr(values=[FormattedValue(value=BinOp(left=Name(id='length', ctx=Load()), op=Add(), right=Num(n=1)), conversion=-1, format_spec=None), Str(s='d')]))]))])"
msg362699 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2020-02-26 16:32
FYI you can use ast CLI:

$ echo 'f"is {x:d}"' | ./python -m ast
Module(
   body=[
      Expr(
         value=JoinedStr(
            values=[
               Constant(value='is ', kind=None),
               FormattedValue(
                  value=Name(id='x', ctx=Load()),
                  conversion=-1,
                  format_spec=JoinedStr(
                     values=[
                        Constant(value='d', kind=None)]))]))],
   type_ignores=[])
msg362741 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2020-02-26 21:22
> FYI you can use ast CLI:

I did not know that. That's awesome, thanks for pointing it out.
History
Date User Action Args
2020-03-04 19:58:04BTaskayasetnosy: + BTaskaya

versions: + Python 3.9, - Python 3.8
2020-02-26 21:22:15eric.smithsetmessages: + msg362741
2020-02-26 16:32:27serhiy.storchakasetnosy: + serhiy.storchaka
messages: + msg362699
2020-02-26 15:22:03eric.smithsetnosy: + eric.smith
messages: + msg362696
2020-02-26 12:43:02Ilya Kamenshchikovcreate