diff options
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | README.rst | 5 | ||||
-rw-r--r-- | __init__.py | 4 | ||||
-rw-r--r-- | _test/roundtrip.py | 10 | ||||
-rw-r--r-- | _test/test_literal.py | 155 | ||||
-rw-r--r-- | compat.py | 1 | ||||
-rw-r--r-- | main.py | 1 | ||||
-rw-r--r-- | reader.py | 1 | ||||
-rw-r--r-- | resolver.py | 7 | ||||
-rw-r--r-- | scanner.py | 20 |
10 files changed, 198 insertions, 10 deletions
@@ -1,3 +1,7 @@ +[0, 15, 6]: 2017-06-10 + - a set() with duplicate elements now throws error in rt loading + - support for toplevel column zero literal/folded scalar in explicit documents + [0, 15, 5]: 2017-06-08 - repeat `load()` on a single `YAML()` instance would fail. @@ -32,8 +32,9 @@ ChangeLog .. should insert NEXT: at the beginning of line for next key -NEXT: - - a set with duplicate elements now throws error in rt loading +0.15.6 (2017-06-10): + - a set() with duplicate elements now throws error in rt loading + - support for toplevel column zero literal/folded scalar in explicit documents 0.15.5 (2017-06-08): - repeat `load()` on a single `YAML()` instance would fail. diff --git a/__init__.py b/__init__.py index 037bed1..1224815 100644 --- a/__init__.py +++ b/__init__.py @@ -11,8 +11,8 @@ if False: # MYPY _package_data = dict( full_package_name='ruamel.yaml', - version_info=(0, 15, 6, 'dev'), - __version__='0.15.6.dev', + version_info=(0, 15, 6), + __version__='0.15.6', author='Anthon van der Neut', author_email='a.van.der.neut@ruamel.eu', description='ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order', # NOQA diff --git a/_test/roundtrip.py b/_test/roundtrip.py index cea1d81..7540bcd 100644 --- a/_test/roundtrip.py +++ b/_test/roundtrip.py @@ -90,3 +90,13 @@ def round_trip(inp, outp=None, extra=None, intermediate=None, indent=None, version=version) print('roundtrip second round data:\n', res, sep='') assert res == doutp + + +class YAML(ruamel.yaml.YAML): + """auto dedent string parameters on load""" + def load(self, stream): + if isinstance(stream, str): + if stream and stream[0] == '\n': + stream = stream[1:] + stream = textwrap.dedent(stream) + return ruamel.yaml.YAML.load(self, stream) diff --git a/_test/test_literal.py b/_test/test_literal.py new file mode 100644 index 0000000..60bc143 --- /dev/null +++ b/_test/test_literal.py @@ -0,0 +1,155 @@ +# coding: utf-8 +from __future__ import print_function + +import pytest # NOQA + +from roundtrip import YAML + + +""" +YAML 1.0 allowed top level literal style without indentation: + "Usually top level nodes are not indented" (example 4.21 in 4.6.3) +YAML 1.1 is a bit vague but says: + "Regardless of style, scalar content must always be indented by at least one space" + (4.4.3) + "In general, the document’s node is indented as if it has a parent indented at -1 spaces." + (4.3.3) +YAML 1.2 is again clear about top level literal scalar after directive in example 9.5: + +%YAML 1.2 +--- | +%!PS-Adobe-2.0 +... +%YAML1.2 +--- +# Empty +... +""" + + +class TestNoIndent: + def test_top_literal_scalar_indent_example_9_5(self): + yaml = YAML() + s = '%!PS-Adobe-2.0' + d = yaml.load(""" + --- | + {} + """.format(s)) + print(d) + assert d == s + '\n' + + def test_top_literal_scalar_no_indent(self): + yaml = YAML() + s = 'testing123' + d = yaml.load(""" + --- | + {} + """.format(s)) + print(d) + assert d == s + '\n' + + def test_top_literal_scalar_no_indent_1_1(self): + yaml = YAML() + s = 'testing123' + d = yaml.load(""" + %YAML 1.1 + --- | + {} + """.format(s)) + print(d) + assert d == s + '\n' + + def test_top_literal_scalar_no_indent_1_1_old_style(self): + from textwrap import dedent + from ruamel.yaml import safe_load + s = 'testing123' + d = safe_load(dedent(""" + %YAML 1.1 + --- | + {} + """.format(s))) + print(d) + assert d == s + '\n' + + def test_top_literal_scalar_no_indent_1_1_raise(self): + from ruamel.yaml.parser import ParserError + yaml = YAML() + yaml.top_level_block_style_scalar_no_indent_error_1_1 = True + s = 'testing123' + with pytest.raises(ParserError): + yaml.load(""" + %YAML 1.1 + --- | + {} + """.format(s)) + + def test_top_literal_scalar_indent_offset_one(self): + yaml = YAML() + s = 'testing123' + d = yaml.load(""" + --- |1 + {} + """.format(s)) + print(d) + assert d == s + '\n' + + def test_top_literal_scalar_indent_offset_four(self): + yaml = YAML() + s = 'testing123' + d = yaml.load(""" + --- |4 + {} + """.format(s)) + print(d) + assert d == s + '\n' + + def test_top_literal_scalar_indent_offset_two_leading_space(self): + yaml = YAML() + s = ' testing123' + d = yaml.load(""" + --- |4 + {s} + {s} + """.format(s=s)) + print(d) + assert d == (s + '\n')*2 + + def test_top_literal_scalar_no_indent_special(self): + yaml = YAML() + s = '%!PS-Adobe-2.0' + d = yaml.load(""" + --- | + {} + """.format(s)) + print(d) + assert d == s + '\n' + + def test_top_folding_scalar_indent(self): + yaml = YAML() + s = '%!PS-Adobe-2.0' + d = yaml.load(""" + --- > + {} + """.format(s)) + print(d) + assert d == s + '\n' + + def test_top_folding_scalar_no_indent(self): + yaml = YAML() + s = 'testing123' + d = yaml.load(""" + --- > + {} + """.format(s)) + print(d) + assert d == s + '\n' + + def test_top_folding_scalar_no_indent_special(self): + yaml = YAML() + s = '%!PS-Adobe-2.0' + d = yaml.load(""" + --- > + {} + """.format(s)) + print(d) + assert d == s + '\n' @@ -11,6 +11,7 @@ import types if False: # MYPY from typing import Any, Dict, Optional, List, Union, BinaryIO, IO, Text, Tuple # NOQA +_DEFAULT_YAML_VERSION = (1, 2) try: from ruamel.ordereddict import ordereddict @@ -106,6 +106,7 @@ class YAML(object): self.tags = None self.default_style = None self.default_flow_style = None + self.top_level_block_style_scalar_no_indent_error_1_1 = False @property def reader(self): @@ -80,6 +80,7 @@ class Reader(object): self.stream = stream # type: Any # as .read is called def reset_reader(self): + # type: () -> None self.name = None # type: Any self.stream_pointer = 0 self.eof = True diff --git a/resolver.py b/resolver.py index 85125ac..c684d60 100644 --- a/resolver.py +++ b/resolver.py @@ -6,16 +6,15 @@ import re if False: # MYPY from typing import Any, Dict, List, Union # NOQA - from ruamel.yaml.compat import string_types, VersionType # NOQA + from ruamel.yaml.compat import VersionType # NOQA +from ruamel.yaml.compat import string_types, _DEFAULT_YAML_VERSION # NOQA from ruamel.yaml.error import * # NOQA from ruamel.yaml.nodes import * # NOQA __all__ = ['BaseResolver', 'Resolver', 'VersionedResolver'] -_DEFAULT_VERSION = (1, 2) - # resolvers consist of # - a list of applicable version # - a tag @@ -440,5 +439,5 @@ class VersionedResolver(BaseResolver): if version is None: version = self._loader_version if version is None: - version = _DEFAULT_VERSION + version = _DEFAULT_YAML_VERSION return version @@ -36,6 +36,7 @@ from ruamel.yaml.compat import utf8, unichr, PY3, check_anchorname_char if False: # MYPY from typing import Any, Dict, Optional, List, Union, Text # NOQA + from ruamel.yaml.compat import VersionType # NOQA __all__ = ['Scanner', 'RoundTripScanner', 'ScannerError'] @@ -77,6 +78,7 @@ class Scanner(object): self.reset_scanner() def reset_scanner(self): + # type: () -> None # Had we reached the end of the stream? self.done = False @@ -136,6 +138,13 @@ class Scanner(object): self.loader.reader # type: ignore return self.loader._reader # type: ignore + @property + def scanner_processing_version(self): # prefix until un-composited + # type: () -> VersionType + if hasattr(self.loader, 'typ'): + return self.loader.resolver.processing_version # type: ignore + return self.loader.processing_version + # Public methods. def check_token(self, *choices): @@ -1044,12 +1053,19 @@ class Scanner(object): # Determine the indentation level and go to the first non-empty line. min_indent = self.indent+1 - if min_indent < 1: - min_indent = 1 if increment is None: + # no increment and top level, min_indent could be 0 + if min_indent < 1 and \ + (style not in '|>' or ( + self.scanner_processing_version == (1, 1)) and + getattr(self.loader, + 'top_level_block_style_scalar_no_indent_error_1_1', False)): + min_indent = 1 breaks, max_indent, end_mark = self.scan_block_scalar_indentation() indent = max(min_indent, max_indent) else: + if min_indent < 1: + min_indent = 1 indent = min_indent+increment-1 breaks, end_mark = self.scan_block_scalar_breaks(indent) line_break = u'' |