diff options
author | Anthon van der Neut <anthon@mnt.org> | 2023-05-06 12:29:03 +0200 |
---|---|---|
committer | Anthon van der Neut <anthon@mnt.org> | 2023-05-06 12:29:03 +0200 |
commit | a7e27772f48e9e7f1040344739f680081da50a41 (patch) | |
tree | 0887b210272f81e1a01e6404e1e1aac25e4558f3 | |
parent | a4e09a2ba0d2adb1b2e63b6bf8fa39c055b9c99b (diff) | |
download | ruamel.yaml-a7e27772f48e9e7f1040344739f680081da50a41.tar.gz |
fix issue: 453, 4470.17.24
-rw-r--r-- | CHANGES | 15 | ||||
-rw-r--r-- | README.rst | 19 | ||||
-rw-r--r-- | __init__.py | 6 | ||||
-rw-r--r-- | _doc/_static/pypi.svg | 2 | ||||
-rw-r--r-- | _test/test_issues.py | 31 | ||||
-rw-r--r-- | comments.py | 33 | ||||
-rw-r--r-- | scanner.py | 7 | ||||
-rw-r--r-- | setup.py | 3 |
8 files changed, 97 insertions, 19 deletions
@@ -1,3 +1,18 @@ +[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 + be the one as you look at the YAML input. + This fixes issue 453 where other + keys of a merged in mapping would show up after an insert (reported by + `Alex Miller <https://sourceforge.net/u/millerdevel/profile/>`__). It + also fixes a call to `.insert()` resulting into the merge key to move + to be the first key if it wasn't already and it is also now possible + to insert a key before a merge key (even if the fist key in the mapping). + - fix (in the pure Python implementation including default) for issue 447. + (reported by `Jack Cherng <https://sourceforge.net/u/jfcherng/profile/>`__, + also brought up by brent on + `StackOverflow <https://stackoverflow.com/q/40072485/1307905>`__) + [0, 17, 23]: 2023-05-05 - fix 458, error on plain scalars starting with word longer than width. (reported by `Kyle Larose <https://sourceforge.net/u/klarose/profile/>`__) @@ -4,8 +4,8 @@ ruamel.yaml ``ruamel.yaml`` is a YAML 1.2 loader/dumper package for Python. -:version: 0.17.23 -:updated: 2023-05-05 +:version: 0.17.24 +:updated: 2023-05-06 :documentation: http://yaml.readthedocs.io :repository: https://sourceforge.net/projects/ruamel-yaml/ :pypi: https://pypi.org/project/ruamel.yaml/ @@ -61,6 +61,21 @@ ChangeLog .. should insert NEXT: at the beginning of line for next key (with empty line) +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 + be the one as you look at the YAML input. + This fixes issue 453 where other + keys of a merged in mapping would show up after an insert (reported by + `Alex Miller <https://sourceforge.net/u/millerdevel/profile/>`__). It + also fixes a call to `.insert()` resulting into the merge key to move + to be the first key if it wasn't already and it is also now possible + to insert a key before a merge key (even if the fist key in the mapping). + - fix (in the pure Python implementation including default) for issue 447. + (reported by `Jack Cherng <https://sourceforge.net/u/jfcherng/profile/>`__, + also brought up by brent on + `StackOverflow <https://stackoverflow.com/q/40072485/1307905>`__) + 0.17.23 (2023-05-05): - fix 458, error on plain scalars starting with word longer than width. (reported by `Kyle Larose <https://sourceforge.net/u/klarose/profile/>`__) diff --git a/__init__.py b/__init__.py index 5dcf734..d548852 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, 23), - __version__='0.17.23', - version_timestamp='2023-05-05 20:19:23', + version_info=(0, 17, 24), + __version__='0.17.24', + version_timestamp='2023-05-06 12:28:17', 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 32bd51f..1784380 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.23</text><text x="585" y="140" transform="scale(.1)" textLength="430">0.17.23</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.24</text><text x="585" y="140" transform="scale(.1)" textLength="430">0.17.24</text></g> </svg> diff --git a/_test/test_issues.py b/_test/test_issues.py index ce78cce..eadf94d 100644 --- a/_test/test_issues.py +++ b/_test/test_issues.py @@ -954,6 +954,11 @@ class TestIssues: yaml.dump(data, buf) assert buf.getvalue() == '%YAML 1.1\n---\nquote: I have seen things\n' + def test_issue_447(self) -> None: + from ruamel.yaml import YAML + + YAML().load("{\n\t\"FOO\": \"BAR\"\n}") + def test_issue_449(self) -> None: inp = """\ emoji_index: !!python/name:materialx.emoji.twemoji @@ -974,6 +979,32 @@ class TestIssues: assert ord(k) == v assert len(cm) == 4 + def test_issue_453(self) -> None: + from io import StringIO + from ruamel.yaml import YAML + + inp = dedent( + """ + to-merge: &anchor + merge-key: should not be duplicated + + to-merge2: &anchor2 + merge-key2: should not be duplicated + + usage: + <<: [*anchor, *anchor2] + usage-key: usage-value + """ + ) + yaml = YAML() + data = yaml.load(inp) + data['usage'].insert(0, 'insert-key', 'insert-value') + out_stream = StringIO() + yaml.dump(data, out_stream) + result = out_stream.getvalue() + print(result) + assert inp.replace('usage:\n', 'usage:\n insert-key: insert-value\n') == result + def test_issue_454(self) -> None: inp = """ test1: 🎉 diff --git a/comments.py b/comments.py index c7a4575..dc128ee 100644 --- a/comments.py +++ b/comments.py @@ -793,16 +793,33 @@ class CommentedMap(ordereddict, CommentedBase): self._ok.update(*kw.keys()) # type: ignore def insert(self, pos: Any, key: Any, value: Any, comment: Optional[Any] = None) -> None: - """insert key value into given position + """insert key value into given position, as defined by source YAML attach comment if provided """ - keys = list(self.keys()) + [key] - ordereddict.insert(self, pos, key, value) - for keytmp in keys: - self._ok.add(keytmp) - for referer in self._ref: - for keytmp in keys: - referer.update_key_value(keytmp) + if key in self._ok: + del self[key] + keys = [k for k in self.keys() if k in self._ok] + ma0 = getattr(self, merge_attrib, [[-1]])[0] + merge_pos = ma0[0] + if merge_pos >= 0: + if merge_pos >= pos: + getattr(self, merge_attrib)[0] = (merge_pos + 1, ma0[1]) + idx_min = pos + idx_max = len(self._ok) + else: + idx_min = pos - 1 + idx_max = len(self._ok) + else: + idx_min = pos + idx_max = len(self._ok) + self[key] = value # at the end + # print(f'{idx_min=} {idx_max=}') + for idx in range(idx_min, idx_max): + self.move_to_end(keys[idx]) + self._ok.add(key) + # for referer in self._ref: + # for keytmp in keys: + # referer.update_key_value(keytmp) if comment is not None: self.yaml_add_eol_comment(comment, key=key) @@ -822,8 +822,9 @@ class Scanner: srf() found = False _the_end = _THE_END + white_space = ' \t' if self.flow_level > 0 else ' ' while not found: - while srp() == ' ': + while srp() in white_space: srf() if srp() == '#': while srp() not in _the_end: @@ -1837,14 +1838,14 @@ class RoundTripScanner(Scanner): # We also need to add the check for `allow_simple_keys == True` to # `unwind_indent` before issuing BLOCK-END. # Scanners for block, flow, and plain scalars need to be modified. - srp = self.reader.peek srf = self.reader.forward if self.reader.index == 0 and srp() == '\uFEFF': srf() found = False + white_space = ' \t' if self.flow_level > 0 else ' ' while not found: - while srp() == ' ': + while srp() in white_space: srf() ch = srp() if ch == '#': @@ -888,7 +888,7 @@ def main(): # if nsp.wheel(kw, setup): # return - with TmpFiles(pkg_data, keep=False): + with TmpFiles(pkg_data, keep=True): for x in ['-c', 'egg_info', '--egg-base', 'pip-egg-info']: if x not in sys.argv: break @@ -912,7 +912,6 @@ def main(): break try_dir = os.path.dirname(try_dir) setup(**kw) - print('done') main() |