diff options
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | __init__.py | 2 | ||||
-rw-r--r-- | _doc/example.rst | 31 | ||||
-rw-r--r-- | _test/test_comments.py | 49 | ||||
-rw-r--r-- | comments.py | 8 | ||||
-rw-r--r-- | compat.py | 15 |
6 files changed, 106 insertions, 3 deletions
@@ -1,4 +1,8 @@ +0.11.10 2016-05-02 + +- added .insert(pos, key, value, comment=None) to CommentedMap + 0.11.10 2016-04-19 - indent=2, block_seq_indent=2 works as expected diff --git a/__init__.py b/__init__.py index 7a0c6f0..9be2082 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, 11, 10), + version_info=(0, 11, 11), 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/example.rst b/_doc/example.rst index 8bf9c6a..4e8ac4a 100644 --- a/_doc/example.rst +++ b/_doc/example.rst @@ -34,9 +34,10 @@ Resulting in :: .. example output small.py +---- YAML handcrafted anchors and references as well as key merging -is preserved. The merged keys can transparently be accessed +are preserved. The merged keys can transparently be accessed using ``[]`` and ``.get()``:: import ruamel.yaml @@ -71,3 +72,31 @@ using ``[]`` and ``.get()``:: .. example code anchor_merge.py +---- + +The ``CommentedMap``, which is the ``dict`` like construct one gets when round-trip loading, +supports insertion of a key into a particular position, while optionally adding a comment:: + + yaml_str = """\ + first_name: Art + occupation: Architect # This is an occupation comment + about: Art Vandelay is a fictional character that George invents... + """ + + data = ruamel.yaml.round_trip_load(yaml_str) + data.insert(1, 'last name', 'Vandelay', comment="new key") + print(ruamel.yaml.round_trip_dump(data)) + +gives:: + + first_name: Art + last name: Vandelay # new key + occupation: Architect # This is an occupation comment + about: Art Vandelay is a fictional character that George invents... + +Please note that the comment is aligned with that of its neighbour (if available). + +The above was inspired by a `question <http://stackoverflow.com/a/36970608/1307905>`_ +posted by *demux* on StackOverflow. + + diff --git a/_test/test_comments.py b/_test/test_comments.py index ffe0b04..b6b12e2 100644 --- a/_test/test_comments.py +++ b/_test/test_comments.py @@ -423,3 +423,52 @@ class TestInsertPopList: - 1 - 2 """) + + +# inspired by demux' question on stackoverflow +# http://stackoverflow.com/a/36970608/1307905 +class TestInsertInMapping: + @property + def ins(self): + return """\ + first_name: Art + occupation: Architect # This is an occupation comment + about: Art Vandelay is a fictional character that George invents... + """ + + def test_insert_at_pos_1(self): + d = round_trip_load(self.ins) + d.insert(1, 'last name', 'Vandelay', comment="new key") + y = round_trip_dump(d) + print(y) + assert y == dedent("""\ + first_name: Art + last name: Vandelay # new key + occupation: Architect # This is an occupation comment + about: Art Vandelay is a fictional character that George invents... + """) + + def test_insert_at_pos_0(self): + d = round_trip_load(self.ins) + d.insert(0, 'last name', 'Vandelay', comment="new key") + y = round_trip_dump(d) + print(y) + assert y == dedent("""\ + last name: Vandelay # new key + first_name: Art + occupation: Architect # This is an occupation comment + about: Art Vandelay is a fictional character that George invents... + """) + + def test_insert_at_pos_3(self): + # much more simple if done with appending. + d = round_trip_load(self.ins) + d.insert(3, 'last name', 'Vandelay', comment="new key") + y = round_trip_dump(d) + print(y) + assert y == dedent("""\ + first_name: Art + occupation: Architect # This is an occupation comment + about: Art Vandelay is a fictional character that George invents... + last name: Vandelay # new key + """) diff --git a/comments.py b/comments.py index 8e5ebb8..4a99931 100644 --- a/comments.py +++ b/comments.py @@ -389,6 +389,14 @@ class CommentedMap(ordereddict, CommentedBase): for x in vals: self[x] = vals[x] + def insert(self, pos, key, value, comment=None): + """insert key value into given position + attach comment if provided + """ + ordereddict.insert(self, pos, key, value) + if comment is not None: + self.yaml_add_eol_comment(comment, key=key) + def mlget(self, key, default=None, list_ok=False): """multi-level get that expects dicts within dicts""" if not isinstance(key, list): @@ -18,7 +18,20 @@ except: # to get the right name import ... as ordereddict doesn't do that class ordereddict(OrderedDict): - pass + if not hasattr(OrderedDict, 'insert'): + def insert(self, pos, key, value): + if pos >= len(self): + self[key] = value + return + od = ordereddict() + od.update(self) + for k in od: + del self[k] + for index, old_key in enumerate(od): + if pos == index: + self[key] = value + self[old_key] = od[old_key] + PY2 = sys.version_info[0] == 2 PY3 = sys.version_info[0] == 3 |