1 import re
2 import weakref
3 from buildbot import util
4
6 """
7 I represent a set of properties that can be interpolated into various
8 strings in buildsteps.
9
10 @ivar properties: dictionary mapping property values to tuples
11 (value, source), where source is a string identifing the source
12 of the property.
13
14 Objects of this class can be read like a dictionary -- in this case,
15 only the property value is returned.
16
17 As a special case, a property value of None is returned as an empty
18 string when used as a mapping.
19 """
20
21 compare_attrs = ('properties',)
22
24 """
25 @param kwargs: initial property values (for testing)
26 """
27 self.properties = {}
28 self.pmap = PropertyMap(self)
29 if kwargs: self.update(kwargs, "TEST")
30
32 d = self.__dict__.copy()
33 del d['pmap']
34 return d
35
39
42
44 """Just get the value for this property."""
45 rv = self.properties[name][0]
46 return rv
47
50
52 """Get the value for the given property."""
53 return self.properties.get(name, (default,))[0]
54
57
59 """Return the properties as a sorted list of (name, value, source)"""
60 l = [ (k, v[0], v[1]) for k,v in self.properties.items() ]
61 l.sort()
62 return l
63
65 return repr(dict([ (k,v[0]) for k,v in self.properties.iteritems() ]))
66
69
70 - def update(self, dict, source):
71 """Update this object from a dictionary, with an explicit source specified."""
72 for k, v in dict.items():
73 self.properties[k] = (v, source)
74
78
80 """
81 Return a variant of value that has any WithProperties objects
82 substituted. This recurses into Python's compound data types.
83 """
84
85
86 if isinstance(value, (str, unicode)):
87 return value
88 elif isinstance(value, WithProperties):
89 return value.render(self.pmap)
90 elif isinstance(value, list):
91 return [ self.render(e) for e in value ]
92 elif isinstance(value, tuple):
93 return tuple([ self.render(e) for e in value ])
94 elif isinstance(value, dict):
95 return dict([ (self.render(k), self.render(v)) for k,v in value.iteritems() ])
96 else:
97 return value
98
100 """
101 Privately-used mapping object to implement WithProperties' substitutions,
102 including the rendering of None as ''.
103 """
104 colon_minus_re = re.compile(r"(.*):-(.*)")
105 colon_plus_re = re.compile(r"(.*):\+(.*)")
109
139
141 """
142 This is a marker class, used fairly widely to indicate that we
143 want to interpolate build properties.
144 """
145
146 compare_attrs = ('fmtstring', 'args')
147
149 self.fmtstring = fmtstring
150 self.args = args
151
153 if self.args:
154 strings = []
155 for name in self.args:
156 strings.append(pmap[name])
157 s = self.fmtstring % tuple(strings)
158 else:
159 s = self.fmtstring % pmap
160 return s
161