Package buildbot :: Package process :: Module properties
[frames] | no frames]

Source Code for Module buildbot.process.properties

  1  import re 
  2  import weakref 
  3  from buildbot import util 
  4   
5 -class Properties(util.ComparableMixin):
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
23 - def __init__(self, **kwargs):
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
31 - def __getstate__(self):
32 d = self.__dict__.copy() 33 del d['pmap'] 34 return d
35
36 - def __setstate__(self, d):
37 self.__dict__ = d 38 self.pmap = PropertyMap(self)
39
40 - def __contains__(self, name):
41 return name in self.properties
42
43 - def __getitem__(self, name):
44 """Just get the value for this property.""" 45 rv = self.properties[name][0] 46 return rv
47
48 - def has_key(self, name):
49 return self.properties.has_key(name)
50
51 - def getProperty(self, name, default=None):
52 """Get the value for the given property.""" 53 return self.properties.get(name, (default,))[0]
54
55 - def getPropertySource(self, name):
56 return self.properties[name][1]
57
58 - def asList(self):
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
64 - def __repr__(self):
65 return repr(dict([ (k,v[0]) for k,v in self.properties.iteritems() ]))
66
67 - def setProperty(self, name, value, source):
68 self.properties[name] = (value, source)
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
75 - def updateFromProperties(self, other):
76 """Update this object based on another object; the other object's """ 77 self.properties.update(other.properties)
78
79 - def render(self, value):
80 """ 81 Return a variant of value that has any WithProperties objects 82 substituted. This recurses into Python's compound data types. 83 """ 84 # we use isinstance to detect Python's standard data types, and call 85 # this function recursively for the values in those types 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
99 -class PropertyMap:
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"(.*):\+(.*)")
106 - def __init__(self, properties):
107 # use weakref here to avoid a reference loop 108 self.properties = weakref.ref(properties)
109
110 - def __getitem__(self, key):
111 properties = self.properties() 112 assert properties is not None 113 114 # %(prop:-repl)s 115 # if prop exists, use it; otherwise, use repl 116 mo = self.colon_minus_re.match(key) 117 if mo: 118 prop, repl = mo.group(1,2) 119 if properties.has_key(prop): 120 rv = properties[prop] 121 else: 122 rv = repl 123 else: 124 # %(prop:+repl)s 125 # if prop exists, use repl; otherwise, an empty string 126 mo = self.colon_plus_re.match(key) 127 if mo: 128 prop, repl = mo.group(1,2) 129 if properties.has_key(prop): 130 rv = repl 131 else: 132 rv = '' 133 else: 134 rv = properties[key] 135 136 # translate 'None' to an empty string 137 if rv is None: rv = '' 138 return rv
139
140 -class WithProperties(util.ComparableMixin):
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
148 - def __init__(self, fmtstring, *args):
149 self.fmtstring = fmtstring 150 self.args = args
151
152 - def render(self, pmap):
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