Merge "Integrate a setuptools command"

This commit is contained in:
Zuul 2018-04-25 09:57:20 +00:00 committed by Gerrit Code Review
commit 52d4c1961d
9 changed files with 221 additions and 1 deletions

3
.gitignore vendored
View File

@ -48,6 +48,9 @@ doc/build
AUTHORS
ChangeLog
# reno generates these
RELEASENOTES.rst
# Editors
*~
.*.swp

View File

@ -8,4 +8,5 @@
design
usage
sphinxext
setuptools
examples

View File

@ -0,0 +1,60 @@
==============================
Python Packaging Integration
==============================
*reno* supports integration with `setuptools`_ and *setuptools* derivatives
like *pbr* through a custom command - ``build_reno``.
.. _pbr: http://docs.openstack.org/developer/pbr/
.. _setuptools: https://setuptools.readthedocs.io/en/latest/
Using setuptools integration
----------------------------
To enable the ``build_reno`` command, you simply need to install *reno*. Once
done, simply run:
.. code-block:: shell
python setup.py build_reno
You can configure the command in ``setup.py`` or ``setup.cfg``. To configure it
from ``setup.py``, add a ``build_reno`` section to ``command_options`` like so:
.. code-block:: python
from setuptools import setup
setup(
name='mypackage',
version='0.1',
...
command_options={
'build_reno': {
'output_file': ('setup.py', 'RELEASENOTES.txt'),
},
},
)
To configure the command from ``setup.cfg``, add a ``build_reno`` section. For
example:
.. code-block:: ini
[build_reno]
output-file = RELEASENOTES.txt
Options for setuptools integration
----------------------------------
These options related to the *setuptools* integration only. For general
configuration of *reno*, refer to :ref:`configuration`.
``repo-root``
The root directory of the Git repository; defaults to ``.``
``rel-notes-dir``
The parent directory; defaults to ``releasenotes``
``output-file``
The filename of the release notes file; defaults to ``RELEASENOTES.rst``

View File

@ -176,6 +176,8 @@ mistakes. The command exits with an error code if there are any
mistakes, so it can be used in a build pipeline to force some
correctness.
.. _configuration:
Configuring Reno
================

View File

@ -0,0 +1,6 @@
---
features:
- |
Add a ``build_reno`` setuptools command that allows users to generate a
release notes document and a reno cache file that can be used to build
release notes documents without the full Git history present.

View File

@ -11,8 +11,11 @@
# under the License.
RELEASE_NOTES_SUBDIR = 'releasenotes'
NOTES_SUBDIR = 'notes'
PRELUDE_SECTION_NAME = 'prelude'
# This is a format string, so it needs to be formatted wherever it is used.
TEMPLATE = """\
---
@ -81,3 +84,9 @@ other:
available in another section, such as the prelude. This may mean repeating
some details.
"""
# default filename of a release notes file generated by the setuptool extension
RELEASE_NOTES_FILENAME = 'RELEASENOTES.rst'
# default path to the root of the repo, used by the setuptools extension
REPO_ROOT = '.'

138
reno/setup_command.py Normal file
View File

@ -0,0 +1,138 @@
# Copyright 2017, Red Hat, Inc.
#
# 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.
"""Custom distutils command.
For more information, refer to the distutils and setuptools source:
- https://github.com/python/cpython/blob/3.6/Lib/distutils/cmd.py
- https://github.com/pypa/setuptools/blob/v36.0.0/setuptools/command/sdist.py
"""
from distutils import cmd
from distutils import errors
from distutils import log
import six
from reno import cache
from reno import config
from reno import defaults
from reno import formatter
from reno import loader
COMMAND_NAME = 'build_reno' # duplicates what's found in setup.cfg
def load_config(distribution):
"""Utility method to parse distutils/setuptools configuration.
This is for use by other libraries to extract the command configuration.
:param distribution: A :class:`distutils.dist.Distribution` object
:returns: A tuple of a :class:`reno.config.Config` object, the output path
of the human-readable release notes file, and the output file of the
reno cache file
"""
option_dict = distribution.get_option_dict(COMMAND_NAME)
if option_dict.get('repo_root') is not None:
repo_root = option_dict.get('repo_root')[1]
else:
repo_root = defaults.REPO_ROOT
if option_dict.get('rel_notes_dir') is not None:
rel_notes_dir = option_dict.get('rel_notes_dir')[1]
else:
rel_notes_dir = defaults.RELEASE_NOTES_SUBDIR
if option_dict.get('output_file') is not None:
output_file = option_dict.get('output_file')[1]
else:
output_file = defaults.RELEASE_NOTES_FILENAME
conf = config.Config(repo_root, rel_notes_dir)
cache_file = loader.get_cache_filename(conf)
return (conf, output_file, cache_file)
class BuildReno(cmd.Command):
"""Distutils command to build reno release notes.
The release note build can be triggered from distutils, and some
configuration can be included in ``setup.py`` or ``setup.cfg`` instead of
being specified from the command-line.
"""
description = 'Build reno release notes'
user_options = [
('repo-root=', None, 'the root directory of the Git repository; '
'defaults to "."'),
('rel-notes-dir=', None, 'the parent directory; defaults to '
'"releasenotes"'),
('output-file=', None, 'the filename of the release notes file'),
]
def initialize_options(self):
self.repo_root = None
self.rel_notes_dir = None
self.output_file = None
def finalize_options(self):
if self.repo_root is None:
self.repo_root = defaults.REPO_ROOT
if self.rel_notes_dir is None:
self.rel_notes_dir = defaults.RELEASE_NOTES_SUBDIR
if self.output_file is None:
self.output_file = defaults.RELEASE_NOTES_FILENAME
# Overriding distutils' Command._ensure_stringlike which doesn't support
# unicode, causing finalize_options to fail if invoked again. Workaround
# for http://bugs.python.org/issue19570
def _ensure_stringlike(self, option, what, default=None):
# type: (unicode, unicode, Any) -> Any
val = getattr(self, option)
if val is None:
setattr(self, option, default)
return default
elif not isinstance(val, six.string_types):
raise errors.DistutilsOptionError("'%s' must be a %s (got `%s`)"
% (option, what, val))
return val
def run(self):
conf = config.Config(self.repo_root, self.rel_notes_dir)
# Generate the cache using the configuration options found
# in the release notes directory and the default output
# filename.
cache_filename = cache.write_cache_db(
conf=conf,
versions_to_include=[], # include all versions
outfilename=None, # generate the default name
)
log.info('wrote cache file to %s', cache_filename)
ldr = loader.Loader(conf)
text = formatter.format_report(
ldr,
conf,
ldr.versions,
title=self.distribution.metadata.name,
)
with open(self.output_file, 'w') as f:
f.write(text)
log.info('wrote release notes to %s', self.output_file)

View File

@ -25,6 +25,8 @@ packages =
[entry_points]
console_scripts =
reno = reno.main:main
distutils.commands =
build_reno = reno.setup_command:BuildReno
[extras]
sphinx =

View File

@ -1,7 +1,6 @@
[tox]
minversion = 1.6
envlist = py35,py27,pep8
skipsdist = True
[testenv]
usedevelop = True