Add pypi_release.py.
I assume no responsibility for damages!
This commit is contained in:
		
							parent
							
								
									4717ccf84e
								
							
						
					
					
						commit
						4c497096fc
					
				
					 1 changed files with 420 additions and 0 deletions
				
			
		
							
								
								
									
										420
									
								
								pypi_release.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										420
									
								
								pypi_release.py
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,420 @@
 | 
				
			||||||
 | 
					import argparse
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					import shutil
 | 
				
			||||||
 | 
					import subprocess
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import textwrap
 | 
				
			||||||
 | 
					import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from voussoirkit import passwordy
 | 
				
			||||||
 | 
					from voussoirkit import winwhich
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					GIT = winwhich.which('git')
 | 
				
			||||||
 | 
					PY = winwhich.which('py')
 | 
				
			||||||
 | 
					TWINE = winwhich.which('twine')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BUMP_PATTERN = r'Bump to version (\d+\.\d+\.\d+)\.'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DEBUG = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PypiReleaseError(Exception):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class BadSetup(PypiReleaseError):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DirtyState(PypiReleaseError):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class NotSemver(PypiReleaseError):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class VersionOutOfOrder(PypiReleaseError):
 | 
				
			||||||
 | 
					    pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# HELPER FUNCTIONS
 | 
				
			||||||
 | 
					################################################################################
 | 
				
			||||||
 | 
					def bump_version(version, versionbump):
 | 
				
			||||||
 | 
					    (major, minor, patch) = [int(x) for x in version.split('.')]
 | 
				
			||||||
 | 
					    if versionbump == 'major':
 | 
				
			||||||
 | 
					        major += 1
 | 
				
			||||||
 | 
					        minor = 0
 | 
				
			||||||
 | 
					        patch = 0
 | 
				
			||||||
 | 
					    elif versionbump == 'minor':
 | 
				
			||||||
 | 
					        minor += 1
 | 
				
			||||||
 | 
					        patch = 0
 | 
				
			||||||
 | 
					    elif versionbump == 'patch':
 | 
				
			||||||
 | 
					        patch += 1
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        raise ValueError(f'versionbump should be major, minor, or patch, not {versionbump}.')
 | 
				
			||||||
 | 
					    version = f'{major}.{minor}.{patch}'
 | 
				
			||||||
 | 
					    return version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def check_call(command, show_command=True):
 | 
				
			||||||
 | 
					    if DEBUG or show_command:
 | 
				
			||||||
 | 
					        print_command(command)
 | 
				
			||||||
 | 
					    return subprocess.check_call(command)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def check_output(command, show_command=True):
 | 
				
			||||||
 | 
					    if DEBUG or show_command:
 | 
				
			||||||
 | 
					        print_command(command)
 | 
				
			||||||
 | 
					    return subprocess.check_output(command, stderr=subprocess.STDOUT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def pick_versionbump(major, minor, patch):
 | 
				
			||||||
 | 
					    mmp = (major, minor, patch)
 | 
				
			||||||
 | 
					    if not all(b in [True, False, None] for b in mmp):
 | 
				
			||||||
 | 
					        raise TypeError('major, minor, patch should all be True, False, or None.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if mmp in [(False, False, False), (None, None, None)]:
 | 
				
			||||||
 | 
					        versionbump = 'patch'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    elif mmp.count(True) > 1:
 | 
				
			||||||
 | 
					        raise TypeError('Must only pick one of major, minor, patch.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    elif major:
 | 
				
			||||||
 | 
					        versionbump = 'major'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    elif minor:
 | 
				
			||||||
 | 
					        versionbump = 'minor'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    elif patch:
 | 
				
			||||||
 | 
					        versionbump = 'patch'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        raise TypeError()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return versionbump
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def print_command(command):
 | 
				
			||||||
 | 
					    cmd = [('"%s"' % x) if (' ' in x or x == '') else x for x in command]
 | 
				
			||||||
 | 
					    cmd = ' '.join(cmd)
 | 
				
			||||||
 | 
					    cmd = cmd.strip()
 | 
				
			||||||
 | 
					    cmd = cmd.replace(GIT, 'git')
 | 
				
			||||||
 | 
					    cmd = cmd.replace(PY, 'py')
 | 
				
			||||||
 | 
					    cmd = cmd.replace(TWINE, 'twine')
 | 
				
			||||||
 | 
					    print(f'> {cmd}')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def semver_split(semver):
 | 
				
			||||||
 | 
					    original = semver
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        semver = semver.strip('v')
 | 
				
			||||||
 | 
					        mmp = semver.split('.')
 | 
				
			||||||
 | 
					        mmp = tuple(int(x) for x in mmp)
 | 
				
			||||||
 | 
					        (major, minor, patch) = mmp
 | 
				
			||||||
 | 
					        return mmp
 | 
				
			||||||
 | 
					    except Exception:
 | 
				
			||||||
 | 
					        raise NotSemver(original)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def slowprint(s=None):
 | 
				
			||||||
 | 
					    slow = 0.05
 | 
				
			||||||
 | 
					    if s is None:
 | 
				
			||||||
 | 
					        print()
 | 
				
			||||||
 | 
					        time.sleep(slow)
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					    for line in s.split('\n'):
 | 
				
			||||||
 | 
					        print(line)
 | 
				
			||||||
 | 
					        time.sleep(slow)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# SETUP.PY
 | 
				
			||||||
 | 
					################################################################################
 | 
				
			||||||
 | 
					def extract_info_from_setup():
 | 
				
			||||||
 | 
					    handle = open('setup.py', 'r', encoding='utf-8')
 | 
				
			||||||
 | 
					    with handle:
 | 
				
			||||||
 | 
					        setup_py = handle.read()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    name = re.findall(r'''\bname=["']([A-Za-z0-9_-]+)["']''', setup_py)
 | 
				
			||||||
 | 
					    if len(name) != 1:
 | 
				
			||||||
 | 
					        raise BadSetup(f'Expected to find 1 name but found {len(name)}.')
 | 
				
			||||||
 | 
					    name = name[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    version = re.findall(r'''\bversion=["'](\d+\.\d+\.\d+)["']''', setup_py)
 | 
				
			||||||
 | 
					    if len(version) != 1:
 | 
				
			||||||
 | 
					        raise BadSetup(f'Expected to find 1 version but found {len(version)}.')
 | 
				
			||||||
 | 
					    version = version[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (setup_py, name, version)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def update_info_in_setup(setup_py, name, version):
 | 
				
			||||||
 | 
					    re_from = fr'''\bname=(["'])({name})(["'])'''
 | 
				
			||||||
 | 
					    re_to = fr'''name=\1\2\3'''
 | 
				
			||||||
 | 
					    setup_py = re.sub(re_from, re_to, setup_py)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    re_from = fr'''\bversion=(["'])(\d+\.\d+\.\d+)(["'])'''
 | 
				
			||||||
 | 
					    re_to = fr'''version=\g<1>{version}\g<3>'''
 | 
				
			||||||
 | 
					    setup_py = re.sub(re_from, re_to, setup_py)
 | 
				
			||||||
 | 
					    return setup_py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def write_setup(setup_py):
 | 
				
			||||||
 | 
					    handle = open('setup.py', 'w', encoding='utf-8')
 | 
				
			||||||
 | 
					    with handle:
 | 
				
			||||||
 | 
					        handle.write(setup_py)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# GIT
 | 
				
			||||||
 | 
					################################################################################
 | 
				
			||||||
 | 
					def git_assert_current_greater_than_latest(latest_release_version, new_version):
 | 
				
			||||||
 | 
					    if latest_release_version >= semver_split(new_version):
 | 
				
			||||||
 | 
					        raise VersionOutOfOrder(f'New version should be {new_version} but {latest_release_version} already exists.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def git_assert_no_stashes():
 | 
				
			||||||
 | 
					    command = [GIT, 'stash', 'list']
 | 
				
			||||||
 | 
					    output = check_output(command, show_command=False)
 | 
				
			||||||
 | 
					    lines = output.strip().splitlines()
 | 
				
			||||||
 | 
					    if len(lines) != 0:
 | 
				
			||||||
 | 
					        raise DirtyState('Please ensure there are no stashes.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def git_assert_pushable():
 | 
				
			||||||
 | 
					    command = [GIT, 'fetch', '--all']
 | 
				
			||||||
 | 
					    check_output(command, show_command=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    command = [GIT, 'merge-base', '@', '@{u}']
 | 
				
			||||||
 | 
					    merge_base = check_output(command, show_command=False).strip()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    command = [GIT, 'rev-parse', '@']
 | 
				
			||||||
 | 
					    my_head = check_output(command, show_command=False).strip()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    command = [GIT, 'rev-parse', '@{u}']
 | 
				
			||||||
 | 
					    remote_head = check_output(command, show_command=False).strip()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if my_head == remote_head:
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					    elif my_head == merge_base:
 | 
				
			||||||
 | 
					        git_commits_since(merge_base.decode(), show=True, inclusive=True)
 | 
				
			||||||
 | 
					        raise DirtyState('Cant push, need to pull first.')
 | 
				
			||||||
 | 
					    elif remote_head == merge_base:
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        git_commits_since(merge_base.decode(), show=True, inclusive=True)
 | 
				
			||||||
 | 
					        raise DirtyState('Cant push, diverged from remote.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def git_commit_bump(version):
 | 
				
			||||||
 | 
					    command = [GIT, 'add', 'setup.py']
 | 
				
			||||||
 | 
					    check_output(command)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    command = [GIT, 'commit', '-m', f'Bump to version {version}.']
 | 
				
			||||||
 | 
					    check_output(command)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def git_commits_since(commit, show, inclusive=False):
 | 
				
			||||||
 | 
					    if commit:
 | 
				
			||||||
 | 
					        if inclusive:
 | 
				
			||||||
 | 
					            commit += '~1'
 | 
				
			||||||
 | 
					        command = [GIT, '--no-pager', 'log', '--oneline', '--graph', '--branches', '--remotes', f'{commit}..']
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        command = [GIT, '--no-pager', 'log', '--oneline', '--graph']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if show:
 | 
				
			||||||
 | 
					        check_call(command, show_command=False)
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        output = check_output(command, show_command=False)
 | 
				
			||||||
 | 
					        lines = output.strip().splitlines()
 | 
				
			||||||
 | 
					        return lines
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def git_current_remote_branch():
 | 
				
			||||||
 | 
					    command = [GIT, 'rev-parse', '--abbrev-ref', '--symbolic-full-name', '@{u}']
 | 
				
			||||||
 | 
					    output = check_output(command, show_command=False)
 | 
				
			||||||
 | 
					    output = output.strip().decode()
 | 
				
			||||||
 | 
					    (remote, branch) = output.split('/')
 | 
				
			||||||
 | 
					    return (remote, branch)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def git_determine_latest_release():
 | 
				
			||||||
 | 
					    (latest_tagged_commit, latest_tag_version) = git_latest_tagged_commit()
 | 
				
			||||||
 | 
					    (latest_bump_commit, latest_bump_version) = git_latest_bump_commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if latest_tagged_commit is None:
 | 
				
			||||||
 | 
					        latest_release_commit = latest_bump_commit
 | 
				
			||||||
 | 
					        latest_release_version = latest_bump_version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    elif latest_bump_commit is None:
 | 
				
			||||||
 | 
					        latest_release_commit = latest_tagged_commit
 | 
				
			||||||
 | 
					        latest_release_version = latest_tag_version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    elif latest_tag_version > latest_bump_version:
 | 
				
			||||||
 | 
					        latest_release_commit = latest_tagged_commit
 | 
				
			||||||
 | 
					        latest_release_version = latest_tag_version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        latest_release_commit = latest_bump_commit
 | 
				
			||||||
 | 
					        latest_release_version = latest_bump_version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (latest_release_commit, latest_release_version)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def git_latest_bump_commit():
 | 
				
			||||||
 | 
					    command = [GIT, 'log', '--oneline', '--no-abbrev-commit', '--grep', 'Bump to version *.', '-1']
 | 
				
			||||||
 | 
					    output = check_output(command, show_command=False)
 | 
				
			||||||
 | 
					    output = output.strip()
 | 
				
			||||||
 | 
					    if not output:
 | 
				
			||||||
 | 
					        return (None, None)
 | 
				
			||||||
 | 
					    commit = output.splitlines()[0].decode()
 | 
				
			||||||
 | 
					    version = re.search(BUMP_PATTERN, commit).group(1)
 | 
				
			||||||
 | 
					    version = semver_split(version)
 | 
				
			||||||
 | 
					    commit = commit.split()[0]
 | 
				
			||||||
 | 
					    return (commit, version)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def git_latest_tagged_commit():
 | 
				
			||||||
 | 
					    command = [GIT, 'log', '--oneline', '--no-abbrev-commit', '--tags=v*.*.*', '-1']
 | 
				
			||||||
 | 
					    output = check_output(command, show_command=False)
 | 
				
			||||||
 | 
					    output = output.strip()
 | 
				
			||||||
 | 
					    if not output:
 | 
				
			||||||
 | 
					        return (None, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    commit = output.splitlines()[0].decode().split()[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for tag in git_tags_on_commit(commit):
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            version = semver_split(tag)
 | 
				
			||||||
 | 
					            break
 | 
				
			||||||
 | 
					        except NotSemver:
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        return (None, None)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return (commit, version)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def git_push(remote, branch):
 | 
				
			||||||
 | 
					    command = [GIT, 'push', remote, branch]
 | 
				
			||||||
 | 
					    check_output(command)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def git_push_tag(remote, tag):
 | 
				
			||||||
 | 
					    command = [GIT, 'push', remote, tag]
 | 
				
			||||||
 | 
					    check_output(command)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def git_show_commit(commit):
 | 
				
			||||||
 | 
					    command = [GIT, 'show', '--oneline', '-s', commit]
 | 
				
			||||||
 | 
					    check_call(command, show_command=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def git_stash_push():
 | 
				
			||||||
 | 
					    token = passwordy.urandom_hex(32)
 | 
				
			||||||
 | 
					    command = [GIT, 'stash', 'push', '--include-untracked', '--message', token]
 | 
				
			||||||
 | 
					    output = check_output(command)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    command = [GIT, 'stash', 'list', '--grep', token]
 | 
				
			||||||
 | 
					    output = check_output(command).strip()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    did_stash = bool(output)
 | 
				
			||||||
 | 
					    return did_stash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def git_stash_restore():
 | 
				
			||||||
 | 
					    command = [GIT, 'stash', 'pop']
 | 
				
			||||||
 | 
					    output = check_output(command)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def git_tag_version(tag):
 | 
				
			||||||
 | 
					    command = [GIT, 'tag', '-a', tag, '-m', '']
 | 
				
			||||||
 | 
					    check_output(command)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def git_tags_on_commit(commit):
 | 
				
			||||||
 | 
					    command = [GIT, 'tag', '--points-at', commit]
 | 
				
			||||||
 | 
					    output = check_output(command, show_command=False)
 | 
				
			||||||
 | 
					    output = output.strip()
 | 
				
			||||||
 | 
					    if not output:
 | 
				
			||||||
 | 
					        return []
 | 
				
			||||||
 | 
					    output = output.decode().splitlines()
 | 
				
			||||||
 | 
					    return output
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# PYPI
 | 
				
			||||||
 | 
					################################################################################
 | 
				
			||||||
 | 
					def pypi_upload(name):
 | 
				
			||||||
 | 
					    egg_dir = f'{name}.egg-info'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    command = [PY, 'setup.py', 'sdist']
 | 
				
			||||||
 | 
					    check_output(command)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    command = [TWINE, 'upload', '-r', 'pypi', 'dist\\*']
 | 
				
			||||||
 | 
					    check_output(command)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    shutil.rmtree('dist')
 | 
				
			||||||
 | 
					    shutil.rmtree(egg_dir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def pypi_release(do_tag=False, versionbump='patch'):
 | 
				
			||||||
 | 
					    git_assert_no_stashes()
 | 
				
			||||||
 | 
					    git_assert_pushable()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    (setup_py, name, old_version) = extract_info_from_setup()
 | 
				
			||||||
 | 
					    new_version = bump_version(old_version, versionbump)
 | 
				
			||||||
 | 
					    new_tag = f'v{new_version}'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    (latest_release_commit, latest_release_version) = git_determine_latest_release()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    git_assert_current_greater_than_latest(latest_release_version, new_version)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    commits_since_last_release = git_commits_since(latest_release_commit, show=False)
 | 
				
			||||||
 | 
					    if len(commits_since_last_release) == 0:
 | 
				
			||||||
 | 
					        print('No new commits to release')
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    (remote, branch) = git_current_remote_branch()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def linebreak():
 | 
				
			||||||
 | 
					        cli_width = shutil.get_terminal_size()[0]
 | 
				
			||||||
 | 
					        line = '#' * (cli_width - 1)
 | 
				
			||||||
 | 
					        line += '\r'
 | 
				
			||||||
 | 
					        line += f'# {name} {new_version} '
 | 
				
			||||||
 | 
					        line = f'\n{line}\n'
 | 
				
			||||||
 | 
					        slowprint(line)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    linebreak()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    slowprint(f'Upgrading {name} from {old_version} --> {new_version}.')
 | 
				
			||||||
 | 
					    slowprint()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if latest_release_commit:
 | 
				
			||||||
 | 
					        slowprint('Latest release:')
 | 
				
			||||||
 | 
					        git_show_commit(latest_release_commit)
 | 
				
			||||||
 | 
					        slowprint()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    slowprint('This release:')
 | 
				
			||||||
 | 
					    git_commits_since(latest_release_commit, show=True)
 | 
				
			||||||
 | 
					    slowprint()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setup_py = update_info_in_setup(setup_py, name, new_version)
 | 
				
			||||||
 | 
					    slowprint('Rewrite setup.py:')
 | 
				
			||||||
 | 
					    slowprint(textwrap.indent(setup_py, '>>> '))
 | 
				
			||||||
 | 
					    slowprint()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    slowprint(f'Release will be pushed to {remote} {branch}.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    linebreak()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    input(f'PRESS ENTER TO RELEASE {name} {new_version}.')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    write_setup(setup_py)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    git_commit_bump(new_version)
 | 
				
			||||||
 | 
					    if do_tag:
 | 
				
			||||||
 | 
					        git_tag_version(new_tag)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    git_push(remote, branch)
 | 
				
			||||||
 | 
					    if do_tag:
 | 
				
			||||||
 | 
					        git_push_tag(remote, new_tag)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    did_stash = git_stash_push()
 | 
				
			||||||
 | 
					    pypi_upload(name)
 | 
				
			||||||
 | 
					    if did_stash:
 | 
				
			||||||
 | 
					        git_stash_restore()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    git_commits_since(latest_release_commit, show=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def pypi_release_argparse(args):
 | 
				
			||||||
 | 
					    global DEBUG
 | 
				
			||||||
 | 
					    if args.debug:
 | 
				
			||||||
 | 
					        DEBUG = True
 | 
				
			||||||
 | 
					    versionbump = pick_versionbump(args.major, args.minor, args.patch)
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        return pypi_release(do_tag=args.do_tag, versionbump=versionbump)
 | 
				
			||||||
 | 
					    except subprocess.CalledProcessError as exc:
 | 
				
			||||||
 | 
					        print(exc.output)
 | 
				
			||||||
 | 
					        return 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def main(argv):
 | 
				
			||||||
 | 
					    parser = argparse.ArgumentParser(description=__doc__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    parser.add_argument('--major', dest='major', action='store_true')
 | 
				
			||||||
 | 
					    parser.add_argument('--minor', dest='minor', action='store_true')
 | 
				
			||||||
 | 
					    parser.add_argument('--patch', dest='patch', action='store_true')
 | 
				
			||||||
 | 
					    parser.add_argument('--do_tag', dest='do_tag', action='store_true')
 | 
				
			||||||
 | 
					    parser.add_argument('--debug', dest='debug', action='store_true')
 | 
				
			||||||
 | 
					    parser.set_defaults(func=pypi_release_argparse)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    args = parser.parse_args(argv)
 | 
				
			||||||
 | 
					    return args.func(args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    raise SystemExit(main(sys.argv[1:]))
 | 
				
			||||||
		Loading…
	
		Reference in a new issue