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