summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthon van der Neut <anthon@mnt.org>2017-06-10 22:59:06 +0200
committerAnthon van der Neut <anthon@mnt.org>2017-06-10 22:59:06 +0200
commit0a26480139476afdd167bc6a900551463da92079 (patch)
tree4beeeb42c594498fae05bc46bc0ae0f0659e05d8
parent63929c2efaef82fa283983d989a08a79cff2e99a (diff)
downloadruamel.yaml-0a26480139476afdd167bc6a900551463da92079.tar.gz
top-level folded/literal scalar col-00.15.6
-rw-r--r--CHANGES4
-rw-r--r--README.rst5
-rw-r--r--__init__.py4
-rw-r--r--_test/roundtrip.py10
-rw-r--r--_test/test_literal.py155
-rw-r--r--compat.py1
-rw-r--r--main.py1
-rw-r--r--reader.py1
-rw-r--r--resolver.py7
-rw-r--r--scanner.py20
10 files changed, 198 insertions, 10 deletions
diff --git a/CHANGES b/CHANGES
index 6a0481a..a401d38 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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.
diff --git a/README.rst b/README.rst
index 6422b7c..89ee836 100644
--- a/README.rst
+++ b/README.rst
@@ -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'
diff --git a/compat.py b/compat.py
index 7f3434f..41c52e7 100644
--- a/compat.py
+++ b/compat.py
@@ -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
diff --git a/main.py b/main.py
index faa3002..c238d2d 100644
--- a/main.py
+++ b/main.py
@@ -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):
diff --git a/reader.py b/reader.py
index b28befc..d200031 100644
--- a/reader.py
+++ b/reader.py
@@ -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
diff --git a/scanner.py b/scanner.py
index 08b2ae0..be4c9e6 100644
--- a/scanner.py
+++ b/scanner.py
@@ -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''