diff options
-rw-r--r-- | .coveragerc | 6 | ||||
-rw-r--r-- | keystoneclient/openstack/common/setup.py | 113 | ||||
-rw-r--r-- | setup.cfg | 2 | ||||
-rw-r--r-- | setup.py | 24 | ||||
-rw-r--r-- | tools/install_venv.py | 4 | ||||
-rw-r--r-- | tools/pip-requires | 6 | ||||
-rw-r--r-- | tools/test-requires | 9 | ||||
-rw-r--r-- | tox.ini | 34 |
8 files changed, 153 insertions, 45 deletions
diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..baf5097 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,6 @@ +[run] +branch = True +omit = /usr*,setup.py,*egg*,.venv/*,.tox/*,keystoneclient/tests/* + +[report] +ignore-errors = True diff --git a/keystoneclient/openstack/common/setup.py b/keystoneclient/openstack/common/setup.py index 60c731a..429ba35 100644 --- a/keystoneclient/openstack/common/setup.py +++ b/keystoneclient/openstack/common/setup.py @@ -23,6 +23,8 @@ import os import re import subprocess +from setuptools.command import sdist + def parse_mailmap(mailmap='.mailmap'): mapping = {} @@ -31,7 +33,8 @@ def parse_mailmap(mailmap='.mailmap'): for l in fp: l = l.strip() if not l.startswith('#') and ' ' in l: - canonical_email, alias = l.split(' ') + canonical_email, alias = [x for x in l.split(' ') + if x.startswith('<')] mapping[alias] = canonical_email return mapping @@ -58,9 +61,19 @@ 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 else: @@ -72,11 +85,18 @@ def parse_requirements(requirements_files=['requirements.txt', 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 @@ -134,8 +154,8 @@ def generate_authors(): 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 + 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: @@ -143,3 +163,90 @@ def generate_authors(): 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 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 @@ -1,4 +1,6 @@ [nosetests] +verbosity=2 +detailed-errors=1 cover-package = keystoneclient cover-erase = true cover-inclusive = true @@ -1,20 +1,18 @@ import os import sys -from setuptools import setup, find_packages -from keystoneclient.openstack.common.setup import generate_authors +import setuptools + +from keystoneclient.openstack.common import setup def read(fname): return open(os.path.join(os.path.dirname(__file__), fname)).read() -requirements = ['httplib2', 'prettytable'] -if sys.version_info < (2, 6): - requirements.append('simplejson') -if sys.version_info < (2, 7): - requirements.append('argparse') +requires = setup.parse_requirements() +depend_links = setup.parse_dependency_links() +tests_require = setup.parse_requirements(['tools/test-requires']) -generate_authors() -setup( +setuptools.setup( name="python-keystoneclient", version="2012.2", description="Client library for OpenStack Keystone API", @@ -23,7 +21,7 @@ setup( license='Apache', author='Nebula Inc, based on work by Rackspace and Jacob Kaplan-Moss', author_email='gabriel.hurley@nebula.com', - packages=find_packages(exclude=['tests', 'tests.*']), + packages=setuptools.find_packages(exclude=['tests', 'tests.*']), classifiers=[ 'Development Status :: 4 - Beta', 'Environment :: Console', @@ -33,9 +31,11 @@ setup( 'Operating System :: OS Independent', 'Programming Language :: Python', ], - install_requires=requirements, + install_requires=requires, + dependency_links=depend_links, + cmdclass=setup.get_cmdclass(), - tests_require=["nose", "mock", "mox"], + tests_require=tests_require, test_suite="nose.collector", entry_points={ diff --git a/tools/install_venv.py b/tools/install_venv.py index e7859d4..05425b2 100644 --- a/tools/install_venv.py +++ b/tools/install_venv.py @@ -204,8 +204,8 @@ def print_help(): help = """ python-keystoneclient development environment setup is complete. - python-keystoneclient development uses virtualenv to track and manage Python - dependencies while in development and testing. + python-keystoneclient development uses virtualenv to track and manage + Python dependencies while in development and testing. To activate the python-keystoneclient virtualenv for the extent of your current shell session you can run: diff --git a/tools/pip-requires b/tools/pip-requires index 9aa889e..0bfb0d0 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -1,11 +1,5 @@ argparse -coverage httplib2 -mock -mox -nose -nosexcover -pep8 prettytable simplejson unittest2 diff --git a/tools/test-requires b/tools/test-requires new file mode 100644 index 0000000..324f27f --- /dev/null +++ b/tools/test-requires @@ -0,0 +1,9 @@ +distribute>=0.6.24 + +mock +mox +nose +nose-exclude +openstack.nose_plugin +pep8==1.2 +sphinx>=1.1.2 @@ -3,34 +3,24 @@ envlist = py26,py27,pep8 [testenv] setenv = VIRTUAL_ENV={envdir} + NOSE_WITH_OPENSTACK=1 + NOSE_OPENSTACK_COLOR=1 + NOSE_OPENSTACK_RED=0.05 + NOSE_OPENSTACK_YELLOW=0.025 + NOSE_OPENSTACK_SHOW_ELAPSED=1 + NOSE_OPENSTACK_STDOUT=1 deps = -r{toxinidir}/tools/pip-requires + -r{toxinidir}/tools/test-requires commands = nosetests {posargs} +[tox:jenkins] +downloadcache = ~/cache/pip + [testenv:pep8] -deps = pep8 -commands = pep8 --repeat --show-source keystoneclient setup.py +commands = pep8 --repeat --show-source --exclude=.venv,.tox,dist,doc . [testenv:cover] -commands = nosetests --with-xcoverage {posargs} +setenv = NOSE_WITH_COVERAGE=1 [testenv:venv] commands = {posargs} - -[testenv:hudson] -downloadcache = ~/cache/pip - -[testenv:jenkins26] -basepython = python2.6 -deps = file://{toxinidir}/.cache.bundle - -[testenv:jenkins27] -basepython = python2.7 -deps = file://{toxinidir}/.cache.bundle - -[testenv:jenkinscover] -deps = file://{toxinidir}/.cache.bundle -commands = nosetests --with-xcoverage {posargs} - -[testenv:jenkinsvenv] -deps = file://{toxinidir}/.cache.bundle -commands = {posargs} |