File: set_version.py

package info (click to toggle)
python-gevent 1.0.1-2
  • links: PTS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 9,948 kB
  • ctags: 12,954
  • sloc: python: 39,061; ansic: 26,289; sh: 13,582; makefile: 833; awk: 18
file content (157 lines) | stat: -rwxr-xr-x 4,547 bytes parent folder | download
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/usr/bin/python
"""Update __version__, version_info and add __changeset__.

'dev' in version_info should be replaced with alpha|beta|candidate|final
'dev' in __version__ should be replaced with a|b|rc|<empty string>
"""

import sys
import os
import re
from optparse import OptionParser
from distutils.version import LooseVersion


version_re = re.compile("^__version__\s*=\s*'([^']+)'", re.M)
version_info_re = re.compile(r"^version_info\s*=\s*([^\n]+)", re.M)
strict_version_re = re.compile(r'^(\d+) \. (\d+) (\. (\d+))? ([ab](\d+))?$', re.VERBOSE)


def read(command):
    popen = os.popen(command)
    data = popen.read()
    retcode = popen.close()
    if retcode:
        sys.exit('Failed (%s) to run %r' % (retcode, command))
    return data.strip()


def get_changeset():
    return read('git describe --tags --always --dirty --long')


def get_version_info(version):
    """
    >>> get_version_info('0.13.6')
    (0, 13, 6, 'final', 0)
    >>> get_version_info('1.1')
    (1, 1, 0, 'final', 0)
    >>> get_version_info('1')
    (1, 0, 0, 'final', 0)
    >>> get_version_info('1.0dev1')
    (1, 0, 0, 'dev', 1)
    >>> get_version_info('1.0a3')
    (1, 0, 0, 'alpha', 3)
    >>> get_version_info('1.0rc1')
    (1, 0, 0, 'candidate', 1)
    """

    repl = {'a': 'alpha',
            'b': 'beta',
            'rc': 'candidate',
            'dev': 'dev'}

    components = LooseVersion(version).version
    result = []

    for component in components:
        if isinstance(component, int):
            result.append(component)
        else:
            while len(result) < 3:
                result.append(0)
            component = repl[component]
            result.append(component)

    while len(result) < 3:
        result.append(0)

    if len(result) == 3:
        result.append('final')
        result.append(0)

    return tuple(result)


def modify_version(filename, new_version):
    # return (current_contents, modified_contents, is_match)
    original_data = open(filename).read()
    assert '__changeset__' not in original_data, 'Must revert the old update first'
    data = original_data

    if new_version:
        new_version_info = get_version_info(new_version)

        def repl_version_info(m):
            return 'version_info = %s' % (new_version_info, )

        data, count = version_info_re.subn(repl_version_info, data)
        if not count:
            raise AssertionError('version_info not found in %s' % filename)
        if count != 1:
            raise AssertionError('version_info found more than once in %s' % filename)

    def repl_version(m):
        result = m.group(0).replace(m.group(1), new_version or m.group(1))
        result += "\n__changeset__ = '%s'" % get_changeset()
        return result

    data, count = version_re.subn(repl_version, data)
    if not count:
        raise AssertionError('__version__ not found in %s' % filename)
    if count != 1:
        raise AssertionError('__version__ found more than once in %s' % filename)

    return original_data, data


def unlink(path):
    try:
        os.unlink(path)
    except OSError, ex:
        if ex.errno == 2:  # No such file or directory
            return
        raise


def write(filename, data):
    # intentionally breaking links here so that util/makedist.py can use "cp --link"
    tmpname = filename + '.tmp.%s' % os.getpid()
    f = open(tmpname, 'w')
    try:
        f.write(data)
        f.flush()
        os.fsync(f.fileno())
        f.close()
        os.rename(tmpname, filename)
    except:
        unlink(tmpname)
        raise


def main():
    global options
    parser = OptionParser()
    parser.add_option('--version', default='dev')
    parser.add_option('--dry-run', action='store_true')
    options, args = parser.parse_args()
    assert len(args) == 1, 'One argument is expected, got %s' % len(args)
    version = options.version
    if version.lower() == 'dev':
        version = ''
    if version and strict_version_re.match(version) is None:
        sys.stderr.write('WARNING: Not a strict version: %r (bdist_msi will fail)' % version)
    filename = args[0]
    original_content, new_content = modify_version(filename, version)
    if options.dry_run:
        tmpname = '/tmp/' + os.path.basename(filename) + '.set_version'
        write(tmpname, new_content)
        if not os.system('diff -u %s %s' % (filename, tmpname)):
            sys.exit('No differences applied')
    else:
        write(filename, new_content)
        print 'Updated %s' % filename


if __name__ == '__main__':
    main()