diff options
-rw-r--r-- | README.rst | 5 | ||||
-rw-r--r-- | __init__.py | 2 | ||||
-rw-r--r-- | _test/test_copy.py | 118 | ||||
-rw-r--r-- | comments.py | 26 | ||||
-rw-r--r-- | configobjwalker.py | 2 | ||||
-rw-r--r-- | tox.ini | 2 |
6 files changed, 151 insertions, 4 deletions
@@ -18,8 +18,11 @@ ChangeLog .. should insert NEXT: at the beginning of line for next key +0.13.5 (2016-12-25): + - fix for issue 84, deepcopy not properly workin (reported by Peter Amstutz) + 0.13.4 (2016-12-05): - - another fxi for issue 82, change to non-global resolver data broke implicit type + - another fix for issue 82, change to non-global resolver data broke implicit type specification 0.13.3 (2016-12-05): diff --git a/__init__.py b/__init__.py index 508e2a2..29911ea 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, 13, 4), + version_info=(0, 13, 5), 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/test_copy.py b/_test/test_copy.py new file mode 100644 index 0000000..37f978d --- /dev/null +++ b/_test/test_copy.py @@ -0,0 +1,118 @@ +# coding: utf-8 + +""" +Testing copy and deepcopy, instigated by Issue 84 (Peter Amstutz) +""" + +import copy + +import pytest # NOQA +import ruamel.yaml # NOQA + +from roundtrip import dedent, round_trip_load, round_trip_dump + + +class TestDeepCopy: + def test_preserve_flow_style_simple(self): + x = dedent("""\ + {foo: bar, baz: quux} + """) + data = round_trip_load(x) + data_copy = copy.deepcopy(data) + y = round_trip_dump(data_copy) + print('x [{}]'.format(x)) + print('y [{}]'.format(y)) + assert y == x + assert data.fa.flow_style() == data_copy.fa.flow_style() + + def test_deepcopy_flow_style_nested_dict(self): + x = dedent("""\ + a: {foo: bar, baz: quux} + """) + data = round_trip_load(x) + assert data['a'].fa.flow_style() is True + data_copy = copy.deepcopy(data) + assert data_copy['a'].fa.flow_style() is True + data_copy['a'].fa.set_block_style() + assert data['a'].fa.flow_style() != data_copy['a'].fa.flow_style() + assert data['a'].fa._flow_style is True + assert data_copy['a'].fa._flow_style is False + y = round_trip_dump(data_copy) + + print('x [{}]'.format(x)) + print('y [{}]'.format(y)) + assert y == dedent("""\ + a: + foo: bar + baz: quux + """) + + def test_deepcopy_flow_style_nested_list(self): + x = dedent("""\ + a: [1, 2, 3] + """) + data = round_trip_load(x) + assert data['a'].fa.flow_style() is True + data_copy = copy.deepcopy(data) + assert data_copy['a'].fa.flow_style() is True + data_copy['a'].fa.set_block_style() + assert data['a'].fa.flow_style() != data_copy['a'].fa.flow_style() + assert data['a'].fa._flow_style is True + assert data_copy['a'].fa._flow_style is False + y = round_trip_dump(data_copy) + + print('x [{}]'.format(x)) + print('y [{}]'.format(y)) + assert y == dedent("""\ + a: + - 1 + - 2 + - 3 + """) + + +class TestCopy: + def test_copy_flow_style_nested_dict(self): + x = dedent("""\ + a: {foo: bar, baz: quux} + """) + data = round_trip_load(x) + assert data['a'].fa.flow_style() is True + data_copy = copy.copy(data) + assert data_copy['a'].fa.flow_style() is True + data_copy['a'].fa.set_block_style() + assert data['a'].fa.flow_style() == data_copy['a'].fa.flow_style() + assert data['a'].fa._flow_style is False + assert data_copy['a'].fa._flow_style is False + y = round_trip_dump(data_copy) + z = round_trip_dump(data) + assert y == z + + assert y == dedent("""\ + a: + foo: bar + baz: quux + """) + + def test_copy_flow_style_nested_list(self): + x = dedent("""\ + a: [1, 2, 3] + """) + data = round_trip_load(x) + assert data['a'].fa.flow_style() is True + data_copy = copy.copy(data) + assert data_copy['a'].fa.flow_style() is True + data_copy['a'].fa.set_block_style() + assert data['a'].fa.flow_style() == data_copy['a'].fa.flow_style() + assert data['a'].fa._flow_style is False + assert data_copy['a'].fa._flow_style is False + y = round_trip_dump(data_copy) + + print('x [{}]'.format(x)) + print('y [{}]'.format(y)) + assert y == dedent("""\ + a: + - 1 + - 2 + - 3 + """) diff --git a/comments.py b/comments.py index dc56594..e549a33 100644 --- a/comments.py +++ b/comments.py @@ -8,6 +8,7 @@ these are not really related, formatting could be factored out as a separate base """ +import copy from collections import MutableSet, Sized, Set # type: ignore from ruamel.yaml.compat import ordereddict, PY2 @@ -296,6 +297,15 @@ class CommentedBase(object): def yaml_set_tag(self, value): self.tag.value = value + def copy_attributes(self, t, deep=False): + for a in [Comment.attrib, Format.attrib, LineCol.attrib, Anchor.attrib, + Tag.attrib, merge_attrib]: + if hasattr(self, a): + if deep: + setattr(t, a, copy.deepcopy(getattr(self, a))) + else: + setattr(t, a, getattr(self, a)) + class CommentedSeq(list, CommentedBase): __slots__ = Comment.attrib, @@ -357,6 +367,14 @@ class CommentedSeq(list, CommentedBase): pre_comments = self.ca.comment[1] = [] return pre_comments + def __deepcopy__(self, memo): + res = CommentedSeq() + memo[id(self)] = res + for k in self: + res.append(copy.deepcopy(k)) + self.copy_attributes(res, deep=True) + return res + class CommentedKeySeq(tuple, CommentedBase): """This primarily exists to be able to roundtrip keys that are sequences""" @@ -731,6 +749,14 @@ class CommentedMap(ordereddict, CommentedBase): def add_yaml_merge(self, value): self.merge.extend(value) + def __deepcopy__(self, memo): + res = CommentedMap() + memo[id(self)] = res + for k in self: + res[k] = copy.deepcopy(self[k]) + self.copy_attributes(res, deep=True) + return res + class CommentedOrderedMap(CommentedMap): __slots__ = Comment.attrib, diff --git a/configobjwalker.py b/configobjwalker.py index bab910c..a6eb54c 100644 --- a/configobjwalker.py +++ b/configobjwalker.py @@ -5,5 +5,5 @@ from ruamel.yaml.util import configobj_walker as new_configobj_walker def configobj_walker(cfg): - warnings.warn("configobj_walker has move to ruamel.yaml.util, please update your code") + warnings.warn("configobj_walker has moved to ruamel.yaml.util, please update your code") return new_configobj_walker(cfg) @@ -15,7 +15,7 @@ norecursedirs = test/lib .tox [testenv:pep8] commands = - flake8 --exclude convert,cmd {posargs} + flake8 --exclude convert,cmd,base {posargs} [flake8] show-source = True |