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


Reply via email to