summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.zuul.yaml14
-rw-r--r--doc/source/contributor/index.rst2
-rw-r--r--doc/source/index.rst1
-rw-r--r--doc/source/user/features.rst31
-rw-r--r--doc/source/user/packagers.rst17
-rw-r--r--doc/source/user/using.rst20
-rw-r--r--lower-constraints.txt2
-rw-r--r--pbr/core.py19
-rw-r--r--pbr/hooks/files.py8
-rw-r--r--pbr/packaging.py13
-rw-r--r--pbr/tests/test_files.py21
-rw-r--r--pbr/tests/test_hooks.py3
-rw-r--r--pbr/tests/test_packaging.py31
-rw-r--r--pbr/util.py57
-rw-r--r--releasenotes/notes/fix-global-replace-of-src-prefix-in-glob-eb850b94ca96993e.yaml9
-rw-r--r--releasenotes/notes/long-descr-content-type-f9a1003acbb8740f.yaml6
-rw-r--r--setup.cfg4
-rw-r--r--test-requirements.txt4
-rw-r--r--tox.ini8
19 files changed, 178 insertions, 92 deletions
diff --git a/.zuul.yaml b/.zuul.yaml
index dd8cd77..df57d8d 100644
--- a/.zuul.yaml
+++ b/.zuul.yaml
@@ -105,24 +105,20 @@
- project:
templates:
+ - lib-forward-testing
+ - lib-forward-testing-python3
+ - openstack-cover-jobs
+ - openstack-lower-constraints-jobs
- openstack-python-jobs
- openstack-python35-jobs
- openstack-python36-jobs
- - lib-forward-testing
- - lib-forward-testing-python3
- - openstack-pypy-jobs-nonvoting
- - publish-openstack-docs-pti
- periodic-stable-jobs
+ - publish-openstack-docs-pti
check:
jobs:
- - openstack-tox-lower-constraints
- pbr-installation-devstack
- pbr-installation-upstream-devstack
gate:
jobs:
- - openstack-tox-lower-constraints
- pbr-installation-devstack
- pbr-installation-upstream-devstack
- post:
- jobs:
- - openstack-tox-cover
diff --git a/doc/source/contributor/index.rst b/doc/source/contributor/index.rst
index b7b4a75..95daead 100644
--- a/doc/source/contributor/index.rst
+++ b/doc/source/contributor/index.rst
@@ -27,7 +27,7 @@ are listed in ``requirements.txt`` and the requirements for testing are in
pip install -r requirements.txt -r test-requirements.txt
-In you go this route, you can interact with the testr command directly.
+If you go this route, you can interact with the testr command directly.
Running ``testr run`` will run the entire test suite. ``testr run --parallel``
will run it in parallel (this is the default incantation tox uses). More
information about testr can be found at: http://wiki.openstack.org/testr
diff --git a/doc/source/index.rst b/doc/source/index.rst
index 60cd461..428d835 100644
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -21,6 +21,7 @@ using an install tool such as *pip*.
* **ChangeLog**: Generate ChangeLog from git log
* **Manifest**: Generate a sensible manifest from git files and some standard
files
+* **Release Notes**: Generate a release notes file using reno
* **Requirements**: Store your dependencies in a pip requirements file
* **long_description**: Use your README file as a long_description
* **Smart find_packages**: Smartly find packages under your root package
diff --git a/doc/source/user/features.rst b/doc/source/user/features.rst
index dfbc18b..46c9d03 100644
--- a/doc/source/user/features.rst
+++ b/doc/source/user/features.rst
@@ -62,7 +62,7 @@ From this, we note a couple of the main features of *pbr*:
- Extensive use of ``setup.cfg`` for configuration
- Automatic package metadata generation (``version``)
- Automatic metadata file generation (``AUTHOR``, ``ChangeLog``,
- ``MANIFEST.in``)
+ ``MANIFEST.in``, ``RELEASENOTES.txt``)
In addition, there are other things that you don't see here but which *pbr*
will do for you:
@@ -181,6 +181,10 @@ probably a good long_description. So we'll just inject the contents of your
You can also specify the exact file you want to use using the
``description-file`` parameter.
+You can set the ``description-content-type`` to a MIME type that may
+help rendering of the description; for example ``text/markdown`` or
+``text/x-rst; charset=UTF-8``.
+
Requirements
~~~~~~~~~~~~
@@ -200,14 +204,16 @@ for your project and will then parse these files, split them up appropriately,
and inject them into the ``install_requires``, ``tests_require`` and/or
``dependency_links`` arguments to ``setup``. Voila!
-You can also have a requirement file for each specific major version of Python.
-If you want to have a different package list for Python 3 then just drop a
-``requirements-py3.txt`` and it will be used instead.
-
Finally, it is possible to specify groups of optional dependencies, or
:ref:`"extra" requirements <extra-requirements>`, in your ``setup.cfg`` rather
than ``setup.py``.
+.. versionchanged:: 5.0
+
+ Previously you could specify requirements for a given major version of
+ Python using requirments files with a ``-pyN`` suffix. This was deprecated
+ in 4.0 and removed in 5.0 in favour of environment markers.
+
Automatic File Generation
-------------------------
@@ -253,6 +259,21 @@ test files.
__ https://packaging.python.org/tutorials/distributing-packages/#manifest-in
+Release Notes
+~~~~~~~~~~~~~
+
+.. admonition:: Summary
+
+ *pbr* will automatically use *reno* \'s ``build_reno`` setuptools command
+ to generate a release notes file, if reno is available and configured.
+
+If using *reno*, you may wish to include a copy of the release notes in your
+packages. *reno* provides a ``build_reno`` `setuptools command`__ and, if reno
+is present and configured, *pbr* will automatically call this to generate a
+release notes file for inclusion in your package.
+
+__ https://docs.openstack.org/reno/latest/user/setuptools.html
+
Setup Commands
--------------
diff --git a/doc/source/user/packagers.rst b/doc/source/user/packagers.rst
index 74af8ac..2e705b0 100644
--- a/doc/source/user/packagers.rst
+++ b/doc/source/user/packagers.rst
@@ -103,3 +103,20 @@ skipped. Similarly setting ``SKIP_WRITE_GIT_CHANGELOG``
will cause logic around generating ``ChangeLog`` file using *git*
information to be skipped.
+
+.. _packaging-releasenotes:
+
+Release Notes
+-------------
+
+*pbr* generates a release notes file, typically called ``RELEASENOTES.rst``,
+if `reno`_ is present and configured. You may wish to disable this
+functionality. If that is the case setting ``SKIP_GENERATE_RENO``
+
+::
+
+ export SKIP_GENERATE_RENO
+
+will disable this feature.
+
+.. _reno: https://docs.openstack.org/reno/latest/
diff --git a/doc/source/user/using.rst b/doc/source/user/using.rst
index b5e28eb..2e58fee 100644
--- a/doc/source/user/using.rst
+++ b/doc/source/user/using.rst
@@ -230,6 +230,13 @@ The ``pbr`` section controls *pbr*-specific options and behaviours.
This can also be configured using the ``SKIP_GENERATE_AUTHORS`` environment
variable, as described :ref:`here <packaging-authors-changelog>`
+``skip_reno``
+ If enabled, *pbr* will not generate a ``RELEASENOTES.txt`` file if `reno`_ is
+ present and configured.
+
+ This can also be configured using the ``SKIP_GENERATE_RENO`` environment
+ variable, as described :ref:`here <packaging-releasenotes>`.
+
``autodoc_tree_index_modules``
A boolean option controlling whether *pbr* should generate an index of
modules using ``sphinx-apidoc``. By default, all files except ``setup.py``
@@ -382,20 +389,18 @@ Requirements
Requirements files are used in place of the ``install_requires`` and
``extras_require`` attributes. Requirement files should be given one of the
-below names. This order is also the order that the requirements are tried in
-(where ``N`` is the Python major version number used to install the package):
+below names. This order is also the order that the requirements are tried in:
-* ``requirements-pyN.txt``
-* ``tools/pip-requires-py3``
* ``requirements.txt``
* ``tools/pip-requires``
Only the first file found is used to install the list of packages it contains.
-.. note::
+.. versionchanged:: 5.0
- The ``requirements-pyN.txt`` file is deprecated - ``requirements.txt``
- should be universal. You can use `Environment markers`_ for this purpose.
+ Previously you could specify requirements for a given major version of
+ Python using requirements files with a ``-pyN`` suffix. This was deprecated
+ in 4.0 and removed in 5.0 in favour of environment markers.
.. _extra-requirements:
@@ -489,3 +494,4 @@ this file.
.. _setuptools: http://www.sphinx-doc.org/en/stable/setuptools.html
.. _sphinxcontrib-apidoc: https://pypi.org/project/sphinxcontrib-apidoc/
+.. _reno: https://docs.openstack.org/reno/latest/
diff --git a/lower-constraints.txt b/lower-constraints.txt
index 44956ce..173a299 100644
--- a/lower-constraints.txt
+++ b/lower-constraints.txt
@@ -26,7 +26,7 @@ six==1.10.0
snowballstemmer==1.2.1
Sphinx==1.6.5
sphinxcontrib-websupport==1.0.1
-stestr==2.0.0
+stestr==2.1.0
testrepository==0.0.18
testresources==2.0.0
testscenarios==0.4
diff --git a/pbr/core.py b/pbr/core.py
index a93253b..645a2ef 100644
--- a/pbr/core.py
+++ b/pbr/core.py
@@ -43,13 +43,13 @@
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
-from distutils import core
-from distutils import errors
import logging
import os
import sys
import warnings
+from distutils import errors
+
from pbr import util
@@ -57,8 +57,8 @@ if sys.version_info[0] == 3:
string_type = str
integer_types = (int,)
else:
- string_type = basestring # flake8: noqa
- integer_types = (int, long) # flake8: noqa
+ string_type = basestring # noqa
+ integer_types = (int, long) # noqa
def pbr(dist, attr, value):
@@ -103,6 +103,15 @@ def pbr(dist, attr, value):
raise errors.DistutilsSetupError(
'Error parsing %s: %s: %s' % (path, e.__class__.__name__, e))
+ # There are some metadata fields that are only supported by
+ # setuptools and not distutils, and hence are not in
+ # dist.metadata. We are OK to write these in. For gory details
+ # see
+ # https://github.com/pypa/setuptools/pull/1343
+ _DISTUTILS_UNSUPPORTED_METADATA = (
+ 'long_description_content_type', 'project_urls', 'provides_extras'
+ )
+
# Repeat some of the Distribution initialization code with the newly
# provided attrs
if attrs:
@@ -115,6 +124,8 @@ def pbr(dist, attr, value):
setattr(dist.metadata, key, val)
elif hasattr(dist, key):
setattr(dist, key, val)
+ elif key in _DISTUTILS_UNSUPPORTED_METADATA:
+ setattr(dist.metadata, key, val)
else:
msg = 'Unknown distribution option: %s' % repr(key)
warnings.warn(msg)
diff --git a/pbr/hooks/files.py b/pbr/hooks/files.py
index 48bf9e3..750ac32 100644
--- a/pbr/hooks/files.py
+++ b/pbr/hooks/files.py
@@ -58,8 +58,12 @@ class FilesConfig(base.BaseConfig):
if not target.endswith(os.path.sep):
target += os.path.sep
for (dirpath, dirnames, fnames) in os.walk(source_prefix):
- finished.append(
- "%s = " % dirpath.replace(source_prefix, target))
+ # As source_prefix is always matched, using replace with a
+ # a limit of one is always going to replace the path prefix
+ # and not accidentally replace some text in the middle of
+ # the path
+ new_prefix = dirpath.replace(source_prefix, target, 1)
+ finished.append("%s = " % new_prefix)
finished.extend(
[" %s" % os.path.join(dirpath, f) for f in fnames])
else:
diff --git a/pbr/packaging.py b/pbr/packaging.py
index c1d729f..baffdb2 100644
--- a/pbr/packaging.py
+++ b/pbr/packaging.py
@@ -81,14 +81,16 @@ def _any_existing(file_list):
def get_reqs_from_files(requirements_files):
existing = _any_existing(requirements_files)
+ # TODO(stephenfin): Remove this in pbr 6.0+
deprecated = [f for f in existing if f in PY_REQUIREMENTS_FILES]
if deprecated:
warnings.warn('Support for \'-pyN\'-suffixed requirements files is '
- 'deprecated in pbr 4.0 and will be removed in 5.0. '
+ 'removed in pbr 5.0 and these files are now ignored. '
'Use environment markers instead. Conflicting files: '
'%r' % deprecated,
DeprecationWarning)
+ existing = [f for f in existing if f not in PY_REQUIREMENTS_FILES]
for requirements_file in existing:
with open(requirements_file, 'r') as fil:
return fil.read().split('\n')
@@ -313,8 +315,6 @@ if __name__ == "__main__":
import sys
import wsgiref.simple_server as wss
- my_ip = socket.gethostbyname(socket.gethostname())
-
parser = argparse.ArgumentParser(
description=%(import_target)s.__doc__,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
@@ -578,6 +578,13 @@ class LocalSDist(sdist.sdist):
if hasattr(self, '_has_reno'):
return self._has_reno
+ option_dict = self.distribution.get_option_dict('pbr')
+ should_skip = options.get_boolean_option(option_dict, 'skip_reno',
+ 'SKIP_GENERATE_RENO')
+ if should_skip:
+ self._has_reno = False
+ return False
+
try:
# versions of reno witout this module will not have the required
# feature, hence the import
diff --git a/pbr/tests/test_files.py b/pbr/tests/test_files.py
index e60b6ca..ed67f7b 100644
--- a/pbr/tests/test_files.py
+++ b/pbr/tests/test_files.py
@@ -35,15 +35,20 @@ class FilesConfigTest(base.BaseTestCase):
])
self.useFixture(pkg_fixture)
pkg_etc = os.path.join(pkg_fixture.base, 'etc')
+ pkg_ansible = os.path.join(pkg_fixture.base, 'ansible',
+ 'kolla-ansible', 'test')
pkg_sub = os.path.join(pkg_etc, 'sub')
subpackage = os.path.join(
pkg_fixture.base, 'fake_package', 'subpackage')
os.makedirs(pkg_sub)
os.makedirs(subpackage)
+ os.makedirs(pkg_ansible)
with open(os.path.join(pkg_etc, "foo"), 'w') as foo_file:
foo_file.write("Foo Data")
with open(os.path.join(pkg_sub, "bar"), 'w') as foo_file:
foo_file.write("Bar Data")
+ with open(os.path.join(pkg_ansible, "baz"), 'w') as baz_file:
+ baz_file.write("Baz Data")
with open(os.path.join(subpackage, "__init__.py"), 'w') as foo_file:
foo_file.write("# empty")
@@ -76,3 +81,19 @@ class FilesConfigTest(base.BaseTestCase):
self.assertIn(
'\netc/pbr/ = \n etc/foo\netc/pbr/sub = \n etc/sub/bar',
config['files']['data_files'])
+
+ def test_data_files_globbing_source_prefix_in_directory_name(self):
+ # We want to test that the string, "docs", is not replaced in a
+ # subdirectory name, "sub-docs"
+ config = dict(
+ files=dict(
+ data_files="\n share/ansible = ansible/*"
+ )
+ )
+ files.FilesConfig(config, 'fake_package').run()
+ self.assertIn(
+ '\nshare/ansible/ = '
+ '\nshare/ansible/kolla-ansible = '
+ '\nshare/ansible/kolla-ansible/test = '
+ '\n ansible/kolla-ansible/test/baz',
+ config['files']['data_files'])
diff --git a/pbr/tests/test_hooks.py b/pbr/tests/test_hooks.py
index 0fcf96c..3f74790 100644
--- a/pbr/tests/test_hooks.py
+++ b/pbr/tests/test_hooks.py
@@ -41,7 +41,9 @@
import os
from testtools import matchers
+from testtools import skipUnless
+from pbr import testr_command
from pbr.tests import base
from pbr.tests import util
@@ -66,6 +68,7 @@ class TestHooks(base.BaseTestCase):
assert 'test_hook_1\ntest_hook_2' in stdout
assert return_code == 0
+ @skipUnless(testr_command.have_testr, "testrepository not available")
def test_custom_commands_known(self):
stdout, _, return_code = self.run_setup('--help-commands')
self.assertFalse(return_code)
diff --git a/pbr/tests/test_packaging.py b/pbr/tests/test_packaging.py
index 50922d2..853844f 100644
--- a/pbr/tests/test_packaging.py
+++ b/pbr/tests/test_packaging.py
@@ -43,7 +43,6 @@ import email.errors
import imp
import os
import re
-import sys
import sysconfig
import tempfile
import textwrap
@@ -56,7 +55,7 @@ import testscenarios
import testtools
from testtools import matchers
import virtualenv
-import wheel.install
+from wheel import wheelfile
from pbr import git
from pbr import packaging
@@ -372,13 +371,13 @@ class TestPackagingWheels(base.BaseTestCase):
relative_wheel_filename = os.listdir(dist_dir)[0]
absolute_wheel_filename = os.path.join(
dist_dir, relative_wheel_filename)
- wheel_file = wheel.install.WheelFile(absolute_wheel_filename)
+ wheel_file = wheelfile.WheelFile(absolute_wheel_filename)
wheel_name = wheel_file.parsed_filename.group('namever')
# Create a directory path to unpack the wheel to
self.extracted_wheel_dir = os.path.join(dist_dir, wheel_name)
# Extract the wheel contents to the directory we just created
- wheel_file.zipfile.extractall(self.extracted_wheel_dir)
- wheel_file.zipfile.close()
+ wheel_file.extractall(self.extracted_wheel_dir)
+ wheel_file.close()
def test_data_directory_has_wsgi_scripts(self):
# Build the path to the scripts directory
@@ -551,28 +550,6 @@ class ParseRequirementsTest(base.BaseTestCase):
result = packaging.parse_requirements([requirements])
self.assertEqual(['pbr'], result)
- @mock.patch('warnings.warn')
- def test_python_version(self, mock_warn):
- with open("requirements-py%d.txt" % sys.version_info[0],
- "w") as fh:
- fh.write("# this is a comment\nfoobar\n# and another one\nfoobaz")
- self.assertEqual(['foobar', 'foobaz'],
- packaging.parse_requirements())
- mock_warn.assert_called_once_with(mock.ANY, DeprecationWarning)
-
- @mock.patch('warnings.warn')
- def test_python_version_multiple_options(self, mock_warn):
- with open("requirements-py1.txt", "w") as fh:
- fh.write("thisisatrap")
- with open("requirements-py%d.txt" % sys.version_info[0],
- "w") as fh:
- fh.write("# this is a comment\nfoobar\n# and another one\nfoobaz")
- self.assertEqual(['foobar', 'foobaz'],
- packaging.parse_requirements())
- # even though we have multiple offending files, this should only be
- # called once
- mock_warn.assert_called_once_with(mock.ANY, DeprecationWarning)
-
class ParseRequirementsTestScenarios(base.BaseTestCase):
diff --git a/pbr/util.py b/pbr/util.py
index 45a3aed..63e913d 100644
--- a/pbr/util.py
+++ b/pbr/util.py
@@ -56,24 +56,21 @@ to be an installation dependency for our packages yet--it is still too unstable
# irritating Python bug that can crop up when using ./setup.py test.
# See: http://www.eby-sarna.com/pipermail/peak/2010-May/003355.html
try:
- import multiprocessing # flake8: noqa
+ import multiprocessing # noqa
except ImportError:
pass
-import logging # flake8: noqa
+import logging # noqa
+from collections import defaultdict
import os
import re
import sys
import traceback
-from collections import defaultdict
-
import distutils.ccompiler
-import pkg_resources
-
-from distutils import log
from distutils import errors
-from setuptools.command.egg_info import manifest_maker
+from distutils import log
+import pkg_resources
from setuptools import dist as st_dist
from setuptools import extension
@@ -244,11 +241,11 @@ def cfg_to_args(path='setup.cfg', script_args=()):
if hook != 'pbr.hooks.setup_hook']
for hook in setup_hooks:
hook_fn = resolve_name(hook)
- try :
+ try:
hook_fn(config)
except SystemExit:
log.error('setup hook %s terminated the installation')
- except:
+ except Exception:
e = sys.exc_info()[1]
log.error('setup hook %s raised exception: %s\n' %
(hook, e))
@@ -288,7 +285,9 @@ def cfg_to_args(path='setup.cfg', script_args=()):
def setup_cfg_to_setup_kwargs(config, script_args=()):
- """Processes the setup.cfg options and converts them to arguments accepted
+ """Convert config options to kwargs.
+
+ Processes the setup.cfg options and converts them to arguments accepted
by setuptools' setup() function.
"""
@@ -354,12 +353,13 @@ def setup_cfg_to_setup_kwargs(config, script_args=()):
# Split install_requires into package,env_marker tuples
# These will be re-assembled later
install_requires = []
- requirement_pattern = '(?P<package>[^;]*);?(?P<env_marker>[^#]*?)(?:\s*#.*)?$'
+ requirement_pattern = (
+ r'(?P<package>[^;]*);?(?P<env_marker>[^#]*?)(?:\s*#.*)?$')
for requirement in in_cfg_value:
m = re.match(requirement_pattern, requirement)
requirement_package = m.group('package').strip()
env_marker = m.group('env_marker').strip()
- install_requires.append((requirement_package,env_marker))
+ install_requires.append((requirement_package, env_marker))
all_requirements[''] = install_requires
elif arg == 'package_dir':
in_cfg_value = {'': in_cfg_value}
@@ -414,7 +414,8 @@ def setup_cfg_to_setup_kwargs(config, script_args=()):
# -> {'fred': ['bar'], 'fred:marker':['foo']}
if 'extras' in config:
- requirement_pattern = '(?P<package>[^:]*):?(?P<env_marker>[^#]*?)(?:\s*#.*)?$'
+ requirement_pattern = (
+ r'(?P<package>[^:]*):?(?P<env_marker>[^#]*?)(?:\s*#.*)?$')
extras = config['extras']
# Add contents of test-requirements, if any, into an extra named
# 'test' if one does not already exist.
@@ -430,7 +431,7 @@ def setup_cfg_to_setup_kwargs(config, script_args=()):
m = re.match(requirement_pattern, requirement)
extras_value = m.group('package').strip()
env_marker = m.group('env_marker')
- extra_requirements.append((extras_value,env_marker))
+ extra_requirements.append((extras_value, env_marker))
all_requirements[extra] = extra_requirements
# Transform the full list of requirements into:
@@ -459,7 +460,7 @@ def setup_cfg_to_setup_kwargs(config, script_args=()):
"Marker evaluation failed, see the following "
"error. For more information see: "
"http://docs.openstack.org/"
- "developer/pbr/compatibility.html#evaluate-marker"
+ "pbr/latest/user/using.html#environment-markers"
)
raise
else:
@@ -473,9 +474,10 @@ def setup_cfg_to_setup_kwargs(config, script_args=()):
def register_custom_compilers(config):
- """Handle custom compilers; this has no real equivalent in distutils, where
- additional compilers could only be added programmatically, so we have to
- hack it in somehow.
+ """Handle custom compilers.
+
+ This has no real equivalent in distutils, where additional compilers could
+ only be added programmatically, so we have to hack it in somehow.
"""
compilers = has_get_option(config, 'global', 'compilers')
@@ -497,7 +499,7 @@ def register_custom_compilers(config):
module_name = compiler.__module__
# Note; this *will* override built in compilers with the same name
- # TODO: Maybe display a warning about this?
+ # TODO(embray): Maybe display a warning about this?
cc = distutils.ccompiler.compiler_class
cc[name] = (module_name, compiler.__name__, desc)
@@ -560,13 +562,14 @@ def get_extension_modules(config):
def get_entry_points(config):
- """Process the [entry_points] section of setup.cfg to handle setuptools
- entry points. This is, of course, not a standard feature of
- distutils2/packaging, but as there is not currently a standard alternative
- in packaging, we provide support for them.
+ """Process the [entry_points] section of setup.cfg.
+
+ Processes setup.cfg to handle setuptools entry points. This is, of course,
+ not a standard feature of distutils2/packaging, but as there is not
+ currently a standard alternative in packaging, we provide support for them.
"""
- if not 'entry_points' in config:
+ if 'entry_points' not in config:
return {}
return dict((option, split_multiline(value))
@@ -600,9 +603,7 @@ def split_csv(value):
# The following classes are used to hack Distribution.command_options a bit
class DefaultGetDict(defaultdict):
- """Like defaultdict, but the get() method also sets and returns the default
- value.
- """
+ """Like defaultdict, but get() also sets and returns the default value."""
def get(self, key, default=None):
if default is None:
diff --git a/releasenotes/notes/fix-global-replace-of-src-prefix-in-glob-eb850b94ca96993e.yaml b/releasenotes/notes/fix-global-replace-of-src-prefix-in-glob-eb850b94ca96993e.yaml
new file mode 100644
index 0000000..b2895aa
--- /dev/null
+++ b/releasenotes/notes/fix-global-replace-of-src-prefix-in-glob-eb850b94ca96993e.yaml
@@ -0,0 +1,9 @@
+---
+fixes:
+ - |
+ Fixes a bug where the directory names of items specified in ``data_files``
+ could be renamed if the source prefix glob was contained within the
+ directory name. See `bug 1810804
+ <https://bugs.launchpad.net/pbr/+bug/1810804>`_ for details. For more
+ information on ``data_files``, see the `distutils documentation
+ <https://docs.python.org/2/distutils/setupscript.html#installing-additional-files>`_.
diff --git a/releasenotes/notes/long-descr-content-type-f9a1003acbb8740f.yaml b/releasenotes/notes/long-descr-content-type-f9a1003acbb8740f.yaml
new file mode 100644
index 0000000..5912332
--- /dev/null
+++ b/releasenotes/notes/long-descr-content-type-f9a1003acbb8740f.yaml
@@ -0,0 +1,6 @@
+---
+fixes:
+ - |
+ The ``description-content-type`` was not being set correctly. It
+ will now be correctly populated when using ``setuptools`` 39.2.0
+ and beyond.
diff --git a/setup.cfg b/setup.cfg
index bd65299..b26be54 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,7 +1,7 @@
[metadata]
name = pbr
author = OpenStack
-author-email = openstack-dev@lists.openstack.org
+author-email = openstack-discuss@lists.openstack.org
summary = Python Build Reasonableness
description-file =
README.rst
@@ -53,5 +53,5 @@ build-dir = doc/build
source-dir = doc/source
warning-is-error = 1
-[wheel]
+[bdist_wheel]
universal = 1
diff --git a/test-requirements.txt b/test-requirements.txt
index 8fdcb83..70e4ca0 100644
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -1,15 +1,17 @@
# 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.
+wheel>=0.32.0 # MIT
fixtures>=3.0.0 # Apache-2.0/BSD
hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
mock>=2.0.0 # BSD
six>=1.10.0 # MIT
-stestr>=2.0.0 # Apache-2.0
+stestr>=2.1.0 # Apache-2.0
testresources>=2.0.0 # Apache-2.0/BSD
testscenarios>=0.4 # Apache-2.0/BSD
testtools>=2.2.0 # MIT
virtualenv>=14.0.6 # MIT
+coverage!=4.4,>=4.0 # Apache-2.0
# optionally exposed by distutils commands
sphinx!=1.6.6,!=1.6.7,>=1.6.2 # BSD
diff --git a/tox.ini b/tox.ini
index d97e6ff..4d460d8 100644
--- a/tox.ini
+++ b/tox.ini
@@ -5,11 +5,15 @@ envlist = py{27,35,36},pep8,docs
[testenv]
usedevelop = True
install_command = pip install {opts} {packages}
-passenv = PBR_INTEGRATION PIPFLAGS PIPVERSION PBRVERSION REPODIR WHEELHOUSE PROJECTS OS_TEST_TIMEOUT OS_STDOUT_CAPTURE OS_STDERR_CAPTURE
+passenv = PBR_INTEGRATION PIPFLAGS PIPVERSION PBRVERSION REPODIR WHEELHOUSE PROJECTS
+setenv =
+ OS_STDOUT_CAPTURE={env:OS_STDOUT_CAPTURE:1}
+ OS_STDERR_CAPTURE={env:OS_STDERR_CAPTURE:1}
+ OS_TEST_TIMEOUT={env:OS_TEST_TIMEOUT:60}
deps =
-c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt}
-r{toxinidir}/test-requirements.txt
-commands = stestr run {posargs}
+commands = stestr run --suppress-attachments {posargs}
[testenv:pep8]
basepython = python3