please icon indicating copy to clipboard operation
please copied to clipboard

Refactor brace handling in strFormat()

Open scyyx5 opened this issue 1 month ago • 1 comments

Problem

The str.format() function in Please was not properly handling escaped braces ({{ and }}), which should be converted to single braces ({ and }) according to Python's standard behavior. This caused issues when users tried to generate JSON or other text with literal braces in BUILD files.

Bug Report: Issue #3356

Root Cause

The original implementation of strFormat() in builtins.go only looked for { followed by } to identify placeholders for variable interpolation. It did not check if braces were escaped by doubling them ({{ or }}), which is the standard Python syntax for literal braces.

Solution

Modified the strFormat() function (lines 585-672 in builtins.go) to implement a proper state machine that handles:

  1. Escaped opening braces ({{): Convert to single {
  2. Escaped closing braces (}}): Convert to single }
  3. Placeholder syntax ({name}): Still interpolates variables (unchanged)
  4. Shell variable syntax (${{var}}): Special case for Please - converts to ${var} (unchanged)

Example Behavior

Before the fix:

"{{hello}}".format()  # Returned: "{{hello}}"

After the fix:

"{{hello}}".format()  # Returns: "{hello}"

Real-world use case (from issue #3356):

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

Output:

{
  "name": "my_app",
  "version": "1.0.0"
}

scyyx5 avatar Nov 03 '25 15:11 scyyx5

I think #3412 fixes the same thing as this - @chrisnovakovic are you planning to push that forward?

Yes, I'm planning on addressing the remaining comments in #3412 (which really amount to comments and error messages).

chrisnovakovic avatar Nov 03 '25 17:11 chrisnovakovic