Skip to content

Commit

Permalink
Add forbid-duplicated-merge-keys option to key-duplicates rule
Browse files Browse the repository at this point in the history
  • Loading branch information
travbale committed Nov 21, 2023
1 parent 8713140 commit f39b0a1
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 1 deletion.
41 changes: 41 additions & 0 deletions tests/rules/test_key_duplicates.py
Expand Up @@ -179,3 +179,44 @@ def test_key_tokens_in_flow_sequences(self):
'[\n'
' flow: sequence, with, key: value, mappings\n'
']\n', conf)

def test_forbid_duplicated_merge_keys(self):
conf = 'key-duplicates: {forbid-duplicated-merge-keys: true}'
self.check('---\n'
'Multiple Merge Keys are NOT OK:\n'
'anchor_one: &anchor_one\n'
' one: one\n'
'anchor_two: &anchor_two\n'
' two: two\n'
'anchor_reference:\n'
' <<: *anchor_one\n'
' <<: *anchor_two\n', conf, problem=(9, 3))
self.check('---\n'
'Multiple Merge Keys are NOT OK:\n'
'anchor_one: &anchor_one\n'
' one: one\n'
'anchor_two: &anchor_two\n'
' two: two\n'
'anchor_reference:\n'
' a: 1\n'
' <<: *anchor_one\n'
' b: 2\n'
' <<: *anchor_two\n', conf, problem=(11, 3))
self.check('---\n'
'Single Merge Key is OK:\n'
'anchor_one: &anchor_one\n'
' one: one\n'
'anchor_two: &anchor_two\n'
' two: two\n'
'anchor_reference:\n'
' <<: [*anchor_one, *anchor_two]\n' , conf)
self.check('---\n'
'Duplicate keys without Merge Keys:\n'
' key: a\n'
' otherkey: b\n'
' key: c\n', conf,
problem=(5, 3))
self.check('---\n'
'No Merge Keys:\n'
' key: a\n'
' otherkey: b\n', conf)
40 changes: 39 additions & 1 deletion yamllint/rules/key_duplicates.py
Expand Up @@ -16,6 +16,18 @@
"""
Use this rule to prevent multiple entries with the same key in mappings.
.. rubric:: Options
* ``forbid-duplicated-merge-keys`` to forbid the usage of multiple merge keys.
.. rubric:: Default values (when enabled)
.. code-block:: yaml
rules:
key-duplicates:
forbid-duplicated-merge-keys: false
.. rubric:: Examples
#. With ``key-duplicates: {}``
Expand Down Expand Up @@ -51,6 +63,29 @@
other
duplication
: 2
#. With `key-duplicates`: {forbid-duplicated-merge-keys: true}``
the following code snippet would **PASS**:
::
anchor_one: &anchor_one
one: one
anchor_two: &anchor_two
two: two
anchor_reference:
<<: [*anchor_one, *anchor_two]
the following code snippet would **FAIL**:
::
anchor_one: &anchor_one
one: one
anchor_two: &anchor_two
two: two
anchor_reference:
<<: *anchor_one
<<: *anchor_two]
"""

import yaml
Expand All @@ -60,6 +95,8 @@

ID = 'key-duplicates'
TYPE = 'token'
CONF = {'forbid-duplicated-merge-keys': bool}
DEFAULT = {'forbid-duplicated-merge-keys': False}

MAP, SEQ = range(2)

Expand Down Expand Up @@ -92,7 +129,8 @@ def check(conf, token, prev, next, nextnext, context):
if len(context['stack']) > 0 and context['stack'][-1].type == MAP:
if (next.value in context['stack'][-1].keys and
# `<<` is "merge key", see http://yaml.org/type/merge.html
next.value != '<<'):
(next.value != '<<' or
conf['forbid-duplicated-merge-keys'])):
yield LintProblem(
next.start_mark.line + 1, next.start_mark.column + 1,
f'duplication of key "{next.value}" in mapping')
Expand Down

0 comments on commit f39b0a1

Please sign in to comment.