139 lines
4.7 KiB
Python
139 lines
4.7 KiB
Python
# 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)
|