diff options
author | Anthon van der Neut <anthon@mnt.org> | 2016-09-21 10:09:18 +0200 |
---|---|---|
committer | Anthon van der Neut <anthon@mnt.org> | 2016-09-21 10:09:18 +0200 |
commit | e08dd6b761c0b45a486beddcab67389830882b4f (patch) | |
tree | 8eef084d547c32984e590790888dba3c712a9553 | |
parent | 4e855c8f3f6b2def2b2953e7bcd1ff07e35e42ed (diff) | |
download | ruamel.yaml-e08dd6b761c0b45a486beddcab67389830882b4f.tar.gz |
round-trip sequence key elements0.12.14
-rw-r--r-- | README.rst | 4 | ||||
-rw-r--r-- | __init__.py | 2 | ||||
-rw-r--r-- | _test/roundtrip.py | 13 | ||||
-rw-r--r-- | _test/test_flowsequencekey.py | 25 | ||||
-rw-r--r-- | comments.py | 47 | ||||
-rw-r--r-- | constructor.py | 7 | ||||
-rw-r--r-- | emitter.py | 7 | ||||
-rw-r--r-- | representer.py | 10 |
8 files changed, 102 insertions, 13 deletions
@@ -18,6 +18,10 @@ ChangeLog :: + 0.12.14 (2016-09-21): + - preserve round-trip sequences that are mapping keys + (prompted by stackoverflow question 39595807 from Nowox) + 0.12.13 (2016-09-15): - Fix for issue #60 representation of CommentedMap with merge keys incorrect (reported by Tal Liron) diff --git a/__init__.py b/__init__.py index 15b8eff..15142b6 100644 --- a/__init__.py +++ b/__init__.py @@ -9,7 +9,7 @@ from __future__ import absolute_import _package_data = dict( full_package_name="ruamel.yaml", - version_info=(0, 12, 13), + version_info=(0, 12, 14), 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 632c206..cd79f2c 100644 --- a/_test/roundtrip.py +++ b/_test/roundtrip.py @@ -28,18 +28,19 @@ def round_trip_load(inp, preserve_quotes=None): def round_trip_dump(data, indent=None, block_seq_indent=None, top_level_colon_align=None, - prefix_colon=None, explicit_start=None, explicit_end=None): + prefix_colon=None, explicit_start=None, explicit_end=None, version=None): return ruamel.yaml.round_trip_dump(data, indent=indent, block_seq_indent=block_seq_indent, top_level_colon_align=top_level_colon_align, prefix_colon=prefix_colon, explicit_start=explicit_start, - explicit_end=explicit_end) + explicit_end=explicit_end, + version=version) def round_trip(inp, outp=None, extra=None, intermediate=None, indent=None, block_seq_indent=None, top_level_colon_align=None, prefix_colon=None, - preserve_quotes=None): + preserve_quotes=None, explicit_start=None, version=None): """ inp: input string to parse outp: expected output (equals input if not specified) @@ -58,11 +59,13 @@ def round_trip(inp, outp=None, extra=None, intermediate=None, indent=None, raise ValueError res = round_trip_dump(data, indent=indent, block_seq_indent=block_seq_indent, top_level_colon_align=top_level_colon_align, - prefix_colon=prefix_colon) + prefix_colon=prefix_colon, explicit_start=explicit_start, + version=version) print('roundtrip data:\n', res, sep='') assert res == doutp res = round_trip_dump(data, indent=indent, block_seq_indent=block_seq_indent, top_level_colon_align=top_level_colon_align, - prefix_colon=prefix_colon) + prefix_colon=prefix_colon, explicit_start=explicit_start, + version=version) print('roundtrip second round data:\n', res, sep='') assert res == doutp diff --git a/_test/test_flowsequencekey.py b/_test/test_flowsequencekey.py new file mode 100644 index 0000000..6f6d7db --- /dev/null +++ b/_test/test_flowsequencekey.py @@ -0,0 +1,25 @@ +# coding: utf-8 + +""" +test flow style sequences as keys roundtrip + +""" + +# import pytest +# import ruamel.yaml + +from roundtrip import round_trip # , dedent, round_trip_load, round_trip_dump + + +class TestFlowStyleSequenceKey: + def test_so_39595807(self): + round_trip(""" + %YAML 1.2 + --- + [2, 3, 4]: + a: + - 1 + - 2 + b: Hello World! + c: 'VoilĂ !' + """, preserve_quotes=True, explicit_start=True, version=(1, 2)) diff --git a/comments.py b/comments.py index 7dd8e8e..34154e8 100644 --- a/comments.py +++ b/comments.py @@ -12,7 +12,8 @@ from collections import MutableSet, Sized, Set # type: ignore from ruamel.yaml.compat import ordereddict, PY2 -__all__ = ["CommentedSeq", "CommentedMap", "CommentedOrderedMap", +__all__ = ["CommentedSeq", "CommentedKeySeq", + "CommentedMap", "CommentedOrderedMap", "CommentedSet", 'comment_attrib', 'merge_attrib'] comment_attrib = '_yaml_comment' @@ -321,8 +322,50 @@ class CommentedSeq(list, CommentedBase): return pre_comments -class CommentedMapView(Sized): +class CommentedKeySeq(tuple, CommentedBase): + """This primarily exists to be able to roundtrip keys that are sequences""" + def _yaml_add_comment(self, comment, key=NoComment): + if key is not NoComment: + self.yaml_key_comment_extend(key, comment) + else: + self.ca.comment = comment + + def _yaml_add_eol_comment(self, comment, key): + self._yaml_add_comment(comment, key=key) + + def _yaml_get_columnX(self, key): + return self.ca.items[key][0].start_mark.column + + def _yaml_get_column(self, key): + column = None + sel_idx = None + pre, post = key-1, key+1 + if pre in self.ca.items: + sel_idx = pre + elif post in self.ca.items: + sel_idx = post + else: + # self.ca.items is not ordered + for row_idx, k1 in enumerate(self): + if row_idx >= key: + break + if row_idx not in self.ca.items: + continue + sel_idx = row_idx + if sel_idx is not None: + column = self._yaml_get_columnX(sel_idx) + return column + def _yaml_get_pre_comment(self): + if self.ca.comment is None: + pre_comments = [] + self.ca.comment = [None, pre_comments] + else: + pre_comments = self.ca.comment[1] = [] + return pre_comments + + +class CommentedMapView(Sized): __slots__ = '_mapping', def __init__(self, mapping): diff --git a/constructor.py b/constructor.py index f2a6cc3..03c88ae 100644 --- a/constructor.py +++ b/constructor.py @@ -956,7 +956,12 @@ class RoundTripConstructor(SafeConstructor): # lists are not hashable, but tuples are if not isinstance(key, collections.Hashable): if isinstance(key, list): - key = tuple(key) + key = CommentedKeySeq(key) + if key_node.flow_style is True: + key.fa.set_flow_style() + elif key_node.flow_style is False: + key.fa.set_block_style() + # key = tuple(key) if PY2: try: hash(key) @@ -465,8 +465,9 @@ class Emitter(object): self.write_pre_comment(self.event) self.write_indent() if self.check_simple_key(): - if self.event.style == '?': - self.write_indicator(u'?', True, indention=True) + if not isinstance(self.event, SequenceStartEvent): # sequence keys + if self.event.style == '?': + self.write_indicator(u'?', True, indention=True) self.states.append(self.expect_block_mapping_simple_value) self.expect_node(mapping=True, simple_key=True) else: @@ -526,6 +527,8 @@ class Emitter(object): length += len(self.analysis.scalar) return (length < self.MAX_SIMPLE_KEY_LENGTH and ( isinstance(self.event, AliasEvent) or + (isinstance(self.event, SequenceStartEvent) and + self.event.flow_style is True) or (isinstance(self.event, ScalarEvent) and not self.analysis.empty and not self.analysis.multiline) or self.check_empty_sequence() or self.check_empty_mapping())) diff --git a/representer.py b/representer.py index 3e67a96..8fcbc7c 100644 --- a/representer.py +++ b/representer.py @@ -576,8 +576,8 @@ Representer.add_multi_representer(object, Representer.represent_object) -from ruamel.yaml.comments import CommentedMap, CommentedOrderedMap, \ - CommentedSeq, CommentedSet, comment_attrib, merge_attrib # NOQA +from ruamel.yaml.comments import CommentedMap, CommentedOrderedMap, CommentedSeq, \ + CommentedKeySeq, CommentedSet, comment_attrib, merge_attrib # NOQA class RoundTripRepresenter(SafeRepresenter): @@ -658,6 +658,12 @@ class RoundTripRepresenter(SafeRepresenter): node.flow_style = best_style return node + def represent_key(self, data): + if isinstance(data, CommentedKeySeq): + return self.represent_sequence(u'tag:yaml.org,2002:seq', data, + flow_style=True) + return SafeRepresenter.represent_key(self, data) + def represent_mapping(self, tag, mapping, flow_style=None): value = [] try: |