From bc3d1241dd842dcfb8797747b4083ba93ffd33cb Mon Sep 17 00:00:00 2001 From: Doug Hellmann Date: Mon, 5 Jun 2017 15:33:16 -0400 Subject: [PATCH] allow release notes sections to be single strings Release notes entries may now be made up of single strings. This simplifies formatting for smaller notes, and eliminates a class of errors associated with escaping reStructuredText inside YAML lists. Change-Id: I7f2fb2d2fd16f49e7ee061582df7bcdd4116f215 Signed-off-by: Doug Hellmann --- .../add-complex-example-6b5927c246456896.yaml | 3 +++ .../flexible-formatting-31c8de2599d3637d.yaml | 5 +++++ reno/loader.py | 14 +++++++++++--- reno/tests/test_loader.py | 6 +++--- 4 files changed, 22 insertions(+), 6 deletions(-) create mode 100644 releasenotes/notes/flexible-formatting-31c8de2599d3637d.yaml diff --git a/examples/notes/add-complex-example-6b5927c246456896.yaml b/examples/notes/add-complex-example-6b5927c246456896.yaml index dfd9a0c..a104287 100644 --- a/examples/notes/add-complex-example-6b5927c246456896.yaml +++ b/examples/notes/add-complex-example-6b5927c246456896.yaml @@ -26,3 +26,6 @@ other: This example is also rendered correctly on multiple lines as a pre-formatted block. +features: + This note is a simple string, and does not retain its + formatting when it is rendered in HTML. diff --git a/releasenotes/notes/flexible-formatting-31c8de2599d3637d.yaml b/releasenotes/notes/flexible-formatting-31c8de2599d3637d.yaml new file mode 100644 index 0000000..a761130 --- /dev/null +++ b/releasenotes/notes/flexible-formatting-31c8de2599d3637d.yaml @@ -0,0 +1,5 @@ +--- +features: + Release notes entries may now be made up of single strings. This + simplifies formatting for smaller notes, and eliminates a class of + errors associated with escaping reStructuredText inside YAML lists. diff --git a/reno/loader.py b/reno/loader.py index f11196e..3df4988 100644 --- a/reno/loader.py +++ b/reno/loader.py @@ -101,6 +101,8 @@ class Loader(object): body = self._scanner.get_file_at_commit(filename, sha) content = yaml.safe_load(body) + cleaned_content = {} + for section_name, section_content in content.items(): if section_name == 'prelude': if not isinstance(section_content, six.string_types): @@ -111,10 +113,15 @@ class Loader(object): filename, ) else: - if not isinstance(section_content, list): + if isinstance(section_content, six.string_types): + # A single string is OK, but wrap it with a list + # so the rest of the code can treat the data model + # consistently. + section_content = [section_content] + elif not isinstance(section_content, list): LOG.warning( ('The %s section of %s ' - 'does not parse as a list of strings. ' + 'does not parse as a string or list of strings. ' 'Is the YAML input escaped properly?') % ( section_name, filename), ) @@ -128,5 +135,6 @@ class Loader(object): ) % (item, section_name, filename, type(item)), ) + cleaned_content[section_name] = section_content - return content + return cleaned_content diff --git a/reno/tests/test_loader.py b/reno/tests/test_loader.py index 8ca9cf8..33b6d28 100644 --- a/reno/tests/test_loader.py +++ b/reno/tests/test_loader.py @@ -67,7 +67,7 @@ class TestValidate(base.TestCase): ldr.parse_note_file('note1', None) self.assertIn('prelude', self.logger.output) - def test_non_prelude_single_string(self): + def test_non_prelude_single_string_converted_to_list(self): note_bodies = yaml.safe_load(textwrap.dedent(''' issues: | This is a single string. @@ -75,8 +75,8 @@ class TestValidate(base.TestCase): 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) + parse_results = ldr.parse_note_file('note1', None) + self.assertIsInstance(parse_results['issues'], list) def test_note_with_colon_as_dict(self): note_bodies = yaml.safe_load(textwrap.dedent('''