diff options
-rw-r--r-- | doc/source/index.rst | 10 | ||||
-rw-r--r-- | pbr/builddoc.py | 9 | ||||
-rw-r--r-- | pbr/packaging.py | 24 | ||||
-rw-r--r-- | pbr/testr_command.py | 27 | ||||
-rw-r--r-- | pbr/tests/base.py | 47 | ||||
-rw-r--r-- | pbr/tests/test_integration.py | 60 | ||||
-rw-r--r-- | pbr/tests/test_packaging.py | 30 | ||||
-rw-r--r-- | test-requirements.txt | 7 | ||||
-rw-r--r-- | tools/integration.sh | 2 |
9 files changed, 122 insertions, 94 deletions
diff --git a/doc/source/index.rst b/doc/source/index.rst index 8b4240c..3045414 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -184,6 +184,7 @@ A simple sample can be found in pbr's own setup.cfg author-email = openstack-dev@lists.openstack.org summary = OpenStack's setup automation in a reusable form description-file = README + home-page = https://launchpad.net/pbr license = Apache-2 classifier = Development Status :: 4 - Beta @@ -263,10 +264,13 @@ for installing entire directory structures, so:: Will result in `/etc/neutron` containing `api-paste.ini` and `dhcp-agent.ini`, both of which pbr will expect to find in the `etc` directory in the root of the source tree. Additionally, `neutron.init` from that dir will be installed -in `/etc/init.d`. +in `/etc/init.d`. All of the files and directories located under `etc/pbr` in +the source tree will be installed into `/etc/pbr`. -All of the files and directories located under `etc/pbr` in the source tree -will be installed into `/etc/pbr`. +Note that this behavior is relative to the effective root of the environment +into which the packages are installed, so depending on available permissions +this could be the actual system-wide `/etc` directory or just a top-level `etc` +subdirectory of a virtualenv. entry_points ------------ diff --git a/pbr/builddoc.py b/pbr/builddoc.py index 7c9916b..60f2afd 100644 --- a/pbr/builddoc.py +++ b/pbr/builddoc.py @@ -26,7 +26,6 @@ except ImportError: try: from sphinx import apidoc from sphinx import application - from sphinx import config from sphinx import setup_command except Exception as e: # NOTE(dhellmann): During the installation of docutils, setuptools @@ -126,16 +125,16 @@ class LocalBuildDoc(setup_command.BuildDoc): confoverrides['release'] = self.release if self.today: confoverrides['today'] = self.today - sphinx_config = config.Config(self.config_dir, 'conf.py', {}, []) - sphinx_config.init_values() - if self.builder == 'man' and len(sphinx_config.man_pages) == 0: - return + app = application.Sphinx( self.source_dir, self.config_dir, self.builder_target_dir, self.doctree_dir, self.builder, confoverrides, status_stream, freshenv=self.fresh_env, warningiserror=True) + if self.builder == 'man' and len(app.config.man_pages) == 0: + return + try: app.build(force_all=self.all_files) except Exception as err: diff --git a/pbr/packaging.py b/pbr/packaging.py index 74d346d..3bc625d 100644 --- a/pbr/packaging.py +++ b/pbr/packaging.py @@ -39,6 +39,7 @@ from pbr import extra_files from pbr import git from pbr import options import pbr.pbr_json +from pbr import testr_command from pbr import version REQUIREMENTS_FILES = ('requirements.txt', 'tools/pip-requires') @@ -170,26 +171,19 @@ class LocalInstall(install.install): return du_install.install.run(self) -try: - from pbr import testr_command - - class TestrTest(testr_command.Testr): - """Make setup.py test do the right thing.""" - - command_name = 'test' - - def run(self): - # Can't use super - base class old-style class - testr_command.Testr.run(self) +class TestrTest(testr_command.Testr): + """Make setup.py test do the right thing.""" - _have_testr = True + command_name = 'test' -except ImportError: - _have_testr = False + def run(self): + # Can't use super - base class old-style class + testr_command.Testr.run(self) def have_testr(): - return _have_testr + return testr_command.have_testr + try: from nose import commands diff --git a/pbr/testr_command.py b/pbr/testr_command.py index 3440f02..141d715 100644 --- a/pbr/testr_command.py +++ b/pbr/testr_command.py @@ -44,12 +44,10 @@ import logging import os import sys -from testrepository import commands - logger = logging.getLogger(__name__) -class Testr(cmd.Command): +class TestrReal(cmd.Command): description = "Run unit tests using testr" @@ -133,3 +131,26 @@ class Testr(cmd.Command): logger.debug("_coverage_after called") os.system("coverage combine") os.system("coverage html -d ./cover %s" % self.omit) + + +class TestrFake(cmd.Command): + description = "Run unit tests using testr" + user_options = [] + + def initialize_options(self): + pass + + def finalize_options(self): + pass + + def run(self): + print("Install testrepository to run 'testr' command properly.") + + +try: + from testrepository import commands + have_testr = True + Testr = TestrReal +except ImportError: + have_testr = False + Testr = TestrFake diff --git a/pbr/tests/base.py b/pbr/tests/base.py index 09bd642..e017b06 100644 --- a/pbr/tests/base.py +++ b/pbr/tests/base.py @@ -47,6 +47,7 @@ import sys import fixtures import testresources import testtools +from testtools import content from pbr import options @@ -147,6 +148,48 @@ class BaseTestCase(testtools.TestCase, testresources.ResourcedTestCase): return result +class CapturedSubprocess(fixtures.Fixture): + """Run a process and capture its output. + + :attr stdout: The output (a string). + :attr stderr: The standard error (a string). + :attr returncode: The return code of the process. + + Note that stdout and stderr are decoded from the bytestrings subprocess + returns using error=replace. + """ + + def __init__(self, label, *args, **kwargs): + """Create a CapturedSubprocess. + + :param label: A label for the subprocess in the test log. E.g. 'foo'. + :param *args: The *args to pass to Popen. + :param **kwargs: The **kwargs to pass to Popen. + """ + super(CapturedSubprocess, self).__init__() + self.label = label + self.args = args + self.kwargs = kwargs + self.kwargs['stderr'] = subprocess.PIPE + self.kwargs['stdin'] = subprocess.PIPE + self.kwargs['stdout'] = subprocess.PIPE + + def setUp(self): + super(CapturedSubprocess, self).setUp() + proc = subprocess.Popen(*self.args, **self.kwargs) + out, err = proc.communicate() + self.out = out.decode('utf-8', 'replace') + self.err = err.decode('utf-8', 'replace') + self.addDetail(self.label + '-stdout', content.text_content(self.out)) + self.addDetail(self.label + '-stderr', content.text_content(self.err)) + self.returncode = proc.returncode + if proc.returncode: + raise AssertionError('Failed process %s' % proc.returncode) + self.addCleanup(delattr, self, 'out') + self.addCleanup(delattr, self, 'err') + self.addCleanup(delattr, self, 'returncode') + + def _run_cmd(args, cwd): """Run the command args in cwd. @@ -158,8 +201,8 @@ def _run_cmd(args, cwd): args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd) streams = tuple(s.decode('latin1').strip() for s in p.communicate()) - for content in streams: - print(content) + for stream_content in streams: + print(stream_content) return (streams) + (p.returncode,) diff --git a/pbr/tests/test_integration.py b/pbr/tests/test_integration.py index 30cc5a2..5dff189 100644 --- a/pbr/tests/test_integration.py +++ b/pbr/tests/test_integration.py @@ -13,12 +13,10 @@ import os.path import shlex -import subprocess import fixtures import testscenarios import testtools -from testtools import content import virtualenv from pbr.tests import base @@ -52,48 +50,6 @@ def all_projects(): yield (short_name, dict(name=name, short_name=short_name)) -class CapturedSubprocess(fixtures.Fixture): - """Run a process and capture its output. - - :attr stdout: The output (a string). - :attr stderr: The standard error (a string). - :attr returncode: The return code of the process. - - Note that stdout and stderr are decoded from the bytestrings subprocess - returns using error=replace. - """ - - def __init__(self, label, *args, **kwargs): - """Create a CapturedSubprocess. - - :param label: A label for the subprocess in the test log. E.g. 'foo'. - :param *args: The *args to pass to Popen. - :param **kwargs: The **kwargs to pass to Popen. - """ - super(CapturedSubprocess, self).__init__() - self.label = label - self.args = args - self.kwargs = kwargs - self.kwargs['stderr'] = subprocess.PIPE - self.kwargs['stdin'] = subprocess.PIPE - self.kwargs['stdout'] = subprocess.PIPE - - def setUp(self): - super(CapturedSubprocess, self).setUp() - proc = subprocess.Popen(*self.args, **self.kwargs) - out, err = proc.communicate() - self.out = out.decode('utf-8', 'replace') - self.err = err.decode('utf-8', 'replace') - self.addDetail(self.label + '-stdout', content.text_content(self.out)) - self.addDetail(self.label + '-stderr', content.text_content(self.err)) - self.returncode = proc.returncode - if proc.returncode: - raise AssertionError('Failed process %s' % proc.returncode) - self.addCleanup(delattr, self, 'out') - self.addCleanup(delattr, self, 'err') - self.addCleanup(delattr, self, 'returncode') - - class TestIntegration(base.BaseTestCase): scenarios = list(all_projects()) @@ -109,7 +65,7 @@ class TestIntegration(base.BaseTestCase): path = self.useFixture(fixtures.TempDir()).path virtualenv.create_environment(path, clear=True) python = os.path.join(path, 'bin', 'python') - self.useFixture(CapturedSubprocess( + self.useFixture(base.CapturedSubprocess( 'mkvenv-' + reason, [python] + PIP_CMD + [ '-U', PIPVERSION, 'wheel', PBRVERSION])) return path, python @@ -126,29 +82,29 @@ class TestIntegration(base.BaseTestCase): # We don't break these into separate tests because we'd need separate # source dirs to isolate from side effects of running pip, and the # overheads of setup would start to beat the benefits of parallelism. - self.useFixture(CapturedSubprocess( + self.useFixture(base.CapturedSubprocess( 'sync-req', ['python', 'update.py', os.path.join(REPODIR, self.short_name)], cwd=os.path.join(REPODIR, 'requirements'))) - self.useFixture(CapturedSubprocess( + self.useFixture(base.CapturedSubprocess( 'commit-requirements', 'git diff --quiet || git commit -amrequirements', cwd=os.path.join(REPODIR, self.short_name), shell=True)) path = os.path.join( self.useFixture(fixtures.TempDir()).path, 'project') - self.useFixture(CapturedSubprocess( + self.useFixture(base.CapturedSubprocess( 'clone', ['git', 'clone', os.path.join(REPODIR, self.short_name), path])) _, python = self.venv('sdist') - self.useFixture(CapturedSubprocess( + self.useFixture(base.CapturedSubprocess( 'sdist', [python, 'setup.py', 'sdist'], cwd=path)) _, python = self.venv('tarball') filename = os.path.join( path, 'dist', os.listdir(os.path.join(path, 'dist'))[0]) - self.useFixture(CapturedSubprocess( + self.useFixture(base.CapturedSubprocess( 'tarball', [python] + PIP_CMD + [filename])) root, python = self.venv('install-git') - self.useFixture(CapturedSubprocess( + self.useFixture(base.CapturedSubprocess( 'install-git', [python] + PIP_CMD + ['git+file://' + path])) if self.short_name == 'nova': found = False @@ -157,7 +113,7 @@ class TestIntegration(base.BaseTestCase): found = True self.assertTrue(found) _, python = self.venv('install-e') - self.useFixture(CapturedSubprocess( + self.useFixture(base.CapturedSubprocess( 'install-e', [python] + PIP_CMD + ['-e', path])) diff --git a/pbr/tests/test_packaging.py b/pbr/tests/test_packaging.py index 9e846d8..81701d1 100644 --- a/pbr/tests/test_packaging.py +++ b/pbr/tests/test_packaging.py @@ -99,12 +99,27 @@ class GPGKeyFixture(fixtures.Fixture): def setUp(self): super(GPGKeyFixture, self).setUp() tempdir = self.useFixture(fixtures.TempDir()) + gnupg_version_re = re.compile('^gpg\s.*\s([\d+])\.([\d+])\.([\d+])') + gnupg_version = base._run_cmd(['gpg', '--version'], tempdir.path) + for line in gnupg_version[0].split('\n'): + gnupg_version = gnupg_version_re.match(line) + if gnupg_version: + gnupg_version = (int(gnupg_version.group(1)), + int(gnupg_version.group(2)), + int(gnupg_version.group(3))) + break + else: + if gnupg_version is None: + gnupg_version = (0, 0, 0) config_file = tempdir.path + '/key-config' f = open(config_file, 'wt') try: + if gnupg_version[0] == 2 and gnupg_version[1] >= 1: + f.write(""" + %no-protection + %transient-key + """) f.write(""" - #%no-protection -- these would be ideal but they are documented - #%transient-key -- but not implemented in gnupg! %no-ask-passphrase Key-Type: RSA Name-Real: Example Key @@ -119,16 +134,9 @@ class GPGKeyFixture(fixtures.Fixture): # Note that --quick-random (--debug-quick-random in GnuPG 2.x) # does not have a corresponding preferences file setting and # must be passed explicitly on the command line instead - gnupg_version_re = re.compile('gpg .* ([12])\.') - gnupg_version = base._run_cmd(['gpg', '--version'], tempdir.path) - for line in gnupg_version[0].split('\n'): - gnupg_version = gnupg_version_re.match(line) - if gnupg_version: - gnupg_version = gnupg_version.group(1) - break - if gnupg_version == '1': + if gnupg_version[0] == 1: gnupg_random = '--quick-random' - elif gnupg_version == '2': + elif gnupg_version[0] >= 2: gnupg_random = '--debug-quick-random' else: gnupg_random = '' diff --git a/test-requirements.txt b/test-requirements.txt index 6e4521c..97f3a79 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,13 +1,16 @@ +# The order of packages is significant, because pip processes them in the order +# of appearance. Changing the order has an impact on the overall integration +# process, which may cause wedges in the gate later. coverage>=3.6 discover fixtures>=0.3.14 hacking>=0.10.0,<0.11 mock>=1.0 python-subunit>=0.0.18 -sphinx>=1.1.2,<1.2 +sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3 six>=1.9.0 testrepository>=0.0.18 testresources>=0.2.4 testscenarios>=0.4 -testtools>=0.9.34 +testtools>=0.9.36,!=1.2.0 virtualenv diff --git a/tools/integration.sh b/tools/integration.sh index ed15fab..50a40b5 100644 --- a/tools/integration.sh +++ b/tools/integration.sh @@ -30,7 +30,7 @@ REPODIR=${REPODIR:-$BASE/new} # TODO: Figure out how to get this on to the box properly sudo apt-get update -sudo apt-get install -y --force-yes libvirt-dev libxml2-dev libxslt-dev libmysqlclient-dev libpq-dev libnspr4-dev pkg-config libsqlite3-dev libzmq-dev libffi-dev libldap2-dev libsasl2-dev ccache +sudo apt-get install -y --force-yes libvirt-dev libxml2-dev libxslt-dev libmysqlclient-dev libpq-dev libnspr4-dev pkg-config libsqlite3-dev libzmq-dev libffi-dev libldap2-dev libsasl2-dev ccache libkrb5-dev # FOR numpy / pyyaml sudo apt-get build-dep -y --force-yes python-numpy |