#!/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

_date_clean_re = re.compile(r'(\d+)(st|nd|rd|th)')


def installed_libraries():
    return Popen(['pip', 'freeze'], stdout=PIPE).communicate()[0]


def has_library_installed(library):
    return library + '==' in installed_libraries()


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

            version = match.group(1).strip()

            if lineiter.next().count('-') != len(line.strip()):
                fail('Invalid hyphen count below version line: %s', line.strip())

            while 1:
                released = lineiter.next().strip()
                if released:
                    break

            match = re.search(r'Released (\w+\s+\d+\w+\s+\d+)', released)

            if match is None:
                fail('Could not find release date in version %s' % version)

            datestr = parse_date(match.group(1).strip())

            return version, datestr


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_clean_re.sub(r'\1', 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('flask_jwt/__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 set_docs_version(version):
    info('Setting docs/conf.py version to %s', version)
    set_filename_version('docs/conf.py', version, 'version')


def build_and_upload():
    Popen([sys.executable, 'setup.py', 'sdist', 'build_sphinx', 'upload', 'upload_sphinx']).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', '-a', tag, '-m', '%s release' % tag]).wait()
    Popen(['git', 'push', '--tags']).wait()


def update_version(version):
    for f in [set_init_version, set_setup_version, set_docs_version]:
        f(version)


def get_branches():
    return set(Popen(['git', 'branch'], stdout=PIPE).communicate()[0].splitlines())


def branch_is(branch):
    return '* ' + branch in get_branches()


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 = rv

    tags = get_git_tags()

    for lib in ['Sphinx', 'Sphinx-PyPI-upload']:
        if not has_library_installed(lib):
            fail('Build requires that %s be installed', lib)

    if version in tags:
        fail('Version "%s" is already tagged', version)
    if release_date.date() != date.today():
        fail('Release date is not today')

    if not branch_is('master'):
        fail('You are not on the master branch')

    if not git_is_clean():
        fail('You have uncommitted changes in git')

    info('Releasing %s (release date %s)',
         version, release_date.strftime('%d/%m/%Y'))

    update_version(version)
    make_git_commit('Bump version number to %s', version)
    make_git_tag(version)
    build_and_upload()


if __name__ == '__main__':
    main()

Add release script