Skip to content

Commit

Permalink
Fix quoted-strings checks in flow maps and sequences
Browse files Browse the repository at this point in the history
Flow maps and sequences need quotes if the values contain any of the
flow tokens ({}, [], ','). However, yamllint generates false positives
in these cases:

$ yamllint -d 'rules: {quoted-strings: {required: only-when-needed}}' - <<<'field: ["string[bracket]"]'
  1:9       error    string value is redundantly quoted with any quotes  (quoted-strings)

To fix this, track when inside a flow map/sequence and skip the quoting
checks except for the quoting type.

Closes #516
  • Loading branch information
robherring committed Nov 22, 2023
1 parent 8713140 commit c4c3b5a
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 5 deletions.
12 changes: 9 additions & 3 deletions tests/rules/test_quoted_strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,11 @@ def test_only_when_needed(self):
' - foo\n'
' - "foo"\n' # fails
'flow-seq: [foo, "foo"]\n' # fails
'flow-map: {a: foo, b: "foo"}\n', # fails
'flow-map: {a: foo, b: "foo"}\n' # fails
'flow-seq2: [foo, "foo,bar", "foo[bar]", "foo{bar}"]\n'
'flow-map2: {a: foo, b: "foo,bar"}\n'
'nested-flow1: {a: foo, b: [foo, "foo,bar"]}\n'
'nested-flow2: [{a: foo}, {b: "foo,bar", c: ["foo[bar]"]}]\n',
conf, problem1=(5, 10), problem2=(8, 10), problem3=(18, 5),
problem4=(19, 17), problem5=(20, 23))
self.check('---\n'
Expand Down Expand Up @@ -299,10 +303,12 @@ def test_only_when_needed_single_quotes(self):
' - foo\n'
' - "foo"\n' # fails
'flow-seq: [foo, "foo"]\n' # fails
'flow-map: {a: foo, b: "foo"}\n', # fails
'flow-map: {a: foo, b: "foo"}\n' # fails
'flow-seq2: [foo, "foo,bar"]\n' # fails
'flow-map2: {a: foo, b: "foo,bar"}\n', # fails
conf, problem1=(5, 10), problem2=(6, 10), problem3=(7, 10),
problem4=(8, 10), problem5=(18, 5), problem6=(19, 17),
problem7=(20, 23))
problem7=(20, 23), problem8=(21, 18), problem9=(22, 24))
self.check('---\n'
'multiline string 1: |\n'
' line 1\n'
Expand Down
19 changes: 17 additions & 2 deletions yamllint/rules/quoted_strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,11 @@ def _quote_match(quote_type, token_style):
(quote_type == 'double' and token_style == '"'))


def _quotes_are_needed(string):
def _quotes_are_needed(string, is_inside_a_flow):
# Quotes needed on strings containing flow tokens
if is_inside_a_flow and set(string) & {',', '[', ']', '{', '}'}:
return True

loader = yaml.BaseLoader('key: ' + string)
# Remove the 5 first tokens corresponding to 'key: ' (StreamStartToken,
# BlockMappingStartToken, KeyToken, ScalarToken(value=key), ValueToken)
Expand All @@ -209,6 +213,16 @@ def _has_quoted_quotes(token):


def check(conf, token, prev, next, nextnext, context):
if 'flow_nest_count' not in context:
context['flow_nest_count'] = 0

if isinstance(token, (yaml.FlowMappingStartToken,
yaml.FlowSequenceStartToken)):
context['flow_nest_count'] += 1
elif isinstance(token, (yaml.FlowMappingEndToken,
yaml.FlowSequenceEndToken)):
context['flow_nest_count'] -= 1

if not (isinstance(token, yaml.tokens.ScalarToken) and
isinstance(prev, (yaml.BlockEntryToken, yaml.FlowEntryToken,
yaml.FlowSequenceStartToken, yaml.TagToken,
Expand Down Expand Up @@ -261,7 +275,8 @@ def check(conf, token, prev, next, nextnext, context):

# Quotes are not strictly needed here
if (token.style and tag == DEFAULT_SCALAR_TAG and token.value and
not _quotes_are_needed(token.value)):
not _quotes_are_needed(token.value,
context['flow_nest_count'] > 0)):
is_extra_required = any(re.search(r, token.value)
for r in conf['extra-required'])
is_extra_allowed = any(re.search(r, token.value)
Expand Down

0 comments on commit c4c3b5a

Please sign in to comment.