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