Fix the formatter regex
Before: {{var}} -> {var}, but the regex matches at the inner brace, but re_replace returns the whole match (match.group(0) = "{var}") unchanged, passing "{{var}}" to Formatter. {{defined_var|def}} -> {{defined_var}}, because the regex matches at the inner brace and re_replace returns "{%s}" % key ("{defined_var}"), passing just "{{defined_var}}" to Formatter. {{undefined_var|def}} -> exception, because the regex again matches at the inner brace and re_replace returns default ("def"), passing "{def}" to Formatter which then fails as def is not a defined variable (assuming it isn't and allow_empty = False). {{undefined_var|defined_var}} -> value of defined_var, same as above, "{defined_var}" is passed to Formatter. By preventing the regex from matching at inner braces, none of these weird cases happen and even-braced strings are passed to Formatter unmodified. Change-Id: I8a74f9b4236ca7bcc72dd207fca23c2bf6a7c801 Co-Authored-By: Tomáš Janoušek <tomas.janousek@gooddata.com>
This commit is contained in:
parent
705051658f
commit
30fe5dae98
@ -81,19 +81,25 @@ class CustomFormatter(Formatter):
|
|||||||
Custom formatter to allow non-existing key references when formatting a
|
Custom formatter to allow non-existing key references when formatting a
|
||||||
string
|
string
|
||||||
"""
|
"""
|
||||||
_expr = '{({{)*(?:obj:)?(?P<key>\w+)(?:\|(?P<default>[\w\s]*))?}(}})*'
|
_expr = """
|
||||||
|
(?<!{){({{)* # non-pair opening {
|
||||||
|
(?:obj:)? # obj:
|
||||||
|
(?P<key>\w+) # key
|
||||||
|
(?:\|(?P<default>[\w\s]*))? # default fallback
|
||||||
|
}(}})*(?!}) # non-pair closing }
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, allow_empty=False):
|
def __init__(self, allow_empty=False):
|
||||||
super(CustomFormatter, self).__init__()
|
super(CustomFormatter, self).__init__()
|
||||||
self.allow_empty = allow_empty
|
self.allow_empty = allow_empty
|
||||||
|
|
||||||
def vformat(self, format_string, args, kwargs):
|
def vformat(self, format_string, args, kwargs):
|
||||||
matcher = re.compile(self._expr)
|
matcher = re.compile(self._expr, re.VERBOSE)
|
||||||
|
|
||||||
# special case of returning the object if the entire string
|
# special case of returning the object if the entire string
|
||||||
# matches a single parameter
|
# matches a single parameter
|
||||||
try:
|
try:
|
||||||
result = re.match('^%s$' % self._expr, format_string)
|
result = re.match('^%s$' % self._expr, format_string, re.VERBOSE)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
return format_string.format(**kwargs)
|
return format_string.format(**kwargs)
|
||||||
if result is not None:
|
if result is not None:
|
||||||
|
23
tests/yamlparser/fixtures/variable_escaping.xml
Normal file
23
tests/yamlparser/fixtures/variable_escaping.xml
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<project>
|
||||||
|
<actions/>
|
||||||
|
<description><!-- Managed by Jenkins Job Builder --></description>
|
||||||
|
<keepDependencies>false</keepDependencies>
|
||||||
|
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
|
||||||
|
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
|
||||||
|
<concurrentBuild>false</concurrentBuild>
|
||||||
|
<canRoam>true</canRoam>
|
||||||
|
<properties/>
|
||||||
|
<scm class="hudson.scm.NullSCM"/>
|
||||||
|
<builders>
|
||||||
|
<hudson.tasks.Shell>
|
||||||
|
<command>echo "{var}"
|
||||||
|
echo "{defined_var|def}"
|
||||||
|
echo "{undefined_var|def}"
|
||||||
|
echo "{undefined_var|defined_var}"
|
||||||
|
</command>
|
||||||
|
</hudson.tasks.Shell>
|
||||||
|
</builders>
|
||||||
|
<publishers/>
|
||||||
|
<buildWrappers/>
|
||||||
|
</project>
|
17
tests/yamlparser/fixtures/variable_escaping.yaml
Normal file
17
tests/yamlparser/fixtures/variable_escaping.yaml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
- project:
|
||||||
|
name: test_template_variable_escaping
|
||||||
|
jobs:
|
||||||
|
- 'template_variable_escaping':
|
||||||
|
defined_var: 'Hello'
|
||||||
|
|
||||||
|
- job-template:
|
||||||
|
name: 'template_variable_escaping'
|
||||||
|
builders:
|
||||||
|
- shell: |
|
||||||
|
echo "{{var}}"
|
||||||
|
echo "{{defined_var|def}}"
|
||||||
|
echo "{{undefined_var|def}}"
|
||||||
|
echo "{{undefined_var|defined_var}}"
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user