#! /usr/bin/env python import sys from setuptools import setup, find_packages, Command from distutils import log class bump_version(Command): description = "increment the package version and commit the changes" user_options = [ ("major", None, "bump the first digit, for incompatible API changes"), ("minor", None, "bump the second digit, for new backward-compatible features"), ("patch", None, "bump the third digit, for bug fixes (default)"), ] def initialize_options(self): self.minor = False self.major = False self.patch = False def finalize_options(self): part = None for attr in ("major", "minor", "patch"): if getattr(self, attr, False): if part is None: part = attr else: from distutils.errors import DistutilsOptionError raise DistutilsOptionError( "version part options are mutually exclusive") self.part = part or "patch" def bumpversion(self, part, **kwargs): """ Run bumpversion.main() with the specified arguments. """ import bumpversion args = ['--verbose'] if self.verbose > 1 else [] for k, v in kwargs.items(): k = "--{}".format(k.replace("_", "-")) is_bool = isinstance(v, bool) and v is True args.extend([k] if is_bool else [k, str(v)]) args.append(part) log.debug( "$ bumpversion %s" % " ".join(a.replace(" ", "\\ ") for a in args)) bumpversion.main(args) def run(self): log.info("bumping '%s' version" % self.part) self.bumpversion(self.part) class release(bump_version): """Drop the developmental release '.devN' suffix from the package version, open the default text $EDITOR to write release notes, commit the changes and generate a git tag. Release notes can also be set with the -m/--message option, or by reading from standard input. """ description = "tag a new release" user_options = [ ("message=", 'm', "message containing the release notes"), ] def initialize_options(self): self.message = None def finalize_options(self): import re current_version = self.distribution.metadata.get_version() if not re.search(r"\.dev[0-9]+", current_version): from distutils.errors import DistutilsSetupError raise DistutilsSetupError( "current version (%s) has no '.devN' suffix.\n " "Run 'setup.py bump_version' with any of " "--major, --minor, --patch options" % current_version) message = self.message if message is None: if sys.stdin.isatty(): # stdin is interactive, use editor to write release notes message = self.edit_release_notes() else: # read release notes from stdin pipe message = sys.stdin.read() if not message.strip(): from distutils.errors import DistutilsSetupError raise DistutilsSetupError("release notes message is empty") self.message = "v{new_version}\n\n%s" % message @staticmethod def edit_release_notes(): """Use the default text $EDITOR to write release notes. If $EDITOR is not set, use 'nano'.""" from tempfile import mkstemp import os import shlex import subprocess text_editor = shlex.split(os.environ.get('EDITOR', 'nano')) fd, tmp = mkstemp(prefix='bumpversion-') try: os.close(fd) with open(tmp, 'w') as f: f.write("\n\n# Write release notes.\n" "# Lines starting with '#' will be ignored.") subprocess.check_call(text_editor + [tmp]) with open(tmp, 'r') as f: changes = "".join( l for l in f.readlines() if not l.startswith('#')) finally: os.remove(tmp) return changes def run(self): log.info("stripping developmental release suffix") # drop '.dev0' suffix, commit with given message and create git tag self.bumpversion("release", tag=True, message="Release {new_version}", tag_message=self.message) needs_pytest = {'pytest', 'test'}.intersection(sys.argv) pytest_runner = ['pytest_runner'] if needs_pytest else [] needs_wheel = {'bdist_wheel'}.intersection(sys.argv) wheel = ['wheel'] if needs_wheel else [] needs_bump2version = {'release', 'bump_version'}.intersection(sys.argv) bump2version = ['bump2version'] if needs_bump2version else [] long_description = """\ ufoLib reads and writes Unified Font Object (UFO) files. UFO is a file format that stores fonts source files. http://unifiedfontobject.org """ setup_params = dict( name="ufoLib", version="2.3.0", description="A low-level UFO reader and writer.", author="Just van Rossum, Tal Leming, Erik van Blokland, others", author_email="info@robofab.com", maintainer="Just van Rossum, Tal Leming, Erik van Blokland", maintainer_email="info@robofab.com", url="https://github.com/unified-font-object/ufoLib", license="OpenSource, BSD-style", platforms=["Any"], long_description=long_description, package_dir={'': 'Lib'}, packages=find_packages('Lib'), include_package_data=True, setup_requires=pytest_runner + wheel + bump2version, tests_require=[ 'pytest>=3.0.2', ], install_requires=[ "fonttools >= 3.1.2, < 4", ], extras_require={ "lxml": [ "lxml >= 4.0, < 5", "singledispatch >= 3.4.0.3, < 4; python_version < '3.4'", ], "testing": [ "pytest >= 3.0.0, <4", "pytest-cov >= 2.5.1, <3", "pytest-randomly >= 1.2.3, <2", ], }, cmdclass={ "release": release, "bump_version": bump_version, }, classifiers=[ "Development Status :: 4 - Beta", "Environment :: Console", "Environment :: Other Environment", "Intended Audience :: Developers", "Intended Audience :: End Users/Desktop", "License :: OSI Approved :: BSD License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python", "Topic :: Multimedia :: Graphics", "Topic :: Multimedia :: Graphics :: Graphics Conversion", ], ) if __name__ == "__main__": setup(**setup_params)