1
2
3
4
5
6
7
8
9
10
11 """
12 Zenoss versioning module.
13
14 """
15 import re
16
18 """
19 A utility function for parsing dot-delimited stings as a version tuple.
20
21 # test some simple version formats
22 >>> version = '1'
23 >>> getVersionTupleFromString(version)
24 (1, 0, 0)
25 >>> version = '1.0'
26 >>> getVersionTupleFromString(version)
27 (1, 0, 0)
28 >>> version = '1.0.0'
29 >>> getVersionTupleFromString(version)
30 (1, 0, 0)
31 >>> version = '1.0.2'
32 >>> getVersionTupleFromString(version)
33 (1, 0, 2)
34
35 # here's one for Fedora
36 >>> version = '2.6.17-1.2174_FC5'
37 >>> getVersionTupleFromString(version)
38 (2, 6, 17)
39
40 # here's a bizzare one
41 >>> version = '1a.23zzX.abs'
42 >>> getVersionTupleFromString(version)
43 (1, 23, 0)
44
45 # checks against ints and floats being passed instead of strings
46 >>> version = 1
47 >>> getVersionTupleFromString(version)
48 (1, 0, 0)
49 >>> version = 1.0
50 >>> getVersionTupleFromString(version)
51 (1, 0, 0)
52 >>> version = 0
53 >>> getVersionTupleFromString(version)
54 (0, 0, 0)
55 >>> version = 'a.1.2'
56 >>> getVersionTupleFromString(version)
57 (0, 1, 2)
58 >>> version = ''
59 >>> getVersionTupleFromString(version)
60 (0, 0, 0)
61 """
62 versionString = str(versionString)
63 versions = re.split('[^0-9]+', versionString.strip())[:3]
64 versions = [int(x or 0) for x in versions] + [0, 0, 0]
65 return tuple(versions[:3])
66
69
72
75
78
80 """
81 A class for obtaining and manipulating version numbers as well as creating
82 the necessary version files Zenoss utilizes.
83
84 >>> v1 = Version('Zenoss', 0, 22)
85 >>> v2 = Version('Zenoss', 0, 23, 4)
86 >>> v3 = Version('Zenoss', 0, 23, 7)
87 >>> v4 = Version('Zenoss', 1)
88 >>> v5 = Version('Zenoss', 1, 0, 2)
89 >>> v6 = Version('Zenoss', 1, 0, 2)
90 >>> v7 = Version('Zenoss', 1, 0, 2, 15729)
91 >>> v8 = Version('Zenoss', 1, 0, 2, 15730)
92 >>> v9 = Version('Zenoss', 1, 0, 3, 15729)
93
94 # test the display methods
95 >>> v9.short()
96 '1.0.3'
97 >>> v9.long()
98 'Zenoss 1.0.3'
99 >>> v9.full()
100 'Zenoss 1.0.3 r15729'
101 >>> v2.tuple()
102 (0, 23, 4)
103
104 # comparisons
105 >>> v1 > v2
106 False
107 >>> v3 > v2
108 True
109 >>> v4 < v3
110 False
111 >>> v4 > v5
112 False
113 >>> v6 > v5
114 False
115 >>> v6 >= v5
116 True
117 >>> v6 == v5
118 True
119
120 # comparison, one with a revision number
121 >>> v7 > v6
122 False
123
124 # revision number comparisons
125 >>> v7 > v8
126 False
127 >>> v8 > v9
128 False
129
130 # comparing non-Version objects with Version objects
131 >>> '1.0.4' > v5
132 True
133 >>> (1,0,1) > v5
134 False
135 >>> 1 == v4
136 True
137 >>> v4 == 1.0
138 True
139 >>> '1.0' == v4
140 True
141
142 # comment/additional info
143 >>> v10 = v9
144 >>> v10.setComment('A super-secret squirrel release')
145 >>> v10.full()
146 'Zenoss 1.0.3 r15729 (A super-secret squirrel release)'
147 """
148 - def __init__(self, name, major=0, minor=0, micro=0, revision=0,
149 comment=''):
150 self.name = name
151 self.major = major
152 self.minor = minor
153 self.micro = micro
154 self.revision = revision
155 self.comment = str(comment)
156
158 """
159 Returns a string of just the version number.
160 """
161 return '%d.%d.%d' % (self.major, self.minor, self.micro)
162
164 """
165 Returns a string with the software name and the version.
166 """
167 return "%s %s" % (self.name, self.short())
168
170 """
171 Returns a string with the software name, the version number, and the
172 subversion revision number, if defined.
173 """
174 comment = ''
175 if self.comment:
176 comment = ' (' + self.comment + ')'
177 return "%s%s%s" % (self.long(), self._formatSVNRevision(), comment)
178
180 """
181 Return a version tuple.
182 """
183 return (self.major, self.minor, self.micro)
184
187
190
193
196
198 """
199 Comparse one verion to another. If the other version supplied is not a
200 Version instance, attempt coercion.
201
202 The assumption here is that any non-Version object being compared to a
203 Version object represents a verion of the same product with the same
204 name but a different version number.
205 """
206 if other is None:
207 return 1
208 if isinstance(other, tuple):
209 version = '.'.join(str(x) for x in other)
210 other = Version.parse("%s %s" % (self.name, version))
211 elif any(isinstance(other, x) for x in (str, int, float, long)):
212 other = Version.parse("%s %s" % (self.name, str(other)))
213 if self.name != other.name:
214 raise IncomparableVersions()
215 return cmp(self.tuple(), other.tuple())
216
224
226 return '%s(%s, %d, %d, %d,%s)' % (
227 self.__class__.__name__,
228 self.name,
229 self.major,
230 self.minor,
231 self.micro,
232 self._formatSVNRevision())
233
235 return '[%s, version %d.%d.%d%s]' % (
236 self.name,
237 self.major,
238 self.minor,
239 self.micro,
240 self._formatSVNRevision())
241
242 - def parse(cls, versionString):
243 """
244 Parse the version info from a string. This method is usable without
245 having instantiated Version, and returns an instantiation.
246
247 The expected form is the following:
248 software_name W.X.Y rZ
249 where W, X, and Y represent the major, minor, and micro version numbers
250 and Z is the subversion revision number.
251
252 Only the software name is required.
253
254 The version number is expected to have at least a major version number.
255 Minor and micro version numbers are optional, but if they are provided,
256 they must be dot-delimited.
257
258 Here are some example usages:
259
260 >>> v = Version.parse('Zenoss')
261 >>> repr(v)
262 'Version(Zenoss, 0, 0, 0,)'
263 >>> print v
264 [Zenoss, version 0.0.0]
265
266 >>> v = Version.parse('Zenoss 1')
267 >>> repr(v)
268 'Version(Zenoss, 1, 0, 0,)'
269 >>> print v
270 [Zenoss, version 1.0.0]
271
272 >>> v = Version.parse('Zenoss 0.26.4')
273 >>> repr(v)
274 'Version(Zenoss, 0, 26, 4,)'
275 >>> print v
276 [Zenoss, version 0.26.4]
277
278
279 >>> v = Version.parse('Zenoss 0.32.1 r13667')
280 >>> repr(v)
281 'Version(Zenoss, 0, 32, 1, r13667)'
282 >>> print v
283 [Zenoss, version 0.32.1 r13667]
284 """
285 versionParts = versionString.strip().split()
286 name = versionParts.pop(0)
287
288 try:
289
290
291 major, minor, micro = getVersionTupleFromString(
292 versionParts.pop(0))
293 try:
294 revision = versionParts.pop(0).strip('r')
295 except IndexError:
296 revision = ''
297 except IndexError:
298 major = minor = micro = 0
299 revision = ''
300 self = Version(name, major, minor, micro, revision)
301 return self
302 parse = classmethod(parse)
303
304
306 import doctest
307 doctest.testmod()
308
309 if __name__ == '__main__':
310 _test()
311