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