Imported Upstream version 4.0.0 upstream/4.0.0
authorJinWang An <jinwang.an@samsung.com>
Mon, 28 Dec 2020 04:45:41 +0000 (13:45 +0900)
committerJinWang An <jinwang.an@samsung.com>
Mon, 28 Dec 2020 04:45:41 +0000 (13:45 +0900)
47 files changed:
AUTHORS
ChangeLog
PKG-INFO
README.rst
doc/source/compatibility.rst [deleted file]
doc/source/conf.py
doc/source/contributor/index.rst [new file with mode: 0644]
doc/source/history.rst [deleted file]
doc/source/index.rst
doc/source/packagers.rst [deleted file]
doc/source/reference/index.rst [new file with mode: 0644]
doc/source/semver.rst [deleted file]
doc/source/testing.rst [deleted file]
doc/source/user/compatibility.rst [new file with mode: 0644]
doc/source/user/features.rst [new file with mode: 0644]
doc/source/user/history.rst [new file with mode: 0644]
doc/source/user/index.rst [new file with mode: 0644]
doc/source/user/packagers.rst [new file with mode: 0644]
doc/source/user/semver.rst [new file with mode: 0644]
doc/source/user/using.rst [new file with mode: 0644]
pbr.egg-info/PKG-INFO
pbr.egg-info/SOURCES.txt
pbr/builddoc.py
pbr/core.py
pbr/packaging.py
pbr/testr_command.py
pbr/tests/test_hooks.py
pbr/tests/test_packaging.py
pbr/tests/test_setup.py
pbr/tests/test_util.py
pbr/tests/test_version.py
pbr/tests/testpackage/setup.cfg
pbr/tests/testpackage/test-requirements.txt
pbr/util.py
pbr/version.py
releasenotes/notes/deprecate-pyN-requirements-364655c38fa5b780.yaml [new file with mode: 0644]
releasenotes/notes/deprecate-testr-nose-integration-56e3e11248d946fc.yaml [new file with mode: 0644]
releasenotes/notes/remove-command-hooks-907d9c2325f306ca.yaml [new file with mode: 0644]
releasenotes/notes/v_version-457b38c8679c5868.yaml [new file with mode: 0644]
releasenotes/source/conf.py [new file with mode: 0644]
releasenotes/source/index.rst [new file with mode: 0644]
releasenotes/source/unreleased.rst [new file with mode: 0644]
setup.cfg
test-requirements.txt
tools/tox_install.sh [deleted file]
tools/tox_releasenotes.sh [new file with mode: 0755]
tox.ini

diff --git a/AUTHORS b/AUTHORS
index 17edd01b9787a075a20d98a5ff211caae3b602df..542e223c9ede619b000871008052fd19b7f8c6d4 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -3,6 +3,7 @@ Akihiro Motoki <motoki@da.jp.nec.com>
 Alex Gaynor <alex.gaynor@gmail.com>
 Alexander Makarov <amakarov@mirantis.com>
 Alfredo Moralejo <amoralej@redhat.com>
+Andreas Jaeger <aj@suse.com>
 Andreas Jaeger <aj@suse.de>
 Andrew Bogott <abogott@wikimedia.org>
 Angus Salkeld <asalkeld@redhat.com>
@@ -37,6 +38,7 @@ Eric Windisch <eric@cloudscaling.com>
 Erik M. Bray <embray@stsci.edu>
 Eugene Kirpichov <ekirpichov@gmail.com>
 Florian Wilhelm <Florian.Wilhelm@blue-yonder.com>
+Gaetan Semet <gaetan@xeberon.net>
 Gage Hugo <gagehugo@gmail.com>
 Gary Kotton <gkotton@redhat.com>
 Giampaolo Lauria <lauria@us.ibm.com>
@@ -47,8 +49,10 @@ Ionuț Arțăriși <iartarisi@suse.cz>
 James E. Blair <jeblair@hp.com>
 James Polley <jp@jamezpolley.com>
 Jason Kölker <jason@koelker.net>
+Jason R. Coombs <jaraco@jaraco.com>
 Jay Pipes <jaypipes@gmail.com>
 Jeremy Stanley <fungi@yuggoth.org>
+Joe D'Andrea <jdandrea@research.att.com>
 Joe Gordon <joe.gordon0@gmail.com>
 Joe Gordon <jogo@cloudscaling.com>
 Joe Heck <heckj@mac.com>
@@ -80,6 +84,7 @@ Octavian Ciuhandu <ociuhandu@cloudbasesolutions.com>
 Ondřej Nový <ondrej.novy@firma.seznam.cz>
 Paul Belanger <pabelanger@redhat.com>
 Rajaram Mallya <rajarammallya@gmail.com>
+Rajath Agasthya <rajagast@cisco.com>
 Ralf Haferkamp <rhafer@suse.de>
 Randall Nortman <openstack@nortman.net>
 Rick Harris <rconradharris@gmail.com>
@@ -117,6 +122,7 @@ YAMAMOTO Takashi <yamamoto@valinux.co.jp>
 Yaguang Tang <heut2008@gmail.com>
 Yuriy Taraday <yorik.sar@gmail.com>
 Zhongyue Luo <zhongyue.nah@intel.com>
+Zuul <zuul@review.openstack.org>
 alexpilotti <ap@pilotti.it>
 cbjchen@cn.ibm.com <cbjchen@cn.ibm.com>
 dineshbhor <dinesh.bhor@nttdata.com>
@@ -125,4 +131,5 @@ lifeless <robertc@robertcollins.net>
 melanie witt <melwitt@yahoo-inc.com>
 nizam <abdul.nizamuddin@nectechnologies.in>
 weiweigu <gu.weiwei@zte.com.cn>
+zhangyangyang <zhangyangyang@unionpay.com>
 zhangyanxian <zhang.yanxian@zte.com.cn>
index 405660f8b9686da469ae3ec4a3163ac82bf52809..bbc9c103e58ea133f9e50dd104f4f0fdd3aec408 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,10 +1,58 @@
 CHANGES
 =======
 
+4.0.0
+-----
+
+* builddoc: Treat '[pbr] autodoc\_tree\_excludes' as a multi-line opt
+* update parse test to use reliable comparison
+* Make docs on env vars a little clearer
+* Updated from global requirements
+* Updated from global requirements
+* future-proof invocation of apidoc
+* emit warning correctly
+* Updated from global requirements
+* deprecations: Deprecate support for '-py{N}' requirements
+* doc: Minor rework of usage doc
+* doc: Rework features doc
+* Support v<semver> version
+* Deprecate testr and nose integration
+* tests: Increase coverage of requirements parsing
+* trivial: Move packaging tests to test\_packaging
+* Put test-requirements into an extra named 'test'
+* Support Description-Content-Type metadata
+* Avoid tox\_install.sh for constraints support
+* Test on Python 3.6
+* Support PEP 345 Project-URL metadata
+* Remove setting of version/release from releasenotes
+* Updated from global requirements
+* Use 'build\_reno' setuptools extension if available
+* Remove unnecessary 'if True'
+* Discover Distribution through the class hierarchy
+* Add reno for release notes management
+* Remove support for command hooks
+* Remove dead code
+* Deprecate support for Sphinx < 1.6
+* builddoc: Use '[sphinx\_build] builders' with Sphinx < 1.6
+* Remove win32/nt checks for wrapper script gen
+* Updated from global requirements
+* Remove py26 support
+* Updated from global requirements
+* Updated from global requirements
+* Updated from global requirements
+* Update URLs in documents according to document migration
+* Updated from global requirements
+* gitignore: Ignore .venv
+* switch from oslosphinx to openstackdocstheme
+* Trivial: Fix docstring
+* turn on warning-as-error flag for doc build
+* rearrange existing documentation using the new standard layout
+
 3.1.1
 -----
 
 * Restore previous IP binding
+* docs: Don't specify pbr version in 'setup.py'
 
 3.1.0
 -----
index 8bde2504aa358f1b6f4051c63e4b6f7794a0578e..1339ea8b5ecdb2937db5db854b3f73c8e6b3dffb 100644 (file)
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,11 +1,14 @@
-Metadata-Version: 1.1
+Metadata-Version: 2.1
 Name: pbr
-Version: 3.1.1
+Version: 4.0.0
 Summary: Python Build Reasonableness
-Home-page: http://docs.openstack.org/developer/pbr/
+Home-page: https://docs.openstack.org/pbr/latest/
 Author: OpenStack
 Author-email: openstack-dev@lists.openstack.org
 License: UNKNOWN
+Project-URL: Bug Tracker, https://bugs.launchpad.net/pbr/
+Project-URL: Documentation, https://docs.openstack.org/pbr/
+Project-URL: Source Code, https://git.openstack.org/cgit/openstack-dev/pbr/
 Description: Introduction
         ============
         
@@ -39,10 +42,10 @@ Description: Introduction
         them as quickly as possible.
         
         * License: Apache License, Version 2.0
-        * Documentation: http://docs.openstack.org/developer/pbr
-        * Source: http://git.openstack.org/cgit/openstack-dev/pbr
-        * Bugs: http://bugs.launchpad.net/pbr
-        * Change Log: https://docs.openstack.org/developer/pbr/history.html
+        * Documentation: https://docs.openstack.org/pbr/latest/
+        * Source: https://git.openstack.org/cgit/openstack-dev/pbr
+        * Bugs: https://bugs.launchpad.net/pbr
+        * Change Log: https://docs.openstack.org/pbr/latest/user/history.html
         
         .. _d2to1: https://pypi.python.org/pypi/d2to1
         .. _distutils2: https://pypi.python.org/pypi/Distutils2
@@ -60,9 +63,9 @@ Classifier: License :: OSI Approved :: Apache Software License
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
 Classifier: Programming Language :: Python :: 3.3
 Classifier: Programming Language :: Python :: 3.4
 Classifier: Programming Language :: Python :: 3.5
+Description-Content-Type: text/x-rst; charset=UTF-8
index 4c4ebba748b112f5e57e0e807c9bfc349c98f42c..9c1df73ecaaca4063fe0f30f990d4f3e2fed9a9f 100644 (file)
@@ -31,10 +31,10 @@ when that library itself will alter how the setup is processed. As Metadata
 them as quickly as possible.
 
 * License: Apache License, Version 2.0
-* Documentation: http://docs.openstack.org/developer/pbr
-* Source: http://git.openstack.org/cgit/openstack-dev/pbr
-* Bugs: http://bugs.launchpad.net/pbr
-* Change Log: https://docs.openstack.org/developer/pbr/history.html
+* Documentation: https://docs.openstack.org/pbr/latest/
+* Source: https://git.openstack.org/cgit/openstack-dev/pbr
+* Bugs: https://bugs.launchpad.net/pbr
+* Change Log: https://docs.openstack.org/pbr/latest/user/history.html
 
 .. _d2to1: https://pypi.python.org/pypi/d2to1
 .. _distutils2: https://pypi.python.org/pypi/Distutils2
diff --git a/doc/source/compatibility.rst b/doc/source/compatibility.rst
deleted file mode 100644 (file)
index 868ac75..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-..
-    The name of this document and the anchor in this document must be
-    treated as a stable API.  Links to this document are coded into
-    pbr and deployed versions of pbr will refer users to this document
-    in the case of certain errors.
-    Ensure any link you use in PBR is defined via a ref with .. _name.
-
-
-===================
-Compatibility Notes
-===================
-
-Useful notes about errors users may encounter when features cannot be
-supported on older versions of setuptools / pip / wheel.
-
-
-setuptools
-==========
-
-
-.. _evaluate-marker:
-
-evaluate_marker
----------------
-
-evaluate_markers may run into issues with the '>', '>=', '<', and '<='
-operators if the installed version of setuptools is less than 17.1.  Projects
-using these operators with markers should specify a minimum version of 17.1
-for setuptools.
-
-
-pip
-===
-
-markers
--------
-
-For versions of pip < 7 with pbr < 1.9, dependencies that use markers will not
-be installed.  Projects using pbr and markers should set a minimum version of
-1.9 for pbr.
-
-
-Recommended setup.py
-====================
-
-:ref:`setup_py`.
-
-
-Sphinx
-======
-
-.. _sphinx-1.5:
-
-Version 1.5.0+
---------------
-
-The ``warning-is-error`` flag is only supported by Sphinx 1.5 and will cause
-errors when used with older versions.
index f0a78ecc37ca8272ed7a9cb95cbbca53de1433dc..cc7f4b35b83c750b232d0949323dd5ab5c86d02d 100644 (file)
@@ -8,14 +8,19 @@ sys.path.insert(0, os.path.abspath('../..'))
 
 # Add any Sphinx extension module names here, as strings. They can be
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
-extensions = ['sphinx.ext.autodoc']
-# make oslosphinx optional to not increase the needed dependencies
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo']
+# make openstackdocstheme optional to not increase the needed dependencies
 try:
-    import oslosphinx
+    import openstackdocstheme
+    extensions.append('openstackdocstheme')
 except ImportError:
-    pass
-else:
-    extensions.append('oslosphinx')
+    openstackdocstheme = None
+
+# openstackdocstheme options
+repository_name = 'openstack/pbr'
+bug_project = 'pbr'
+bug_tag = ''
+html_last_updated_fmt = '%Y-%m-%d %H:%M'
 
 # autodoc generation is a bit aggressive and a nuisance when doing heavy
 # text edit cycles.
@@ -50,7 +55,10 @@ exclude_trees = []
 
 # The theme to use for HTML and HTML Help pages.  Major themes that come with
 # Sphinx are currently 'default' and 'sphinxdoc'.
-html_theme = 'default'
+if openstackdocstheme is not None:
+    html_theme = 'openstackdocs'
+else:
+    html_theme = 'default'
 
 # Output file base name for HTML help builder.
 htmlhelp_basename = '%sdoc' % project
diff --git a/doc/source/contributor/index.rst b/doc/source/contributor/index.rst
new file mode 100644 (file)
index 0000000..b7b4a75
--- /dev/null
@@ -0,0 +1,36 @@
+==============
+ Contributing
+==============
+
+Basic Details
+=============
+
+.. include:: ../../../CONTRIBUTING.rst
+
+Running the Tests for pbr
+=========================
+
+The testing system is based on a combination of `tox`_ and `testr`_. The canonical
+approach to running tests is to simply run the command ``tox``. This will
+create virtual environments, populate them with dependencies and run all of
+the tests that OpenStack CI systems run. Behind the scenes, tox is running
+``testr run --parallel``, but is set up such that you can supply any additional
+testr arguments that are needed to tox. For example, you can run:
+``tox -- --analyze-isolation`` to cause tox to tell testr to add
+``--analyze-isolation`` to its argument list.
+
+It is also possible to run the tests inside of a virtual environment
+you have created, or it is possible that you have all of the dependencies
+installed locally already. If you'd like to go this route, the requirements
+are listed in ``requirements.txt`` and the requirements for testing are in
+``test-requirements.txt``. Installing them via pip, for instance, is simply::
+
+  pip install -r requirements.txt -r test-requirements.txt
+
+In 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
+
+.. _tox: http://tox.testrun.org/
+.. _testr: https://wiki.openstack.org/wiki/Testr
diff --git a/doc/source/history.rst b/doc/source/history.rst
deleted file mode 100644 (file)
index 1d8f5cd..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-=================
- Release History
-=================
-
-.. include:: ../../ChangeLog
index 4ff2d7a835aa10ee872f95f129d5d55da25efab4..60cd46172b51ee64e3f9333a431d7f043ee8e379 100644 (file)
 pbr - Python Build Reasonableness
 =================================
 
-A library for managing setuptools packaging needs in a consistent manner.
+A library for managing *setuptools* packaging needs in a consistent manner.
 
-`pbr` reads and then filters the `setup.cfg` data through a setup hook to
-fill in default values and provide more sensible behaviors, and then feeds
-the results in as the arguments to a call to `setup.py` - so the heavy
-lifting of handling python packaging needs is still being done by
-`setuptools`.
+*pbr* reads and then filters the ``setup.cfg`` data through a setup hook to
+fill in default values and provide more sensible behaviors, and then feeds the
+results in as the arguments to a call to ``setup.py`` - so the heavy lifting of
+handling Python packaging needs is still being done by *setuptools*.
 
-Note that we don't support the `easy_install` aspects of setuptools: while
-we depend on setup_requires, for any install_requires we recommend that they
-be installed prior to running `setup.py install` - either by hand, or by using
-an install tool such as `pip`.
+Note that we don't support the ``easy_install`` aspects of *setuptools*: while
+we depend on ``setup_requires``, for any ``install_requires`` we recommend that
+they be installed prior to running ``setup.py install`` - either by hand, or by
+using an install tool such as *pip*.
 
-What It Does
-============
-
-PBR can and does do a bunch of things for you:
+*pbr* can and does do a bunch of things for you:
 
 * **Version**: Manage version number based on git revisions and tags
 * **AUTHORS**: Generate AUTHORS file from git log
 * **ChangeLog**: Generate ChangeLog from git log
 * **Manifest**: Generate a sensible manifest from git files and some standard
   files
-* **Sphinx Autodoc**: Generate autodoc stub files for your whole module
 * **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
+* **Sphinx Autodoc**: Generate autodoc stub files for your whole module
 
-Version
--------
-
-Versions can be managed two ways - postversioning and preversioning.
-Postversioning is the default, and preversioning is enabled by setting
-``version`` in the setup.cfg ``metadata`` section. In both cases version
-strings are inferred from git.
-
-If the currently checked out revision is tagged, that tag is used as
-the version.
-
-If the currently checked out revision is not tagged, then we take the
-last tagged version number and increment it to get a minimum target
-version.
-
-We then walk git history back to the last release. Within each commit we look
-for a Sem-Ver: pseudo header, and if found parse it looking for keywords.
-Unknown symbols are not an error (so that folk can't wedge pbr or break their
-tree), but we will emit an info level warning message. Known symbols:
-``feature``, ``api-break``, ``deprecation``, ``bugfix``. A missing
-Sem-Ver line is equivalent to ``Sem-Ver: bugfix``. The ``bugfix`` symbol causes
-a patch level increment to the version. The ``feature`` and ``deprecation``
-symbols cause a minor version increment. The ``api-break`` symbol causes a
-major version increment.
-
-If postversioning is in use, we use the resulting version number as the target
-version.
-
-If preversioning is in use we check that the version set in the metadata
-section of `setup.cfg` is greater than the version we infer using the above
-method.  If the inferred version is greater than the preversioning value we
-raise an error, otherwise we use the version from `setup.cfg` as the target.
-
-We then generate dev version strings based on the commits since the last
-release and include the current git sha to disambiguate multiple dev versions
-with the same number of commits since the release.
-
-.. note::
-
-   `pbr` expects git tags to be signed for use in calculating versions
-
-The versions are expected to be compliant with :doc:`semver`.
-
-The ``version.SemanticVersion`` class can be used to query versions of a
-package and present it in various forms - ``debian_version()``,
-``release_string()``, ``rpm_string()``, ``version_string()``, or
-``version_tuple()``.
-
-AUTHORS and ChangeLog
----------------------
-
-Why keep an `AUTHORS` or a `ChangeLog` file when git already has all of the
-information you need? `AUTHORS` generation supports filtering/combining based
-on a standard `.mailmap` file.
-
-Manifest
---------
-
-Just like `AUTHORS` and `ChangeLog`, why keep a list of files you wish to
-include when you can find many of these in git. `MANIFEST.in` generation
-ensures almost all files stored in git, with the exception of `.gitignore`,
-`.gitreview` and `.pyc` files, are automatically included in your
-distribution. In addition, the generated `AUTHORS` and `ChangeLog` files are
-also included. In many cases, this removes the need for an explicit
-'MANIFEST.in' file
-
-Sphinx Autodoc
---------------
-
-Sphinx can produce auto documentation indexes based on signatures and
-docstrings of your project but you have to give it index files to tell it
-to autodoc each module: that's kind of repetitive and boring. PBR will scan
-your project, find all of your modules, and generate all of the stub files for
-you.
-
-Sphinx documentation setups are altered to generate man pages by default. They
-also have several pieces of information that are known to setup.py injected
-into the sphinx config.
-
-See the pbr_ section for details on configuring your project for autodoc.
-
-Requirements
-------------
-
-You may not have noticed, but there are differences in how pip
-`requirements.txt` files work and how distutils wants to be told about
-requirements. The pip way is nicer because it sure does make it easier to
-populate a virtualenv for testing or to just install everything you need.
-Duplicating the information, though, is super lame. To solve this issue, `pbr`
-will let you use `requirements.txt`-format files to describe the requirements
-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
-`"extra" requirements`_, in your `setup.cfg` rather than `setup.py`.
-
-long_description
-----------------
-
-There is no need to maintain two long descriptions- and your README file is
-probably a good long_description. So we'll just inject the contents of your
-README.rst, README.txt or README file into your empty long_description. Yay
-for you.
-
-Usage
-=====
-
-`pbr` is a setuptools plugin and so to use it you must use setuptools and call
-``setuptools.setup()``. While the normal setuptools facilities are available,
-pbr makes it possible to express them through static data files.
-
-.. _setup_py:
-
-setup.py
+Contents
 --------
 
-`pbr` only requires a minimal `setup.py` file compared to a standard setuptools
-project. This is because most configuration is located in static configuration
-files. This recommended minimal `setup.py` file should look something like this::
-
-    #!/usr/bin/env python
-
-    from setuptools import setup
-
-    setup(
-        setup_requires=['pbr>=1.9', 'setuptools>=17.1'],
-        pbr=True,
-    )
-
-.. note::
-
-   It is necessary to specify ``pbr=True`` to enabled `pbr` functionality.
-
-.. note::
-
-   While one can pass any arguments supported by setuptools to `setup()`,
-   any conflicting arguments supplied in `setup.cfg` will take precedence.
-
-setup.cfg
----------
-
-The `setup.cfg` file is an ini-like file that can mostly replace the `setup.py`
-file. It is based on the distutils2_ `setup.cfg` file. A simple sample can be
-found in `pbr`'s own `setup.cfg` (it uses its own machinery to install
-itself)::
-
-    [metadata]
-    name = pbr
-    author = OpenStack Foundation
-    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
-        Environment :: Console
-        Environment :: OpenStack
-        Intended Audience :: Developers
-        Intended Audience :: Information Technology
-        License :: OSI Approved :: Apache Software License
-        Operating System :: OS Independent
-        Programming Language :: Python
-    keywords =
-        setup
-        distutils
-
-    [files]
-    packages =
-        pbr
-    data_files =
-        etc/pbr = etc/*
-        etc/init =
-            pbr.packaging.conf
-            pbr.version.conf
-
-    [entry_points]
-    console_scripts =
-        pbr = pbr.cmd:main
-    pbr.config.drivers =
-        plain = pbr.cfg.driver:Plain
-
-`pbr` provides its own section in these documents, ostensibly called ``pbr``,
-and provides a custom version of Sphinx's ``build_sphinx`` section. Most other
-sections are provided by setuptools and may influence either the build itself
-or the output of various `setuptools commands`__. The remaining sections are
-provided by libraries that provide setuptools extensions, such as
-``extract_mesages`` (provided by `Babel`__). Some of these are described below.
-
-__ https://setuptools.readthedocs.io/en/latest/setuptools.html#command-reference
-__ http://babel.pocoo.org/en/latest/setup.html
-__ http://www.sphinx-doc.org/en/stable/setuptools.html
-
-.. note::
-
-   Comments may be used in `setup.cfg`, however all comments should start with
-   a `#` and may be on a single line, or in line, with at least one white space
-   character immediately preceding the `#`. Semicolons are not a supported
-   comment delimiter. For instance::
-
-       [section]
-       # A comment at the start of a dedicated line
-       key =
-           value1 # An in line comment
-           value2
-           # A comment on a dedicated line
-           value3
-
-files
-~~~~~
-
-The ``files`` section defines the install location of files in the package
-using three fundamental keys: ``packages``, ``namespace_packages``, and
-``data_files``.
-
-``packages``
-
-  A list of top-level packages that should be installed. The behavior of
-  packages is similar to ``setuptools.find_packages`` in that it recurses the
-  python package hierarchy below the given top level and installs all of it. If
-  ``packages`` is not specified, it defaults to the value of the ``name`` field
-  given in the ``[metadata]`` section.
-
-``namespace_packages``
-
-  Similar to ``packages``, but is a list of packages that provide namespace
-  packages.
-
-``data_files``
-
-  A list of files to be installed. The format is an indented block that
-  contains key value pairs which specify target directory and source file to
-  install there. More than one source file for a directory may be indicated
-  with a further indented list. Source files are stripped of leading
-  directories.  Additionally, `pbr` supports a simple file globbing syntax for
-  installing entire directory structures, thus::
-
-   [files]
-   data_files =
-       etc/pbr = etc/pbr/*
-       etc/neutron =
-           etc/api-paste.ini
-           etc/dhcp-agent.ini
-       etc/init.d = neutron.init
-
-  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`. 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.
-
-pbr
-~~~
-
-The ``pbr`` section controls `pbr` specific options and behaviours.
-
-``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` are
-  included, but this can be overridden using the ``autodoc_tree_excludes``
-  option.
-
-``autodoc_tree_excludes``
-
-  A list of modules to exclude when building documentation using
-  `sphinx-apidoc`. Defaults to ``[setup.py]``. Refer to the `sphinx-apidoc man
-  page`_ for more information.
-
-``autodoc_index_modules``
-
-  A boolean option controlling whether `pbr` should itself generates
-  documentation for Python modules of the project. By default, all found Python
-  modules are included; some of them can be excluded by listing them in
-  ``autodoc_exclude_modules``.
-
-``autodoc_exclude_modules``
-
-  A list of modules to exclude when building module documentation using `pbr`.
-  `fnmatch` style pattern (e.g. `myapp.tests.*`) can be used.
-
-``api_doc_dir``
-
-  A subdirectory inside the ``build_sphinx.source_dir`` where
-  auto-generated API documentation should be written, if
-  ``autodoc_index_modules`` is set to True. Defaults to ``"api"``.
-
-.. note::
-
-   When using ``autodoc_tree_excludes`` or ``autodoc_index_modules`` you may
-   also need to set ``exclude_patterns`` in your Sphinx configuration file
-   (generally found at `doc/source/conf.py` in most OpenStack projects)
-   otherwise Sphinx may complain about documents that are not in a toctree.
-   This is especially true if the ``[sphinx_build] warning-is-error`` option is
-   set. See the `Sphinx build configuration file`_ documentation for more
-   information on configuring Sphinx.
-
-.. versionchanged:: 2.0
-
-   The ``pbr`` section used to take a ``warnerrors`` option that would enable
-   the ``-W`` (Turn warnings into errors.) option when building Sphinx. This
-   feature was broken in 1.10 and was removed in pbr 2.0 in favour of the
-   ``[build_sphinx] warning-is-error`` provided in Sphinx 1.5+.
-
-build_sphinx
-~~~~~~~~~~~~
-
-The ``build_sphinx`` section is a version of the ``build_sphinx`` setuptools
-plugin provided with Sphinx. This plugin extends the original plugin to add the
-following:
-
-- Automatic generation of module documentation using the apidoc__ tool
-
-- Automatic configuration of the `project`, `version` and `release` settings
-  using information from `pbr` itself
-
-- Support for multiple builders using the ``builders`` configuration option
-
-  .. note::
-
-     Sphinx 1.6 adds support for multiple builders using the default `builder`
-     option. You should refer to this file for more information.
-
-The version of ``build_sphinx`` provided by `pbr` provides a single additional
-option.
-
-``builders``
-
-  A space or comma separated list of builders to run. For example, to build
-  both HTML and man page documentation, you would define the following in your
-  `setup.cfg`:
-
-  .. code-block:: ini
-
-      [build_sphinx]
-      builders = html,man
-      source-dir = doc/source
-      build-dir = doc/build
-      all-files = 1
-
-``source_dir``
-
-  The path to the source directory where the Sphinx documentation tree
-  is.
-
-For information on the remaining options, refer to the `Sphinx
-documentation`__. In addition, the ``autodoc_index_modules``,
-``autodoc_tree_index_modules``, ``autodoc_exclude_modules`` and
-``autodoc_tree_excludes`` options in the ``pbr`` section will affect the output
-of the automatic module documentation generation.
-
-.. versionchanged:: 3.0
-
-   The ``build_sphinx`` plugin used to default to building both HTML and man
-   page output. This is no longer the case, and you should explicitly set
-   ``builders`` to ``html man`` if you wish to retain this behavior.
-
-__ http://www.sphinx-doc.org/en/stable/man/sphinx-apidoc.html
-__ http://www.sphinx-doc.org/en/stable/setuptools.html
-
-entry_points
-~~~~~~~~~~~~
-
-The ``entry_points`` section defines entry points for generated console scripts
-and python libraries. This is actually provided by `setuptools`__ but is
-documented here owing to its importance.
-
-The general syntax of specifying entry points is a top level name indicating
-the entry point group name, followed by one or more key value pairs naming
-the entry point to be installed. For instance::
-
-    [entry_points]
-    console_scripts =
-        pbr = pbr.cmd:main
-    pbr.config.drivers =
-        plain = pbr.cfg.driver:Plain
-        fancy = pbr.cfg.driver:Fancy
-
-Will cause a console script called `pbr` to be installed that executes the
-`main` function found in `pbr.cmd`. Additionally, two entry points will be
-installed for `pbr.config.drivers`, one called `plain` which maps to the
-`Plain` class in `pbr.cfg.driver` and one called `fancy` which maps to the
-`Fancy` class in `pbr.cfg.driver`.
-
-__ https://setuptools.readthedocs.io/en/latest/setuptools.html#options
-
-Requirements
-------------
-
-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):
-
-* 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::
-
-   The 'requirements-pyN.txt' file is deprecated - 'requirements.txt' should
-   be universal. You can use `Environment markers`_ for this purpose.
-
-Extra requirements
-~~~~~~~~~~~~~~~~~~
-
-Groups of optional dependencies, or `"extra" requirements`_, can be described
-in your `setup.cfg`, rather than needing to be added to `setup.py`. An example
-(which also demonstrates the use of environment markers) is shown below.
-
-Environment markers
-~~~~~~~~~~~~~~~~~~~
-
-Environment markers are `conditional dependencies`_ which can be added to the
-requirements (or to a group of extra requirements) automatically, depending
-on the environment the installer is running in. They can be added to
-requirements in the requirements file, or to extras defined in `setup.cfg`,
-but the format is slightly different for each.
-
-For ``requirements.txt``::
-
-    argparse; python_version=='2.6'
-
-This will result in the package depending on ``argparse`` only if it's being
-installed into Python 2.6
-
-For extras specified in `setup.cfg`, add an ``extras`` section. For instance,
-to create two groups of extra requirements with additional constraints on the
-environment, you can use::
-
-    [extras]
-    security =
-        aleph
-        bet:python_version=='3.2'
-        gimel:python_version=='2.7'
-    testing =
-        quux:python_version=='2.7'
-
-
-Testing
--------
-
-`pbr` overrides the ``setuptools`` hook ``test`` (i.e. ``setup.py test``). The
-following sequence is followed:
-
-#. If a ``.testr.conf`` file exists and `testrepository
-   <https://pypi.python.org/pypi/testrepository>`__ is installed, `pbr`
-   will use it as the test runner.  See the ``testr`` documentation
-   for more details.
-
-   .. note::
-
-     This is separate to ``setup.py testr`` (note the extra ``r``) which
-     is provided directly by the ``testrepository`` package.  Be careful
-     as there is some overlap of command arguments.
-
-#. Although deprecated, if ``[nosetests]`` is defined in ``setup.cfg``
-   and `nose <http://nose.readthedocs.io/en/latest/>`__ is installed,
-   the ``nose`` runner will be used.
-
-#. In other cases no override will be installed and the ``test``
-   command will revert to `setuptools
-   <http://setuptools.readthedocs.io/en/latest/setuptools.html#test-build-package-and-run-a-unittest-suite>`__.
-
-A typical usage would be in ``tox.ini`` such as::
-
-  [tox]
-  minversion = 2.0
-  skipsdist = True
-  envlist = py33,py34,py35,py26,py27,pypy,pep8,docs
-
-  [testenv]
-  usedevelop = True
-  setenv =
-    VIRTUAL_ENV={envdir}
-    CLIENT_NAME=pbr
-  deps = .
-       -r{toxinidir}/test-requirements.txt
-  commands =
-    python setup.py test --testr-args='{posargs}'
-
-The argument ``--coverage`` will set ``PYTHON`` to ``coverage run`` to
-produce a coverage report.  ``--coverage-package-name`` can be used to
-modify or narrow the packages traced.
-
-Additional Docs
-===============
-
 .. toctree::
-   :maxdepth: 1
-
-   packagers
-   semver
-   testing
-   compatibility
-   api/modules
-   history
-
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
+   :maxdepth: 2
 
-.. _"extra" requirements:
- https://www.python.org/dev/peps/pep-0426/#extras-optional-dependencies
-.. _conditional dependencies:
- https://www.python.org/dev/peps/pep-0426/#environment-markers
-.. _distutils2: http://alexis.notmyidea.org/distutils2/setupcfg.html
-.. _sphinx-apidoc man page: http://sphinx-doc.org/man/sphinx-apidoc.html
-.. _Sphinx build configuration file: http://sphinx-doc.org/config.html
+   user/index
+   reference/index
+   contributor/index
diff --git a/doc/source/packagers.rst b/doc/source/packagers.rst
deleted file mode 100644 (file)
index 29fc86e..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-===============================
- Notes for Package maintainers
-===============================
-
-If you are maintaining packages of software that uses `pbr`, there are some
-features you probably want to be aware of that can make your life easier.
-They are exposed by environment variables, so adding them to rules or spec
-files should be fairly easy.
-
-Versioning
-==========
-
-`pbr`, when run in a git repo, derives the version of a package from the
-git tags. When run in a tarball with a proper egg-info dir, it will happily
-pull the version from that. So for the most part, the package maintainers
-shouldn't need to care. However, if you are doing something like keeping a
-git repo with the sources and the packaging intermixed and it's causing pbr
-to get confused about whether its in its own git repo or not, you can set
-`PBR_VERSION`:
-
-::
-
-  PBR_VERSION=1.2.3
-
-and all version calculation logic will be completely skipped and the supplied
-version will be considered absolute.
-
-Distribution version numbers
-============================
-
-`pbr` will automatically calculate upstream version numbers for dpkg and rpm
-using systems. Releases are easy (and obvious). When packaging preleases though
-things get more complex. Firstly, semver does not provide for any sort order
-between pre-releases and development snapshots, so it can be complex (perhaps
-intractable) to package both into one repository - we recommend with either
-packaging pre-release releases (alpha/beta/rc's) or dev snapshots but not both.
-Secondly, as pre-releases and snapshots have the same major/minor/patch version
-as the version they lead up to, but have to sort before it, we cannot map their
-version naturally into the rpm version namespace: instead we represent their
-versions as versions of the release before.
-
-Dependencies
-============
-
-As of 1.0.0 `pbr` doesn't alter the dependency behaviour of `setuptools`.
-
-Older versions would invoke `pip` internally under some circumstances and
-required the environment variable `SKIP_PIP_INSTALL` to be set to prevent
-that. Since 1.0.0 we now document that dependencies should be installed before
-installing a `pbr` using package. We don't support easy install, but neither
-do we interfere with it today. If you observe easy install being triggered when
-building a binary package, then you've probably missed one or more package
-requirements.
-
-Note: we reserve the right to disable easy install via `pbr` in future, since
-we don't want to debug or support the interactions that can occur when using
-it.
-
-Tarballs
-========
-
-`pbr` includes everything in a source tarball that is in the original `git`
-repository. This can again cause havoc if a package maintainer is doing fancy
-things with combined `git` repos, and is generating a source tarball using
-`python setup.py sdist` from that repo. If that is the workflow the packager
-is using, setting `SKIP_GIT_SDIST`:
-
-::
-
-  SKIP_GIT_SDIST=1
-
-will cause all logic around using git to find the files that should be in the
-source tarball to be skipped. Beware though, that because `pbr` packages
-automatically find all of the files, most of them do not have a complete
-`MANIFEST.in` file, so its possible that a tarball produced in that way will
-be missing files.
-
-AUTHORS and ChangeLog
-=====================
-
-`pbr` generates AUTHORS and ChangeLog files from git information. This
-can cause problem in distro packaging if package maintainer is using git
-repository for packaging source. If that is the case setting
-`SKIP_GENERATE_AUTHORS`
-
-::
-
-   SKIP_GENERATE_AUTHORS=1
-
-will cause logic around generating AUTHORS using git information to be
-skipped. Similarly setting `SKIP_WRITE_GIT_CHANGELOG`
-
-::
-
-   SKIP_WRITE_GIT_CHANGELOG=1
-
-will cause logic around generating ChangeLog file using git
-information to be skipped.
diff --git a/doc/source/reference/index.rst b/doc/source/reference/index.rst
new file mode 100644 (file)
index 0000000..68a9c32
--- /dev/null
@@ -0,0 +1,8 @@
+===================
+ pbr API Reference
+===================
+
+.. toctree::
+   :glob:
+
+   api/*
diff --git a/doc/source/semver.rst b/doc/source/semver.rst
deleted file mode 100644 (file)
index c5cf5bf..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-Linux/Python Compatible Semantic Versioning 3.0.0
-=================================================
-
-This is a fork of Semantic Versioning 2.0. The specific changes have to do
-with the format of pre-release and build labels, specifically to make them
-not confusing when co-existing with Linux distribution packaging and Python
-packaging. Inspiration for the format of the pre-release and build labels
-came from Python's PEP440.
-
-Changes vs SemVer 2.0
----------------------
-
-#. dev versions are defined. These are extremely useful when
-   dealing with CI and CD systems when 'every commit is a release' is not
-   feasible.
-
-#. All versions have been made PEP-440 compatible, because of our deep
-   roots in Python. Pre-release versions are now separated by . not -, and
-   use a/b/c rather than alpha/beta etc.
-
-Summary
--------
-
-Given a version number MAJOR.MINOR.PATCH,
-increment the:
-
-#. MAJOR version when you make incompatible API changes,
-#. MINOR version when you add functionality in a backwards-compatible
-   manner, and
-#. PATCH version when you make backwards-compatible bug fixes.
-
-Introduction
-------------
-
-In the world of software management there exists a dread place called
-"dependency hell." The bigger your system grows and the more packages
-you integrate into your software, the more likely you are to find
-yourself, one day, in this pit of despair.
-
-In systems with many dependencies, releasing new package versions can
-quickly become a nightmare. If the dependency specifications are too
-tight, you are in danger of version lock (the inability to upgrade a
-package without having to release new versions of every dependent
-package). If dependencies are specified too loosely, you will inevitably
-be bitten by version promiscuity (assuming compatibility with more
-future versions than is reasonable). Dependency hell is where you are
-when version lock and/or version promiscuity prevent you from easily and
-safely moving your project forward.
-
-As a solution to this problem, I propose a simple set of rules and
-requirements that dictate how version numbers are assigned and
-incremented. These rules are based on but not necessarily limited to
-pre-existing widespread common practices in use in both closed and
-open-source software. For this system to work, you first need to declare
-a public API. This may consist of documentation or be enforced by the
-code itself. Regardless, it is important that this API be clear and
-precise. Once you identify your public API, you communicate changes to
-it with specific increments to your version number. Consider a version
-format of X.Y.Z (Major.Minor.Patch). Bug fixes not affecting the API
-increment the patch version, backwards compatible API additions/changes
-increment the minor version, and backwards incompatible API changes
-increment the major version.
-
-I call this system "Semantic Versioning." Under this scheme, version
-numbers and the way they change convey meaning about the underlying code
-and what has been modified from one version to the next.
-
-Semantic Versioning Specification (SemVer)
-------------------------------------------
-
-The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
-"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
-document are to be interpreted as described in `RFC
-2119 <http://tools.ietf.org/html/rfc2119>`__.
-
-#.  Software using Semantic Versioning MUST declare a public API. This
-    API could be declared in the code itself or exist strictly in
-    documentation. However it is done, it should be precise and
-    comprehensive.
-
-#.  A normal version number MUST take the form X.Y.Z where X, Y, and Z
-    are non-negative integers, and MUST NOT contain leading zeroes. X is
-    the major version, Y is the minor version, and Z is the patch
-    version. Each element MUST increase numerically. For instance: 1.9.0
-    -> 1.10.0 -> 1.11.0.
-
-#.  Once a versioned package has been released, the contents of that
-    version MUST NOT be modified. Any modifications MUST be released as
-    a new version.
-
-#.  Major version zero (0.y.z) is for initial development. Anything may
-    change at any time. The public API should not be considered stable.
-
-#.  Version 1.0.0 defines the public API. The way in which the version
-    number is incremented after this release is dependent on this public
-    API and how it changes.
-
-#.  Patch version Z (x.y.Z \| x > 0) MUST be incremented if only
-    backwards compatible bug fixes are introduced. A bug fix is defined
-    as an internal change that fixes incorrect behavior.
-
-#.  Minor version Y (x.Y.z \| x > 0) MUST be incremented if new,
-    backwards compatible functionality is introduced to the public API.
-    It MUST be incremented if any public API functionality is marked as
-    deprecated. It MAY be incremented if substantial new functionality
-    or improvements are introduced within the private code. It MAY
-    include patch level changes. Patch version MUST be reset to 0 when
-    minor version is incremented.
-
-#.  Major version X (X.y.z \| X > 0) MUST be incremented if any
-    backwards incompatible changes are introduced to the public API. It
-    MAY also include minor and patch level changes. Patch and minor
-    version MUST be reset to 0 when major version is incremented.
-
-#.  A pre-release version MAY be denoted by appending a dot
-    separated identifier immediately following the patch version.
-    The identifier MUST comprise only a, b, c followed by non-negative
-    integer value. The identifier MUST NOT be empty.
-    Pre-release versions have a lower precedence than the associated normal
-    version. A pre-release version indicates that
-    the version is unstable and might not satisfy the intended
-    compatibility requirements as denoted by its associated normal
-    version. Examples: 1.0.0.a1, 1.0.0.b99, 1.0.0.c1000.
-
-#.  A development version MAY be denoted by appending a dot separated
-    identifier immediately following the patch version.
-    The identifier MUST comprise the string dev followed by non-negative
-    integer value. The identifier MUST NOT be empty. Development versions
-    have a lower precedence than the associated normal version or pre-release
-    version. A development version is a completely unsupported and conveys no
-    API promises when related to other versions. They are more useful as
-    communication vehicles between developers of a community, whereas
-    pre-releases, while potentially prone to break still, are intended for
-    externally facing communication of not-yet-released ideas. Dev versions
-    are not public artifacts and should never be placed in public
-    repositories: they are intended as developer-local resources. Examples:
-    1.0.0.dev1, 1.0.0.a1.dev1
-
-#.  git version metadata MAY be denoted by appending a dot separated
-    identifier immediately following a development or pre-release version.
-    The identifier MUST comprise the character g followed by a seven
-    character git short-sha. The sha MUST NOT be empty. git version
-    metadata MUST be ignored when determining version precedence. Thus
-    two versions that differ only in the git version, have the same
-    precedence. Example: 1.0.0.a1.g95a9beb.
-
-#.  Build metadata MAY be denoted by appending a plus sign and a series
-    of dot separated identifiers immediately following the patch or
-    pre-release version. Identifiers MUST comprise only ASCII
-    alphanumerics [0-9A-Za-z]. Identifiers MUST NOT be empty. Build
-    metadata MUST be ignored when determining version precedence. Thus
-    two versions that differ only in the build metadata, have the same
-    precedence. Examples: 1.0.0.a1+001, 1.0.0+20130313144700,
-    1.0.0.b1+exp.sha.5114f85.
-
-#.  Precedence refers to how versions are compared to each other when
-    ordered. Precedence MUST be calculated by separating the version
-    into major, minor, patch, pre-release, and development identifiers in
-    that order (Build metadata does not figure into precedence). Precedence
-    is determined by the first difference when comparing each of these
-    identifiers from left to right as follows: Major, minor, and patch
-    versions are always compared numerically. Example: 1.0.0 < 2.0.0 <
-    2.1.0 < 2.1.1. When major, minor, and patch are equal, a pre-release
-    version has lower precedence than a normal version. Example:
-    1.0.0.a1 < 1.0.0. When major, minor, patch and pre-release are equal, a
-    development version has a lower precedence than a normal version and of a
-    pre-release version. Example: 1.0.0.dev1 < 1.0.0 and 1.0.0.dev9 <
-    1.0.0.a1 and 1.0.0.a1 < 1.0.0.a2.dev4. Precedence for two pre-release
-    versions with the same major, minor, and patch version MUST be determined
-    by comparing the identifier to the right of the patch version as follows:
-    if the alpha portion matches, the numeric portion is compared in
-    numerical sort order. If the alpha portion does not match, the sort order
-    is dev < a < b < c. Example: 1.0.0.dev8 < 1.0.0.dev9 < 1.0.0.a1.dev3 <
-    1.0.0.a1 < 1.0.0.b2 < 1.0.0.c1 < 1.0.0.  Precedence for dev versions if
-    all other components are equal is done by comparing their numeric
-    component. If all other components are not equal, predence is determined
-    by comparing the other components.
-
-Why Use Semantic Versioning?
-----------------------------
-
-This is not a new or revolutionary idea. In fact, you probably do
-something close to this already. The problem is that "close" isn't good
-enough. Without compliance to some sort of formal specification, version
-numbers are essentially useless for dependency management. By giving a
-name and clear definition to the above ideas, it becomes easy to
-communicate your intentions to the users of your software. Once these
-intentions are clear, flexible (but not too flexible) dependency
-specifications can finally be made.
-
-A simple example will demonstrate how Semantic Versioning can make
-dependency hell a thing of the past. Consider a library called
-"Firetruck." It requires a Semantically Versioned package named
-"Ladder." At the time that Firetruck is created, Ladder is at version
-3.1.0. Since Firetruck uses some functionality that was first introduced
-in 3.1.0, you can safely specify the Ladder dependency as greater than
-or equal to 3.1.0 but less than 4.0.0. Now, when Ladder version 3.1.1
-and 3.2.0 become available, you can release them to your package
-management system and know that they will be compatible with existing
-dependent software.
-
-As a responsible developer you will, of course, want to verify that any
-package upgrades function as advertised. The real world is a messy
-place; there's nothing we can do about that but be vigilant. What you
-can do is let Semantic Versioning provide you with a sane way to release
-and upgrade packages without having to roll new versions of dependent
-packages, saving you time and hassle.
-
-If all of this sounds desirable, all you need to do to start using
-Semantic Versioning is to declare that you are doing so and then follow
-the rules. Link to this website from your README so others know the
-rules and can benefit from them.
-
-FAQ
----
-
-How should I deal with revisions in the 0.y.z initial development phase?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-The simplest thing to do is start your initial development release at
-0.1.0 and then increment the minor version for each subsequent release.
-
-How do I know when to release 1.0.0?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-If your software is being used in production, it should probably already
-be 1.0.0. If you have a stable API on which users have come to depend,
-you should be 1.0.0. If you're worrying a lot about backwards
-compatibility, you should probably already be 1.0.0.
-
-Doesn't this discourage rapid development and fast iteration?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Major version zero is all about rapid development. If you're changing
-the API every day you should either still be in version 0.y.z or on a
-separate development branch working on the next major version.
-
-If even the tiniest backwards incompatible changes to the public API require a major version bump, won't I end up at version 42.0.0 very rapidly?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-This is a question of responsible development and foresight.
-Incompatible changes should not be introduced lightly to software that
-has a lot of dependent code. The cost that must be incurred to upgrade
-can be significant. Having to bump major versions to release
-incompatible changes means you'll think through the impact of your
-changes, and evaluate the cost/benefit ratio involved.
-
-Documenting the entire public API is too much work!
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-It is your responsibility as a professional developer to properly
-document software that is intended for use by others. Managing software
-complexity is a hugely important part of keeping a project efficient,
-and that's hard to do if nobody knows how to use your software, or what
-methods are safe to call. In the long run, Semantic Versioning, and the
-insistence on a well defined public API can keep everyone and everything
-running smoothly.
-
-What do I do if I accidentally release a backwards incompatible change as a minor version?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-As soon as you realize that you've broken the Semantic Versioning spec,
-fix the problem and release a new minor version that corrects the
-problem and restores backwards compatibility. Even under this
-circumstance, it is unacceptable to modify versioned releases. If it's
-appropriate, document the offending version and inform your users of the
-problem so that they are aware of the offending version.
-
-What should I do if I update my own dependencies without changing the public API?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-That would be considered compatible since it does not affect the public
-API. Software that explicitly depends on the same dependencies as your
-package should have their own dependency specifications and the author
-will notice any conflicts. Determining whether the change is a patch
-level or minor level modification depends on whether you updated your
-dependencies in order to fix a bug or introduce new functionality. I
-would usually expect additional code for the latter instance, in which
-case it's obviously a minor level increment.
-
-What if I inadvertently alter the public API in a way that is not compliant with the version number change (i.e. the code incorrectly introduces a major breaking change in a patch release)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Use your best judgment. If you have a huge audience that will be
-drastically impacted by changing the behavior back to what the public
-API intended, then it may be best to perform a major version release,
-even though the fix could strictly be considered a patch release.
-Remember, Semantic Versioning is all about conveying meaning by how the
-version number changes. If these changes are important to your users,
-use the version number to inform them.
-
-How should I handle deprecating functionality?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Deprecating existing functionality is a normal part of software
-development and is often required to make forward progress. When you
-deprecate part of your public API, you should do two things: (1) update
-your documentation to let users know about the change, (2) issue a new
-minor release with the deprecation in place. Before you completely
-remove the functionality in a new major release there should be at least
-one minor release that contains the deprecation so that users can
-smoothly transition to the new API.
-
-Does SemVer have a size limit on the version string?
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-No, but use good judgment. A 255 character version string is probably
-overkill, for example. Also, specific systems may impose their own
-limits on the size of the string.
-
-About
------
-
-The Linux/Python Compatible Semantic Versioning specification is maintained
-by the `OpenStack <http://openstack.org>`_ project.
-
-It is based on The Semantic Versioning specification, which was
-authored by `Tom Preston-Werner <http://tom.preston-werner.com>`__,
-with inputs from `PEP 440 <http://www.python.org/dev/peps/pep-0440/>`_
-
-If you'd like to leave feedback, please `open an issue
-<https://bugs.launchpad.net/pbr/+filebug>`_.
-
-License
--------
-
-Creative Commons - CC BY 3.0 http://creativecommons.org/licenses/by/3.0/
diff --git a/doc/source/testing.rst b/doc/source/testing.rst
deleted file mode 100644 (file)
index eccb1e3..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-Running the Tests for pbr
-=========================
-
-The testing system is based on a combination of `tox`_ and `testr`_. The canonical
-approach to running tests is to simply run the command ``tox``. This will
-create virtual environments, populate them with dependencies and run all of
-the tests that OpenStack CI systems run. Behind the scenes, tox is running
-``testr run --parallel``, but is set up such that you can supply any additional
-testr arguments that are needed to tox. For example, you can run:
-``tox -- --analyze-isolation`` to cause tox to tell testr to add
-``--analyze-isolation`` to its argument list.
-
-It is also possible to run the tests inside of a virtual environment
-you have created, or it is possible that you have all of the dependencies
-installed locally already. If you'd like to go this route, the requirements
-are listed in ``requirements.txt`` and the requirements for testing are in
-``test-requirements.txt``. Installing them via pip, for instance, is simply::
-
-  pip install -r requirements.txt -r test-requirements.txt
-
-In 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
-
-.. _tox: http://tox.testrun.org/
-.. _testr: https://wiki.openstack.org/wiki/Testr
diff --git a/doc/source/user/compatibility.rst b/doc/source/user/compatibility.rst
new file mode 100644 (file)
index 0000000..868ac75
--- /dev/null
@@ -0,0 +1,58 @@
+..
+    The name of this document and the anchor in this document must be
+    treated as a stable API.  Links to this document are coded into
+    pbr and deployed versions of pbr will refer users to this document
+    in the case of certain errors.
+    Ensure any link you use in PBR is defined via a ref with .. _name.
+
+
+===================
+Compatibility Notes
+===================
+
+Useful notes about errors users may encounter when features cannot be
+supported on older versions of setuptools / pip / wheel.
+
+
+setuptools
+==========
+
+
+.. _evaluate-marker:
+
+evaluate_marker
+---------------
+
+evaluate_markers may run into issues with the '>', '>=', '<', and '<='
+operators if the installed version of setuptools is less than 17.1.  Projects
+using these operators with markers should specify a minimum version of 17.1
+for setuptools.
+
+
+pip
+===
+
+markers
+-------
+
+For versions of pip < 7 with pbr < 1.9, dependencies that use markers will not
+be installed.  Projects using pbr and markers should set a minimum version of
+1.9 for pbr.
+
+
+Recommended setup.py
+====================
+
+:ref:`setup_py`.
+
+
+Sphinx
+======
+
+.. _sphinx-1.5:
+
+Version 1.5.0+
+--------------
+
+The ``warning-is-error`` flag is only supported by Sphinx 1.5 and will cause
+errors when used with older versions.
diff --git a/doc/source/user/features.rst b/doc/source/user/features.rst
new file mode 100644 (file)
index 0000000..4ccac4f
--- /dev/null
@@ -0,0 +1,312 @@
+==========
+ Features
+==========
+
+To understand what *pbr* can do for you, it's probably best to look at two
+projects: one using pure *setuptools*, and another using *pbr*. First, let's
+look at the *setuptools* project.
+
+.. code-block:: none
+
+   $ tree -L 1
+   .
+   ├── AUTHORS
+   ├── CHANGES
+   ├── LICENSE
+   ├── MANIFEST.in
+   ├── README.rst
+   ├── requirements.txt
+   ├── setup.cfg
+   ├── setup.py
+   └── somepackage
+
+   $ cat setup.py
+   setuptools.setup(
+       name='mypackage',
+       version='1.0.0',
+       description='A short description',
+       long_description="""A much longer description...""",
+       author="John Doe",
+       author_email='john.doe@example.com',
+       license='BSD',
+   )
+
+Here's a similar package using *pbr*:
+
+.. code-block:: none
+
+   $ tree -L 1
+   .
+   ├── LICENSE
+   ├── README.rst
+   ├── setup.cfg
+   ├── setup.py
+   └── somepackage
+
+   $ cat setup.py
+   setuptools.setup(
+       pbr=True
+   )
+
+   $ cat setup.cfg
+   [metadata]
+   name = mypackage
+   description = A short description
+   description-file = README.rst
+   author = John Doe
+   author-email = john.doe@example.com
+   license = BSD
+
+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``)
+
+In addition, there are other things that you don't see here but which *pbr*
+will do for you:
+
+- Helpful extensions to *setuptools* commands
+
+setup.cfg
+---------
+
+.. admonition:: Summary
+
+    *pbr* uses ``setup.cfg`` for all configuration, though ``setup.py`` is
+    still required.
+
+One of the main features of *distutils2* was the use of a ``setup.cfg``
+INI-style configuration file. This was used to define a package's metadata and
+other options that were normally supplied to the ``setup()`` function.
+
+Recent versions of `setuptools`__ have implemented some of this support, but
+*pbr* still allows for the definition of the following sections in
+``setup.cfg``:
+
+- ``files``
+- ``entry_points``
+- ``backwards_compat``
+
+For more information on these sections, refer to :doc:`/user/using`.
+
+__ https://setuptools.readthedocs.io/en/latest/setuptools.html#configuring-setup-using-setup-cfg-files
+
+Package Metadata
+----------------
+
+.. admonition:: Summary
+
+    *pbr* removes the need to define a lot of configuration in either
+    ``setup.py`` or ``setup.cfg`` by extracting this information from Git.
+
+Version
+~~~~~~~
+
+.. admonition:: Summary
+
+    *pbr* will automatically configure your version for you by parsing
+    semantically-versioned Git tags.
+
+Versions can be managed two ways - *post-versioning* and *pre-versioning*.
+*Post-versioning* is the default while *pre-versioning* is enabled by setting
+``version`` in the ``setup.cfg`` ``metadata`` section. In both cases the actual
+version strings are inferred from Git.
+
+If the currently checked out revision is tagged, that tag is used as
+the version.
+
+If the currently checked out revision is not tagged, then we take the
+last tagged version number and increment it to get a minimum target
+version.
+
+.. note::
+
+   *pbr* supports both bare version tag (e.g. ``0.1.0``) and version prefixed
+   with ``v`` or ``V`` (e.g. ``v0.1.0``)
+
+We then walk Git history back to the last release. Within each commit we look
+for a ``Sem-Ver:`` pseudo header and, if found, parse it looking for keywords.
+Unknown symbols are not an error (so that folk can't wedge *pbr* or break their
+tree), but we will emit an info-level warning message. The following symbols
+are recognized:
+
+- ``feature``
+- ``api-break``
+- ``deprecation``
+- ``bugfix``
+
+A missing ``Sem-Ver`` line is equivalent to ``Sem-Ver: bugfix``. The ``bugfix``
+symbol causes a patch level increment to the version. The ``feature`` and
+``deprecation`` symbols cause a minor version increment. The ``api-break``
+symbol causes a major version increment.
+
+If *post-versioning* is in use, we use the resulting version number as the target
+version.
+
+If *pre-versioning* is in use, we check that the version set in the metadata
+section of ``setup.cfg`` is greater than the version we infer using the above
+method. If the inferred version is greater than the *pre-versioning* value we
+raise an error, otherwise we use the version from ``setup.cfg`` as the target.
+
+We then generate dev version strings based on the commits since the last
+release and include the current Git SHA to disambiguate multiple dev versions
+with the same number of commits since the release.
+
+.. note::
+
+   *pbr* expects Git tags to be signed for use in calculating versions.
+
+The versions are expected to be compliant with :doc:`semver`.
+
+The ``version.SemanticVersion`` class can be used to query versions of a
+package and present it in various forms - ``debian_version()``,
+``release_string()``, ``rpm_string()``, ``version_string()``, or
+``version_tuple()``.
+
+Long Description
+~~~~~~~~~~~~~~~~
+
+.. admonition:: Summary
+
+    *pbr* can extract the contents of a ``README`` and use this as your long
+    description
+
+There is no need to maintain two long descriptions and your ``README`` file is
+probably a good long_description. So we'll just inject the contents of your
+``README.rst``, ``README.txt`` or ``README`` file into your empty
+``long_description``.
+
+You can also specify the exact file you want to use using the
+``description-file`` parameter.
+
+Requirements
+~~~~~~~~~~~~
+
+.. admonition:: Summary
+
+    *pbr* will extract requirements from ``requirements.txt`` files and
+    automatically populate the ``install_requires``, ``tests_require`` and
+    ``dependency_links`` arguments to ``setup`` with them.
+
+You may not have noticed, but there are differences in how pip
+``requirements.txt`` files work and how *setuptools* wants to be told about
+requirements. The *pip* way is nicer because it sure does make it easier to
+populate a *virtualenv* for testing or to just install everything you need.
+Duplicating the information, though, is super lame. To solve this issue, *pbr*
+will let you use ``requirements.txt``-format files to describe the requirements
+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``.
+
+Automatic File Generation
+-------------------------
+
+.. admonition:: Summary
+
+    *pbr* can automatically generate a couple of files, which would normally
+    have to be maintained manually, by using Git data.
+
+AUTHORS, ChangeLog
+~~~~~~~~~~~~~~~~~~
+
+.. admonition:: Summary
+
+    *pbr* will automatically generate an ``AUTHORS`` and a ``ChangeLog`` file
+    using Git logs.
+
+Why keep an ``AUTHORS`` or a ``ChangeLog`` file when Git already has all of the
+information you need? ``AUTHORS`` generation supports filtering/combining based
+on a standard ``.mailmap`` file.
+
+Manifest
+~~~~~~~~
+
+.. admonition:: Summary
+
+    *pbr* will automatically generate a ``MANIFEST.in`` file based on the files
+    Git is tracking.
+
+Just like ``AUTHORS`` and ``ChangeLog``, why keep a list of files you wish to
+include when you can find many of these in Git. ``MANIFEST.in`` generation
+ensures almost all files stored in Git, with the exception of ``.gitignore``,
+``.gitreview`` and ``.pyc`` files, are automatically included in your
+distribution. In addition, the generated ``AUTHORS`` and ``ChangeLog`` files
+are also included. In many cases, this removes the need for an explicit
+``MANIFEST.in`` file, though one can be provided to exclude files that are
+tracked via Git but which should not be included in the final release, such as
+test files.
+
+.. note::
+
+   ``MANIFEST.in`` files have no effect on binary distributions such as wheels.
+   Refer to the `Python packaging tutorial`__ for more information.
+
+__ https://packaging.python.org/tutorials/distributing-packages/#manifest-in
+
+Setup Commands
+--------------
+
+``build_sphinx``
+~~~~~~~~~~~~~~~~
+
+.. admonition:: Summary
+
+    *pbr* will override the Sphinx ``build_sphinx`` command to use
+    *pbr*-provided package metadata and automatically generate API
+    documentation.
+
+Sphinx can produce auto documentation indexes based on signatures and
+docstrings of your project but you have to give it index files to tell it to
+*autodoc* each module: that's kind of repetitive and boring. *pbr* will scan
+your project, find all of your modules, and generate all of the stub files for
+you.
+
+In addition, Sphinx documentation setups are altered to have several pieces of
+information that are known to ``setup.py`` injected into the Sphinx config.
+
+See the :ref:`pbr-setup-cfg` section of the configuration file for
+details on configuring your project for *autodoc*.
+
+``test``
+~~~~~~~~
+
+.. admonition:: Summary
+
+    *pbr* will automatically alias the ``test`` command to use the testing tool
+    of your choice.
+
+.. deprecated:: 4.0
+
+*pbr* overrides the *setuptools* ``test`` command if using `testrepository`__
+or `nose`__ (deprecated).
+
+- *pbr* will check for a ``.testr.conf`` file. If this exists and
+  *testrepository* is installed, the ``test`` command will alias the *testr*
+  test runner. If this is not the case...
+
+  .. note::
+
+    This is separate to ``setup.py testr`` (note the extra ``r``) which is
+    provided directly by the ``testrepository`` package. Be careful as there is
+    some overlap of command arguments.
+
+- *pbr* will check if ``[nosetests]`` is defined in ``setup.cfg``. If this
+  exists and *nose* is installed, the ``test`` command will alias the *nose*
+  runner. If this is not the case...
+
+- In other cases no override will be installed and the ``test`` command will
+  revert to the `setuptools default`__.
+
+__ https://testrepository.readthedocs.io/en/latest/
+__ https://nose.readthedocs.io/en/latest/
+__ https://setuptools.readthedocs.io/en/latest/setuptools.html#test-build-package-and-run-a-unittest-suite
diff --git a/doc/source/user/history.rst b/doc/source/user/history.rst
new file mode 100644 (file)
index 0000000..55439e7
--- /dev/null
@@ -0,0 +1,5 @@
+=================
+ Release History
+=================
+
+.. include:: ../../../ChangeLog
diff --git a/doc/source/user/index.rst b/doc/source/user/index.rst
new file mode 100644 (file)
index 0000000..7854dc5
--- /dev/null
@@ -0,0 +1,12 @@
+===========
+ Using pbr
+===========
+
+.. toctree::
+
+   features
+   using
+   packagers
+   semver
+   compatibility
+   history
diff --git a/doc/source/user/packagers.rst b/doc/source/user/packagers.rst
new file mode 100644 (file)
index 0000000..a8faa31
--- /dev/null
@@ -0,0 +1,98 @@
+===============================
+ Notes for Package maintainers
+===============================
+
+If you are maintaining packages of software that uses `pbr`, there are some
+features you probably want to be aware of that can make your life easier.
+They are exposed by environment variables, so adding them to rules or spec
+files should be fairly easy.
+
+Versioning
+==========
+
+`pbr`, when run in a git repo, derives the version of a package from the
+git tags. When run in a tarball with a proper egg-info dir, it will happily
+pull the version from that. So for the most part, the package maintainers
+shouldn't need to care. However, if you are doing something like keeping a
+git repo with the sources and the packaging intermixed and it's causing pbr
+to get confused about whether its in its own git repo or not, you can set
+`PBR_VERSION`:
+
+::
+
+  export PBR_VERSION=1.2.3
+
+and all version calculation logic will be completely skipped and the supplied
+version will be considered absolute.
+
+Distribution version numbers
+============================
+
+`pbr` will automatically calculate upstream version numbers for dpkg and rpm
+using systems. Releases are easy (and obvious). When packaging preleases though
+things get more complex. Firstly, semver does not provide for any sort order
+between pre-releases and development snapshots, so it can be complex (perhaps
+intractable) to package both into one repository - we recommend with either
+packaging pre-release releases (alpha/beta/rc's) or dev snapshots but not both.
+Secondly, as pre-releases and snapshots have the same major/minor/patch version
+as the version they lead up to, but have to sort before it, we cannot map their
+version naturally into the rpm version namespace: instead we represent their
+versions as versions of the release before.
+
+Dependencies
+============
+
+As of 1.0.0 `pbr` doesn't alter the dependency behaviour of `setuptools`.
+
+Older versions would invoke `pip` internally under some circumstances and
+required the environment variable `SKIP_PIP_INSTALL` to be set to prevent
+that. Since 1.0.0 we now document that dependencies should be installed before
+installing a `pbr` using package. We don't support easy install, but neither
+do we interfere with it today. If you observe easy install being triggered when
+building a binary package, then you've probably missed one or more package
+requirements.
+
+Note: we reserve the right to disable easy install via `pbr` in future, since
+we don't want to debug or support the interactions that can occur when using
+it.
+
+Tarballs
+========
+
+`pbr` includes everything in a source tarball that is in the original `git`
+repository. This can again cause havoc if a package maintainer is doing fancy
+things with combined `git` repos, and is generating a source tarball using
+`python setup.py sdist` from that repo. If that is the workflow the packager
+is using, setting `SKIP_GIT_SDIST`:
+
+::
+
+  export SKIP_GIT_SDIST=1
+
+will cause all logic around using git to find the files that should be in the
+source tarball to be skipped. Beware though, that because `pbr` packages
+automatically find all of the files, most of them do not have a complete
+`MANIFEST.in` file, so its possible that a tarball produced in that way will
+be missing files.
+
+AUTHORS and ChangeLog
+=====================
+
+`pbr` generates AUTHORS and ChangeLog files from git information. This
+can cause problem in distro packaging if package maintainer is using git
+repository for packaging source. If that is the case setting
+`SKIP_GENERATE_AUTHORS`
+
+::
+
+   export SKIP_GENERATE_AUTHORS=1
+
+will cause logic around generating AUTHORS using git information to be
+skipped. Similarly setting `SKIP_WRITE_GIT_CHANGELOG`
+
+::
+
+   export SKIP_WRITE_GIT_CHANGELOG=1
+
+will cause logic around generating ChangeLog file using git
+information to be skipped.
diff --git a/doc/source/user/semver.rst b/doc/source/user/semver.rst
new file mode 100644 (file)
index 0000000..c5cf5bf
--- /dev/null
@@ -0,0 +1,327 @@
+Linux/Python Compatible Semantic Versioning 3.0.0
+=================================================
+
+This is a fork of Semantic Versioning 2.0. The specific changes have to do
+with the format of pre-release and build labels, specifically to make them
+not confusing when co-existing with Linux distribution packaging and Python
+packaging. Inspiration for the format of the pre-release and build labels
+came from Python's PEP440.
+
+Changes vs SemVer 2.0
+---------------------
+
+#. dev versions are defined. These are extremely useful when
+   dealing with CI and CD systems when 'every commit is a release' is not
+   feasible.
+
+#. All versions have been made PEP-440 compatible, because of our deep
+   roots in Python. Pre-release versions are now separated by . not -, and
+   use a/b/c rather than alpha/beta etc.
+
+Summary
+-------
+
+Given a version number MAJOR.MINOR.PATCH,
+increment the:
+
+#. MAJOR version when you make incompatible API changes,
+#. MINOR version when you add functionality in a backwards-compatible
+   manner, and
+#. PATCH version when you make backwards-compatible bug fixes.
+
+Introduction
+------------
+
+In the world of software management there exists a dread place called
+"dependency hell." The bigger your system grows and the more packages
+you integrate into your software, the more likely you are to find
+yourself, one day, in this pit of despair.
+
+In systems with many dependencies, releasing new package versions can
+quickly become a nightmare. If the dependency specifications are too
+tight, you are in danger of version lock (the inability to upgrade a
+package without having to release new versions of every dependent
+package). If dependencies are specified too loosely, you will inevitably
+be bitten by version promiscuity (assuming compatibility with more
+future versions than is reasonable). Dependency hell is where you are
+when version lock and/or version promiscuity prevent you from easily and
+safely moving your project forward.
+
+As a solution to this problem, I propose a simple set of rules and
+requirements that dictate how version numbers are assigned and
+incremented. These rules are based on but not necessarily limited to
+pre-existing widespread common practices in use in both closed and
+open-source software. For this system to work, you first need to declare
+a public API. This may consist of documentation or be enforced by the
+code itself. Regardless, it is important that this API be clear and
+precise. Once you identify your public API, you communicate changes to
+it with specific increments to your version number. Consider a version
+format of X.Y.Z (Major.Minor.Patch). Bug fixes not affecting the API
+increment the patch version, backwards compatible API additions/changes
+increment the minor version, and backwards incompatible API changes
+increment the major version.
+
+I call this system "Semantic Versioning." Under this scheme, version
+numbers and the way they change convey meaning about the underlying code
+and what has been modified from one version to the next.
+
+Semantic Versioning Specification (SemVer)
+------------------------------------------
+
+The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+document are to be interpreted as described in `RFC
+2119 <http://tools.ietf.org/html/rfc2119>`__.
+
+#.  Software using Semantic Versioning MUST declare a public API. This
+    API could be declared in the code itself or exist strictly in
+    documentation. However it is done, it should be precise and
+    comprehensive.
+
+#.  A normal version number MUST take the form X.Y.Z where X, Y, and Z
+    are non-negative integers, and MUST NOT contain leading zeroes. X is
+    the major version, Y is the minor version, and Z is the patch
+    version. Each element MUST increase numerically. For instance: 1.9.0
+    -> 1.10.0 -> 1.11.0.
+
+#.  Once a versioned package has been released, the contents of that
+    version MUST NOT be modified. Any modifications MUST be released as
+    a new version.
+
+#.  Major version zero (0.y.z) is for initial development. Anything may
+    change at any time. The public API should not be considered stable.
+
+#.  Version 1.0.0 defines the public API. The way in which the version
+    number is incremented after this release is dependent on this public
+    API and how it changes.
+
+#.  Patch version Z (x.y.Z \| x > 0) MUST be incremented if only
+    backwards compatible bug fixes are introduced. A bug fix is defined
+    as an internal change that fixes incorrect behavior.
+
+#.  Minor version Y (x.Y.z \| x > 0) MUST be incremented if new,
+    backwards compatible functionality is introduced to the public API.
+    It MUST be incremented if any public API functionality is marked as
+    deprecated. It MAY be incremented if substantial new functionality
+    or improvements are introduced within the private code. It MAY
+    include patch level changes. Patch version MUST be reset to 0 when
+    minor version is incremented.
+
+#.  Major version X (X.y.z \| X > 0) MUST be incremented if any
+    backwards incompatible changes are introduced to the public API. It
+    MAY also include minor and patch level changes. Patch and minor
+    version MUST be reset to 0 when major version is incremented.
+
+#.  A pre-release version MAY be denoted by appending a dot
+    separated identifier immediately following the patch version.
+    The identifier MUST comprise only a, b, c followed by non-negative
+    integer value. The identifier MUST NOT be empty.
+    Pre-release versions have a lower precedence than the associated normal
+    version. A pre-release version indicates that
+    the version is unstable and might not satisfy the intended
+    compatibility requirements as denoted by its associated normal
+    version. Examples: 1.0.0.a1, 1.0.0.b99, 1.0.0.c1000.
+
+#.  A development version MAY be denoted by appending a dot separated
+    identifier immediately following the patch version.
+    The identifier MUST comprise the string dev followed by non-negative
+    integer value. The identifier MUST NOT be empty. Development versions
+    have a lower precedence than the associated normal version or pre-release
+    version. A development version is a completely unsupported and conveys no
+    API promises when related to other versions. They are more useful as
+    communication vehicles between developers of a community, whereas
+    pre-releases, while potentially prone to break still, are intended for
+    externally facing communication of not-yet-released ideas. Dev versions
+    are not public artifacts and should never be placed in public
+    repositories: they are intended as developer-local resources. Examples:
+    1.0.0.dev1, 1.0.0.a1.dev1
+
+#.  git version metadata MAY be denoted by appending a dot separated
+    identifier immediately following a development or pre-release version.
+    The identifier MUST comprise the character g followed by a seven
+    character git short-sha. The sha MUST NOT be empty. git version
+    metadata MUST be ignored when determining version precedence. Thus
+    two versions that differ only in the git version, have the same
+    precedence. Example: 1.0.0.a1.g95a9beb.
+
+#.  Build metadata MAY be denoted by appending a plus sign and a series
+    of dot separated identifiers immediately following the patch or
+    pre-release version. Identifiers MUST comprise only ASCII
+    alphanumerics [0-9A-Za-z]. Identifiers MUST NOT be empty. Build
+    metadata MUST be ignored when determining version precedence. Thus
+    two versions that differ only in the build metadata, have the same
+    precedence. Examples: 1.0.0.a1+001, 1.0.0+20130313144700,
+    1.0.0.b1+exp.sha.5114f85.
+
+#.  Precedence refers to how versions are compared to each other when
+    ordered. Precedence MUST be calculated by separating the version
+    into major, minor, patch, pre-release, and development identifiers in
+    that order (Build metadata does not figure into precedence). Precedence
+    is determined by the first difference when comparing each of these
+    identifiers from left to right as follows: Major, minor, and patch
+    versions are always compared numerically. Example: 1.0.0 < 2.0.0 <
+    2.1.0 < 2.1.1. When major, minor, and patch are equal, a pre-release
+    version has lower precedence than a normal version. Example:
+    1.0.0.a1 < 1.0.0. When major, minor, patch and pre-release are equal, a
+    development version has a lower precedence than a normal version and of a
+    pre-release version. Example: 1.0.0.dev1 < 1.0.0 and 1.0.0.dev9 <
+    1.0.0.a1 and 1.0.0.a1 < 1.0.0.a2.dev4. Precedence for two pre-release
+    versions with the same major, minor, and patch version MUST be determined
+    by comparing the identifier to the right of the patch version as follows:
+    if the alpha portion matches, the numeric portion is compared in
+    numerical sort order. If the alpha portion does not match, the sort order
+    is dev < a < b < c. Example: 1.0.0.dev8 < 1.0.0.dev9 < 1.0.0.a1.dev3 <
+    1.0.0.a1 < 1.0.0.b2 < 1.0.0.c1 < 1.0.0.  Precedence for dev versions if
+    all other components are equal is done by comparing their numeric
+    component. If all other components are not equal, predence is determined
+    by comparing the other components.
+
+Why Use Semantic Versioning?
+----------------------------
+
+This is not a new or revolutionary idea. In fact, you probably do
+something close to this already. The problem is that "close" isn't good
+enough. Without compliance to some sort of formal specification, version
+numbers are essentially useless for dependency management. By giving a
+name and clear definition to the above ideas, it becomes easy to
+communicate your intentions to the users of your software. Once these
+intentions are clear, flexible (but not too flexible) dependency
+specifications can finally be made.
+
+A simple example will demonstrate how Semantic Versioning can make
+dependency hell a thing of the past. Consider a library called
+"Firetruck." It requires a Semantically Versioned package named
+"Ladder." At the time that Firetruck is created, Ladder is at version
+3.1.0. Since Firetruck uses some functionality that was first introduced
+in 3.1.0, you can safely specify the Ladder dependency as greater than
+or equal to 3.1.0 but less than 4.0.0. Now, when Ladder version 3.1.1
+and 3.2.0 become available, you can release them to your package
+management system and know that they will be compatible with existing
+dependent software.
+
+As a responsible developer you will, of course, want to verify that any
+package upgrades function as advertised. The real world is a messy
+place; there's nothing we can do about that but be vigilant. What you
+can do is let Semantic Versioning provide you with a sane way to release
+and upgrade packages without having to roll new versions of dependent
+packages, saving you time and hassle.
+
+If all of this sounds desirable, all you need to do to start using
+Semantic Versioning is to declare that you are doing so and then follow
+the rules. Link to this website from your README so others know the
+rules and can benefit from them.
+
+FAQ
+---
+
+How should I deal with revisions in the 0.y.z initial development phase?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The simplest thing to do is start your initial development release at
+0.1.0 and then increment the minor version for each subsequent release.
+
+How do I know when to release 1.0.0?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If your software is being used in production, it should probably already
+be 1.0.0. If you have a stable API on which users have come to depend,
+you should be 1.0.0. If you're worrying a lot about backwards
+compatibility, you should probably already be 1.0.0.
+
+Doesn't this discourage rapid development and fast iteration?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Major version zero is all about rapid development. If you're changing
+the API every day you should either still be in version 0.y.z or on a
+separate development branch working on the next major version.
+
+If even the tiniest backwards incompatible changes to the public API require a major version bump, won't I end up at version 42.0.0 very rapidly?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is a question of responsible development and foresight.
+Incompatible changes should not be introduced lightly to software that
+has a lot of dependent code. The cost that must be incurred to upgrade
+can be significant. Having to bump major versions to release
+incompatible changes means you'll think through the impact of your
+changes, and evaluate the cost/benefit ratio involved.
+
+Documenting the entire public API is too much work!
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It is your responsibility as a professional developer to properly
+document software that is intended for use by others. Managing software
+complexity is a hugely important part of keeping a project efficient,
+and that's hard to do if nobody knows how to use your software, or what
+methods are safe to call. In the long run, Semantic Versioning, and the
+insistence on a well defined public API can keep everyone and everything
+running smoothly.
+
+What do I do if I accidentally release a backwards incompatible change as a minor version?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+As soon as you realize that you've broken the Semantic Versioning spec,
+fix the problem and release a new minor version that corrects the
+problem and restores backwards compatibility. Even under this
+circumstance, it is unacceptable to modify versioned releases. If it's
+appropriate, document the offending version and inform your users of the
+problem so that they are aware of the offending version.
+
+What should I do if I update my own dependencies without changing the public API?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+That would be considered compatible since it does not affect the public
+API. Software that explicitly depends on the same dependencies as your
+package should have their own dependency specifications and the author
+will notice any conflicts. Determining whether the change is a patch
+level or minor level modification depends on whether you updated your
+dependencies in order to fix a bug or introduce new functionality. I
+would usually expect additional code for the latter instance, in which
+case it's obviously a minor level increment.
+
+What if I inadvertently alter the public API in a way that is not compliant with the version number change (i.e. the code incorrectly introduces a major breaking change in a patch release)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Use your best judgment. If you have a huge audience that will be
+drastically impacted by changing the behavior back to what the public
+API intended, then it may be best to perform a major version release,
+even though the fix could strictly be considered a patch release.
+Remember, Semantic Versioning is all about conveying meaning by how the
+version number changes. If these changes are important to your users,
+use the version number to inform them.
+
+How should I handle deprecating functionality?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Deprecating existing functionality is a normal part of software
+development and is often required to make forward progress. When you
+deprecate part of your public API, you should do two things: (1) update
+your documentation to let users know about the change, (2) issue a new
+minor release with the deprecation in place. Before you completely
+remove the functionality in a new major release there should be at least
+one minor release that contains the deprecation so that users can
+smoothly transition to the new API.
+
+Does SemVer have a size limit on the version string?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+No, but use good judgment. A 255 character version string is probably
+overkill, for example. Also, specific systems may impose their own
+limits on the size of the string.
+
+About
+-----
+
+The Linux/Python Compatible Semantic Versioning specification is maintained
+by the `OpenStack <http://openstack.org>`_ project.
+
+It is based on The Semantic Versioning specification, which was
+authored by `Tom Preston-Werner <http://tom.preston-werner.com>`__,
+with inputs from `PEP 440 <http://www.python.org/dev/peps/pep-0440/>`_
+
+If you'd like to leave feedback, please `open an issue
+<https://bugs.launchpad.net/pbr/+filebug>`_.
+
+License
+-------
+
+Creative Commons - CC BY 3.0 http://creativecommons.org/licenses/by/3.0/
diff --git a/doc/source/user/using.rst b/doc/source/user/using.rst
new file mode 100644 (file)
index 0000000..d0ff3bd
--- /dev/null
@@ -0,0 +1,412 @@
+=======
+ Usage
+=======
+
+*pbr* is a *setuptools* plugin and so to use it you must use *setuptools* and
+call ``setuptools.setup()``. While the normal *setuptools* facilities are
+available, *pbr* makes it possible to express them through static data files.
+
+.. _setup_py:
+
+``setup.py``
+------------
+
+*pbr* only requires a minimal ``setup.py`` file compared to a standard
+*setuptools* project. This is because most configuration is located in static
+configuration files. This recommended minimal ``setup.py`` file should look
+something like this::
+
+    #!/usr/bin/env python
+
+    from setuptools import setup
+
+    setup(
+        setup_requires=['pbr'],
+        pbr=True,
+    )
+
+.. note::
+
+   It is necessary to specify ``pbr=True`` to enabled *pbr* functionality.
+
+.. note::
+
+   While one can pass any arguments supported by setuptools to ``setup()``,
+   any conflicting arguments supplied in ``setup.cfg`` will take precedence.
+
+.. _setup_cfg:
+
+``setup.cfg``
+-------------
+
+The ``setup.cfg`` file is an INI-like file that can mostly replace the
+``setup.py`` file. It is similar to the ``setup.cfg`` file found in recent
+versions of `setuptools`__. A simple sample can be found in *pbr*'s own
+``setup.cfg`` (it uses its own machinery to install itself):
+
+::
+
+    [metadata]
+    name = pbr
+    author = OpenStack Foundation
+    author-email = openstack-dev@lists.openstack.org
+    summary = OpenStack's setup automation in a reusable form
+    description-file = README.rst
+    description-content-type = text/x-rst; charset=UTF-8
+    home-page = https://launchpad.net/pbr
+    project_urls =
+        Bug Tracker = https://bugs.launchpad.net/pbr/
+        Documentation = https://docs.openstack.org/pbr/
+        Source Code = https://git.openstack.org/cgit/openstack-dev/pbr/
+    license = Apache-2
+    classifier =
+        Development Status :: 4 - Beta
+        Environment :: Console
+        Environment :: OpenStack
+        Intended Audience :: Developers
+        Intended Audience :: Information Technology
+        License :: OSI Approved :: Apache Software License
+        Operating System :: OS Independent
+        Programming Language :: Python
+    keywords =
+        setup
+        distutils
+
+    [files]
+    packages =
+        pbr
+    data_files =
+        etc/pbr = etc/*
+        etc/init =
+            pbr.packaging.conf
+            pbr.version.conf
+
+    [entry_points]
+    console_scripts =
+        pbr = pbr.cmd:main
+    pbr.config.drivers =
+        plain = pbr.cfg.driver:Plain
+
+Recent versions of `setuptools`_ provide many of the same sections as *pbr*.
+However, *pbr* does provide a number of additional sections:
+
+- ``files``
+- ``entry_points``
+- ``backwards_compat``
+- ``pbr``
+
+In addition, there are some modifications to other sections:
+
+- ``metadata``
+- ``build_sphinx``
+
+For all other sections, you should refer to either the `setuptools`_
+documentation or the documentation of the package that provides the section,
+such as the ``extract_mesages`` section provided by Babel__.
+
+.. note::
+
+   Comments may be used in ``setup.cfg``, however all comments should start
+   with a ``#`` and may be on a single line, or in line, with at least one
+   white space character immediately preceding the ``#``. Semicolons are not a
+   supported comment delimiter. For instance::
+
+       [section]
+       # A comment at the start of a dedicated line
+       key =
+           value1 # An in line comment
+           value2
+           # A comment on a dedicated line
+           value3
+
+__ http://setuptools.readthedocs.io/en/latest/setuptools.html#configuring-setup-using-setup-cfg-files
+__ http://babel.pocoo.org/en/latest/setup.html
+
+``files``
+~~~~~~~~~
+
+The ``files`` section defines the install location of files in the package
+using three fundamental keys: ``packages``, ``namespace_packages``, and
+``data_files``.
+
+``packages``
+  A list of top-level packages that should be installed. The behavior of
+  packages is similar to ``setuptools.find_packages`` in that it recurses the
+  Python package hierarchy below the given top level and installs all of it. If
+  ``packages`` is not specified, it defaults to the value of the ``name`` field
+  given in the ``[metadata]`` section.
+
+``namespace_packages``
+  Similar to ``packages``, but is a list of packages that provide namespace
+  packages.
+
+``data_files``
+  A list of files to be installed. The format is an indented block that
+  contains key value pairs which specify target directory and source file to
+  install there. More than one source file for a directory may be indicated
+  with a further indented list. Source files are stripped of leading
+  directories. Additionally, *pbr* supports a simple file globbing syntax for
+  installing entire directory structures. For example::
+
+      [files]
+      data_files =
+          etc/pbr = etc/pbr/*
+          etc/neutron =
+              etc/api-paste.ini
+              etc/dhcp-agent.ini
+          etc/init.d = neutron.init
+
+  This 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 directory will be installed in ``/etc/init.d``. 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``
+~~~~~~~~~~~~~~~~
+
+The ``entry_points`` section defines entry points for generated console scripts
+and Python libraries. This is actually provided by *setuptools* but is
+documented here owing to its importance.
+
+The general syntax of specifying entry points is a top level name indicating
+the entry point group name, followed by one or more key value pairs naming
+the entry point to be installed. For instance::
+
+    [entry_points]
+    console_scripts =
+        pbr = pbr.cmd:main
+    pbr.config.drivers =
+        plain = pbr.cfg.driver:Plain
+        fancy = pbr.cfg.driver:Fancy
+
+Will cause a console script called *pbr* to be installed that executes the
+``main`` function found in ``pbr.cmd``. Additionally, two entry points will be
+installed for ``pbr.config.drivers``, one called ``plain`` which maps to the
+``Plain`` class in ``pbr.cfg.driver`` and one called ``fancy`` which maps to
+the ``Fancy`` class in ``pbr.cfg.driver``.
+
+``backwards_compat``
+~~~~~~~~~~~~~~~~~~~~~
+
+.. todo:: Describe this section
+
+.. _pbr-setup-cfg:
+
+``pbr``
+~~~~~~~
+
+The ``pbr`` section controls *pbr*-specific options and behaviours.
+
+``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``
+  are included, but this can be overridden using the ``autodoc_tree_excludes``
+  option.
+
+``autodoc_tree_excludes``
+
+  A list of modules to exclude when building documentation using
+  ``sphinx-apidoc``. Defaults to ``[setup.py]``. Refer to the
+  `sphinx-apidoc man page`__ for more information.
+
+__ http://sphinx-doc.org/man/sphinx-apidoc.html
+
+``autodoc_index_modules``
+
+  A boolean option controlling whether *pbr* should itself generates
+  documentation for Python modules of the project. By default, all found Python
+  modules are included; some of them can be excluded by listing them in
+  ``autodoc_exclude_modules``.
+
+``autodoc_exclude_modules``
+
+  A list of modules to exclude when building module documentation using *pbr*.
+  *fnmatch* style pattern (e.g. ``myapp.tests.*``) can be used.
+
+``api_doc_dir``
+
+  A subdirectory inside the ``build_sphinx.source_dir`` where auto-generated
+  API documentation should be written, if ``autodoc_index_modules`` is set to
+  True. Defaults to ``"api"``.
+
+.. note::
+
+   When using ``autodoc_tree_excludes`` or ``autodoc_index_modules`` you may
+   also need to set ``exclude_patterns`` in your Sphinx configuration file
+   (generally found at ``doc/source/conf.py`` in most OpenStack projects)
+   otherwise Sphinx may complain about documents that are not in a toctree.
+   This is especially true if the ``[sphinx_build] warning-is-error`` option is
+   set. See the `Sphinx build configuration file`__ documentation for more
+   information on configuring Sphinx.
+
+__ http://sphinx-doc.org/config.html
+
+.. versionchanged:: 2.0
+
+   The ``pbr`` section used to take a ``warnerrors`` option that would enable
+   the ``-W`` (Turn warnings into errors.) option when building Sphinx. This
+   feature was broken in 1.10 and was removed in pbr 2.0 in favour of the
+   ``[build_sphinx] warning-is-error`` provided in Sphinx 1.5+.
+
+``metadata``
+~~~~~~~~~~~~
+
+.. todo:: Describe this section
+
+.. _build_sphinx-setup-cfg:
+
+``build_sphinx``
+~~~~~~~~~~~~~~~~
+
+.. versionchanged:: 3.0
+
+   The ``build_sphinx`` plugin used to default to building both HTML and man
+   page output. This is no longer the case, and you should explicitly set
+   ``builders`` to ``html man`` if you wish to retain this behavior.
+
+The ``build_sphinx`` section is a version of the ``build_sphinx`` *setuptools*
+plugin provided with Sphinx. This plugin extends the original plugin to add the
+following:
+
+- Automatic generation of module documentation using the ``sphinx-apidoc`` tool
+
+- Automatic configuration of the ``project``, ``version`` and ``release``
+  settings using information from *pbr* itself
+
+- Support for multiple builders using the ``builders`` configuration option
+
+  .. note::
+
+     Only applies to Sphinx < 1.6. See documentation on ``builders`` below.
+
+The version of ``build_sphinx`` provided by *pbr* provides a single additional
+option.
+
+``builders``
+  A comma separated list of builders to run. For example, to build both HTML
+  and man page documentation, you would define the following in your
+  ``setup.cfg``:
+
+  .. code-block:: ini
+
+      [build_sphinx]
+      builders = html,man
+      source-dir = doc/source
+      build-dir = doc/build
+      all-files = 1
+      warning-is-error = 1
+
+  .. deprecated:: 3.2.0
+
+     Sphinx 1.6+ adds support for specifying multiple builders in the default
+     ``builder`` option. You should use this option instead. Refer to the
+     `Sphinx documentation`_ for more information.
+
+For information on the remaining options, refer to the `Sphinx documentation`_.
+In addition, the ``autodoc_index_modules``, ``autodoc_tree_index_modules``,
+``autodoc_exclude_modules`` and ``autodoc_tree_excludes`` options :ref:`in the
+pbr section <pbr-setup-cfg>` will affect the output of the automatic module
+documentation generation.
+
+.. _Sphinx documentation: http://www.sphinx-doc.org/en/stable/setuptools.html
+
+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):
+
+* ``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::
+
+   The ``requirements-pyN.txt`` file is deprecated - ``requirements.txt``
+   should be universal. You can use `Environment markers`_ for this purpose.
+
+.. _extra-requirements:
+
+Extra requirements
+~~~~~~~~~~~~~~~~~~
+
+Groups of optional dependencies, or `"extra" requirements`__, can be described
+in your ``setup.cfg``, rather than needing to be added to ``setup.py``. An
+example (which also demonstrates the use of environment markers) is shown
+below.
+
+__ https://www.python.org/dev/peps/pep-0426/#extras-optional-dependencies
+
+Environment markers
+~~~~~~~~~~~~~~~~~~~
+
+Environment markers are `conditional dependencies`__ which can be added to the
+requirements (or to a group of extra requirements) automatically, depending on
+the environment the installer is running in. They can be added to requirements
+in the requirements file, or to extras defined in ``setup.cfg``, but the format
+is slightly different for each.
+
+For ``requirements.txt``::
+
+    argparse; python_version=='2.6'
+
+This will result in the package depending on ``argparse`` only if it's being
+installed into Python 2.6.
+
+For extras specified in ``setup.cfg``, add an ``extras`` section. For instance,
+to create two groups of extra requirements with additional constraints on the
+environment, you can use::
+
+    [extras]
+    security =
+        aleph
+        bet:python_version=='3.2'
+        gimel:python_version=='2.7'
+    testing =
+        quux:python_version=='2.7'
+
+__ https://www.python.org/dev/peps/pep-0426/#environment-markers
+
+Testing
+-------
+
+.. deprecated:: 4.0
+
+As described in :doc:`/user/features`, *pbr* may override the ``test`` command
+depending on the test runner used.
+
+A typical usage would be in ``tox.ini`` such as::
+
+  [tox]
+  minversion = 2.0
+  skipsdist = True
+  envlist = py33,py34,py35,py26,py27,pypy,pep8,docs
+
+  [testenv]
+  usedevelop = True
+  setenv =
+    VIRTUAL_ENV={envdir}
+    CLIENT_NAME=pbr
+  deps = .
+       -r{toxinidir}/test-requirements.txt
+  commands =
+    python setup.py test --testr-args='{posargs}'
+
+The argument ``--coverage`` will set ``PYTHON`` to ``coverage run`` to produce
+a coverage report.  ``--coverage-package-name`` can be used to modify or narrow
+the packages traced.
+
+.. _setuptools: http://www.sphinx-doc.org/en/stable/setuptools.html
index 8bde2504aa358f1b6f4051c63e4b6f7794a0578e..1339ea8b5ecdb2937db5db854b3f73c8e6b3dffb 100644 (file)
@@ -1,11 +1,14 @@
-Metadata-Version: 1.1
+Metadata-Version: 2.1
 Name: pbr
-Version: 3.1.1
+Version: 4.0.0
 Summary: Python Build Reasonableness
-Home-page: http://docs.openstack.org/developer/pbr/
+Home-page: https://docs.openstack.org/pbr/latest/
 Author: OpenStack
 Author-email: openstack-dev@lists.openstack.org
 License: UNKNOWN
+Project-URL: Bug Tracker, https://bugs.launchpad.net/pbr/
+Project-URL: Documentation, https://docs.openstack.org/pbr/
+Project-URL: Source Code, https://git.openstack.org/cgit/openstack-dev/pbr/
 Description: Introduction
         ============
         
@@ -39,10 +42,10 @@ Description: Introduction
         them as quickly as possible.
         
         * License: Apache License, Version 2.0
-        * Documentation: http://docs.openstack.org/developer/pbr
-        * Source: http://git.openstack.org/cgit/openstack-dev/pbr
-        * Bugs: http://bugs.launchpad.net/pbr
-        * Change Log: https://docs.openstack.org/developer/pbr/history.html
+        * Documentation: https://docs.openstack.org/pbr/latest/
+        * Source: https://git.openstack.org/cgit/openstack-dev/pbr
+        * Bugs: https://bugs.launchpad.net/pbr
+        * Change Log: https://docs.openstack.org/pbr/latest/user/history.html
         
         .. _d2to1: https://pypi.python.org/pypi/d2to1
         .. _distutils2: https://pypi.python.org/pypi/Distutils2
@@ -60,9 +63,9 @@ Classifier: License :: OSI Approved :: Apache Software License
 Classifier: Operating System :: OS Independent
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
 Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
 Classifier: Programming Language :: Python :: 3.3
 Classifier: Programming Language :: Python :: 3.4
 Classifier: Programming Language :: Python :: 3.5
+Description-Content-Type: text/x-rst; charset=UTF-8
index 9041710bdc4b25c03ec6236d077e5ece091d99c6..0ced9f264ad3d778e1d18d34edade9eb4b5dbe24 100644 (file)
@@ -10,13 +10,17 @@ setup.cfg
 setup.py
 test-requirements.txt
 tox.ini
-doc/source/compatibility.rst
 doc/source/conf.py
-doc/source/history.rst
 doc/source/index.rst
-doc/source/packagers.rst
-doc/source/semver.rst
-doc/source/testing.rst
+doc/source/contributor/index.rst
+doc/source/reference/index.rst
+doc/source/user/compatibility.rst
+doc/source/user/features.rst
+doc/source/user/history.rst
+doc/source/user/index.rst
+doc/source/user/packagers.rst
+doc/source/user/semver.rst
+doc/source/user/using.rst
 pbr/__init__.py
 pbr/builddoc.py
 pbr/core.py
@@ -81,5 +85,12 @@ pbr/tests/testpackage/pbr_testpackage/wsgi.py
 pbr/tests/testpackage/pbr_testpackage/package_data/1.txt
 pbr/tests/testpackage/pbr_testpackage/package_data/2.txt
 pbr/tests/testpackage/src/testext.c
+releasenotes/notes/deprecate-pyN-requirements-364655c38fa5b780.yaml
+releasenotes/notes/deprecate-testr-nose-integration-56e3e11248d946fc.yaml
+releasenotes/notes/remove-command-hooks-907d9c2325f306ca.yaml
+releasenotes/notes/v_version-457b38c8679c5868.yaml
+releasenotes/source/conf.py
+releasenotes/source/index.rst
+releasenotes/source/unreleased.rst
 tools/integration.sh
-tools/tox_install.sh
\ No newline at end of file
+tools/tox_releasenotes.sh
\ No newline at end of file
index c1a2e6f475304a997a1303bc7a1ad34c080397bb..167d13e04a5be8ef9a66c2abcb4f0fc4189b9352 100644 (file)
@@ -25,7 +25,19 @@ except ImportError:
     import io as cStringIO
 
 try:
-    from sphinx import apidoc
+    import sphinx
+    # NOTE(dhellmann): Newer versions of Sphinx have moved the apidoc
+    # module into sphinx.ext and the API is slightly different (the
+    # function expects sys.argv[1:] instead of sys.argv[:]. So, figure
+    # out where we can import it from and set a flag so we can invoke
+    # it properly. See this change in sphinx for details:
+    # https://github.com/sphinx-doc/sphinx/commit/87630c8ae8bff8c0e23187676e6343d8903003a6
+    try:
+        from sphinx.ext import apidoc
+        apidoc_use_padding = False
+    except ImportError:
+        from sphinx import apidoc
+        apidoc_use_padding = True
     from sphinx import application
     from sphinx import setup_command
 except Exception as e:
@@ -42,6 +54,7 @@ except Exception as e:
     raise ImportError(str(e))
 from pbr import git
 from pbr import options
+from pbr import version
 
 
 _rst_template = """%(heading)s
@@ -117,7 +130,9 @@ class LocalBuildDoc(setup_command.BuildDoc):
 
     def _sphinx_tree(self):
             source_dir = self._get_source_dir()
-            cmd = ['apidoc', '.', '-H', 'Modules', '-o', source_dir]
+            cmd = ['-H', 'Modules', '-o', source_dir, '.']
+            if apidoc_use_padding:
+                cmd.insert(0, 'apidoc')
             apidoc.main(cmd + self.autodoc_tree_excludes)
 
     def _sphinx_run(self):
@@ -186,15 +201,34 @@ class LocalBuildDoc(setup_command.BuildDoc):
                         "autodoc_exclude_modules",
                         [None, ""])[1].split()))
 
-        # TODO(stephenfin): Deprecate this functionality once we depend on
-        # Sphinx 1.6, which includes a similar feature, in g-r
-        # https://github.com/sphinx-doc/sphinx/pull/3476
         self.finalize_options()
-        if hasattr(self, "builder_target_dirs"):
-            # Sphinx >= 1.6.1
+
+        is_multibuilder_sphinx = version.SemanticVersion.from_pip_string(
+            sphinx.__version__) >= version.SemanticVersion(1, 6)
+
+        # TODO(stephenfin): Remove support for Sphinx < 1.6 in 4.0
+        if not is_multibuilder_sphinx:
+            log.warn('[pbr] Support for Sphinx < 1.6 will be dropped in '
+                     'pbr 4.0. Upgrade to Sphinx 1.6+')
+
+        # TODO(stephenfin): Remove this at the next MAJOR version bump
+        if self.builders != ['html']:
+            log.warn("[pbr] Sphinx 1.6 added native support for "
+                     "specifying multiple builders in the "
+                     "'[sphinx_build] builder' configuration option, "
+                     "found in 'setup.cfg'. As a result, the "
+                     "'[sphinx_build] builders' option has been "
+                     "deprecated and will be removed in pbr 4.0. Migrate "
+                     "to the 'builder' configuration option.")
+            if is_multibuilder_sphinx:
+                self.builder = self.builders
+
+        if is_multibuilder_sphinx:
+            # Sphinx >= 1.6
             return setup_command.BuildDoc.run(self)
+
         # Sphinx < 1.6
-        for builder in self.builders:
+        for builder in self.builder:
             self.builder = builder
             self.finalize_options()
             self._sphinx_run()
@@ -208,6 +242,8 @@ class LocalBuildDoc(setup_command.BuildDoc):
         self.autodoc_tree_excludes = ['setup.py']
 
     def finalize_options(self):
+        from pbr import util
+
         # Not a new style class, super keyword does not work.
         setup_command.BuildDoc.finalize_options(self)
 
@@ -228,8 +264,8 @@ class LocalBuildDoc(setup_command.BuildDoc):
         opt = 'autodoc_tree_excludes'
         option_dict = self.distribution.get_option_dict('pbr')
         if opt in option_dict:
-            self.autodoc_tree_excludes = option_dict[opt][1]
-            self.ensure_string_list(opt)
+            self.autodoc_tree_excludes = util.split_multiline(
+                option_dict[opt][1])
 
         # handle Sphinx < 1.5.0
         if not hasattr(self, 'warning_is_error'):
index 71d1e5696009e2de568423e5d92e0cce2b60ad34..a93253baddf4796a1d3be3c80ef0f0979cf95d54 100644 (file)
@@ -50,22 +50,9 @@ import os
 import sys
 import warnings
 
-from setuptools import dist
-
 from pbr import util
 
 
-_saved_core_distribution = core.Distribution
-
-
-def _monkeypatch_distribution():
-    core.Distribution = dist._get_unpatched(core.Distribution)
-
-
-def _restore_distribution_monkeypatch():
-    core.Distribution = _saved_core_distribution
-
-
 if sys.version_info[0] == 3:
     string_type = str
     integer_types = (int,)
@@ -94,63 +81,54 @@ def pbr(dist, attr, value):
     not work well with distributions that do use a `Distribution` subclass.
     """
 
+    if not value:
+        return
+    if isinstance(value, string_type):
+        path = os.path.abspath(value)
+    else:
+        path = os.path.abspath('setup.cfg')
+    if not os.path.exists(path):
+        raise errors.DistutilsFileError(
+            'The setup.cfg file %s does not exist.' % path)
+
+    # Converts the setup.cfg file to setup() arguments
     try:
-        _monkeypatch_distribution()
-        if not value:
-            return
-        if isinstance(value, string_type):
-            path = os.path.abspath(value)
-        else:
-            path = os.path.abspath('setup.cfg')
-        if not os.path.exists(path):
-            raise errors.DistutilsFileError(
-                'The setup.cfg file %s does not exist.' % path)
-
-        # Converts the setup.cfg file to setup() arguments
-        try:
-            attrs = util.cfg_to_args(path, dist.script_args)
-        except Exception:
-            e = sys.exc_info()[1]
-            # NB: This will output to the console if no explicit logging has
-            # been setup - but thats fine, this is a fatal distutils error, so
-            # being pretty isn't the #1 goal.. being diagnosable is.
-            logging.exception('Error parsing')
-            raise errors.DistutilsSetupError(
-                'Error parsing %s: %s: %s' % (path, e.__class__.__name__, e))
-
-        # Repeat some of the Distribution initialization code with the newly
-        # provided attrs
-        if attrs:
-            # Skips 'options' and 'licence' support which are rarely used; may
-            # add back in later if demanded
-            for key, val in attrs.items():
-                if hasattr(dist.metadata, 'set_' + key):
-                    getattr(dist.metadata, 'set_' + key)(val)
-                elif hasattr(dist.metadata, key):
-                    setattr(dist.metadata, key, val)
-                elif hasattr(dist, key):
-                    setattr(dist, key, val)
-                else:
-                    msg = 'Unknown distribution option: %s' % repr(key)
-                    warnings.warn(msg)
-
-        # Re-finalize the underlying Distribution
-        core.Distribution.finalize_options(dist)
-
-        # This bit comes out of distribute/setuptools
-        if isinstance(dist.metadata.version, integer_types + (float,)):
-            # Some people apparently take "version number" too literally :)
-            dist.metadata.version = str(dist.metadata.version)
-
-        # This bit of hackery is necessary so that the Distribution will ignore
-        # normally unsupport command options (namely pre-hooks and post-hooks).
-        # dist.command_options is normally a dict mapping command names to
-        # dicts of their options.  Now it will be a defaultdict that returns
-        # IgnoreDicts for the each command's options so we can pass through the
-        # unsupported options
-        ignore = ['pre_hook.*', 'post_hook.*']
-        dist.command_options = util.DefaultGetDict(
-            lambda: util.IgnoreDict(ignore)
-        )
-    finally:
-        _restore_distribution_monkeypatch()
+        attrs = util.cfg_to_args(path, dist.script_args)
+    except Exception:
+        e = sys.exc_info()[1]
+        # NB: This will output to the console if no explicit logging has
+        # been setup - but thats fine, this is a fatal distutils error, so
+        # being pretty isn't the #1 goal.. being diagnosable is.
+        logging.exception('Error parsing')
+        raise errors.DistutilsSetupError(
+            'Error parsing %s: %s: %s' % (path, e.__class__.__name__, e))
+
+    # Repeat some of the Distribution initialization code with the newly
+    # provided attrs
+    if attrs:
+        # Skips 'options' and 'licence' support which are rarely used; may
+        # add back in later if demanded
+        for key, val in attrs.items():
+            if hasattr(dist.metadata, 'set_' + key):
+                getattr(dist.metadata, 'set_' + key)(val)
+            elif hasattr(dist.metadata, key):
+                setattr(dist.metadata, key, val)
+            elif hasattr(dist, key):
+                setattr(dist, key, val)
+            else:
+                msg = 'Unknown distribution option: %s' % repr(key)
+                warnings.warn(msg)
+
+    # Re-finalize the underlying Distribution
+    try:
+        super(dist.__class__, dist).finalize_options()
+    except TypeError:
+        # If dist is not declared as a new-style class (with object as
+        # a subclass) then super() will not work on it. This is the case
+        # for Python 2. In that case, fall back to doing this the ugly way
+        dist.__class__.__bases__[-1].finalize_options(dist)
+
+    # This bit comes out of distribute/setuptools
+    if isinstance(dist.metadata.version, integer_types + (float,)):
+        # Some people apparently take "version number" too literally :)
+        dist.metadata.version = str(dist.metadata.version)
index c8eedbdb16df54916f9e871cbb89e5d55ad0fe69..38b4982fd237c7f2c81e5eeb88af6ebf83e06ec9 100644 (file)
@@ -27,6 +27,7 @@ import email.errors
 import os
 import re
 import sys
+import warnings
 
 import pkg_resources
 import setuptools
@@ -45,6 +46,8 @@ from pbr import testr_command
 from pbr import version
 
 REQUIREMENTS_FILES = ('requirements.txt', 'tools/pip-requires')
+PY_REQUIREMENTS_FILES = [x % sys.version_info[0] for x in (
+    'requirements-py%d.txt', 'tools/pip-requires-py%d')]
 TEST_REQUIREMENTS_FILES = ('test-requirements.txt', 'tools/test-requires')
 
 
@@ -56,9 +59,8 @@ def get_requirements_files():
     # - REQUIREMENTS_FILES with -py2 or -py3 in the name
     #   (e.g. requirements-py3.txt)
     # - REQUIREMENTS_FILES
-    return (list(map(('-py' + str(sys.version_info[0])).join,
-                     map(os.path.splitext, REQUIREMENTS_FILES)))
-            + list(REQUIREMENTS_FILES))
+
+    return PY_REQUIREMENTS_FILES + list(REQUIREMENTS_FILES)
 
 
 def append_text_list(config, key, text_list):
@@ -77,9 +79,20 @@ def _any_existing(file_list):
 
 # Get requirements from the first file that exists
 def get_reqs_from_files(requirements_files):
-    for requirements_file in _any_existing(requirements_files):
+    existing = _any_existing(requirements_files)
+
+    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. '
+                      'Use environment markers instead. Conflicting files: '
+                      '%r' % deprecated,
+                      DeprecationWarning)
+
+    for requirements_file in existing:
         with open(requirements_file, 'r') as fil:
             return fil.read().split('\n')
+
     return []
 
 
@@ -259,8 +272,14 @@ try:
         """Fallback test runner if testr is a no-go."""
 
         command_name = 'test'
+        description = 'DEPRECATED: Run unit tests using nose'
 
         def run(self):
+            warnings.warn('nose integration in pbr is deprecated. Please use '
+                          'the native nose setuptools configuration or call '
+                          'nose directly',
+                          DeprecationWarning)
+
             # Can't use super - base class old-style class
             commands.nosetests.run(self)
 
@@ -390,8 +409,6 @@ class LocalDevelop(develop.develop):
     command_name = 'develop'
 
     def install_wrapper_scripts(self, dist):
-        if sys.platform == 'win32':
-            return develop.develop.install_wrapper_scripts(self, dist)
         if not self.exclude_scripts:
             for args in override_get_script_args(dist):
                 self.write_script(*args)
@@ -445,13 +462,7 @@ class LocalInstallScripts(install_scripts.install_scripts):
             # entry-points listed for this package.
             return
 
-        if os.name != 'nt':
-            get_script_args = override_get_script_args
-        else:
-            get_script_args = easy_install.get_script_args
-            executable = '"%s"' % executable
-
-        for args in get_script_args(dist, executable, is_wininst):
+        for args in override_get_script_args(dist, executable, is_wininst):
             self.write_script(*args)
 
 
@@ -532,11 +543,57 @@ class LocalSDist(sdist.sdist):
 
     command_name = 'sdist'
 
+    def checking_reno(self):
+        """Ensure reno is installed and configured.
+
+        We can't run reno-based commands if reno isn't installed/available, and
+        don't want to if the user isn't using it.
+        """
+        if hasattr(self, '_has_reno'):
+            return self._has_reno
+
+        try:
+            # versions of reno witout this module will not have the required
+            # feature, hence the import
+            from reno import setup_command  # noqa
+        except ImportError:
+            log.info('[pbr] reno was not found or is too old. Skipping '
+                     'release notes')
+            self._has_reno = False
+            return False
+
+        conf, output_file, cache_file = setup_command.load_config(
+            self.distribution)
+
+        if not os.path.exists(os.path.join(conf.reporoot, conf.notespath)):
+            log.info('[pbr] reno does not appear to be configured. Skipping '
+                     'release notes')
+            self._has_reno = False
+            return False
+
+        self._files = [output_file, cache_file]
+
+        log.info('[pbr] Generating release notes')
+        self._has_reno = True
+
+        return True
+
+    sub_commands = [('build_reno', checking_reno)] + sdist.sdist.sub_commands
+
     def run(self):
         _from_git(self.distribution)
         # sdist.sdist is an old style class, can't use super()
         sdist.sdist.run(self)
 
+    def make_distribution(self):
+        # This is included in make_distribution because setuptools doesn't use
+        # 'get_file_list'. As such, this is the only hook point that runs after
+        # the commands in 'sub_commands'
+        if self.checking_reno():
+            self.filelist.extend(self._files)
+            self.filelist.sort()
+        sdist.sdist.make_distribution(self)
+
 try:
     from pbr import builddoc
     _have_sphinx = True
index cd179a27a65bd691bf763ffa536ed4244cd095b9..d143565fb66f664fafdebba377599fedd4884355 100644 (file)
@@ -45,13 +45,14 @@ import distutils.errors
 import logging
 import os
 import sys
+import warnings
 
 logger = logging.getLogger(__name__)
 
 
 class TestrReal(cmd.Command):
 
-    description = "Run unit tests using testr"
+    description = "DEPRECATED: Run unit tests using testr"
 
     user_options = [
         ('coverage', None, "Replace PYTHON with coverage and merge coverage "
@@ -100,6 +101,11 @@ class TestrReal(cmd.Command):
     def run(self):
         """Set up testr repo, then run testr."""
         logger.debug("run called")
+
+        warnings.warn('testr integration in pbr is deprecated. Please use '
+                      'the \'testr\' setup command or call testr directly',
+                      DeprecationWarning)
+
         if not os.path.isdir(".testrepository"):
             self._run_testr("init")
 
index 07597060ad3f9c482334e8f0f947bf3f23c9fd55..0fcf96cac2cad32cbbde1e21451e6c8fbfefebd4 100644 (file)
@@ -39,9 +39,7 @@
 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 
 import os
-import textwrap
 
-from testtools import content
 from testtools import matchers
 
 from pbr.tests import base
@@ -56,10 +54,6 @@ class TestHooks(base.BaseTestCase):
             cfg.set('global', 'setup-hooks',
                     'pbr_testpackage._setup_hooks.test_hook_1\n'
                     'pbr_testpackage._setup_hooks.test_hook_2')
-            cfg.set('build_ext', 'pre-hook.test_pre_hook',
-                    'pbr_testpackage._setup_hooks.test_pre_hook')
-            cfg.set('build_ext', 'post-hook.test_post_hook',
-                    'pbr_testpackage._setup_hooks.test_post_hook')
 
     def test_global_setup_hooks(self):
         """Test setup_hooks.
@@ -72,28 +66,6 @@ class TestHooks(base.BaseTestCase):
         assert 'test_hook_1\ntest_hook_2' in stdout
         assert return_code == 0
 
-    def test_command_hooks(self):
-        """Test command hooks.
-
-        Simple test that the appropriate command hooks run at the
-        beginning/end of the appropriate command.
-        """
-
-        stdout, _, return_code = self.run_setup('egg_info')
-        assert 'build_ext pre-hook' not in stdout
-        assert 'build_ext post-hook' not in stdout
-        assert return_code == 0
-
-        stdout, stderr, return_code = self.run_setup('build_ext')
-        self.addDetailUniqueName('stderr', content.text_content(stderr))
-        assert textwrap.dedent("""
-            running build_ext
-            running pre_hook pbr_testpackage._setup_hooks.test_pre_hook for command build_ext
-            build_ext pre-hook
-        """) in stdout  # flake8: noqa
-        self.expectThat(stdout, matchers.EndsWith('build_ext post-hook'))
-        assert return_code == 0
-
     def test_custom_commands_known(self):
         stdout, _, return_code = self.run_setup('--help-commands')
         self.assertFalse(return_code)
index 9efcbd7892e1284e675d676edb856e336b2ac324..5512d5d62aa995aec42f51fd340a21a0aa8ae0c2 100644 (file)
@@ -43,6 +43,7 @@ import email.errors
 import imp
 import os
 import re
+import sys
 import sysconfig
 import tempfile
 import textwrap
@@ -51,6 +52,7 @@ import fixtures
 import mock
 import pkg_resources
 import six
+import testscenarios
 import testtools
 from testtools import matchers
 import virtualenv
@@ -486,9 +488,47 @@ class TestPresenceOfGit(base.BaseTestCase):
             self.assertEqual(False, git._git_is_installed())
 
 
-class TestIndexInRequirements(base.BaseTestCase):
+class ParseRequirementsTest(base.BaseTestCase):
 
-    def test_index_in_requirement(self):
+    def test_empty_requirements(self):
+        actual = packaging.parse_requirements([])
+        self.assertEqual([], actual)
+
+    def test_default_requirements(self):
+        """Ensure default files used if no files provided."""
+        tempdir = tempfile.mkdtemp()
+        requirements = os.path.join(tempdir, 'requirements.txt')
+        with open(requirements, 'w') as f:
+            f.write('pbr')
+        # the defaults are relative to where pbr is called from so we need to
+        # override them. This is OK, however, as we want to validate that
+        # defaults are used - not what those defaults are
+        with mock.patch.object(packaging, 'REQUIREMENTS_FILES', (
+                requirements,)):
+            result = packaging.parse_requirements()
+        self.assertEqual(['pbr'], result)
+
+    def test_override_with_env(self):
+        """Ensure environment variable used if no files provided."""
+        _, tmp_file = tempfile.mkstemp(prefix='openstack', suffix='.setup')
+        with open(tmp_file, 'w') as fh:
+            fh.write("foo\nbar")
+        self.useFixture(
+            fixtures.EnvironmentVariable('PBR_REQUIREMENTS_FILES', tmp_file))
+        self.assertEqual(['foo', 'bar'],
+                         packaging.parse_requirements())
+
+    def test_override_with_env_multiple_files(self):
+        _, tmp_file = tempfile.mkstemp(prefix='openstack', suffix='.setup')
+        with open(tmp_file, 'w') as fh:
+            fh.write("foo\nbar")
+        self.useFixture(
+            fixtures.EnvironmentVariable('PBR_REQUIREMENTS_FILES',
+                                         "no-such-file," + tmp_file))
+        self.assertEqual(['foo', 'bar'],
+                         packaging.parse_requirements())
+
+    def test_index_present(self):
         tempdir = tempfile.mkdtemp()
         requirements = os.path.join(tempdir, 'requirements.txt')
         with open(requirements, 'w') as f:
@@ -498,10 +538,7 @@ class TestIndexInRequirements(base.BaseTestCase):
         result = packaging.parse_requirements([requirements])
         self.assertEqual([], result)
 
-
-class TestNestedRequirements(base.BaseTestCase):
-
-    def test_nested_requirement(self):
+    def test_nested_requirements(self):
         tempdir = tempfile.mkdtemp()
         requirements = os.path.join(tempdir, 'requirements.txt')
         nested = os.path.join(tempdir, 'nested.txt')
@@ -512,6 +549,94 @@ class TestNestedRequirements(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):
+
+    versioned_scenarios = [
+        ('non-versioned', {'versioned': False, 'expected': ['bar']}),
+        ('versioned', {'versioned': True, 'expected': ['bar>=1.2.3']})
+    ]
+
+    scenarios = [
+        ('normal', {'url': "foo\nbar", 'expected': ['foo', 'bar']}),
+        ('normal_with_comments', {
+            'url': "# this is a comment\nfoo\n# and another one\nbar",
+            'expected': ['foo', 'bar']}),
+        ('removes_index_lines', {'url': '-f foobar', 'expected': []}),
+    ]
+
+    scenarios = scenarios + testscenarios.multiply_scenarios([
+        ('ssh_egg_url', {'url': 'git+ssh://foo.com/zipball#egg=bar'}),
+        ('git_https_egg_url', {'url': 'git+https://foo.com/zipball#egg=bar'}),
+        ('http_egg_url', {'url': 'https://foo.com/zipball#egg=bar'}),
+    ], versioned_scenarios)
+
+    scenarios = scenarios + testscenarios.multiply_scenarios(
+        [
+            ('git_egg_url',
+                {'url': 'git://foo.com/zipball#egg=bar', 'name': 'bar'})
+        ], [
+            ('non-editable', {'editable': False}),
+            ('editable', {'editable': True}),
+        ],
+        versioned_scenarios)
+
+    def test_parse_requirements(self):
+        tmp_file = tempfile.NamedTemporaryFile()
+        req_string = self.url
+        if hasattr(self, 'editable') and self.editable:
+            req_string = ("-e %s" % req_string)
+        if hasattr(self, 'versioned') and self.versioned:
+            req_string = ("%s-1.2.3" % req_string)
+        with open(tmp_file.name, 'w') as fh:
+            fh.write(req_string)
+        self.assertEqual(self.expected,
+                         packaging.parse_requirements([tmp_file.name]))
+
+
+class ParseDependencyLinksTest(base.BaseTestCase):
+
+    def setUp(self):
+        super(ParseDependencyLinksTest, self).setUp()
+        _, self.tmp_file = tempfile.mkstemp(prefix="openstack",
+                                            suffix=".setup")
+
+    def test_parse_dependency_normal(self):
+        with open(self.tmp_file, "w") as fh:
+            fh.write("http://test.com\n")
+        self.assertEqual(
+            ["http://test.com"],
+            packaging.parse_dependency_links([self.tmp_file]))
+
+    def test_parse_dependency_with_git_egg_url(self):
+        with open(self.tmp_file, "w") as fh:
+            fh.write("-e git://foo.com/zipball#egg=bar")
+        self.assertEqual(
+            ["git://foo.com/zipball#egg=bar"],
+            packaging.parse_dependency_links([self.tmp_file]))
+
 
 class TestVersions(base.BaseTestCase):
 
@@ -759,7 +884,7 @@ class TestRequirementParsing(base.BaseTestCase):
         expected_requirements = {
             None: ['bar', 'requests-aws>=0.1.4'],
             ":(python_version=='2.6')": ['quux<1.0'],
-            ":(python_version=='2.7')": ['Routes>=1.12.3,!=2.0,!=2.1',
+            ":(python_version=='2.7')": ['Routes!=2.0,!=2.1,>=1.12.3',
                                          'requests-kerberos>=0.6'],
             'test': ['foo'],
             "test:(python_version=='2.7')": ['baz>3.2', 'bar>3.3']
@@ -778,7 +903,20 @@ class TestRequirementParsing(base.BaseTestCase):
             generated_requirements = dict(
                 pkg_resources.split_sections(requires))
 
-        self.assertEqual(expected_requirements, generated_requirements)
+        # NOTE(dhellmann): We have to spell out the comparison because
+        # the rendering for version specifiers in a range is not
+        # consistent across versions of setuptools.
+
+        for section, expected in expected_requirements.items():
+            exp_parsed = [
+                pkg_resources.Requirement.parse(s)
+                for s in expected
+            ]
+            gen_parsed = [
+                pkg_resources.Requirement.parse(s)
+                for s in generated_requirements[section]
+            ]
+            self.assertEqual(exp_parsed, gen_parsed)
 
 
 def get_soabi():
index 0b9c81be9c26d4ef0c1fe47339c4b8ad43772f98..85d40ebf30dccf60d9b27ea4f8a6f7f480bcd178 100644 (file)
@@ -17,9 +17,6 @@
 from __future__ import print_function
 
 import os
-import sys
-import tempfile
-import testscenarios
 
 try:
     import cStringIO as io
@@ -446,115 +443,3 @@ class APIAutoDocTest(base.BaseTestCase):
         self.assertTrue(
             os.path.exists(
                 "contributor/api/fake_package.fake_private_module.rst"))
-
-
-class ParseRequirementsTestScenarios(base.BaseTestCase):
-
-    versioned_scenarios = [
-        ('non-versioned', {'versioned': False, 'expected': ['bar']}),
-        ('versioned', {'versioned': True, 'expected': ['bar>=1.2.3']})
-    ]
-
-    scenarios = [
-        ('normal', {'url': "foo\nbar", 'expected': ['foo', 'bar']}),
-        ('normal_with_comments', {
-            'url': "# this is a comment\nfoo\n# and another one\nbar",
-            'expected': ['foo', 'bar']}),
-        ('removes_index_lines', {'url': '-f foobar', 'expected': []}),
-    ]
-
-    scenarios = scenarios + testscenarios.multiply_scenarios([
-        ('ssh_egg_url', {'url': 'git+ssh://foo.com/zipball#egg=bar'}),
-        ('git_https_egg_url', {'url': 'git+https://foo.com/zipball#egg=bar'}),
-        ('http_egg_url', {'url': 'https://foo.com/zipball#egg=bar'}),
-    ], versioned_scenarios)
-
-    scenarios = scenarios + testscenarios.multiply_scenarios(
-        [
-            ('git_egg_url',
-                {'url': 'git://foo.com/zipball#egg=bar', 'name': 'bar'})
-        ], [
-            ('non-editable', {'editable': False}),
-            ('editable', {'editable': True}),
-        ],
-        versioned_scenarios)
-
-    def test_parse_requirements(self):
-        tmp_file = tempfile.NamedTemporaryFile()
-        req_string = self.url
-        if hasattr(self, 'editable') and self.editable:
-            req_string = ("-e %s" % req_string)
-        if hasattr(self, 'versioned') and self.versioned:
-            req_string = ("%s-1.2.3" % req_string)
-        with open(tmp_file.name, 'w') as fh:
-            fh.write(req_string)
-        self.assertEqual(self.expected,
-                         packaging.parse_requirements([tmp_file.name]))
-
-
-class ParseRequirementsTest(base.BaseTestCase):
-
-    def setUp(self):
-        super(ParseRequirementsTest, self).setUp()
-        (fd, self.tmp_file) = tempfile.mkstemp(prefix='openstack',
-                                               suffix='.setup')
-
-    def test_parse_requirements_override_with_env(self):
-        with open(self.tmp_file, 'w') as fh:
-            fh.write("foo\nbar")
-        self.useFixture(
-            fixtures.EnvironmentVariable('PBR_REQUIREMENTS_FILES',
-                                         self.tmp_file))
-        self.assertEqual(['foo', 'bar'],
-                         packaging.parse_requirements())
-
-    def test_parse_requirements_override_with_env_multiple_files(self):
-        with open(self.tmp_file, 'w') as fh:
-            fh.write("foo\nbar")
-        self.useFixture(
-            fixtures.EnvironmentVariable('PBR_REQUIREMENTS_FILES',
-                                         "no-such-file," + self.tmp_file))
-        self.assertEqual(['foo', 'bar'],
-                         packaging.parse_requirements())
-
-    def test_get_requirement_from_file_empty(self):
-        actual = packaging.get_reqs_from_files([])
-        self.assertEqual([], actual)
-
-    def test_parse_requirements_python_version(self):
-        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())
-
-    def test_parse_requirements_right_python_version(self):
-        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())
-
-
-class ParseDependencyLinksTest(base.BaseTestCase):
-
-    def setUp(self):
-        super(ParseDependencyLinksTest, self).setUp()
-        (fd, self.tmp_file) = tempfile.mkstemp(prefix="openstack",
-                                               suffix=".setup")
-
-    def test_parse_dependency_normal(self):
-        with open(self.tmp_file, "w") as fh:
-            fh.write("http://test.com\n")
-        self.assertEqual(
-            ["http://test.com"],
-            packaging.parse_dependency_links([self.tmp_file]))
-
-    def test_parse_dependency_with_git_egg_url(self):
-        with open(self.tmp_file, "w") as fh:
-            fh.write("-e git://foo.com/zipball#egg=bar")
-        self.assertEqual(
-            ["git://foo.com/zipball#egg=bar"],
-            packaging.parse_dependency_links([self.tmp_file]))
index 048b2b96815a1ab010e3c1d48c7c00e088e54d9e..370a7deee25e1adce773e99c55f167e9767f2d3f 100644 (file)
@@ -36,8 +36,12 @@ class TestExtrasRequireParsingScenarios(base.BaseTestCase):
                     baz>=3.2
                     foo
                 """,
-            'expected_extra_requires': {'first': ['foo', 'bar==1.0'],
-                                        'second': ['baz>=3.2', 'foo']}
+            'expected_extra_requires': {
+                'first': ['foo', 'bar==1.0'],
+                'second': ['baz>=3.2', 'foo'],
+                'test': ['requests-mock'],
+                "test:(python_version=='2.6')": ['ordereddict'],
+            }
         }),
         ('with_markers', {
             'config_text': """
index 14c8d173674447fc4e7b872f4f4a1b46cebbdef7..d861d572031141fd92aaf8844503d9b89ae84905 100644 (file)
@@ -84,6 +84,19 @@ class TestSemanticVersion(base.BaseTestCase):
             lambda: from_pip_string('1.2.3.post5.dev6'),
             matchers.raises(ValueError))
 
+    def test_from_pip_string_v_version(self):
+        parsed = from_pip_string('v1.2.3')
+        expected = version.SemanticVersion(1, 2, 3)
+        self.expectThat(expected, matchers.Equals(parsed))
+
+        expected = version.SemanticVersion(1, 2, 3, 'a', 5, dev_count=6)
+        parsed = from_pip_string('V1.2.3.0a4.post6')
+        self.expectThat(expected, matchers.Equals(parsed))
+
+        self.expectThat(
+            lambda: from_pip_string('x1.2.3'),
+            matchers.raises(ValueError))
+
     def test_from_pip_string_legacy_nonzero_lead_in(self):
         # reported in bug 1361251
         expected = version.SemanticVersion(
index 242c9c613bfb0c5686c216d6cad6dfc55243c10b..bf4c26a2758ac178ed115f9bec0e731c14d80acf 100644 (file)
@@ -6,10 +6,15 @@ version = 0.1.dev
 author = OpenStack
 author-email = openstack-dev@lists.openstack.org
 home-page = http://pypi.python.org/pypi/pbr
+project_urls =
+    Bug Tracker = https://bugs.launchpad.net/pbr/
+    Documentation = https://docs.openstack.org/pbr/
+    Source Code = https://git.openstack.org/cgit/openstack-dev/pbr/
 summary = Test package for testing pbr
 description-file =
     README.txt
     CHANGES.txt
+description-content-type = text/plain; charset=UTF-8
 requires-python = >=2.5
 
 requires-dist =
@@ -51,7 +56,3 @@ optional = True
 #    pbr_testpackage._setup_hooks.test_hook_1
 #    pbr_testpackage._setup_hooks.test_hook_2
 commands = pbr_testpackage._setup_hooks.test_command
-
-[build_ext]
-#pre-hook.test_pre_hook = pbr_testpackage._setup_hooks.test_pre_hook
-#post-hook.test_post_hook = pbr_testpackage._setup_hooks.test_post_hook
index f283aff52509d7ddc1dcfcc30b83db86d52e1883..8755eb4caea86fcdec52e163036caf9d8fac1616 100644 (file)
@@ -1 +1,2 @@
 ordereddict;python_version=='2.6'
+requests-mock
index a117785517b23ba1f4880780c12dc6628c41dbed..163feb83fc9044bf22b2d55271ce07c627c1cb4b 100644 (file)
@@ -101,9 +101,11 @@ D1_D2_SETUP_ARGS = {
     "maintainer": ("metadata",),
     "maintainer_email": ("metadata",),
     "url": ("metadata", "home_page"),
+    "project_urls": ("metadata",),
     "description": ("metadata", "summary"),
     "keywords": ("metadata",),
     "long_description": ("metadata", "description"),
+    "long_description_content_type": ("metadata", "description_content_type"),
     "download_url": ("metadata",),
     "classifiers": ("metadata", "classifier"),
     "platforms": ("metadata", "platform"),  # **
@@ -148,6 +150,9 @@ MULTI_FIELDS = ("classifiers",
                 "tests_require",
                 "cmdclass")
 
+# setup() arguments that can have mapping values in setup.cfg
+MAP_FIELDS = ("project_urls",)
+
 # setup() arguments that contain boolean values
 BOOL_FIELDS = ("use_2to3", "zip_safe", "include_package_data")
 
@@ -193,9 +198,9 @@ def cfg_to_args(path='setup.cfg', script_args=()):
     This method uses an existing setup.cfg to generate a dictionary of
     keywords that can be used by distutils.core.setup(kwargs**).
 
-    :param file:
+    :param path:
         The setup.cfg path.
-    :parm script_args:
+    :param script_args:
         List of commands setup.py was called with.
     :raises DistutilsFileError:
         When the setup.cfg file is not found.
@@ -264,8 +269,6 @@ def cfg_to_args(path='setup.cfg', script_args=()):
         if entry_points:
             kwargs['entry_points'] = entry_points
 
-        wrap_commands(kwargs)
-
         # Handle the [files]/extra_files option
         files_extra_files = has_get_option(config, 'files', 'extra_files')
         if files_extra_files:
@@ -323,6 +326,12 @@ def setup_cfg_to_setup_kwargs(config, script_args=()):
             in_cfg_value = split_csv(in_cfg_value)
         if arg in MULTI_FIELDS:
             in_cfg_value = split_multiline(in_cfg_value)
+        elif arg in MAP_FIELDS:
+            in_cfg_map = {}
+            for i in split_multiline(in_cfg_value):
+                k, v = i.split('=')
+                in_cfg_map[k.strip()] = v.strip()
+            in_cfg_value = in_cfg_map
         elif arg in BOOL_FIELDS:
             # Provide some flexibility here...
             if in_cfg_value.lower() in ('true', 't', '1', 'yes', 'y'):
@@ -402,6 +411,13 @@ def setup_cfg_to_setup_kwargs(config, script_args=()):
     if 'extras' in config:
         requirement_pattern = '(?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.
+        if 'test' not in extras:
+            from pbr import packaging
+            extras['test'] = "\n".join(packaging.parse_requirements(
+                packaging.TEST_REQUIREMENTS_FILES)).replace(';', ':')
+
         for extra in extras:
             extra_requirements = []
             requirements = split_multiline(extras[extra])
@@ -552,103 +568,6 @@ def get_entry_points(config):
                 for option, value in config['entry_points'].items())
 
 
-def wrap_commands(kwargs):
-    dist = st_dist.Distribution()
-
-    # This should suffice to get the same config values and command classes
-    # that the actual Distribution will see (not counting cmdclass, which is
-    # handled below)
-    dist.parse_config_files()
-
-    # Setuptools doesn't patch get_command_list, and as such we do not get
-    # extra commands from entry_points.  As we need to be compatable we deal
-    # with this here.
-    for ep in pkg_resources.iter_entry_points('distutils.commands'):
-        if ep.name not in dist.cmdclass:
-            if hasattr(ep, 'resolve'):
-                cmdclass = ep.resolve()
-            else:
-                # Old setuptools does not have ep.resolve, and load with
-                # arguments is depricated in 11+.  Use resolve, 12+, if we
-                # can, otherwise fall back to load.
-                # Setuptools 11 will throw a deprication warning, as it
-                # uses _load instead of resolve.
-                cmdclass = ep.load(False)
-            dist.cmdclass[ep.name] = cmdclass
-
-    for cmd, _ in dist.get_command_list():
-        hooks = {}
-        for opt, val in dist.get_option_dict(cmd).items():
-            val = val[1]
-            if opt.startswith('pre_hook.') or opt.startswith('post_hook.'):
-                hook_type, alias = opt.split('.', 1)
-                hook_dict = hooks.setdefault(hook_type, {})
-                hook_dict[alias] = val
-        if not hooks:
-            continue
-
-        if 'cmdclass' in kwargs and cmd in kwargs['cmdclass']:
-            cmdclass = kwargs['cmdclass'][cmd]
-        else:
-            cmdclass = dist.get_command_class(cmd)
-
-        new_cmdclass = wrap_command(cmd, cmdclass, hooks)
-        kwargs.setdefault('cmdclass', {})[cmd] = new_cmdclass
-
-
-def wrap_command(cmd, cmdclass, hooks):
-    def run(self, cmdclass=cmdclass):
-        self.run_command_hooks('pre_hook')
-        cmdclass.run(self)
-        self.run_command_hooks('post_hook')
-
-    return type(cmd, (cmdclass, object),
-                {'run': run, 'run_command_hooks': run_command_hooks,
-                 'pre_hook': hooks.get('pre_hook'),
-                 'post_hook': hooks.get('post_hook')})
-
-
-def run_command_hooks(cmd_obj, hook_kind):
-    """Run hooks registered for that command and phase.
-
-    *cmd_obj* is a finalized command object; *hook_kind* is either
-    'pre_hook' or 'post_hook'.
-    """
-
-    if hook_kind not in ('pre_hook', 'post_hook'):
-        raise ValueError('invalid hook kind: %r' % hook_kind)
-
-    hooks = getattr(cmd_obj, hook_kind, None)
-
-    if hooks is None:
-        return
-
-    for hook in hooks.values():
-        if isinstance(hook, str):
-            try:
-                hook_obj = resolve_name(hook)
-            except ImportError:
-                err = sys.exc_info()[1] # For py3k
-                raise errors.DistutilsModuleError('cannot find hook %s: %s' %
-                                                  (hook,err))
-        else:
-            hook_obj = hook
-
-        if not hasattr(hook_obj, '__call__'):
-            raise errors.DistutilsOptionError('hook %r is not callable' % hook)
-
-        log.info('running %s %s for command %s',
-                 hook_kind, hook, cmd_obj.get_command_name())
-
-        try :
-            hook_obj(cmd_obj)
-        except:
-            e = sys.exc_info()[1]
-            log.error('hook %s raised exception: %s\n' % (hook, e))
-            log.error(traceback.format_exc())
-            sys.exit(1)
-
-
 def has_get_option(config, section, option):
     if section in config and option in config[section]:
         return config[section][option]
@@ -661,7 +580,7 @@ def split_multiline(value):
 
     value = [element for element in
              (line.strip() for line in value.split('\n'))
-             if element]
+             if element and not element.startswith('#')]
     return value
 
 
@@ -674,21 +593,6 @@ def split_csv(value):
     return value
 
 
-def monkeypatch_method(cls):
-    """A function decorator to monkey-patch a method of the same name on the
-    given class.
-    """
-
-    def wrapper(func):
-        orig = getattr(cls, func.__name__, None)
-        if orig and not hasattr(orig, '_orig'):  # Already patched
-            setattr(func, '_orig', orig)
-            setattr(cls, func.__name__, func)
-        return func
-
-    return wrapper
-
-
 # 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
@@ -699,20 +603,3 @@ class DefaultGetDict(defaultdict):
         if default is None:
             default = self.default_factory()
         return super(DefaultGetDict, self).setdefault(key, default)
-
-
-class IgnoreDict(dict):
-    """A dictionary that ignores any insertions in which the key is a string
-    matching any string in `ignore`.  The ignore list can also contain wildcard
-    patterns using '*'.
-    """
-
-    def __init__(self, ignore):
-        self.__ignore = re.compile(r'(%s)' % ('|'.join(
-                                   [pat.replace('*', '.*')
-                                    for pat in ignore])))
-
-    def __setitem__(self, key, val):
-        if self.__ignore.match(key):
-            return
-        super(IgnoreDict, self).__setitem__(key, val)
index 474faf16a0db64d7fa3e8885d627956f62592506..5eb217afe89900fe32fcd48c78460e3962a05912 100644 (file)
@@ -149,6 +149,7 @@ class SemanticVersion(object):
     @classmethod
     def _from_pip_string_unsafe(klass, version_string):
         # Versions need to start numerically, ignore if not
+        version_string = version_string.lstrip('vV')
         if not version_string[:1].isdigit():
             raise ValueError("Invalid version %r" % version_string)
         input_components = version_string.split('.')
diff --git a/releasenotes/notes/deprecate-pyN-requirements-364655c38fa5b780.yaml b/releasenotes/notes/deprecate-pyN-requirements-364655c38fa5b780.yaml
new file mode 100644 (file)
index 0000000..3ed9bc7
--- /dev/null
@@ -0,0 +1,5 @@
+---
+deprecations:
+  - |
+    Support for ``pyN``-suffixed requirement files has been deprecated:
+    environment markers should be used instead.
diff --git a/releasenotes/notes/deprecate-testr-nose-integration-56e3e11248d946fc.yaml b/releasenotes/notes/deprecate-testr-nose-integration-56e3e11248d946fc.yaml
new file mode 100644 (file)
index 0000000..1356847
--- /dev/null
@@ -0,0 +1,10 @@
+---
+deprecations:
+  - |
+    *testr* and *nose* integration has been deprecated. This feature allowed
+    *pbr* to dynamically configure the test runner used when running
+    ``setup.py test``. However, this target has fallen out of favour in both
+    the OpenStack and broader Python ecosystem, and both *testr* and *nose*
+    offer native setuptools commands that can be manually aliased to ``test``
+    on a per-project basis, if necessary. This feature will be removed in a
+    future release.
diff --git a/releasenotes/notes/remove-command-hooks-907d9c2325f306ca.yaml b/releasenotes/notes/remove-command-hooks-907d9c2325f306ca.yaml
new file mode 100644 (file)
index 0000000..c6ce753
--- /dev/null
@@ -0,0 +1,6 @@
+---
+upgrade:
+  - |
+    Support for entry point command hooks has been removed. This feature was
+    poorly tested, poorly documented, and broken in some environments.
+    Support for global hooks is not affected.
diff --git a/releasenotes/notes/v_version-457b38c8679c5868.yaml b/releasenotes/notes/v_version-457b38c8679c5868.yaml
new file mode 100644 (file)
index 0000000..696ba41
--- /dev/null
@@ -0,0 +1,5 @@
+---
+features:
+  - |
+    Support version parsing of git tag with the ``v<semver>`` pattern
+    (or ``V<semver>``), in addition to ``<semver>``.
diff --git a/releasenotes/source/conf.py b/releasenotes/source/conf.py
new file mode 100644 (file)
index 0000000..56f7ecd
--- /dev/null
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+# 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.
+
+# pbr Release Notes documentation build configuration file
+
+
+# -- General configuration ------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+    'openstackdocstheme',
+    'reno.sphinxext',
+]
+
+# The master toctree document.
+master_doc = 'index'
+
+# Release notes are version independent
+# The short X.Y version.
+version = ''
+# The full version, including alpha/beta/rc tags.
+release = ''
+
+
+# -- Options for HTML output ----------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+html_theme = 'openstackdocs'
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%Y-%m-%d %H:%M'
+
+
+# -- Options for openstackdocstheme ---------------------------------------
+
+repository_name = 'openstack-dev/pbr'
+bug_project = 'pbr'
+bug_tag = ''
diff --git a/releasenotes/source/index.rst b/releasenotes/source/index.rst
new file mode 100644 (file)
index 0000000..e6e6346
--- /dev/null
@@ -0,0 +1,8 @@
+=================
+pbr Release Notes
+=================
+
+.. toctree::
+   :maxdepth: 1
+
+   unreleased
diff --git a/releasenotes/source/unreleased.rst b/releasenotes/source/unreleased.rst
new file mode 100644 (file)
index 0000000..875030f
--- /dev/null
@@ -0,0 +1,5 @@
+============================
+Current Series Release Notes
+============================
+
+.. release-notes::
index 899e5f3ba04e5906312877228c5730d70ed16ab2..2e153eae7312f91c786367263f9306736c5308fd 100644 (file)
--- a/setup.cfg
+++ b/setup.cfg
@@ -5,7 +5,12 @@ author-email = openstack-dev@lists.openstack.org
 summary = Python Build Reasonableness
 description-file = 
        README.rst
-home-page = http://docs.openstack.org/developer/pbr/
+description-content-type = text/x-rst; charset=UTF-8
+home-page = https://docs.openstack.org/pbr/latest/
+project_urls = 
+       Bug Tracker = https://bugs.launchpad.net/pbr/
+       Documentation = https://docs.openstack.org/pbr/
+       Source Code = https://git.openstack.org/cgit/openstack-dev/pbr/
 requires-python = >=2.6
 classifier = 
        Development Status :: 5 - Production/Stable
@@ -17,7 +22,6 @@ classifier =
        Operating System :: OS Independent
        Programming Language :: Python
        Programming Language :: Python :: 2
-       Programming Language :: Python :: 2.6
        Programming Language :: Python :: 2.7
        Programming Language :: Python :: 3
        Programming Language :: Python :: 3.3
@@ -37,6 +41,7 @@ autodoc_tree_index_modules = True
 autodoc_tree_excludes = 
        setup.py
        pbr/tests/
+api_doc_dir = reference/api
 
 [entry_points]
 distutils.setup_keywords = 
@@ -50,6 +55,7 @@ console_scripts =
 all-files = 1
 build-dir = doc/build
 source-dir = doc/source
+warning-is-error = 1
 
 [wheel]
 universal = 1
index 9df6553a2b0cea70e4726773c489d9f1bd0bd667..de914907d81043752cbaff6ac34582701e5a6ec7 100644 (file)
@@ -4,13 +4,14 @@
 coverage!=4.4,>=4.0 # Apache-2.0
 fixtures>=3.0.0 # Apache-2.0/BSD
 hacking!=0.13.0,<0.14,>=0.12.0 # Apache-2.0
-mock>=2.0 # BSD
-python-subunit>=0.0.18 # Apache-2.0/BSD
-sphinx!=1.6.1,>=1.5.1 # BSD
-oslosphinx>=4.7.0 # Apache-2.0
-six>=1.9.0 # MIT
+mock>=2.0.0 # BSD
+python-subunit>=1.0.0 # Apache-2.0/BSD
+sphinx!=1.6.6,!=1.6.7,>=1.6.2 # BSD
+openstackdocstheme>=1.18.1 # Apache-2.0
+reno>=2.5.0 # Apache-2.0
+six>=1.10.0 # MIT
 testrepository>=0.0.18 # Apache-2.0/BSD
-testresources>=0.2.4 # Apache-2.0/BSD
+testresources>=2.0.0 # Apache-2.0/BSD
 testscenarios>=0.4 # Apache-2.0/BSD
-testtools>=1.4.0 # MIT
-virtualenv>=13.1.0 # MIT
+testtools>=2.2.0 # MIT
+virtualenv>=14.0.6 # MIT
diff --git a/tools/tox_install.sh b/tools/tox_install.sh
deleted file mode 100755 (executable)
index e61b63a..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env bash
-
-# Client constraint file contains this client version pin that is in conflict
-# with installing the client from source. We should remove the version pin in
-# the constraints file before applying it for from-source installation.
-
-CONSTRAINTS_FILE="$1"
-shift 1
-
-set -e
-
-# NOTE(tonyb): Place this in the tox enviroment's log dir so it will get
-# published to logs.openstack.org for easy debugging.
-localfile="$VIRTUAL_ENV/log/upper-constraints.txt"
-
-if [[ "$CONSTRAINTS_FILE" != http* ]]; then
-    CONSTRAINTS_FILE="file://$CONSTRAINTS_FILE"
-fi
-# NOTE(tonyb): need to add curl to bindep.txt if the project supports bindep
-curl "$CONSTRAINTS_FILE" --insecure --progress-bar --output "$localfile"
-
-pip install -c"$localfile" openstack-requirements
-
-# This is the main purpose of the script: Allow local installation of
-# the current repo. It is listed in constraints file and thus any
-# install will be constrained and we need to unconstrain it.
-edit-constraints "$localfile" -- "$CLIENT_NAME"
-
-pip install -c"$localfile" -U "$@"
-exit $?
diff --git a/tools/tox_releasenotes.sh b/tools/tox_releasenotes.sh
new file mode 100755 (executable)
index 0000000..fc64b99
--- /dev/null
@@ -0,0 +1,28 @@
+#!/usr/bin/env bash
+
+rm -rf releasenotes/build
+
+sphinx-build -a -E -W \
+    -d releasenotes/build/doctrees \
+    -b html \
+    releasenotes/source releasenotes/build/html
+BUILD_RESULT=$?
+
+UNCOMMITTED_NOTES=$(git status --porcelain | \
+    awk '$1 ~ "M|A|??" && $2 ~ /releasenotes\/notes/ {print $2}')
+
+if [ "${UNCOMMITTED_NOTES}" ]
+then
+    cat <<EOF
+
+REMINDER: The following changes to release notes have not been committed:
+
+${UNCOMMITTED_NOTES}
+
+While that may be intentional, keep in mind that release notes are built from
+committed changes, not the working directory.
+
+EOF
+fi
+
+exit ${BUILD_RESULT}
diff --git a/tox.ini b/tox.ini
index 823a8e869a4836f7f69e9a060a870fddc87df627..e4492674cb9f5cfc91cc2a7e4b9cefc5c8f29ad0 100644 (file)
--- a/tox.ini
+++ b/tox.ini
@@ -1,15 +1,15 @@
 [tox]
 minversion = 2.0
-envlist = py33,py34,py35,py26,py27,pypy,pep8,docs
+envlist = py33,py34,py35,py36,py27,pypy,pep8,docs
 
 [testenv]
 usedevelop = True
-install_command = {toxinidir}/tools/tox_install.sh {env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt} {opts} {packages}
+whitelist_externals = bash
+install_command = pip install {opts} {packages}
 passenv = PBR_INTEGRATION PIPFLAGS PIPVERSION PBRVERSION REPODIR WHEELHOUSE PROJECTS OS_TEST_TIMEOUT OS_STDOUT_CAPTURE OS_STDERR_CAPTURE
-setenv =
-    VIRTUAL_ENV={envdir}
-    CLIENT_NAME=pbr
-deps = -r{toxinidir}/test-requirements.txt
+deps =
+     -c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt}
+     -r{toxinidir}/test-requirements.txt
 commands =
   python setup.py test --testr-args='{posargs}'
 
@@ -22,6 +22,9 @@ commands = flake8 {posargs}
 [testenv:docs]
 commands = python setup.py build_sphinx
 
+[testenv:releasenotes]
+commands = bash -c {toxinidir}/tools/tox_releasenotes.sh
+
 [testenv:cover]
 commands =
   python setup.py test --coverage