Welcome, guest | Sign In | My Account | Store | Cart

This module provide useful class for manipulating with version info in the form: major.minor.release.build

Main operations is comparing between different versions. Also it could be useful for pretty formatting of version numbers, or to use as container for version info.

Loaded with examples (they actually are doctests for this module).

Python, 134 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# (C) Alexander Belchenko, 2007

"""This module provide useful class for manipulating
with version info in the form:

    major.minor.release.build

Main operations is comparing between different versions


Examples:

>>> v1 = VersionInfo('1')
>>> print v1
1.0
>>> print `v1`
VersionInfo('1.0.0.0')
>>> print '%(major)d.%(minor)d.%(release)d.%(build)d' % v1
1.0.0.0

>>> v2 = VersionInfo((2, 0))
>>> print v2
2.0

>>> v2 == '2.0.0.0'
True
>>> v1 == v2
False
>>> v1 < v2
True

>>> v3 = VersionInfo([2,0,3,4])
>>> print v3
2.0.3.4
>>> v3.major
2
>>> v3.minor
0
>>> v3.release
3
>>> v3.build
4

>>> v3 > v2
True

>>> v4 = VersionInfo('3.34')
>>> v5 = VersionInfo('3.3')
>>> v4 > v5
True

>>> v1 > '0.9'
True
>>> v2 >= '2.0'
True
>>> v3 > (2,0,2,5)
True
>>> v3 > (2,0,3,1)
True
>>> v4 > '2.0'
True

>>> '0.9' < v1 < '1.1'
True
>>> ('0.9' < v5 < '1.1') or v5 == '3.3'
True
"""


class VersionInfo(object):
    """Version info container and comparator"""

    __slots__ = ['major', 'minor', 'release', 'build']

    def __init__(self, v):
        if isinstance(v, basestring):
            # convert string to list
            v = [int(i) for i in v.split('.')]
        else:
            v = list(v)
        # build from sequence
        size = len(v)
        if size > 4:
            raise ValueError('Incorrect version info format. '
                             'Accepted max 4 numbers')
        if size < 4:
            v += [0] * (4-size)

        for ix, name in enumerate(self.__slots__):
            num = int(v[ix])
            setattr(self, name, num)

    def __getitem__(self, name):
        return getattr(self, name)

    def __repr__(self):
        return ("VersionInfo('%(major)d.%(minor)d.%(release)d.%(build)d')"
                % self)

    def __str__(self):
        if self.build > 0:
            fmt = '%(major)d.%(minor)d.%(release)d.%(build)d'
        elif self.release > 0:
            fmt = '%(major)d.%(minor)d.%(release)d'
        else:
            fmt = '%(major)d.%(minor)d'
        return fmt % self

    def __cmp__(self, other):
        """Called for objects comparison.
        Return a negative integer if self < other,
        zero if self == other,
        a positive integer if self > other.
        """
        if not isinstance(other, VersionInfo):
            other = VersionInfo(other)
        res = 0
        for name in self.__slots__:
            res = getattr(self, name) - getattr(other, name)
            if res != 0:
                break
        return res


def _test():
    import doctest
    doctest.testmod()


if __name__ == '__main__':
    print '*' * 70
    print 'T E S T'
    print '*' * 70
    _test()