Commit 7a7469f9 authored by Jason R. Coombs's avatar Jason R. Coombs

Spaces for indent

parent 22ee649e
...@@ -19,259 +19,259 @@ import re ...@@ -19,259 +19,259 @@ import re
import requests import requests
try: try:
input = raw_input input = raw_input
except NameError: except NameError:
pass pass
try: try:
zip_longest = itertools.zip_longest zip_longest = itertools.zip_longest
except AttributeError: except AttributeError:
zip_longest = itertools.izip_longest zip_longest = itertools.izip_longest
try: try:
import keyring import keyring
except Exception: except Exception:
pass pass
VERSION = '0.9' VERSION = '0.9'
PACKAGE_INDEX = 'https://pypi.python.org/pypi' PACKAGE_INDEX = 'https://pypi.python.org/pypi'
def set_versions(): def set_versions():
global VERSION global VERSION
version = input("Release as version [%s]> " % VERSION) or VERSION version = input("Release as version [%s]> " % VERSION) or VERSION
if version != VERSION: if version != VERSION:
VERSION = bump_versions(version) VERSION = bump_versions(version)
def infer_next_version(version): def infer_next_version(version):
""" """
Infer a next version from the current version by incrementing the last Infer a next version from the current version by incrementing the last
number or appending a number. number or appending a number.
>>> infer_next_version('1.0') >>> infer_next_version('1.0')
'1.1' '1.1'
>>> infer_next_version('1.0b') >>> infer_next_version('1.0b')
'1.0b1' '1.0b1'
>>> infer_next_version('1.0.9') >>> infer_next_version('1.0.9')
'1.0.10' '1.0.10'
>>> infer_next_version('1') >>> infer_next_version('1')
'2' '2'
>>> infer_next_version('') >>> infer_next_version('')
'1' '1'
""" """
def incr(match): def incr(match):
ver = int(match.group(0) or '0') ver = int(match.group(0) or '0')
return str(ver + 1) return str(ver + 1)
return re.sub('\d*$', incr, version) return re.sub('\d*$', incr, version)
files_with_versions = ( files_with_versions = (
'docs/conf.py', 'setup.py', 'release.py', 'ez_setup.py', 'docs/conf.py', 'setup.py', 'release.py', 'ez_setup.py',
'setuptools/__init__.py', 'setuptools/__init__.py',
) )
def get_repo_name(): def get_repo_name():
""" """
Get the repo name from the hgrc default path. Get the repo name from the hgrc default path.
""" """
default = subprocess.check_output('hg paths default').strip().decode('utf-8') default = subprocess.check_output('hg paths default').strip().decode('utf-8')
parts = default.split('/') parts = default.split('/')
if parts[-1] == '': if parts[-1] == '':
parts.pop() parts.pop()
return '/'.join(parts[-2:]) return '/'.join(parts[-2:])
def get_mercurial_creds(system='https://bitbucket.org', username=None): def get_mercurial_creds(system='https://bitbucket.org', username=None):
""" """
Return named tuple of username,password in much the same way that Return named tuple of username,password in much the same way that
Mercurial would (from the keyring). Mercurial would (from the keyring).
""" """
# todo: consider getting this from .hgrc # todo: consider getting this from .hgrc
username = username or getpass.getuser() username = username or getpass.getuser()
keyring_username = '@@'.join((username, system)) keyring_username = '@@'.join((username, system))
system = 'Mercurial' system = 'Mercurial'
password = ( password = (
keyring.get_password(system, keyring_username) keyring.get_password(system, keyring_username)
if 'keyring' in globals() if 'keyring' in globals()
else None else None
) )
if not password: if not password:
password = getpass.getpass() password = getpass.getpass()
Credential = collections.namedtuple('Credential', 'username password') Credential = collections.namedtuple('Credential', 'username password')
return Credential(username, password) return Credential(username, password)
def add_milestone_and_version(version): def add_milestone_and_version(version):
base = 'https://api.bitbucket.org' base = 'https://api.bitbucket.org'
for type in 'milestones', 'versions': for type in 'milestones', 'versions':
url = (base + '/1.0/repositories/{repo}/issues/{type}' url = (base + '/1.0/repositories/{repo}/issues/{type}'
.format(repo = get_repo_name(), type=type)) .format(repo = get_repo_name(), type=type))
resp = requests.post(url=url, resp = requests.post(url=url,
data='name='+version, auth=get_mercurial_creds()) data='name='+version, auth=get_mercurial_creds())
resp.raise_for_status() resp.raise_for_status()
def bump_versions(target_ver): def bump_versions(target_ver):
for filename in files_with_versions: for filename in files_with_versions:
bump_version(filename, target_ver) bump_version(filename, target_ver)
subprocess.check_call(['hg', 'ci', '-m', subprocess.check_call(['hg', 'ci', '-m',
'Bumped to {target_ver} in preparation for next ' 'Bumped to {target_ver} in preparation for next '
'release.'.format(**vars())]) 'release.'.format(**vars())])
return target_ver return target_ver
def bump_version(filename, target_ver): def bump_version(filename, target_ver):
with open(filename, 'rb') as f: with open(filename, 'rb') as f:
lines = [ lines = [
line.replace(VERSION.encode('ascii'), target_ver.encode('ascii')) line.replace(VERSION.encode('ascii'), target_ver.encode('ascii'))
for line in f for line in f
] ]
with open(filename, 'wb') as f: with open(filename, 'wb') as f:
f.writelines(lines) f.writelines(lines)
def do_release(): def do_release():
assert all(map(os.path.exists, files_with_versions)), ( assert all(map(os.path.exists, files_with_versions)), (
"Expected file(s) missing") "Expected file(s) missing")
assert has_sphinx(), "You must have Sphinx installed to release" assert has_sphinx(), "You must have Sphinx installed to release"
set_versions() set_versions()
res = input('Have you read through the SCM changelog and ' res = input('Have you read through the SCM changelog and '
'confirmed the changelog is current for releasing {VERSION}? ' 'confirmed the changelog is current for releasing {VERSION}? '
.format(**globals())) .format(**globals()))
if not res.lower().startswith('y'): if not res.lower().startswith('y'):
print("Please do that") print("Please do that")
raise SystemExit(1) raise SystemExit(1)
print("Travis-CI tests: http://travis-ci.org/#!/jaraco/setuptools") print("Travis-CI tests: http://travis-ci.org/#!/jaraco/setuptools")
res = input('Have you or has someone verified that the tests ' res = input('Have you or has someone verified that the tests '
'pass on this revision? ') 'pass on this revision? ')
if not res.lower().startswith('y'): if not res.lower().startswith('y'):
print("Please do that") print("Please do that")
raise SystemExit(2) raise SystemExit(2)
subprocess.check_call(['hg', 'tag', VERSION]) subprocess.check_call(['hg', 'tag', VERSION])
subprocess.check_call(['hg', 'update', VERSION]) subprocess.check_call(['hg', 'update', VERSION])
upload_to_pypi() upload_to_pypi()
upload_ez_setup() upload_ez_setup()
# update to the tip for the next operation # update to the tip for the next operation
subprocess.check_call(['hg', 'update']) subprocess.check_call(['hg', 'update'])
# we just tagged the current version, bump for the next release. # we just tagged the current version, bump for the next release.
next_ver = bump_versions(infer_next_version(VERSION)) next_ver = bump_versions(infer_next_version(VERSION))
# push the changes # push the changes
subprocess.check_call(['hg', 'push']) subprocess.check_call(['hg', 'push'])
add_milestone_and_version(next_ver) add_milestone_and_version(next_ver)
def upload_to_pypi(): def upload_to_pypi():
linkify('CHANGES.txt', 'CHANGES (links).txt') linkify('CHANGES.txt', 'CHANGES (links).txt')
has_docs = build_docs() has_docs = build_docs()
if os.path.isdir('./dist'): if os.path.isdir('./dist'):
shutil.rmtree('./dist') shutil.rmtree('./dist')
cmd = [ cmd = [
sys.executable, 'setup.py', '-q', sys.executable, 'setup.py', '-q',
'egg_info', '-RD', '-b', '', 'egg_info', '-RD', '-b', '',
'sdist', 'sdist',
'register', '-r', PACKAGE_INDEX, 'register', '-r', PACKAGE_INDEX,
'upload', '-r', PACKAGE_INDEX, 'upload', '-r', PACKAGE_INDEX,
] ]
if has_docs: if has_docs:
cmd.extend([ cmd.extend([
'upload_docs', '-r', PACKAGE_INDEX 'upload_docs', '-r', PACKAGE_INDEX
]) ])
env = os.environ.copy() env = os.environ.copy()
env["SETUPTOOLS_INSTALL_WINDOWS_SPECIFIC_FILES"] = "1" env["SETUPTOOLS_INSTALL_WINDOWS_SPECIFIC_FILES"] = "1"
subprocess.check_call(cmd, env=env) subprocess.check_call(cmd, env=env)
def upload_ez_setup(): def upload_ez_setup():
""" """
TODO: upload ez_setup.py to a permalinked location. Currently, this TODO: upload ez_setup.py to a permalinked location. Currently, this
location is https://bitbucket.org/pypa/setuptools/downloads/ez_setup.py . location is https://bitbucket.org/pypa/setuptools/downloads/ez_setup.py .
In the long term, it should be on PyPI. In the long term, it should be on PyPI.
""" """
def has_sphinx(): def has_sphinx():
try: try:
devnull = open(os.path.devnull, 'wb') devnull = open(os.path.devnull, 'wb')
subprocess.Popen(['sphinx-build', '--version'], stdout=devnull, subprocess.Popen(['sphinx-build', '--version'], stdout=devnull,
stderr=subprocess.STDOUT).wait() stderr=subprocess.STDOUT).wait()
except Exception: except Exception:
return False return False
return True return True
def build_docs(): def build_docs():
if not os.path.isdir('docs'): if not os.path.isdir('docs'):
return return
if os.path.isdir('docs/build'): if os.path.isdir('docs/build'):
shutil.rmtree('docs/build') shutil.rmtree('docs/build')
cmd = [ cmd = [
'sphinx-build', 'sphinx-build',
'-b', 'html', '-b', 'html',
'-d', 'build/doctrees', '-d', 'build/doctrees',
'.', '.',
'build/html', 'build/html',
] ]
subprocess.check_call(cmd, cwd='docs') subprocess.check_call(cmd, cwd='docs')
return True return True
def linkify(source, dest): def linkify(source, dest):
with open(source) as source: with open(source) as source:
out = _linkified_text(source.read()) out = _linkified_text(source.read())
with open(dest, 'w') as dest: with open(dest, 'w') as dest:
dest.write(out) dest.write(out)
def _linkified(rst_path): def _linkified(rst_path):
"return contents of reStructureText file with linked issue references" "return contents of reStructureText file with linked issue references"
rst_file = open(rst_path) rst_file = open(rst_path)
rst_content = rst_file.read() rst_content = rst_file.read()
rst_file.close() rst_file.close()
return _linkified_text(rst_content) return _linkified_text(rst_content)
def _linkified_text(rst_content): def _linkified_text(rst_content):
# first identify any existing HREFs so they're not changed # first identify any existing HREFs so they're not changed
HREF_pattern = re.compile('`.*?`_', re.MULTILINE | re.DOTALL) HREF_pattern = re.compile('`.*?`_', re.MULTILINE | re.DOTALL)
# split on the HREF pattern, returning the parts to be linkified # split on the HREF pattern, returning the parts to be linkified
plain_text_parts = HREF_pattern.split(rst_content) plain_text_parts = HREF_pattern.split(rst_content)
anchors = [] anchors = []
linkified_parts = [_linkified_part(part, anchors) linkified_parts = [_linkified_part(part, anchors)
for part in plain_text_parts] for part in plain_text_parts]
pairs = zip_longest( pairs = zip_longest(
linkified_parts, linkified_parts,
HREF_pattern.findall(rst_content), HREF_pattern.findall(rst_content),
fillvalue='', fillvalue='',
) )
rst_content = ''.join(flatten(pairs)) rst_content = ''.join(flatten(pairs))
anchors = sorted(anchors) anchors = sorted(anchors)
bitroot = 'https://bitbucket.org/tarek/distribute' bitroot = 'https://bitbucket.org/tarek/distribute'
rst_content += "\n" rst_content += "\n"
for x in anchors: for x in anchors:
issue = re.findall(r'\d+', x)[0] issue = re.findall(r'\d+', x)[0]
rst_content += '.. _`%s`: %s/issue/%s\n' % (x, bitroot, issue) rst_content += '.. _`%s`: %s/issue/%s\n' % (x, bitroot, issue)
rst_content += "\n" rst_content += "\n"
return rst_content return rst_content
def flatten(listOfLists): def flatten(listOfLists):
"Flatten one level of nesting" "Flatten one level of nesting"
return itertools.chain.from_iterable(listOfLists) return itertools.chain.from_iterable(listOfLists)
def _linkified_part(text, anchors): def _linkified_part(text, anchors):
""" """
Linkify a part and collect any anchors generated Linkify a part and collect any anchors generated
""" """
revision = re.compile(r'\b(issue\s+#?\d+)\b', re.M | re.I) revision = re.compile(r'\b(issue\s+#?\d+)\b', re.M | re.I)
anchors.extend(revision.findall(text)) # ['Issue #43', ...] anchors.extend(revision.findall(text)) # ['Issue #43', ...]
return revision.sub(r'`\1`_', text) return revision.sub(r'`\1`_', text)
if __name__ == '__main__': if __name__ == '__main__':
do_release() do_release()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment