Hello community, here is the log from the commit of package python-reno for openSUSE:Factory checked in at 2016-08-26 23:17:52 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-reno (Old) and /work/SRC/openSUSE:Factory/.python-reno.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-reno" Changes: -------- --- /work/SRC/openSUSE:Factory/python-reno/python-reno.changes 2016-06-07 23:49:31.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.python-reno.new/python-reno.changes 2016-08-26 23:17:59.000000000 +0200 @@ -1,0 +2,17 @@ +Thu Aug 25 12:54:11 UTC 2016 - tbecht...@suse.com + +- Use pypi.io as Source url + +------------------------------------------------------------------- +Thu Aug 25 12:09:26 UTC 2016 - tbecht...@suse.com + +- update to 1.8.0: + * ignore all coverage output files + * add warnings for malformated input + * add API for writing the cache file + * report extra files with warnings + * Ignore empty sections in notes + * Clean up oslo-incubator stuff + * [Trivial] Remove executable privilege of doc/source/conf.py + +------------------------------------------------------------------- Old: ---- reno-1.6.2.tar.gz New: ---- reno-1.8.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-reno.spec ++++++ --- /var/tmp/diff_new_pack.hvjvpl/_old 2016-08-26 23:18:02.000000000 +0200 +++ /var/tmp/diff_new_pack.hvjvpl/_new 2016-08-26 23:18:02.000000000 +0200 @@ -17,13 +17,13 @@ Name: python-reno -Version: 1.6.2 +Version: 1.8.0 Release: 0 Summary: RElease NOtes manager License: Apache-2.0 Group: Development/Languages/Python Url: http://www.openstack.org/ -Source: https://pypi.python.org/packages/source/r/reno/reno-%{version}.tar.gz +Source: https://pypi.io/packages/source/r/reno/reno-%{version}.tar.gz BuildRequires: python-Babel BuildRequires: python-PyYAML BuildRequires: python-devel ++++++ reno-1.6.2.tar.gz -> reno-1.8.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/AUTHORS new/reno-1.8.0/AUTHORS --- old/reno-1.6.2/AUTHORS 2016-04-07 10:37:22.000000000 +0200 +++ new/reno-1.8.0/AUTHORS 2016-06-23 20:25:20.000000000 +0200 @@ -1,7 +1,10 @@ Brant Knudson <bknud...@us.ibm.com> +ChangBo Guo(gcb) <eric....@easystack.cn> +Clint Byrum <cl...@fewbar.com> Doug Hellmann <d...@doughellmann.com> Graham Hayes <graham.ha...@hpe.com> Ian Cordasco <graffatcolmin...@gmail.com> Louis Taylor <lo...@kragniz.eu> Mike Perez <thin...@gmail.com> Monty Taylor <mord...@inaugust.com> +ZhiQiang Fan <aji.zq...@gmail.com> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/ChangeLog new/reno-1.8.0/ChangeLog --- old/reno-1.6.2/ChangeLog 2016-04-07 10:37:22.000000000 +0200 +++ new/reno-1.8.0/ChangeLog 2016-06-23 20:25:20.000000000 +0200 @@ -1,6 +1,21 @@ CHANGES ======= +1.8.0 +----- + +* ignore all coverage output files +* add warnings for malformated input +* add API for writing the cache file +* report extra files with warnings + +1.7.0 +----- + +* Ignore empty sections in notes +* Clean up oslo-incubator stuff +* [Trivial] Remove executable privilege of doc/source/conf.py + 1.6.2 ----- @@ -10,6 +25,9 @@ ----- * handle deleted notes properly +* make the cache command write to a file by default +* use the cache file instead of scanner when possible +* add 'cache' command to write a cache file * refactor argument buildup to make it more reusable * improve test coverage * always show coverage report for test runs diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/PKG-INFO new/reno-1.8.0/PKG-INFO --- old/reno-1.6.2/PKG-INFO 2016-04-07 10:37:23.000000000 +0200 +++ new/reno-1.8.0/PKG-INFO 2016-06-23 20:25:20.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: reno -Version: 1.6.2 +Version: 1.8.0 Summary: RElease NOtes manager Home-page: http://www.openstack.org/ Author: OpenStack diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/openstack-common.conf new/reno-1.8.0/openstack-common.conf --- old/reno-1.6.2/openstack-common.conf 2016-04-07 10:35:17.000000000 +0200 +++ new/reno-1.8.0/openstack-common.conf 1970-01-01 01:00:00.000000000 +0100 @@ -1,6 +0,0 @@ -[DEFAULT] - -# The list of modules to copy from oslo-incubator.git - -# The base module to hold the copy of openstack.common -base=reno diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/reno/cache.py new/reno-1.8.0/reno/cache.py --- old/reno-1.6.2/reno/cache.py 1970-01-01 01:00:00.000000000 +0100 +++ new/reno-1.8.0/reno/cache.py 2016-06-23 20:23:20.000000000 +0200 @@ -0,0 +1,124 @@ +# 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. + +import os +import sys + +from reno import loader +from reno import scanner +from reno import utils + +import yaml + + +def build_cache_db(reporoot, notesdir, branch, collapse_pre_releases, + versions_to_include, earliest_version): + notes = scanner.get_notes_by_version( + reporoot, notesdir, branch, + collapse_pre_releases=collapse_pre_releases, + earliest_version=earliest_version, + ) + + # Default to including all versions returned by the scanner. + if not versions_to_include: + versions_to_include = list(notes.keys()) + + # Build a cache data structure including the file contents as well + # as the basic data returned by the scanner. + file_contents = {} + for version in versions_to_include: + for filename, sha in notes[version]: + body = scanner.get_file_at_commit( + reporoot, + filename, + sha, + ) + # We want to save the contents of the file, which is YAML, + # inside another YAML file. That looks terribly ugly with + # all of the escapes needed to format it properly as + # embedded YAML, so parse the input and convert it to a + # data structure that can be serialized cleanly. + y = yaml.safe_load(body) + file_contents[filename] = y + + cache = { + 'notes': [ + {'version': k, 'files': v} + for k, v in notes.items() + ], + 'file-contents': file_contents, + } + return cache + + +def write_cache_db(reporoot, notesdir, branch, collapse_pre_releases, + versions_to_include, earliest_version, + outfilename=None): + """Create a cache database file for the release notes data. + + Build the cache database from scanning the project history and + write it to a file within the project. + + By default, the data is written to the same file the scanner will + try to read when it cannot look at the git history. If outfilename + is given and is '-' the data is written to stdout + instead. Otherwise, if outfilename is given, the data overwrites + the named file. + + """ + if outfilename == '-': + stream = sys.stdout + close_stream = False + elif outfilename: + stream = open(outfilename, 'w') + close_stream = True + else: + outfilename = loader.get_cache_filename(reporoot, notesdir) + if not os.path.exists(os.path.dirname(outfilename)): + os.makedirs(os.path.dirname(outfilename)) + stream = open(outfilename, 'w') + close_stream = True + try: + cache = build_cache_db( + reporoot=reporoot, + notesdir=notesdir, + branch=branch, + collapse_pre_releases=collapse_pre_releases, + versions_to_include=versions_to_include, + earliest_version=earliest_version, + ) + yaml.safe_dump( + cache, + stream, + allow_unicode=True, + explicit_start=True, + encoding='utf-8', + ) + finally: + if close_stream: + stream.close() + + +def cache_cmd(args): + "Generates a release notes cache" + reporoot = args.reporoot.rstrip('/') + '/' + notesdir = utils.get_notes_dir(args) + write_cache_db( + reporoot=reporoot, + notesdir=notesdir, + branch=args.branch, + collapse_pre_releases=args.collapse_pre_releases, + versions_to_include=args.version, + earliest_version=args.earliest_version, + outfilename=args.output, + ) + return diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/reno/formatter.py new/reno-1.8.0/reno/formatter.py --- old/reno-1.6.2/reno/formatter.py 2016-04-07 10:35:17.000000000 +0200 +++ new/reno-1.8.0/reno/formatter.py 2016-06-23 20:23:19.000000000 +0200 @@ -12,10 +12,6 @@ from __future__ import print_function -from reno import scanner - -import yaml - _SECTION_ORDER = [ ('features', 'New Features'), @@ -41,7 +37,7 @@ ]) + '\n' -def format_report(reporoot, scanner_output, versions_to_include, title=None): +def format_report(loader, versions_to_include, title=None): report = [] if title: report.append('=' * len(title)) @@ -52,14 +48,9 @@ # Read all of the notes files. file_contents = {} for version in versions_to_include: - for filename, sha in scanner_output[version]: - body = scanner.get_file_at_commit( - reporoot, - filename, - sha, - ) - y = yaml.safe_load(body) - file_contents[filename] = y + for filename, sha in loader[version]: + body = loader.parse_note_file(filename, sha) + file_contents[filename] = body for version in versions_to_include: report.append(version) @@ -67,7 +58,7 @@ report.append('') # Add the preludes. - notefiles = scanner_output[version] + notefiles = loader[version] for n, sha in notefiles: if 'prelude' in file_contents[n]: report.append(file_contents[n]['prelude']) @@ -77,6 +68,7 @@ notes = [ n for fn, sha in notefiles + if file_contents[fn].get(section_name) for n in file_contents[fn].get(section_name, []) ] if notes: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/reno/lister.py new/reno-1.8.0/reno/lister.py --- old/reno-1.6.2/reno/lister.py 2016-04-07 10:35:17.000000000 +0200 +++ new/reno-1.8.0/reno/lister.py 2016-06-23 20:23:19.000000000 +0200 @@ -14,7 +14,7 @@ import logging -from reno import scanner +from reno import loader from reno import utils LOG = logging.getLogger(__name__) @@ -26,17 +26,19 @@ reporoot = args.reporoot.rstrip('/') + '/' notesdir = utils.get_notes_dir(args) collapse = args.collapse_pre_releases - notes = scanner.get_notes_by_version( - reporoot, notesdir, args.branch, + ldr = loader.Loader( + reporoot=reporoot, + notesdir=notesdir, + branch=args.branch, collapse_pre_releases=collapse, earliest_version=args.earliest_version, ) if args.version: versions = args.version else: - versions = notes.keys() + versions = ldr.versions for version in versions: - notefiles = notes[version] + notefiles = ldr[version] print(version) for n, sha in notefiles: if n.startswith(reporoot): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/reno/loader.py new/reno-1.8.0/reno/loader.py --- old/reno-1.6.2/reno/loader.py 1970-01-01 01:00:00.000000000 +0100 +++ new/reno-1.8.0/reno/loader.py 2016-06-23 20:23:20.000000000 +0200 @@ -0,0 +1,145 @@ +# 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. + +import logging +import os.path + +from reno import scanner + +import six +import yaml + +LOG = logging.getLogger(__name__) + + +def get_cache_filename(reporoot, notesdir): + return os.path.join(reporoot, notesdir, 'reno.cache') + + +class Loader(object): + "Load the release notes for a given repository." + + def __init__(self, reporoot, notesdir, branch=None, + collapse_pre_releases=True, + earliest_version=None, + ignore_cache=False): + """Initialize a Loader. + + The versions are presented in reverse chronological order. + + Notes files are associated with the earliest version for which + they were available, regardless of whether they changed later. + + :param reporoot: Path to the root of the git repository. + :type reporoot: str + :param notesdir: The directory under *reporoot* with the release notes. + :type notesdir: str + :param branch: The name of the branch to scan. Defaults to current. + :type branch: str + :param collapse_pre_releases: When true, merge pre-release versions + into the final release, if it is present. + :type collapse_pre_releases: bool + :param earliest_version: The oldest version to include. + :type earliest_version: str + :param ignore_cache: Do not load a cache file if it is present. + :type ignore_cache: bool + + """ + self._reporoot = reporoot + self._notesdir = notesdir + self._branch = branch + self._collapse_pre_releases = collapse_pre_releases + self._earliest_version = earliest_version + self._ignore_cache = ignore_cache + + self._cache = None + self._scanner_output = None + self._cache_filename = get_cache_filename(reporoot, notesdir) + + self._load_data() + + def _load_data(self): + cache_file_exists = os.path.exists(self._cache_filename) + + if self._ignore_cache and cache_file_exists: + LOG.debug('ignoring cache file %s', self._cache_filename) + + if (not self._ignore_cache) and cache_file_exists: + with open(self._cache_filename, 'r') as f: + self._cache = yaml.safe_load(f.read()) + # Save the cached scanner output to the same attribute + # it would be in if we had loaded it "live". This + # simplifies some of the logic in the other methods. + self._scanner_output = { + n['version']: n['files'] + for n in self._cache['notes'] + } + else: + self._scanner_output = scanner.get_notes_by_version( + reporoot=self._reporoot, + notesdir=self._notesdir, + branch=self._branch, + collapse_pre_releases=self._collapse_pre_releases, + earliest_version=self._earliest_version, + ) + + @property + def versions(self): + "A list of all of the versions found." + return list(self._scanner_output.keys()) + + def __getitem__(self, version): + "Return data about the files that should go into a given version." + return self._scanner_output[version] + + def parse_note_file(self, filename, sha): + """Return the data structure encoded in the note file. + + Emit warnings for content that does not look valid in some + way, but return it anway for backwards-compatibility. + + """ + if self._cache: + content = self._cache['file-contents'][filename] + else: + body = scanner.get_file_at_commit(self._reporoot, filename, sha) + content = yaml.safe_load(body) + + for section_name, section_content in content.items(): + if section_name == 'prelude': + if not isinstance(section_content, six.string_types): + LOG.warning( + ('The prelude section of %s ' + 'does not parse as a single string. ' + 'Is the YAML input escaped properly?') % + filename, + ) + else: + if not isinstance(section_content, list): + LOG.warning( + ('The %s section of %s ' + 'does not parse as a list of strings. ' + 'Is the YAML input escaped properly?') % ( + section_name, filename), + ) + else: + for item in section_content: + if not isinstance(item, six.string_types): + LOG.warning( + ('The item %r in the %s section of %s ' + 'parses as a %s instead of a string. ' + 'Is the YAML input escaped properly?' + ) % (item, section_name, + filename, type(item)), + ) + + return content diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/reno/main.py new/reno-1.8.0/reno/main.py --- old/reno-1.6.2/reno/main.py 2016-04-07 10:35:17.000000000 +0200 +++ new/reno-1.8.0/reno/main.py 2016-06-23 20:23:19.000000000 +0200 @@ -14,6 +14,7 @@ import logging import sys +from reno import cache from reno import create from reno import defaults from reno import lister @@ -38,6 +39,10 @@ (('--earliest-version',), dict(default=None, help='stop when this version is reached in the history')), + (('--ignore-cache',), + dict(default=False, + action='store_true', + help='if there is a cache file present, do not use it')), ] @@ -111,6 +116,24 @@ _build_query_arg_group(do_report) do_report.set_defaults(func=report.report_cmd) + do_cache = subparsers.add_parser( + 'cache', + help='generate release notes cache', + ) + do_cache.add_argument( + 'reporoot', + help='root of the git repository', + ) + do_cache.add_argument( + '--output', '-o', + default=None, + help=('output filename, ' + 'defaults to the cache file within the notesdir, ' + 'use "-" for stdout'), + ) + _build_query_arg_group(do_cache) + do_cache.set_defaults(func=cache.cache_cmd) + args = parser.parse_args() logging.basicConfig( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/reno/report.py new/reno-1.8.0/reno/report.py --- old/reno-1.6.2/reno/report.py 2016-04-07 10:35:17.000000000 +0200 +++ new/reno-1.8.0/reno/report.py 2016-06-23 20:23:19.000000000 +0200 @@ -13,7 +13,7 @@ from __future__ import print_function from reno import formatter -from reno import scanner +from reno import loader from reno import utils @@ -22,18 +22,19 @@ reporoot = args.reporoot.rstrip('/') + '/' notesdir = utils.get_notes_dir(args) collapse = args.collapse_pre_releases - notes = scanner.get_notes_by_version( - reporoot, notesdir, args.branch, + ldr = loader.Loader( + reporoot=reporoot, + notesdir=notesdir, + branch=args.branch, collapse_pre_releases=collapse, earliest_version=args.earliest_version, ) if args.version: versions = args.version else: - versions = notes.keys() + versions = ldr.versions text = formatter.format_report( - reporoot, - notes, + ldr, versions, title='Release Notes', ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/reno/scanner.py new/reno-1.8.0/reno/scanner.py --- old/reno-1.6.2/reno/scanner.py 2016-04-07 10:35:17.000000000 +0200 +++ new/reno-1.8.0/reno/scanner.py 2016-06-23 20:23:19.000000000 +0200 @@ -233,11 +233,12 @@ # files. Even if this list ends up empty, we continue doing # the other processing so that we record all of the known # versions. - filenames = [ - f - for f in hlines[2:] - if fnmatch.fnmatch(f, notesdir + '/*.yaml') - ] + filenames = [] + for f in hlines[2:]: + if fnmatch.fnmatch(f, notesdir + '/*.yaml'): + filenames.append(f) + elif fnmatch.fnmatch(f, notesdir + '/*'): + LOG.warn('found and ignored extra file %s', f) # If there are no tags in this block, assume the most recently # seen version. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/reno/sphinxext.py new/reno-1.8.0/reno/sphinxext.py --- old/reno-1.6.2/reno/sphinxext.py 2016-04-07 10:35:18.000000000 +0200 +++ new/reno-1.8.0/reno/sphinxext.py 2016-06-23 20:23:19.000000000 +0200 @@ -14,7 +14,7 @@ from reno import defaults from reno import formatter -from reno import scanner +from reno import loader from docutils import nodes from docutils.parsers import rst @@ -61,8 +61,10 @@ info('scanning %s for %s release notes' % (os.path.join(reporoot, notesdir), branch or 'current branch')) - notes = scanner.get_notes_by_version( - reporoot, notesdir, branch, + ldr = loader.Loader( + reporoot=reporoot, + notesdir=notesdir, + branch=branch, collapse_pre_releases=collapse, earliest_version=earliest_version, ) @@ -72,10 +74,9 @@ for v in version_opt.split(',') ] else: - versions = notes.keys() + versions = ldr.versions text = formatter.format_report( - reporoot, - notes, + ldr, versions, title=title, ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/reno/tests/base.py new/reno-1.8.0/reno/tests/base.py --- old/reno-1.6.2/reno/tests/base.py 2016-04-07 10:35:17.000000000 +0200 +++ new/reno-1.8.0/reno/tests/base.py 2016-06-23 20:23:20.000000000 +0200 @@ -15,9 +15,19 @@ # License for the specific language governing permissions and limitations # under the License. -from oslotest import base +import fixtures +import testtools -class TestCase(base.BaseTestCase): +class TestCase(testtools.TestCase): """Test case base class for all unit tests.""" + + def setUp(self): + super(TestCase, self).setUp() + self._stdout_fixture = fixtures.StringStream('stdout') + self.stdout = self.useFixture(self._stdout_fixture).stream + self.useFixture(fixtures.MonkeyPatch('sys.stdout', self.stdout)) + self._stderr_fixture = fixtures.StringStream('stderr') + self.stderr = self.useFixture(self._stderr_fixture).stream + self.useFixture(fixtures.MonkeyPatch('sys.stderr', self.stderr)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/reno/tests/test_cache.py new/reno-1.8.0/reno/tests/test_cache.py --- old/reno-1.6.2/reno/tests/test_cache.py 1970-01-01 01:00:00.000000000 +0100 +++ new/reno-1.8.0/reno/tests/test_cache.py 2016-06-23 20:23:19.000000000 +0200 @@ -0,0 +1,89 @@ +# -*- 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. + +import textwrap + +from reno import cache +from reno.tests import base + +from oslotest import mockpatch + +import mock + + +class TestCache(base.TestCase): + + scanner_output = { + '0.0.0': [('note1', 'shaA')], + '1.0.0': [('note2', 'shaB'), ('note3', 'shaC')], + } + + note_bodies = { + 'note1': textwrap.dedent(""" + prelude: > + This is the prelude. + """), + 'note2': textwrap.dedent(""" + issues: + - This is the first issue. + - This is the second issue. + """), + 'note3': textwrap.dedent(""" + features: + - We added a feature! + """) + } + + def _get_note_body(self, reporoot, filename, sha): + return self.note_bodies.get(filename, '') + + def setUp(self): + super(TestCache, self).setUp() + self.useFixture( + mockpatch.Patch('reno.scanner.get_file_at_commit', + new=self._get_note_body) + ) + + def test_build_cache_db(self): + with mock.patch('reno.scanner.get_notes_by_version') as gnbv: + gnbv.return_value = self.scanner_output + db = cache.build_cache_db( + reporoot=None, + notesdir=None, + branch=None, + collapse_pre_releases=True, + versions_to_include=[], + earliest_version=None, + ) + expected = { + 'notes': [ + {'version': k, 'files': v} + for k, v in self.scanner_output.items() + ], + 'file-contents': { + 'note1': { + 'prelude': 'This is the prelude.\n', + }, + 'note2': { + 'issues': [ + 'This is the first issue.', + 'This is the second issue.', + ], + }, + 'note3': { + 'features': ['We added a feature!'], + }, + }, + } + self.assertEqual(expected, db) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/reno/tests/test_formatter.py new/reno-1.8.0/reno/tests/test_formatter.py --- old/reno-1.6.2/reno/tests/test_formatter.py 2016-04-07 10:35:17.000000000 +0200 +++ new/reno-1.8.0/reno/tests/test_formatter.py 2016-06-23 20:23:19.000000000 +0200 @@ -12,12 +12,11 @@ # License for the specific language governing permissions and limitations # under the License. -import textwrap - from reno import formatter +from reno import loader from reno.tests import base -from oslotest import mockpatch +import mock class TestFormatter(base.TestCase): @@ -30,19 +29,21 @@ versions = ['0.0.0', '1.0.0'] note_bodies = { - 'note1': textwrap.dedent(""" - prelude: > - This is the prelude. - """), - 'note2': textwrap.dedent(""" - issues: - - This is the first issue. - - This is the second issue. - """), - 'note3': textwrap.dedent(""" - features: - - We added a feature! - """) + 'note1': { + 'prelude': 'This is the prelude.', + }, + 'note2': { + 'issues': [ + 'This is the first issue.', + 'This is the second issue.', + ], + }, + 'note3': { + 'features': [ + 'We added a feature!', + ], + 'upgrade': None, + }, } def _get_note_body(self, reporoot, filename, sha): @@ -50,15 +51,26 @@ def setUp(self): super(TestFormatter, self).setUp() - self.useFixture( - mockpatch.Patch('reno.scanner.get_file_at_commit', - new=self._get_note_body) - ) + + def _load(ldr): + ldr._scanner_output = self.scanner_output + ldr._cache = { + 'file-contents': self.note_bodies + } + + with mock.patch('reno.loader.Loader._load_data', _load): + self.ldr = loader.Loader( + reporoot='reporoot', + notesdir='notesdir', + branch=None, + collapse_pre_releases=None, + earliest_version=None, + ignore_cache=False, + ) def test_with_title(self): result = formatter.format_report( - reporoot=None, - scanner_output=self.scanner_output, + loader=self.ldr, versions_to_include=self.versions, title='This is the title', ) @@ -66,8 +78,7 @@ def test_versions(self): result = formatter.format_report( - reporoot=None, - scanner_output=self.scanner_output, + loader=self.ldr, versions_to_include=self.versions, title='This is the title', ) @@ -76,8 +87,7 @@ def test_without_title(self): result = formatter.format_report( - reporoot=None, - scanner_output=self.scanner_output, + loader=self.ldr, versions_to_include=self.versions, title=None, ) @@ -85,8 +95,7 @@ def test_section_order(self): result = formatter.format_report( - reporoot=None, - scanner_output=self.scanner_output, + loader=self.ldr, versions_to_include=self.versions, title=None, ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/reno/tests/test_loader.py new/reno-1.8.0/reno/tests/test_loader.py --- old/reno-1.6.2/reno/tests/test_loader.py 1970-01-01 01:00:00.000000000 +0100 +++ new/reno-1.8.0/reno/tests/test_loader.py 2016-06-23 20:23:20.000000000 +0200 @@ -0,0 +1,92 @@ +# -*- 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. + +import logging +import textwrap + +from reno import loader +from reno.tests import base + +import fixtures +import mock +import six +import yaml + + +class TestValidate(base.TestCase): + + scanner_output = { + '0.0.0': [('note', 'shaA')], + } + + versions = ['0.0.0'] + + def setUp(self): + super(TestValidate, self).setUp() + self.logger = self.useFixture( + fixtures.FakeLogger( + format='%(message)s', + level=logging.WARNING, + ) + ) + + def _make_loader(self, note_bodies): + def _load(ldr): + ldr._scanner_output = self.scanner_output + ldr._cache = { + 'file-contents': {'note1': note_bodies}, + } + + with mock.patch('reno.loader.Loader._load_data', _load): + return loader.Loader( + reporoot='reporoot', + notesdir='notesdir', + branch=None, + collapse_pre_releases=None, + earliest_version=None, + ignore_cache=False, + ) + + def test_prelude_list(self): + note_bodies = yaml.safe_load(textwrap.dedent(''' + prelude: + - This is the first comment. + - This is a second. + ''')) + self.assertIsInstance(note_bodies['prelude'], list) + ldr = self._make_loader(note_bodies) + ldr.parse_note_file('note1', None) + self.assertIn('prelude', self.logger.output) + + def test_non_prelude_single_string(self): + note_bodies = yaml.safe_load(textwrap.dedent(''' + issues: | + This is a single string. + ''')) + print(type(note_bodies['issues'])) + self.assertIsInstance(note_bodies['issues'], six.string_types) + ldr = self._make_loader(note_bodies) + ldr.parse_note_file('note1', None) + self.assertIn('list of strings', self.logger.output) + + def test_note_with_colon_as_dict(self): + note_bodies = yaml.safe_load(textwrap.dedent(''' + issues: + - This is the first issue. + - dict: This is parsed as a dictionary. + ''')) + self.assertIsInstance(note_bodies['issues'][-1], dict) + ldr = self._make_loader(note_bodies) + ldr.parse_note_file('note1', None) + self.assertIn('dict', self.logger.output) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/reno.egg-info/PKG-INFO new/reno-1.8.0/reno.egg-info/PKG-INFO --- old/reno-1.6.2/reno.egg-info/PKG-INFO 2016-04-07 10:37:22.000000000 +0200 +++ new/reno-1.8.0/reno.egg-info/PKG-INFO 2016-06-23 20:25:20.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: reno -Version: 1.6.2 +Version: 1.8.0 Summary: RElease NOtes manager Home-page: http://www.openstack.org/ Author: OpenStack diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/reno.egg-info/SOURCES.txt new/reno-1.8.0/reno.egg-info/SOURCES.txt --- old/reno-1.6.2/reno.egg-info/SOURCES.txt 2016-04-07 10:37:23.000000000 +0200 +++ new/reno-1.8.0/reno.egg-info/SOURCES.txt 2016-06-23 20:25:20.000000000 +0200 @@ -9,7 +9,6 @@ MANIFEST.in README.rst babel.cfg -openstack-common.conf requirements.txt setup.cfg setup.py @@ -39,10 +38,12 @@ releasenotes/notes/sphinx-extension-4a092b4102370246.yaml releasenotes/notes/support-multi-line-notes-328853d8d596fd64.yaml reno/__init__.py +reno/cache.py reno/create.py reno/defaults.py reno/formatter.py reno/lister.py +reno/loader.py reno/main.py reno/report.py reno/scanner.py @@ -58,7 +59,9 @@ reno.egg-info/top_level.txt reno/tests/__init__.py reno/tests/base.py +reno/tests/test_cache.py reno/tests/test_create.py reno/tests/test_formatter.py +reno/tests/test_loader.py reno/tests/test_scanner.py reno/tests/test_utils.py \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/reno.egg-info/pbr.json new/reno-1.8.0/reno.egg-info/pbr.json --- old/reno-1.6.2/reno.egg-info/pbr.json 2016-04-07 10:37:22.000000000 +0200 +++ new/reno-1.8.0/reno.egg-info/pbr.json 2016-06-23 20:25:20.000000000 +0200 @@ -1 +1 @@ -{"git_version": "11a2b7a", "is_release": true} \ No newline at end of file +{"git_version": "50c6ed3", "is_release": true} \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/setup.cfg new/reno-1.8.0/setup.cfg --- old/reno-1.6.2/setup.cfg 2016-04-07 10:37:23.000000000 +0200 +++ new/reno-1.8.0/setup.cfg 2016-06-23 20:25:20.000000000 +0200 @@ -54,7 +54,7 @@ output_file = reno/locale/reno.pot [egg_info] -tag_date = 0 tag_build = +tag_date = 0 tag_svn_revision = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/reno-1.6.2/tox.ini new/reno-1.8.0/tox.ini --- old/reno-1.6.2/tox.ini 2016-04-07 10:35:17.000000000 +0200 +++ new/reno-1.8.0/tox.ini 2016-06-23 20:23:19.000000000 +0200 @@ -36,4 +36,4 @@ show-source = True ignore = E123,E125 builtins = _ -exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build +exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build