From 6c07bb6bc6333000da0a6604a22c86fbf90264c6 Mon Sep 17 00:00:00 2001 From: Monty Taylor Date: Sun, 2 Jun 2013 08:32:22 -0400 Subject: [PATCH] Migrate to pbr. Change-Id: Id9c9837b040c634103bcc30d590e995c3b6c309d --- .gitignore | 4 + MANIFEST.in | 1 - gerritbot/openstack/__init__.py | 0 gerritbot/openstack/common/__init__.py | 0 gerritbot/openstack/common/setup.py | 351 ------------------------- gerritbot/openstack/common/version.py | 149 ----------- gerritbot/version.py | 20 -- openstack-common.conf | 7 - setup.cfg | 32 ++- setup.py | 52 +--- tools/pip-requires | 3 + tox.ini | 2 +- 12 files changed, 40 insertions(+), 581 deletions(-) delete mode 100644 gerritbot/openstack/__init__.py delete mode 100644 gerritbot/openstack/common/__init__.py delete mode 100644 gerritbot/openstack/common/setup.py delete mode 100644 gerritbot/openstack/common/version.py delete mode 100644 gerritbot/version.py delete mode 100644 openstack-common.conf diff --git a/.gitignore b/.gitignore index 49789cf..108b518 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,8 @@ .tox +AUTHORS +ChangeLog +*egg-info +dist/* build/* *.pyc doc/build/* diff --git a/MANIFEST.in b/MANIFEST.in index 2bcc892..74fc557 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,3 @@ -include gerritbot/versioninfo include AUTHORS include ChangeLog diff --git a/gerritbot/openstack/__init__.py b/gerritbot/openstack/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/gerritbot/openstack/common/__init__.py b/gerritbot/openstack/common/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/gerritbot/openstack/common/setup.py b/gerritbot/openstack/common/setup.py deleted file mode 100644 index 2be72e6..0000000 --- a/gerritbot/openstack/common/setup.py +++ /dev/null @@ -1,351 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Utilities with minimum-depends for use in setup.py -""" - -import datetime -import os -import re -import subprocess -import sys - -from setuptools.command import sdist - - -def parse_mailmap(mailmap='.mailmap'): - mapping = {} - if os.path.exists(mailmap): - fp = open(mailmap, 'r') - for l in fp: - l = l.strip() - if not l.startswith('#') and ' ' in l: - canonical_email, alias = [x for x in l.split(' ') - if x.startswith('<')] - mapping[alias] = canonical_email - return mapping - - -def canonicalize_emails(changelog, mapping): - """Takes in a string and an email alias mapping and replaces all - instances of the aliases in the string with their real email. - """ - for alias, email in mapping.iteritems(): - changelog = changelog.replace(alias, email) - return changelog - - -# Get requirements from the first file that exists -def get_reqs_from_files(requirements_files): - reqs_in = [] - for requirements_file in requirements_files: - if os.path.exists(requirements_file): - return open(requirements_file, 'r').read().split('\n') - return [] - - -def parse_requirements(requirements_files=['requirements.txt', - 'tools/pip-requires']): - requirements = [] - for line in get_reqs_from_files(requirements_files): - # For the requirements list, we need to inject only the portion - # after egg= so that distutils knows the package it's looking for - # such as: - # -e git://github.com/openstack/nova/master#egg=nova - if re.match(r'\s*-e\s+', line): - requirements.append(re.sub(r'\s*-e\s+.*#egg=(.*)$', r'\1', - line)) - # such as: - # http://github.com/openstack/nova/zipball/master#egg=nova - elif re.match(r'\s*https?:', line): - requirements.append(re.sub(r'\s*https?:.*#egg=(.*)$', r'\1', - line)) - # -f lines are for index locations, and don't get used here - elif re.match(r'\s*-f\s+', line): - pass - # argparse is part of the standard library starting with 2.7 - # adding it to the requirements list screws distro installs - elif line == 'argparse' and sys.version_info >= (2, 7): - pass - else: - requirements.append(line) - - return requirements - - -def parse_dependency_links(requirements_files=['requirements.txt', - 'tools/pip-requires']): - dependency_links = [] - # dependency_links inject alternate locations to find packages listed - # in requirements - for line in get_reqs_from_files(requirements_files): - # skip comments and blank lines - if re.match(r'(\s*#)|(\s*$)', line): - continue - # lines with -e or -f need the whole line, minus the flag - if re.match(r'\s*-[ef]\s+', line): - dependency_links.append(re.sub(r'\s*-[ef]\s+', '', line)) - # lines that are only urls can go in unmolested - elif re.match(r'\s*https?:', line): - dependency_links.append(line) - return dependency_links - - -def write_requirements(): - venv = os.environ.get('VIRTUAL_ENV', None) - if venv is not None: - with open("requirements.txt", "w") as req_file: - output = subprocess.Popen(["pip", "-E", venv, "freeze", "-l"], - stdout=subprocess.PIPE) - requirements = output.communicate()[0].strip() - req_file.write(requirements) - - -def _run_shell_command(cmd): - output = subprocess.Popen(["/bin/sh", "-c", cmd], - stdout=subprocess.PIPE) - out = output.communicate() - if len(out) == 0: - return None - if len(out[0].strip()) == 0: - return None - return out[0].strip() - - -def _get_git_next_version_suffix(branch_name): - datestamp = datetime.datetime.now().strftime('%Y%m%d') - if branch_name == 'milestone-proposed': - revno_prefix = "r" - else: - revno_prefix = "" - _run_shell_command("git fetch origin +refs/meta/*:refs/remotes/meta/*") - milestone_cmd = "git show meta/openstack/release:%s" % branch_name - milestonever = _run_shell_command(milestone_cmd) - if not milestonever: - milestonever = "" - post_version = _get_git_post_version() - # post version should look like: - # 0.1.1.4.gcc9e28a - # where the bit after the last . is the short sha, and the bit between - # the last and second to last is the revno count - (revno, sha) = post_version.split(".")[-2:] - first_half = "%(milestonever)s~%(datestamp)s" % locals() - second_half = "%(revno_prefix)s%(revno)s.%(sha)s" % locals() - return ".".join((first_half, second_half)) - - -def _get_git_current_tag(): - return _run_shell_command("git tag --contains HEAD") - - -def _get_git_tag_info(): - return _run_shell_command("git describe --tags") - - -def _get_git_post_version(): - current_tag = _get_git_current_tag() - if current_tag is not None: - return current_tag - else: - tag_info = _get_git_tag_info() - if tag_info is None: - base_version = "0.0" - cmd = "git --no-pager log --oneline" - out = _run_shell_command(cmd) - revno = len(out.split("\n")) - sha = _run_shell_command("git describe --always") - else: - tag_infos = tag_info.split("-") - base_version = "-".join(tag_infos[:-2]) - (revno, sha) = tag_infos[-2:] - return "%s.%s.%s" % (base_version, revno, sha) - - -def write_git_changelog(): - """Write a changelog based on the git changelog.""" - if os.path.isdir('.git'): - git_log_cmd = 'git log --stat' - changelog = _run_shell_command(git_log_cmd) - mailmap = parse_mailmap() - with open("ChangeLog", "w") as changelog_file: - changelog_file.write(canonicalize_emails(changelog, mailmap)) - - -def generate_authors(): - """Create AUTHORS file using git commits.""" - jenkins_email = 'jenkins@review.openstack.org' - old_authors = 'AUTHORS.in' - new_authors = 'AUTHORS' - if os.path.isdir('.git'): - # don't include jenkins email address in AUTHORS file - git_log_cmd = ("git log --format='%aN <%aE>' | sort -u | " - "grep -v " + jenkins_email) - changelog = _run_shell_command(git_log_cmd) - mailmap = parse_mailmap() - with open(new_authors, 'w') as new_authors_fh: - new_authors_fh.write(canonicalize_emails(changelog, mailmap)) - if os.path.exists(old_authors): - with open(old_authors, "r") as old_authors_fh: - new_authors_fh.write('\n' + old_authors_fh.read()) - -_rst_template = """%(heading)s -%(underline)s - -.. automodule:: %(module)s - :members: - :undoc-members: - :show-inheritance: -""" - - -def read_versioninfo(project): - """Read the versioninfo file. If it doesn't exist, we're in a github - zipball, and there's really no way to know what version we really - are, but that should be ok, because the utility of that should be - just about nil if this code path is in use in the first place.""" - versioninfo_path = os.path.join(project, 'versioninfo') - if os.path.exists(versioninfo_path): - with open(versioninfo_path, 'r') as vinfo: - version = vinfo.read().strip() - else: - version = "0.0.0" - return version - - -def write_versioninfo(project, version): - """Write a simple file containing the version of the package.""" - open(os.path.join(project, 'versioninfo'), 'w').write("%s\n" % version) - - -def get_cmdclass(): - """Return dict of commands to run from setup.py.""" - - cmdclass = dict() - - def _find_modules(arg, dirname, files): - for filename in files: - if filename.endswith('.py') and filename != '__init__.py': - arg["%s.%s" % (dirname.replace('/', '.'), - filename[:-3])] = True - - class LocalSDist(sdist.sdist): - """Builds the ChangeLog and Authors files from VC first.""" - - def run(self): - write_git_changelog() - generate_authors() - # sdist.sdist is an old style class, can't use super() - sdist.sdist.run(self) - - cmdclass['sdist'] = LocalSDist - - # If Sphinx is installed on the box running setup.py, - # enable setup.py to build the documentation, otherwise, - # just ignore it - try: - from sphinx.setup_command import BuildDoc - - class LocalBuildDoc(BuildDoc): - def generate_autoindex(self): - print "**Autodocumenting from %s" % os.path.abspath(os.curdir) - modules = {} - option_dict = self.distribution.get_option_dict('build_sphinx') - source_dir = os.path.join(option_dict['source_dir'][1], 'api') - if not os.path.exists(source_dir): - os.makedirs(source_dir) - for pkg in self.distribution.packages: - if '.' not in pkg: - os.path.walk(pkg, _find_modules, modules) - module_list = modules.keys() - module_list.sort() - autoindex_filename = os.path.join(source_dir, 'autoindex.rst') - with open(autoindex_filename, 'w') as autoindex: - autoindex.write(""".. toctree:: - :maxdepth: 1 - -""") - for module in module_list: - output_filename = os.path.join(source_dir, - "%s.rst" % module) - heading = "The :mod:`%s` Module" % module - underline = "=" * len(heading) - values = dict(module=module, heading=heading, - underline=underline) - - print "Generating %s" % output_filename - with open(output_filename, 'w') as output_file: - output_file.write(_rst_template % values) - autoindex.write(" %s.rst\n" % module) - - def run(self): - if not os.getenv('SPHINX_DEBUG'): - self.generate_autoindex() - - for builder in ['html', 'man']: - self.builder = builder - self.finalize_options() - self.project = self.distribution.get_name() - self.version = self.distribution.get_version() - self.release = self.distribution.get_version() - BuildDoc.run(self) - cmdclass['build_sphinx'] = LocalBuildDoc - except ImportError: - pass - - return cmdclass - - -def get_git_branchname(): - for branch in _run_shell_command("git branch --color=never").split("\n"): - if branch.startswith('*'): - _branch_name = branch.split()[1].strip() - if _branch_name == "(no": - _branch_name = "no-branch" - return _branch_name - - -def get_pre_version(projectname, base_version): - """Return a version which is leading up to a version that will - be released in the future.""" - if os.path.isdir('.git'): - current_tag = _get_git_current_tag() - if current_tag is not None: - version = current_tag - else: - branch_name = os.getenv('BRANCHNAME', - os.getenv('GERRIT_REFNAME', - get_git_branchname())) - version_suffix = _get_git_next_version_suffix(branch_name) - version = "%s~%s" % (base_version, version_suffix) - write_versioninfo(projectname, version) - return version - else: - version = read_versioninfo(projectname) - return version - - -def get_post_version(projectname): - """Return a version which is equal to the tag that's on the current - revision if there is one, or tag plus number of additional revisions - if the current revision has no tag.""" - - if os.path.isdir('.git'): - version = _get_git_post_version() - write_versioninfo(projectname, version) - return version - return read_versioninfo(projectname) diff --git a/gerritbot/openstack/common/version.py b/gerritbot/openstack/common/version.py deleted file mode 100644 index ca350ed..0000000 --- a/gerritbot/openstack/common/version.py +++ /dev/null @@ -1,149 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2012 OpenStack LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Utilities for consuming the auto-generated versioninfo files. -""" - -import datetime -import pkg_resources -import os - -import setup - - -class _deferred_version_string(object): - """Internal helper class which provides delayed version calculation.""" - def __init__(self, version_info, prefix): - self.version_info = version_info - self.prefix = prefix - - def __str__(self): - return "%s%s" % (self.prefix, self.version_info.version_string()) - - def __repr__(self): - return "%s%s" % (self.prefix, self.version_info.version_string()) - - -class VersionInfo(object): - - def __init__(self, package, python_package=None, pre_version=None): - """Object that understands versioning for a package - :param package: name of the top level python namespace. For glance, - this would be "glance" for python-glanceclient, it - would be "glanceclient" - :param python_package: optional name of the project name. For - glance this can be left unset. For - python-glanceclient, this would be - "python-glanceclient" - :param pre_version: optional version that the project is working to - """ - self.package = package - if python_package is None: - self.python_package = package - else: - self.python_package = python_package - self.pre_version = pre_version - self.version = None - - def _generate_version(self): - """Defer to the openstack.common.setup routines for making a - version from git.""" - if self.pre_version is None: - return setup.get_post_version(self.python_package) - else: - return setup.get_pre_version(self.python_package, self.pre_version) - - def _newer_version(self, pending_version): - """Check to see if we're working with a stale version or not. - We expect a version string that either looks like: - 2012.2~f3~20120708.10.4426392 - which is an unreleased version of a pre-version, or: - 0.1.1.4.gcc9e28a - which is an unreleased version of a post-version, or: - 0.1.1 - Which is a release and which should match tag. - For now, if we have a date-embedded version, check to see if it's - old, and if so re-generate. Otherwise, just deal with it. - """ - try: - version_date = int(self.version.split("~")[-1].split('.')[0]) - if version_date < int(datetime.date.today().strftime('%Y%m%d')): - return self._generate_version() - else: - return pending_version - except Exception: - return pending_version - - def version_string_with_vcs(self, always=False): - """Return the full version of the package including suffixes indicating - VCS status. - - For instance, if we are working towards the 2012.2 release, - canonical_version_string should return 2012.2 if this is a final - release, or else something like 2012.2~f1~20120705.20 if it's not. - - :param always: if true, skip all version caching - """ - if always: - self.version = self._generate_version() - - if self.version is None: - - requirement = pkg_resources.Requirement.parse(self.python_package) - versioninfo = "%s/versioninfo" % self.package - try: - raw_version = pkg_resources.resource_string(requirement, - versioninfo) - self.version = self._newer_version(raw_version.strip()) - except (IOError, pkg_resources.DistributionNotFound): - self.version = self._generate_version() - - return self.version - - def canonical_version_string(self, always=False): - """Return the simple version of the package excluding any suffixes. - - For instance, if we are working towards the 2012.2 release, - canonical_version_string should return 2012.2 in all cases. - - :param always: if true, skip all version caching - """ - return self.version_string_with_vcs(always).split('~')[0] - - def version_string(self, always=False): - """Return the base version of the package. - - For instance, if we are working towards the 2012.2 release, - version_string should return 2012.2 if this is a final release, or - 2012.2-dev if it is not. - - :param always: if true, skip all version caching - """ - version_parts = self.version_string_with_vcs(always).split('~') - if len(version_parts) == 1: - return version_parts[0] - else: - return '%s-dev' % (version_parts[0],) - - def deferred_version_string(self, prefix=""): - """Generate an object which will expand in a string context to - the results of version_string(). We do this so that don't - call into pkg_resources every time we start up a program when - passing version information into the CONF constructor, but - rather only do the calculation when and if a version is requested - """ - return _deferred_version_string(self, prefix) diff --git a/gerritbot/version.py b/gerritbot/version.py deleted file mode 100644 index 8b5bbfd..0000000 --- a/gerritbot/version.py +++ /dev/null @@ -1,20 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack LLC -# Copyright 2012 Hewlett-Packard Development Company, L.P. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from gerritbot.openstack.common import version as common_version - -version_info = common_version.VersionInfo('gerritbot') diff --git a/openstack-common.conf b/openstack-common.conf deleted file mode 100644 index efc5299..0000000 --- a/openstack-common.conf +++ /dev/null @@ -1,7 +0,0 @@ -[DEFAULT] - -# The list of modules to copy from openstack-common -modules=setup,version - -# The base module to hold the copy of openstack.common -base=gerritbot diff --git a/setup.cfg b/setup.cfg index a333b18..e84865a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,10 +1,28 @@ -[nosetests] -cover-package = gerritbot -cover-html = true -cover-erase = true -cover-inclusive = true -verbosity=2 -detailed-errors=1 +[metadata] +name = gerritbot +summary = Gerrit IRC Bot +description-file = + README.rst +author = OpenStack Infrastructure Team +author-email = openstack-infra@lists.openstack.org +home-page = http://ci.openstack.org/ +classifier = + Intended Audience :: Information Technology + Intended Audience :: System Administrators + License :: OSI Approved :: Apache Software License + Operating System :: POSIX :: Linux + Programming Language :: Python + Programming Language :: Python :: 2 + Programming Language :: Python :: 2.7 + Programming Language :: Python :: 2.6 + +[global] +setup-hooks = + pbr.hooks.setup_hook + +[entry_points] +console_scripts = + gerritbot = gerritbot.bot:main [build_sphinx] all_files = 1 diff --git a/setup.py b/setup.py index 0f4a8dd..59a0090 100644 --- a/setup.py +++ b/setup.py @@ -1,59 +1,21 @@ -# Copyright 2011 OpenStack, LLC -# Copyright 2012 Hewlett-Packard Development Company, L.P. +#!/usr/bin/env python +# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +# http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. # See the License for the specific language governing permissions and # limitations under the License. -import os import setuptools - -from gerritbot.openstack.common import setup -from gerritbot.version import version_info as version - -requires = setup.parse_requirements() -tests_require = setup.parse_requirements(['tools/test-requires']) -depend_links = setup.parse_dependency_links() - - -def read_file(file_name): - return open(os.path.join(os.path.dirname(__file__), file_name)).read() - - setuptools.setup( - name="gerritbot", - version=version.canonical_version_string(always=True), - author='Hewlett-Packard Development Company, L.P.', - author_email='openstack@lists.launchpad.net', - description="Gerrit IRC Bot.", - license="Apache License, Version 2.0", - url="https://github.com/openstack-ci/gerritbot", - packages=setuptools.find_packages(exclude=['tests', 'tests.*']), - include_package_data=True, - setup_requires=['setuptools_git>=0.4'], - cmdclass=setup.get_cmdclass(), - install_requires=requires, - dependency_links=depend_links, - tests_require=tests_require, - test_suite="nose.collector", - classifiers=[ - "Environment :: Console", - "Intended Audience :: Developers", - "Intended Audience :: Information Technology", - "License :: OSI Approved :: Apache Software License", - "Operating System :: OS Independent", - "Programming Language :: Python" - ], - entry_points={ - "console_scripts": ["gerritbot = gerritbot.bot:main"] - } -) + setup_requires=['d2to1', 'pbr'], + d2to1=True) diff --git a/tools/pip-requires b/tools/pip-requires index efecad9..0aefcba 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -1,3 +1,6 @@ +d2to1>=0.2.10,<0.3 +pbr>=0.5,<0.6 + gerritlib irc pyyaml diff --git a/tox.ini b/tox.ini index aea1592..dd914ce 100644 --- a/tox.ini +++ b/tox.ini @@ -22,7 +22,7 @@ setenv = NOSE_WITH_COVERAGE=1 [testenv:pyflakes] deps = pyflakes -commands = pyflakes gerritbot/bot.py gerritbot/version.py setup.py +commands = pyflakes gerritbot/bot.py setup.py [testenv:venv] commands = {posargs}