| #!/usr/bin/env python |
| # -*- coding: utf-8 -*- |
| """ |
| make-release |
| ~~~~~~~~~~~~ |
| |
| Helper script that performs a release. Does pretty much everything |
| automatically for us. |
| |
| :copyright: (c) 2011 by Armin Ronacher. |
| :license: BSD, see LICENSE for more details. |
| """ |
| import sys |
| import os |
| import re |
| from datetime import datetime, date |
| from subprocess import Popen, PIPE |
| |
| try: |
| import wheel |
| except ImportError: |
| wheel = None |
| |
| _date_strip_re = re.compile(r'(?<=\d)(st|nd|rd|th)') |
| |
| |
| def parse_changelog(): |
| with open('CHANGES') as f: |
| lineiter = iter(f) |
| for line in lineiter: |
| match = re.search('^Version\s+(.*)', line.strip()) |
| if match is None: |
| continue |
| length = len(match.group(1)) |
| version = match.group(1).strip() |
| if lineiter.next().count('-') != len(match.group(0)): |
| continue |
| while 1: |
| change_info = lineiter.next().strip() |
| if change_info: |
| break |
| |
| match = re.search(r'(?:codename (.*),\s*)?' |
| r'released on (\w+\s+\d+\w+\s+\d+)(?i)', |
| change_info) |
| if match is None: |
| continue |
| |
| codename, datestr = match.groups() |
| return version, parse_date(datestr), codename |
| |
| |
| def bump_version(version): |
| try: |
| parts = map(int, version.split('.')) |
| except ValueError: |
| fail('Current version is not numeric') |
| parts[-1] += 1 |
| return '.'.join(map(str, parts)) |
| |
| |
| def parse_date(string): |
| string = _date_strip_re.sub('', string) |
| return datetime.strptime(string, '%B %d %Y') |
| |
| |
| def set_filename_version(filename, version_number, pattern): |
| changed = [] |
| def inject_version(match): |
| before, old, after = match.groups() |
| changed.append(True) |
| return before + version_number + after |
| with open(filename) as f: |
| contents = re.sub(r"^(\s*%s\s*=\s*')(.+?)(')(?sm)" % pattern, |
| inject_version, f.read()) |
| |
| if not changed: |
| fail('Could not find %s in %s', pattern, filename) |
| |
| with open(filename, 'w') as f: |
| f.write(contents) |
| |
| |
| def set_init_version(version): |
| info('Setting __init__.py version to %s', version) |
| set_filename_version('jinja2/__init__.py', version, '__version__') |
| |
| |
| def set_setup_version(version): |
| info('Setting setup.py version to %s', version) |
| set_filename_version('setup.py', version, 'version') |
| |
| |
| def build_and_upload(): |
| cmd = [sys.executable, 'setup.py', 'release', 'sdist', 'upload'] |
| if wheel is not None: |
| cmd.insert(4, 'bdist_wheel') |
| Popen(cmd).wait() |
| |
| |
| def fail(message, *args): |
| print >> sys.stderr, 'Error:', message % args |
| sys.exit(1) |
| |
| |
| def info(message, *args): |
| print >> sys.stderr, message % args |
| |
| |
| def get_git_tags(): |
| return set(Popen(['git', 'tag'], stdout=PIPE).communicate()[0].splitlines()) |
| |
| |
| def git_is_clean(): |
| return Popen(['git', 'diff', '--quiet']).wait() == 0 |
| |
| |
| def make_git_commit(message, *args): |
| message = message % args |
| Popen(['git', 'commit', '-am', message]).wait() |
| |
| |
| def make_git_tag(tag): |
| info('Tagging "%s"', tag) |
| Popen(['git', 'tag', tag]).wait() |
| |
| |
| def main(): |
| os.chdir(os.path.join(os.path.dirname(__file__), '..')) |
| |
| rv = parse_changelog() |
| if rv is None: |
| fail('Could not parse changelog') |
| |
| version, release_date, codename = rv |
| dev_version = bump_version(version) + '-dev' |
| |
| info('Releasing %s (codename %s, release date %s)', |
| version, codename, release_date.strftime('%d/%m/%Y')) |
| tags = get_git_tags() |
| |
| if version in tags: |
| fail('Version "%s" is already tagged', version) |
| if release_date.date() != date.today(): |
| fail('Release date is not today (%s != %s)', release_date.date(), date.today()) |
| |
| if not git_is_clean(): |
| fail('You have uncommitted changes in git') |
| |
| if wheel is None: |
| print ('Warning: You need to install the wheel package ' |
| 'to upload a wheel distribution.') |
| |
| set_init_version(version) |
| set_setup_version(version) |
| make_git_commit('Bump version number to %s', version) |
| make_git_tag(version) |
| build_and_upload() |
| set_init_version(dev_version) |
| set_setup_version(dev_version) |
| |
| |
| if __name__ == '__main__': |
| main() |