version.py 3.56 KB
Newer Older
1
2
3
4
5
6
#!/usr/bin/env python
#
# version.py - fslpy version information.
#
# Author: Paul McCarthy <pauldmccarthy@gmail.com>
#
7
"""The primary purpose of this module is as a container for the ``fslpy``
8
version number. A handful of convenience functions for managing version
9
numbers are also defined here.
10
11

.. autosummary::
12
   :nosignatures:
13
14

   __version__
15
16
   parseVersionString
   compareVersions
17
   patchVersion
18
19
20


The ``fslpy`` version number consists of three numbers, separated by a period,
21
22
23
roughly obeys the Semantic Versioning conventions (http://semver.org/), and
is compatible with PEP 440 (https://www.python.org/dev/peps/pep-0440/):

24
25
26
27
28
29
30
31

 1. The major release number. This gets updated for major/external releases.

 2. The minor release number. This gets updated for minor/internal releases,
    which involve new features, bug-fixes, and other updates.

 3. The point release number. This gets updated for minor/internal releases,
    which primarily involve bug-fixes and minor changes.
32
33


Paul McCarthy's avatar
Paul McCarthy committed
34
The sole exception to the above convention are development versions, which end
35
in ``'.dev'``.
36
37
"""

38

39
40
41
import os.path as op
import            re
import            string
42
43


Paul McCarthy's avatar
Paul McCarthy committed
44
__version__ = '1.8.0.dev0'
45
"""Current version number, as a string. """
46
47
48
49
50
51
52
53
54
55
56
57


def parseVersionString(versionString):
    """Parses the given version string, and returns a tuple containing
    the individual components of the version number (see the description
    of the :attr:`__version__` attribute).

    An error is raised if the ``versionString`` is invalid.
    """

    components = versionString.split('.')

58
    # Truncate after three elements -
Paul McCarthy's avatar
Paul McCarthy committed
59
    # a development (unreleased version
60
61
62
63
64
65
    # number will end with '.dev', but
    # we ignore this for the purposes of
    # comparison.
    if len(components) == 4 and components[3] == 'dev':
        components = components[:3]

66
67
    # Major, minor, and point
    # version are always numeric
68
69
    major, minor, point = [c for c in components]

70
    # But early versions of FSLeyes
71
72
73
74
    # used a letter at the end
    # to denote a hotfix release.
    # Don't break if we get one
    # of these old version numbers.
75
    point = point.rstrip(string.ascii_letters)
76

77
    return [int(c) for c in [major, minor, point]]
78
79
80
81
82
83
84
85
86
87
88
89
90
91


def compareVersions(v1, v2, ignorePoint=False):
    """Compares the given ``fslpy`` version numbers.

    :arg v1:          Version number to compare
    :arg v2:          Version number to compare
    :arg ignorePoint: Defaults to ``False``. If ``True``, the point release
                      numbers are ignored in the comparison.

    :returns: One of the following:

                - -1 if ``v1`` < ``v2`` (i.e. ``v1`` is older than ``v2``)
                -  0 if ``v1`` == ``v2``
Paul McCarthy's avatar
Paul McCarthy committed
92
                -  1 if ``v1`` > ``v2``
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
    """

    v1 = parseVersionString(v1)
    v2 = parseVersionString(v2)

    if ignorePoint:
        v1 = v1[:2]
        v2 = v2[:2]

    for p1, p2 in zip(v1, v2):

        if p1 > p2: return  1
        if p1 < p2: return -1

    return 0
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131


def patchVersion(filename, newversion):
    """Patches the given ``filename``, in place, with the given
    ``newversion``. Searches for a line of the form::

        __version__ = '<oldversion>'

    and replaces ``<oldversion>`` with ``newversion``.
    """
    filename = op.abspath(filename)

    with open(filename, 'rt') as f:
        lines = f.readlines()

    pattern = re.compile('^__version__ *= *\'.*\' *$')

    for i, line in enumerate(lines):
        if pattern.match(line):
            lines[i] = '__version__ = \'{0}\'\n'.format(newversion)
            break

    with open(filename, 'wt') as f:
        lines = f.writelines(lines)