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 os 
 19  import re 
 20  import sys 
 21   
 22   
23 -def getVersionTupleFromString(versionString):
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
73 -class VersionError(Exception):
74 pass
75
76 -class IncomparableVersions(VersionError):
77 pass
78
79 -class ComponentVersionError(VersionError):
80 pass
81
82 -class VersionNotSupported(VersionError):
83 pass
84
85 -class Version(object):
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
163 - def short(self):
164 """ 165 Returns a string of just the version number. 166 """ 167 return '%d.%d.%d' % (self.major, self.minor, self.micro)
168
169 - def long(self):
170 """ 171 Returns a string with the software name and the version. 172 """ 173 return "%s %s" % (self.name, self.short())
174
175 - def full(self):
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
185 - def tuple(self):
186 """ 187 Return a version tuple. 188 """ 189 return (self.major, self.minor, self.micro)
190
191 - def incrMajor(self):
192 self.major += 1
193
194 - def incrMinor(self):
195 self.minor += 1
196
197 - def incrMicro(self):
198 self.micro += 1
199
200 - def setComment(self, comment):
201 self.comment = comment
202
203 - def __cmp__(self, other):
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
223 - def _formatSVNRevision(self):
224 svnrev = self.revision 225 if svnrev: 226 svnrev = ' r%s' % svnrev 227 else: 228 svnrev = '' 229 return svnrev
230
231 - def __repr__(self):
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
240 - def __str__(self):
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 #raise str(versionParts) 294 try: 295 # we want to always have a tuple of the right size returned, 296 # regardless of the number of elements in ther 'versions' iterable 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
311 -def _test():
312 import doctest 313 doctest.testmod()
314 315 if __name__ == '__main__': 316 _test() 317