Refactor brace handling in strFormat()
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:
- Escaped opening braces (
{{): Convert to single{ - Escaped closing braces (
}}): Convert to single} - Placeholder syntax (
{name}): Still interpolates variables (unchanged) - 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"
}
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).