~ubuntu-branches/ubuntu/trusty/python-babel/trusty

« back to all changes in this revision

Viewing changes to scripts/make-release.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2013-10-28 10:11:31 UTC
  • mfrom: (4.1.2 sid)
  • Revision ID: package-import@ubuntu.com-20131028101131-zwbmm8sc29iemmlr
Tags: 1.3-2ubuntu1
* Merge from Debian unstable.  Remaining changes:
  - debian/rules: Run the testsuite during builds.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/env python
 
2
# -*- coding: utf-8 -*-
 
3
"""
 
4
    make-release
 
5
    ~~~~~~~~~~~~
 
6
 
 
7
    Helper script that performs a release.  Does pretty much everything
 
8
    automatically for us.
 
9
 
 
10
    :copyright: (c) 2013 by Armin Ronacher.
 
11
    :license: BSD, see LICENSE for more details.
 
12
"""
 
13
import sys
 
14
import os
 
15
import re
 
16
from datetime import datetime, date
 
17
from subprocess import Popen, PIPE
 
18
 
 
19
_date_clean_re = re.compile(r'(\d+)(st|nd|rd|th)')
 
20
 
 
21
 
 
22
def parse_changelog():
 
23
    with open('CHANGES') as f:
 
24
        lineiter = iter(f)
 
25
        for line in lineiter:
 
26
            match = re.search('^Version\s+(.*)', line.strip())
 
27
            if match is None:
 
28
                continue
 
29
            length = len(match.group(1))
 
30
            version = match.group(1).strip()
 
31
            if lineiter.next().count('-') != len(match.group(0)):
 
32
                continue
 
33
            while 1:
 
34
                change_info = lineiter.next().strip()
 
35
                if change_info:
 
36
                    break
 
37
 
 
38
            match = re.search(r'released on (\w+\s+\d+\w+\s+\d+)'
 
39
                              r'(?:, codename (.*))?(?i)', change_info)
 
40
            if match is None:
 
41
                continue
 
42
 
 
43
            datestr, codename = match.groups()
 
44
            return version, parse_date(datestr), codename
 
45
 
 
46
 
 
47
def bump_version(version):
 
48
    try:
 
49
        parts = map(int, version.split('.'))
 
50
    except ValueError:
 
51
        fail('Current version is not numeric')
 
52
    if parts[-1] != 0:
 
53
        parts[-1] += 1
 
54
    else:
 
55
        parts[0] += 1
 
56
    return '.'.join(map(str, parts))
 
57
 
 
58
 
 
59
def parse_date(string):
 
60
    string = _date_clean_re.sub(r'\1', string)
 
61
    return datetime.strptime(string, '%B %d %Y')
 
62
 
 
63
 
 
64
def set_filename_version(filename, version_number, pattern):
 
65
    changed = []
 
66
    def inject_version(match):
 
67
        before, old, after = match.groups()
 
68
        changed.append(True)
 
69
        return before + version_number + after
 
70
    with open(filename) as f:
 
71
        contents = re.sub(r"^(\s*%s\s*=\s*')(.+?)(')(?sm)" % pattern,
 
72
                          inject_version, f.read())
 
73
 
 
74
    if not changed:
 
75
        fail('Could not find %s in %s', pattern, filename)
 
76
 
 
77
    with open(filename, 'w') as f:
 
78
        f.write(contents)
 
79
 
 
80
 
 
81
def set_init_version(version):
 
82
    info('Setting __init__.py version to %s', version)
 
83
    set_filename_version('babel/__init__.py', version, '__version__')
 
84
 
 
85
 
 
86
def set_setup_version(version):
 
87
    info('Setting setup.py version to %s', version)
 
88
    set_filename_version('setup.py', version, 'version')
 
89
 
 
90
 
 
91
def build_and_upload():
 
92
    Popen([sys.executable, 'setup.py', 'release', 'sdist', 'upload']).wait()
 
93
 
 
94
 
 
95
def fail(message, *args):
 
96
    print >> sys.stderr, 'Error:', message % args
 
97
    sys.exit(1)
 
98
 
 
99
 
 
100
def info(message, *args):
 
101
    print >> sys.stderr, message % args
 
102
 
 
103
 
 
104
def get_git_tags():
 
105
    return set(Popen(['git', 'tag'], stdout=PIPE).communicate()[0].splitlines())
 
106
 
 
107
 
 
108
def git_is_clean():
 
109
    return Popen(['git', 'diff', '--quiet']).wait() == 0
 
110
 
 
111
 
 
112
def make_git_commit(message, *args):
 
113
    message = message % args
 
114
    Popen(['git', 'commit', '-am', message]).wait()
 
115
 
 
116
 
 
117
def make_git_tag(tag):
 
118
    info('Tagging "%s"', tag)
 
119
    Popen(['git', 'tag', tag]).wait()
 
120
 
 
121
 
 
122
def main():
 
123
    os.chdir(os.path.join(os.path.dirname(__file__), '..'))
 
124
 
 
125
    rv = parse_changelog()
 
126
    if rv is None:
 
127
        fail('Could not parse changelog')
 
128
 
 
129
    version, release_date, codename = rv
 
130
    dev_version = bump_version(version) + '-dev'
 
131
 
 
132
    info('Releasing %s (codename %s, release date %s)',
 
133
         version, codename, release_date.strftime('%d/%m/%Y'))
 
134
    tags = get_git_tags()
 
135
 
 
136
    if version in tags:
 
137
        fail('Version "%s" is already tagged', version)
 
138
    if release_date.date() != date.today():
 
139
        fail('Release date is not today (%s != %s)')
 
140
 
 
141
    if not git_is_clean():
 
142
        fail('You have uncommitted changes in git')
 
143
 
 
144
    set_init_version(version)
 
145
    set_setup_version(version)
 
146
    make_git_commit('Bump version number to %s', version)
 
147
    make_git_tag(version)
 
148
    build_and_upload()
 
149
    set_init_version(dev_version)
 
150
    set_setup_version(dev_version)
 
151
 
 
152
 
 
153
if __name__ == '__main__':
 
154
    main()