Merge branch 'varfind-cleanups' of git://github.com/dhozac/ansible into devel
This commit is contained in:
commit
f8e946b71d
2 changed files with 47 additions and 37 deletions
|
@ -220,36 +220,39 @@ def parse_json(raw_data):
|
||||||
|
|
||||||
_LISTRE = re.compile(r"(\w+)\[(\d+)\]")
|
_LISTRE = re.compile(r"(\w+)\[(\d+)\]")
|
||||||
|
|
||||||
class VarNotFoundException(Exception):
|
def _varFindLimitSpace(space, part, depth):
|
||||||
pass
|
if space is None:
|
||||||
|
return space
|
||||||
def _varLookup(path, vars, depth=0):
|
if part[0] == '{' and part[-1] == '}':
|
||||||
''' find the contents of a possibly complex variable in vars. '''
|
part = part[1:-1]
|
||||||
|
part = varReplace(part, vars, depth=depth + 1)
|
||||||
space = vars
|
if part in space:
|
||||||
for part in path:
|
space = space[part]
|
||||||
part = varReplace(part, vars, depth=depth + 1)
|
elif "[" in part:
|
||||||
if part in space:
|
m = _LISTRE.search(part)
|
||||||
space = space[part]
|
if not m:
|
||||||
elif "[" in part:
|
return None
|
||||||
m = _LISTRE.search(part)
|
else:
|
||||||
if not m:
|
|
||||||
raise VarNotFoundException()
|
|
||||||
try:
|
try:
|
||||||
space = space[m.group(1)][int(m.group(2))]
|
space = space[m.group(1)][int(m.group(2))]
|
||||||
except (KeyError, IndexError):
|
except (KeyError, IndexError):
|
||||||
raise VarNotFoundException()
|
return None
|
||||||
else:
|
else:
|
||||||
raise VarNotFoundException()
|
return None
|
||||||
return space
|
return space
|
||||||
|
|
||||||
def _varFind(text):
|
def _varFind(text, vars, depth=0):
|
||||||
start = text.find("$")
|
start = text.find("$")
|
||||||
if start == -1:
|
if start == -1:
|
||||||
return None
|
return None
|
||||||
var_start = start + 1
|
# $ as last character
|
||||||
if var_start >= len(text):
|
if start + 1 == len(text):
|
||||||
return None
|
return None
|
||||||
|
# Escaped var
|
||||||
|
if start > 0 and text[start - 1] == '\\':
|
||||||
|
return {'replacement': '$', 'start': start - 1, 'end': start + 1}
|
||||||
|
|
||||||
|
var_start = start + 1
|
||||||
if text[var_start] == '{':
|
if text[var_start] == '{':
|
||||||
is_complex = True
|
is_complex = True
|
||||||
brace_level = 1
|
brace_level = 1
|
||||||
|
@ -260,6 +263,7 @@ def _varFind(text):
|
||||||
end = var_start
|
end = var_start
|
||||||
path = []
|
path = []
|
||||||
part_start = (var_start, brace_level)
|
part_start = (var_start, brace_level)
|
||||||
|
space = vars
|
||||||
while end < len(text) and ((is_complex and brace_level > 0) or not is_complex):
|
while end < len(text) and ((is_complex and brace_level > 0) or not is_complex):
|
||||||
if text[end].isalnum() or text[end] == '_':
|
if text[end].isalnum() or text[end] == '_':
|
||||||
pass
|
pass
|
||||||
|
@ -271,10 +275,7 @@ def _varFind(text):
|
||||||
pass
|
pass
|
||||||
elif is_complex and text[end] == '.':
|
elif is_complex and text[end] == '.':
|
||||||
if brace_level == part_start[1]:
|
if brace_level == part_start[1]:
|
||||||
if text[part_start[0]] == '{':
|
space = _varFindLimitSpace(space, text[part_start[0]:end], depth)
|
||||||
path.append(text[part_start[0] + 1:end - 1])
|
|
||||||
else:
|
|
||||||
path.append(text[part_start[0]:end])
|
|
||||||
part_start = (end + 1, brace_level)
|
part_start = (end + 1, brace_level)
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
|
@ -284,8 +285,10 @@ def _varFind(text):
|
||||||
var_end -= 1
|
var_end -= 1
|
||||||
if text[var_end] != '}' or brace_level != 0:
|
if text[var_end] != '}' or brace_level != 0:
|
||||||
return None
|
return None
|
||||||
path.append(text[part_start[0]:var_end])
|
if var_end == part_start[0]:
|
||||||
return {'path': path, 'start': start, 'end': end}
|
return None
|
||||||
|
space = _varFindLimitSpace(space, text[part_start[0]:var_end], depth)
|
||||||
|
return {'replacement': space, 'start': start, 'end': end}
|
||||||
|
|
||||||
def varReplace(raw, vars, depth=0, expand_lists=False):
|
def varReplace(raw, vars, depth=0, expand_lists=False):
|
||||||
''' Perform variable replacement of $variables in string raw using vars dictionary '''
|
''' Perform variable replacement of $variables in string raw using vars dictionary '''
|
||||||
|
@ -297,7 +300,7 @@ def varReplace(raw, vars, depth=0, expand_lists=False):
|
||||||
done = [] # Completed chunks to return
|
done = [] # Completed chunks to return
|
||||||
|
|
||||||
while raw:
|
while raw:
|
||||||
m = _varFind(raw)
|
m = _varFind(raw, vars, depth)
|
||||||
if not m:
|
if not m:
|
||||||
done.append(raw)
|
done.append(raw)
|
||||||
break
|
break
|
||||||
|
@ -305,13 +308,12 @@ def varReplace(raw, vars, depth=0, expand_lists=False):
|
||||||
# Determine replacement value (if unknown variable then preserve
|
# Determine replacement value (if unknown variable then preserve
|
||||||
# original)
|
# original)
|
||||||
|
|
||||||
try:
|
replacement = m['replacement']
|
||||||
replacement = _varLookup(m['path'], vars, depth)
|
if expand_lists and isinstance(replacement, (list, tuple)):
|
||||||
if expand_lists and isinstance(replacement, (list, tuple)):
|
replacement = ",".join(replacement)
|
||||||
replacement = ",".join(replacement)
|
if isinstance(replacement, (str, unicode)):
|
||||||
if isinstance(replacement, (str, unicode)):
|
replacement = varReplace(replacement, vars, depth=depth+1, expand_lists=expand_lists)
|
||||||
replacement = varReplace(replacement, vars, depth=depth+1, expand_lists=expand_lists)
|
if replacement is None:
|
||||||
except VarNotFoundException:
|
|
||||||
replacement = raw[m['start']:m['end']]
|
replacement = raw[m['start']:m['end']]
|
||||||
|
|
||||||
start, end = m['start'], m['end']
|
start, end = m['start'], m['end']
|
||||||
|
@ -362,12 +364,12 @@ def varReplaceWithItems(basedir, varname, vars):
|
||||||
''' helper function used by with_items '''
|
''' helper function used by with_items '''
|
||||||
|
|
||||||
if isinstance(varname, basestring):
|
if isinstance(varname, basestring):
|
||||||
m = _varFind(varname)
|
m = _varFind(varname, vars)
|
||||||
if not m:
|
if not m:
|
||||||
return varname
|
return varname
|
||||||
if m['start'] == 0 and m['end'] == len(varname):
|
if m['start'] == 0 and m['end'] == len(varname):
|
||||||
try:
|
try:
|
||||||
return varReplaceWithItems(basedir, _varLookup(m['path'], vars), vars)
|
return varReplaceWithItems(basedir, m['replacement'], vars)
|
||||||
except VarNotFoundException:
|
except VarNotFoundException:
|
||||||
return varname
|
return varname
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -230,6 +230,14 @@ class TestUtils(unittest.TestCase):
|
||||||
res = ansible.utils.varReplace(template, vars, expand_lists=True)
|
res = ansible.utils.varReplace(template, vars, expand_lists=True)
|
||||||
assert res == 'yum pkg=foo,bar,baz state=installed'
|
assert res == 'yum pkg=foo,bar,baz state=installed'
|
||||||
|
|
||||||
|
def test_varReplace_escaped_var(self):
|
||||||
|
vars = {
|
||||||
|
'foo': 'bar',
|
||||||
|
}
|
||||||
|
template = 'action \$foo'
|
||||||
|
res = ansible.utils.varReplace(template, vars)
|
||||||
|
assert res == 'action $foo'
|
||||||
|
|
||||||
def test_template_varReplace_iterated(self):
|
def test_template_varReplace_iterated(self):
|
||||||
template = 'hello $who'
|
template = 'hello $who'
|
||||||
vars = {
|
vars = {
|
||||||
|
|
Loading…
Reference in a new issue