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

Source Code for Module Products.ZenUtils.Version

  1  ############################################################################## 
  2  #  
  3  # Copyright (C) Zenoss, Inc. 2007, all rights reserved. 
  4  #  
  5  # This content is made available according to terms specified in 
  6  # License.zenoss under the directory where your Zenoss product is installed. 
  7  #  
  8  ############################################################################## 
  9   
 10   
 11  """ 
 12  Zenoss versioning module. 
 13   
 14  """ 
 15  import re 
 16   
17 -def getVersionTupleFromString(versionString):
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
67 -class VersionError(Exception):
68 pass
69
70 -class IncomparableVersions(VersionError):
71 pass
72
73 -class ComponentVersionError(VersionError):
74 pass
75
76 -class VersionNotSupported(VersionError):
77 pass
78
79 -class Version(object):
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
157 - def short(self):
158 """ 159 Returns a string of just the version number. 160 """ 161 return '%d.%d.%d' % (self.major, self.minor, self.micro)
162
163 - def long(self):
164 """ 165 Returns a string with the software name and the version. 166 """ 167 return "%s %s" % (self.name, self.short())
168
169 - def full(self):
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
179 - def tuple(self):
180 """ 181 Return a version tuple. 182 """ 183 return (self.major, self.minor, self.micro)
184
185 - def incrMajor(self):
186 self.major += 1
187
188 - def incrMinor(self):
189 self.minor += 1
190
191 - def incrMicro(self):
192 self.micro += 1
193
194 - def setComment(self, comment):
195 self.comment = comment
196
197 - def __cmp__(self, other):
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
217 - def _formatSVNRevision(self):
218 svnrev = self.revision 219 if svnrev: 220 svnrev = ' r%s' % svnrev 221 else: 222 svnrev = '' 223 return svnrev
224
225 - def __repr__(self):
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
234 - def __str__(self):
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 #raise str(versionParts) 288 try: 289 # we want to always have a tuple of the right size returned, 290 # regardless of the number of elements in ther 'versions' iterable 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
305 -def _test():
306 import doctest 307 doctest.testmod()
308 309 if __name__ == '__main__': 310 _test() 311