Package ZenUtils :: Module Version
[hide private]
[frames] | no frames]

Source Code for Module ZenUtils.Version

  1  ########################################################################### 
  2  # 
  3  # This program is part of Zenoss Core, an open source monitoring platform. 
  4  # Copyright (C) 2007, Zenoss Inc. 
  5  # 
  6  # This program is free software; you can redistribute it and/or modify it 
  7  # under the terms of the GNU General Public License version 2 as published by 
  8  # the Free Software Foundation. 
  9  # 
 10  # For complete information please visit: http://www.zenoss.com/oss/ 
 11  # 
 12  ########################################################################### 
 13   
 14  """ 
 15  Zenoss versioning module. 
 16   
 17  """ 
 18  import re 
 19   
20 -def getVersionTupleFromString(versionString):
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
70 -class VersionError(Exception):
71 pass
72
73 -class IncomparableVersions(VersionError):
74 pass
75
76 -class ComponentVersionError(VersionError):
77 pass
78
79 -class VersionNotSupported(VersionError):
80 pass
81
82 -class Version(object):
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
160 - def short(self):
161 """ 162 Returns a string of just the version number. 163 """ 164 return '%d.%d.%d' % (self.major, self.minor, self.micro)
165
166 - def long(self):
167 """ 168 Returns a string with the software name and the version. 169 """ 170 return "%s %s" % (self.name, self.short())
171
172 - def full(self):
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
182 - def tuple(self):
183 """ 184 Return a version tuple. 185 """ 186 return (self.major, self.minor, self.micro)
187
188 - def incrMajor(self):
189 self.major += 1
190
191 - def incrMinor(self):
192 self.minor += 1
193
194 - def incrMicro(self):
195 self.micro += 1
196
197 - def setComment(self, comment):
198 self.comment = comment
199
200 - def __cmp__(self, other):
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
220 - def _formatSVNRevision(self):
221 svnrev = self.revision 222 if svnrev: 223 svnrev = ' r%s' % svnrev 224 else: 225 svnrev = '' 226 return svnrev
227
228 - def __repr__(self):
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
237 - def __str__(self):
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 #raise str(versionParts) 291 try: 292 # we want to always have a tuple of the right size returned, 293 # regardless of the number of elements in ther 'versions' iterable 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
308 -def _test():
309 import doctest 310 doctest.testmod()
311 312 if __name__ == '__main__': 313 _test() 314