summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--_test/test_anchor.py28
-rw-r--r--constructor.py38
2 files changed, 63 insertions, 3 deletions
diff --git a/_test/test_anchor.py b/_test/test_anchor.py
index 294d7f1..4c7a9f2 100644
--- a/_test/test_anchor.py
+++ b/_test/test_anchor.py
@@ -10,7 +10,7 @@ import pytest
from textwrap import dedent
import platform
-from roundtrip import round_trip, dedent, round_trip_load, round_trip_dump # NOQA
+from roundtrip import round_trip, dedent, round_trip_load, round_trip_dump, YAML # NOQA
def load(s):
@@ -325,9 +325,8 @@ class TestMergeKeysValues:
d: y4
-
a: 1
- <<: *mx
+ <<: [*mx, *my]
m: 6
- <<: *my
""")
# in the following d always has "expanded" the merges
@@ -491,6 +490,29 @@ class TestDuplicateKeyThroughAnchor:
with pytest.raises(DuplicateKeyError):
round_trip_load(s)
+ def test_duplicate_key_01(self):
+ # so issue https://stackoverflow.com/a/52852106/1307905
+ from ruamel.yaml import version_info
+ from ruamel.yaml.constructor import DuplicateKeyFutureWarning, DuplicateKeyError
+
+ s = dedent("""\
+ - &name-name
+ a: 1
+ - &help-name
+ b: 2
+ - <<: *name-name
+ <<: *help-name
+ """)
+ if version_info < (0, 15, 1):
+ pass
+ else:
+ with pytest.raises(DuplicateKeyError):
+ yaml = YAML(typ='safe')
+ yaml.load(s)
+ with pytest.raises(DuplicateKeyError):
+ yaml = YAML()
+ yaml.load(s)
+
class TestFullCharSetAnchors:
def test_master_of_orion(self):
diff --git a/constructor.py b/constructor.py
index 2983414..8600c9f 100644
--- a/constructor.py
+++ b/constructor.py
@@ -353,6 +353,25 @@ class SafeConstructor(BaseConstructor):
while index < len(node.value):
key_node, value_node = node.value[index]
if key_node.tag == u'tag:yaml.org,2002:merge':
+ if merge: # double << key
+ args = [
+ 'while constructing a mapping',
+ node.start_mark,
+ 'found duplicate key "{}"'.format(key_node.value),
+ key_node.start_mark,
+ """
+ To suppress this check see:
+ http://yaml.readthedocs.io/en/latest/api.html#duplicate-keys
+ """,
+ """\
+ Duplicate keys will become an error in future releases, and are errors
+ by default when using the new API.
+ """,
+ ]
+ if self.allow_duplicate_keys is None:
+ warnings.warn(DuplicateKeyFutureWarning(*args))
+ else:
+ raise DuplicateKeyError(*args)
del node.value[index]
if isinstance(value_node, MappingNode):
self.flatten_mapping(value_node)
@@ -1275,6 +1294,25 @@ class RoundTripConstructor(SafeConstructor):
while index < len(node.value):
key_node, value_node = node.value[index]
if key_node.tag == u'tag:yaml.org,2002:merge':
+ if merge_map_list: # double << key
+ args = [
+ 'while constructing a mapping',
+ node.start_mark,
+ 'found duplicate key "{}"'.format(key_node.value),
+ key_node.start_mark,
+ """
+ To suppress this check see:
+ http://yaml.readthedocs.io/en/latest/api.html#duplicate-keys
+ """,
+ """\
+ Duplicate keys will become an error in future releases, and are errors
+ by default when using the new API.
+ """,
+ ]
+ if self.allow_duplicate_keys is None:
+ warnings.warn(DuplicateKeyFutureWarning(*args))
+ else:
+ raise DuplicateKeyError(*args)
del node.value[index]
if isinstance(value_node, MappingNode):
merge_map_list.append((index, constructed(value_node)))