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

# Source Code for Module Products.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 or (at your
      8  # option) any later version as published by 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 any(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