1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 """ This class enables developer to use ${xxx} pattern in their dict and
21 get them replaced recursively.
22 """
23 import re
24 import types
25 import UserDict
26
27
29 """ Internal class
30 """
32 string = ""
33 for elem in self:
34 string += " "+elem
35 return string
36
37
39 """ Implements a dictionary that escapes the key values recursively. """
40
41 - def __init__(self, dict={}, failonerror=False):
42 UserDict.UserDict.__init__(self, dict)
43 self.__failonerror = failonerror
44
46 """ Overrides the usual __getitem__ to insert values of other keys referenced in this key's
47 value. """
48 if key in self.data:
49 value = self.data[key]
50 result = value
51 if isinstance(value, types.ListType):
52 result = _CustomArray()
53 for elem in value:
54 (string, changes) = re.subn(r'\${(?P<name>[._a-zA-Z0-9]+)}', r'%(\g<name>)s', elem)
55 if changes > 0:
56 result.append(string % self)
57 else:
58 result.append(elem)
59 else:
60 (string, changes) = re.subn(r'\${(?P<name>[._a-zA-Z0-9]+)}', r'%(\g<name>)s', value)
61 if changes > 0:
62 result = string % self
63 return result
64 elif not self.__failonerror:
65 return "${%s}" % key
66 raise KeyError("Could not find key '%s'" % key)
67
68
69
71 """ Escape a string recursively.
72
73 :param input_string: the string to be escaped.
74 :param config: a dictionnary containing the values to escape.
75 :return: the escaped string.
76 """
77 data = EscapedDict(config)
78 match = re.search(r'\${(?P<name>[._a-zA-Z0-9]+)}', input_string)
79 if match != None:
80 for property_name in match.groups():
81 property_value = data[property_name]
82 property_value = re.sub(r'\\', r'\\\\', property_value)
83 input_string = re.sub('\${' + property_name + '}', property_value, input_string)
84 return input_string
85