diff options
author | Anthon van der Neut <anthon@mnt.org> | 2023-05-09 19:57:35 +0200 |
---|---|---|
committer | Anthon van der Neut <anthon@mnt.org> | 2023-05-09 19:57:35 +0200 |
commit | accf77e5f97bd55fe62c67b3cc9bfdaad15dd6f3 (patch) | |
tree | c67a1b907c7b97d55dab46268b8b27438cb18bbe | |
parent | 31986190f69f68b454260f8c9a04d8697a476d15 (diff) | |
download | ruamel.yaml-accf77e5f97bd55fe62c67b3cc9bfdaad15dd6f3.tar.gz |
fix issue: 4590.17.25
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | README.rst | 8 | ||||
-rw-r--r-- | __init__.py | 6 | ||||
-rw-r--r-- | _doc/_static/pypi.svg | 2 | ||||
-rw-r--r-- | _test/test_issues.py | 48 | ||||
-rw-r--r-- | emitter.py | 60 |
6 files changed, 95 insertions, 33 deletions
@@ -1,3 +1,7 @@ +[0, 17, 25]: 2023-05-09 + - fix for regression while dumping wrapped strings with too many backslashes removed + (issue 459, reported by `Lele Gaifax <https://sourceforge.net/u/lele/profile/>`__) + [0, 17, 24]: 2023-05-06 - rewrite of ``CommentedMap.insert()``. If you have a merge key in the YAML document for the mapping you insert to, the position value should @@ -4,8 +4,8 @@ ruamel.yaml ``ruamel.yaml`` is a YAML 1.2 loader/dumper package for Python. -:version: 0.17.24 -:updated: 2023-05-06 +:version: 0.17.25 +:updated: 2023-05-09 :documentation: http://yaml.readthedocs.io :repository: https://sourceforge.net/projects/ruamel-yaml/ :pypi: https://pypi.org/project/ruamel.yaml/ @@ -61,6 +61,10 @@ ChangeLog .. should insert NEXT: at the beginning of line for next key (with empty line) +0.17.25 (2023-05-09): + - fix for regression while dumping wrapped strings with too many backslashes removed + (issue 459, reported by `Lele Gaifax <https://sourceforge.net/u/lele/profile/>`__) + 0.17.24 (2023-05-06): - rewrite of ``CommentedMap.insert()``. If you have a merge key in the YAML document for the mapping you insert to, the position value should diff --git a/__init__.py b/__init__.py index d548852..c676d16 100644 --- a/__init__.py +++ b/__init__.py @@ -5,9 +5,9 @@ if False: # MYPY _package_data = dict( full_package_name='ruamel.yaml', - version_info=(0, 17, 24), - __version__='0.17.24', - version_timestamp='2023-05-06 12:28:17', + version_info=(0, 17, 25), + __version__='0.17.25', + version_timestamp='2023-05-09 19:56:50', 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/_doc/_static/pypi.svg b/_doc/_static/pypi.svg index 1784380..b5c8870 100644 --- a/_doc/_static/pypi.svg +++ b/_doc/_static/pypi.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="86" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="86" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h33v20H0z"/><path fill="#007ec6" d="M33 0h53v20H33z"/><path fill="url(#b)" d="M0 0h86v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"> <text x="175" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="230">pypi</text><text x="175" y="140" transform="scale(.1)" textLength="230">pypi</text><text x="585" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">0.17.24</text><text x="585" y="140" transform="scale(.1)" textLength="430">0.17.24</text></g> </svg> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="86" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="a"><rect width="86" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#a)"><path fill="#555" d="M0 0h33v20H0z"/><path fill="#007ec6" d="M33 0h53v20H33z"/><path fill="url(#b)" d="M0 0h86v20H0z"/></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="110"> <text x="175" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="230">pypi</text><text x="175" y="140" transform="scale(.1)" textLength="230">pypi</text><text x="585" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">0.17.25</text><text x="585" y="140" transform="scale(.1)" textLength="430">0.17.25</text></g> </svg> diff --git a/_test/test_issues.py b/_test/test_issues.py index eadf94d..f0a7ede 100644 --- a/_test/test_issues.py +++ b/_test/test_issues.py @@ -957,7 +957,7 @@ class TestIssues: def test_issue_447(self) -> None: from ruamel.yaml import YAML - YAML().load("{\n\t\"FOO\": \"BAR\"\n}") + YAML().load('{\n\t"FOO": "BAR"\n}') def test_issue_449(self) -> None: inp = """\ @@ -1039,11 +1039,55 @@ class TestIssues: yaml = YAML() out_stream = StringIO() - in_string = "a" * 128 + in_string = 'a' * 128 yaml.dump(in_string, out_stream) result = out_stream.getvalue() assert in_string == result.splitlines()[0] + def test_issue_459(self) -> None: + from io import StringIO + from ruamel.yaml import YAML + + MYOBJ = { + 'data': dedent( + """\ + example: "first" + data: + - flag: true + integer: 1 + float: 1.0 + string: "this is a string" + list: + - first + - second + - third + circle: + x: 10cm + y: 10cm + radius: 2.24cm + + - flag: false + integer: 2 + float: 2.0 + string: "this is another string" + list: + - first + - second + - third + circle: + x: 20cm + y: 20cm + radius: 2.24cm + """ + ) + } + yaml = YAML() + yaml.width = 60 + out_stream = StringIO() + yaml.dump([MYOBJ], out_stream) + data = yaml.load(out_stream.getvalue()) + assert data[0]['data'] == MYOBJ['data'] + # @pytest.mark.xfail(strict=True, reason='bla bla', raises=AssertionError) # def test_issue_ xxx(self) -> None: @@ -1350,7 +1350,7 @@ class Emitter: self.write_line_break() if self.requested_indent != 0: self.write_indent() - self.write_indicator(u'"', True) + self.write_indicator('"', True) start = end = 0 while end <= len(text): ch = None @@ -1358,15 +1358,15 @@ class Emitter: ch = text[end] if ( ch is None - or ch in u'"\\\x85\u2028\u2029\uFEFF' + or ch in '"\\\x85\u2028\u2029\uFEFF' or not ( - u'\x20' <= ch <= u'\x7E' + '\x20' <= ch <= '\x7E' or ( self.allow_unicode and ( - (u'\xA0' <= ch <= u'\uD7FF') - or (u'\uE000' <= ch <= u'\uFFFD') - or (u'\U00010000' <= ch <= u'\U0010FFFF') + ('\xA0' <= ch <= '\uD7FF') + or ('\uE000' <= ch <= '\uFFFD') + or ('\U00010000' <= ch <= '\U0010FFFF') ) ) ) @@ -1380,13 +1380,13 @@ class Emitter: start = end if ch is not None: if ch in self.ESCAPE_REPLACEMENTS: - data = u'\\' + self.ESCAPE_REPLACEMENTS[ch] - elif ch <= u'\xFF': - data = u'\\x%02X' % ord(ch) - elif ch <= u'\uFFFF': - data = u'\\u%04X' % ord(ch) + data = '\\' + self.ESCAPE_REPLACEMENTS[ch] + elif ch <= '\xFF': + data = '\\x%02X' % ord(ch) + elif ch <= '\uFFFF': + data = '\\u%04X' % ord(ch) else: - data = u'\\U%08X' % ord(ch) + data = '\\U%08X' % ord(ch) self.column += len(data) if bool(self.encoding): data = data.encode(self.encoding) @@ -1394,18 +1394,26 @@ class Emitter: start = end + 1 if ( 0 < end < len(text) - 1 - and (ch == u' ' or start >= end) + and (ch == ' ' or start >= end) and self.column + (end - start) > self.best_width and split ): # SO https://stackoverflow.com/a/75634614/1307905 # data = text[start:end] + u'\\' # <<< replaced with following six lines - need_backquote = ( - text[end] == u' ' - and (len(text) > end) - and text[end + 1] == u' ' - ) - data = text[start:end] + (u'\\' if need_backquote else u'') + need_backquote = True + if len(text) > end: + space_pos = text.index(' ', end) + try: + if ( + '"' not in text[end:space_pos] + and "'" not in text[end:space_pos] + and text[space_pos + 1] != ' ' + and text[end - 1 : end + 1] != ' ' + ): + need_backquote = False + except IndexError: + pass + data = text[start:end] + ('\\' if need_backquote else '') if start < end: start = end self.column += len(data) @@ -1415,18 +1423,18 @@ class Emitter: self.write_indent() self.whitespace = False self.indention = False - if text[start] == u' ': + if text[start] == ' ': if not need_backquote: # remove leading space it will load from the newline start += 1 # data = u'\\' # <<< replaced with following line - data = u'\\' if need_backquote else u'' + data = '\\' if need_backquote else '' self.column += len(data) if bool(self.encoding): data = data.encode(self.encoding) self.stream.write(data) end += 1 - self.write_indicator(u'"', False) + self.write_indicator('"', False) def determine_block_hints(self, text: Any) -> Any: indent = 0 @@ -1634,9 +1642,11 @@ class Emitter: else: if ch is None or ch in ' \n\x85\u2028\u2029': data = text[start:end] - if (len(data) > self.best_width - and self.indent is not None - and self.column > self.indent): + if ( + len(data) > self.best_width + and self.indent is not None + and self.column > self.indent + ): # words longer than line length get a line of their own self.write_indent() self.column += len(data) |