diff options
author | Anthon van der Neut <anthon@mnt.org> | 2016-05-02 08:50:15 +0200 |
---|---|---|
committer | Anthon van der Neut <anthon@mnt.org> | 2016-05-02 08:50:15 +0200 |
commit | 4fa9ad23e69dcea31fe1b3dc15dc3cc1510b797c (patch) | |
tree | cef93d3c5c2c9e40f58360df87958e3d8b8175fa | |
parent | ad69246c90b178e99a752769ee4ac70dd4dedb26 (diff) | |
download | ruamel.yaml-4fa9ad23e69dcea31fe1b3dc15dc3cc1510b797c.tar.gz |
allow insert in CommentedMap (Py3) and add comment0.11.11
The insert() would only be available for CommentedMap on Py2 (thanks to
ruamel.ordereddict). The standard library lacks this functionality.
The method was added in the compatibility layer, and on CommentedMap
the optional comment parameter allows directly setting an end-of-line
comment on the inserted key.
-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 |