please icon indicating copy to clipboard operation
please copied to clipboard

str.format(): issue with parsing parentheses

Open SkeneZr opened this issue 9 months ago • 3 comments

I think there's a bug in the str.format() function, following the please update from version 16.19.0 to version 17.14.0, there's a regression on my use of the str.format() function:

In older version, I did something like this:

    cmd = """
    cat > $OUT << EOF
{{
  "name": "{name}",
  "version": "{version}",
}}
EOF
  """.format(
        name = API_NAME,
        version = API_VERSION,
    ),

I got this:

{
  "name": "api_name",
  "version": "X.1.0",
}

but after updating, I got:

{{
  "name": "{name}",
  "version": "X.1.0",
}}

I tried several modifications to find a solution, with something like this:

    cmd = """
    cat > $OUT << EOF
{
  "name": "{name}",
  "version": "{version}",
}
EOF
  """.format(
        name = NAME,
        version = VERSION,
    ),

with this result:

{
  "name": "{name}",
  "version": "X.1.0",
}

If I change order like this:

    cmd = """
    cat > $OUT << EOF
{
  "version": "{version}",
  "name": "{name}",
}
EOF
  """.format(
        name = NAME,
        version = VERSION,
    ),

result:

{
  "version": "{version}",
  "name": "api_name",
}

finally, I had a brace:

    cmd = """
    cat > $OUT << EOF
{
  "name": "}{name}",
  "version": "{version}",
}
EOF
  """.format(
        name = NAME,
        version = VERSION,
    ),

result:

{
  "name": "}api_name",
  "version": "X.1.0",
}

So maybe I miss understood something about str.format() and skipping brace, or this function don't skip any opened brace and wait a closed brace.

SkeneZr avatar Mar 20 '25 09:03 SkeneZr

Please could you provide a complete BUILD file with a minimal illustrative example?

Out of curiosity, do you get the same behaviour when using f-strings?

toastwaffle avatar Mar 20 '25 10:03 toastwaffle

This is a simple genrule that fills a file with variables from build_defs/defaults.build_defs (API_NAME, API_VERSION)

genrule(
    name = "version",
    out = "src/www/version",
    cmd = """
    cat > $OUT << EOF
{{
  "name": "{name}",
  "version": "{version}",
  "release": "{release}"
}}
EOF
  """.format(
        name = API_NAME,
        version = API_VERSION,
        release = "dev",
    ),
    visibility = [
        "//package/...",
    ],
)
``

I dont know how to use variable of default file with f-string, I have error if I write `${API_NAME}`

SkeneZr avatar Mar 20 '25 11:03 SkeneZr

FYI we now have a json() built in that can take a python dict and product a json string output for it.

This does seem like a bug though. We should be following the behaviour that python has, which would convert {{ and }} into { and }.

Tatskaari avatar Jul 22 '25 09:07 Tatskaari