diff options
Diffstat (limited to 'setup.py')
-rw-r--r-- | setup.py | 223 |
1 files changed, 186 insertions, 37 deletions
@@ -7,7 +7,25 @@ This script supports publishing Pystache to PyPI. This docstring contains instructions to Pystache maintainers on how to release a new version of Pystache. -(1) Push to PyPI. To release a new version of Pystache to PyPI-- +(1) Prepare the release. + +Make sure the code is finalized and merged to master. Bump the version +number in setup.py, etc. + +Generate the reStructuredText long_description using-- + + python setup.py prep + +and be sure this new version is checked in. You must have pandoc installed +to do this step: + + http://johnmacfarlane.net/pandoc/ + +It helps to review this auto-generated file on GitHub prior to uploading +because the long description will be sent to PyPI and appear there after +publishing. + +(2) Push to PyPI. To release a new version of Pystache to PyPI-- http://pypi.python.org/pypi/pystache @@ -15,8 +33,7 @@ create a PyPI user account if you do not already have one. The user account will need permissions to push to PyPI. A current "Package Index Owner" of Pystache can grant you those permissions. -When you have permissions, run the following (after preparing the release, -merging to master, bumping the version number in setup.py, etc): +When you have permissions, run the following: python setup.py publish @@ -35,7 +52,7 @@ as described here, for example: http://docs.python.org/release/2.5.2/dist/pypirc.html -(2) Tag the release on GitHub. Here are some commands for tagging. +(3) Tag the release on GitHub. Here are some commands for tagging. List current tags: @@ -52,12 +69,24 @@ Push a tag to GitHub: """ import os +import shutil import sys + +OPTION_FORCE_2TO3 = '--force2to3' + py_version = sys.version_info -# Distribute works with Python 2.3.5 and above: +# distutils does not seem to support the following setup() arguments. +# It displays a UserWarning when setup() is passed those options: +# +# * entry_points +# * install_requires +# +# distribute works with Python 2.3.5 and above: +# # http://packages.python.org/distribute/setuptools.html#building-and-distributing-packages-with-distribute +# if py_version < (2, 3, 5): # TODO: this might not work yet. import distutils as dist @@ -67,16 +96,20 @@ else: import setuptools as dist setup = dist.setup -# TODO: use the logging module instead of printing. -# TODO: include the following in a verbose mode. -# print("Using: version %s of %s" % (repr(dist.__version__), repr(dist))) - VERSION = '0.5.2' # Also change in pystache/__init__.py. -HISTORY_PATH = 'HISTORY.rst' +FILE_ENCODING = 'utf-8' + +README_PATH = 'README.md' +HISTORY_PATH = 'HISTORY.md' LICENSE_PATH = 'LICENSE' -README_PATH = 'README.rst' + +DESCRIPTION_PATH = 'setup_description.rst' + +TEMP_REST_EXTENSION = '.temp.rst' + +PREP_COMMAND = 'prep' CLASSIFIERS = ( 'Development Status :: 4 - Beta', @@ -106,49 +139,115 @@ def read(path): finally: f.close() - return b.decode('utf-8') + return b.decode(FILE_ENCODING) -def publish(): +def write(u, path): """ - Publish this package to PyPI (aka "the Cheeseshop"). + Write a unicode string to a file (as utf-8). """ - os.system('python setup.py sdist upload') + print("Writing to: %s" % path) + # This function implementation was chosen to be compatible across Python 2/3. + f = open(path, "wb") + try: + b = u.encode(FILE_ENCODING) + f.write(b) + finally: + f.close() + + +def make_temp_path(path): + root, ext = os.path.splitext(path) + temp_path = root + TEMP_REST_EXTENSION + return temp_path -def make_long_description(): +def make_description_file(target_path): """ - Return the long description for the package. + Generate the long_description needed for setup.py. + + The long description needs to be formatted as reStructuredText: + + http://docs.python.org/distutils/setupscript.html#additional-meta-data """ + # Comments in reST begin with two dots. + intro = """\ +.. This file is auto-generated by setup.py for PyPI using pandoc, so this +.. file should not be edited. Edits should go in the source files. +""" + + readme_path = convert_md_to_rst(README_PATH) + history_path = convert_md_to_rst(HISTORY_PATH) + license = """\ License ======= """ + read(LICENSE_PATH) - sections = [read(README_PATH), read(HISTORY_PATH), license] - return '\n\n'.join(sections) + sections = [intro, read(readme_path), read(history_path), license] + description = '\n'.join(sections) -if sys.argv[-1] == 'publish': - publish() - sys.exit() + write(description, target_path) + + +def prep(): + make_description_file(DESCRIPTION_PATH) + +def publish(): + """ + Publish this package to PyPI (aka "the Cheeseshop"). + + """ + temp_path = make_temp_path(DESCRIPTION_PATH) + make_description_file(temp_path) + + if read(temp_path) != read(DESCRIPTION_PATH): + print("""\ +Description file not up-to-date: %s +Run the following command and commit the changes-- + + python setup.py %s +""" % (DESCRIPTION_PATH, PREP_COMMAND)) + sys.exit() + + print("Description up-to-date: %s" % DESCRIPTION_PATH) + + answer = raw_input("Are you sure you want to publish to PyPI (yes/no)?") + + if answer != "yes": + exit("Aborted: nothing published") + + os.system('python setup.py sdist upload') + + +def convert_md_to_rst(path): + """ + Convert the given file from markdown to reStructuredText. + + Returns the new path. + + """ + temp_path = make_temp_path(path) + print("Converting: %s to %s" % (path, temp_path)) + + if os.path.exists(temp_path): + os.remove(temp_path) + + # Pandoc uses the UTF-8 character encoding for both input and output. + command = "pandoc --write=rst --output=%s %s" % (temp_path, path) + os.system(command) + + if not os.path.exists(temp_path): + s = ("Error running: %s\n" + " Did you install pandoc per the %s docstring?" % (command, __file__)) + sys.exit(s) + + return temp_path -# We follow the guidance here for compatibility with using setuptools instead -# of Distribute under Python 2 (on the subject of new, unrecognized keyword -# arguments to setup()): -# -# http://packages.python.org/distribute/python3.html#note-on-compatibility-with-setuptools -# -if py_version < (3, ): - extra = {} -else: - extra = { - # Causes 2to3 to be run during the build step. - 'use_2to3': True, - } # We use the package simplejson for older Python versions since Python # does not contain the module json before 2.6: @@ -180,10 +279,59 @@ PACKAGES = [ ] +def parse_args(sys_argv): + """ + Modify sys_argv in place and return whether to force use of 2to3. + + """ + should_force2to3 = False + if len(sys_argv) > 1 and sys_argv[1] == OPTION_FORCE_2TO3: + sys_argv.pop(1) + should_force2to3 = True + + return should_force2to3 + + +# The purpose of this function is to follow the guidance suggested here: +# +# http://packages.python.org/distribute/python3.html#note-on-compatibility-with-setuptools +# +# The guidance is for better compatibility when using setuptools (e.g. with +# earlier versions of Python 2) instead of Distribute, because of new +# keyword arguments to setup() that setuptools may not recognize. +def get_extra_args(should_force2to3): + """ + Return a dictionary of extra args to pass to setup(). + + """ + extra = {} + if py_version >= (3, ) or should_force2to3: + # Causes 2to3 to be run during the build step. + extra['use_2to3'] = True + + return extra + + def main(sys_argv): - long_description = make_long_description() + # TODO: use the logging module instead of printing. + # TODO: include the following in a verbose mode. + print("pystache: using: version %s of %s" % (repr(dist.__version__), repr(dist))) + + should_force2to3 = parse_args(sys_argv) + + command = sys_argv[-1] + + if command == 'publish': + publish() + sys.exit() + elif command == PREP_COMMAND: + prep() + sys.exit() + + long_description = read(DESCRIPTION_PATH) template_files = ['*.mustache', '*.txt'] + extra_args = get_extra_args(should_force2to3) setup(name='pystache', version=VERSION, @@ -193,6 +341,7 @@ def main(sys_argv): author='Chris Wanstrath', author_email='chris@ozmm.org', maintainer='Chris Jerdonek', + maintainer_email='chris.jerdonek@gmail.com', url='http://github.com/defunkt/pystache', install_requires=INSTALL_REQUIRES, packages=PACKAGES, @@ -209,7 +358,7 @@ def main(sys_argv): ], }, classifiers = CLASSIFIERS, - **extra + **extra_args ) |