Skip to content

Commit

Permalink
quoted-strings: Fix broken rule
Browse files Browse the repository at this point in the history
Original implementation was completely broken. Documentation and actual
behavior were different. Numbers and booleans were detected as wrong, as
well as explicit types.

Fixes #136 and #130.
  • Loading branch information
adrienverge committed Oct 16, 2018
1 parent 524d721 commit 71a2a50
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 49 deletions.
56 changes: 28 additions & 28 deletions tests/rules/test_quoted_strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,19 @@ def test_disabled(self):
def test_quote_type_any(self):
conf = 'quoted-strings: {quote-type: any}\n'
self.check('---\n'
'string1: "foo"\n'
'number1: 123\n' # fails
'string2: foo\n' # fails
'boolean1: true\n'
'number1: 123\n'
'string1: foo\n' # fails
'string2: "foo"\n'
'string3: \'bar\'\n'
'string4: !!str genericstring\n' # fails
'string5: !!str 456\n' # fails
'string4: !!str genericstring\n'
'string5: !!str 456\n'
'string6: !!str "quotedgenericstring"\n'
'binary: !!binary binstring\n'
'integer: !!int intstring\n'
'boolean1: !!bool boolstring\n'
'boolean2: !!bool "quotedboolstring"\n',
conf, problem1=(3, 10), problem2=(4, 10),
problem3=(6, 16), problem4=(7, 16))
'boolean2: !!bool boolstring\n'
'boolean3: !!bool "quotedboolstring"\n',
conf, problem=(4, 10))
self.check('---\n'
'multiline string 1: |\n'
' line 1\n'
Expand All @@ -65,19 +65,19 @@ def test_quote_type_any(self):
def test_quote_type_single(self):
conf = 'quoted-strings: {quote-type: single}\n'
self.check('---\n'
'string1: "foo"\n' # fails
'number1: 123\n' # fails
'string2: foo\n' # fails
'boolean1: true\n'
'number1: 123\n'
'string1: foo\n' # fails
'string2: "foo"\n' # fails
'string3: \'bar\'\n'
'string4: !!str genericstring\n' # fails
'string5: !!str 456\n' # fails
'string6: !!str "quotedgenericstring"\n' # fails
'string4: !!str genericstring\n'
'string5: !!str 456\n'
'string6: !!str "quotedgenericstring"\n'
'binary: !!binary binstring\n'
'integer: !!int intstring\n'
'boolean1: !!bool boolstring\n'
'boolean2: !!bool "quotedboolstring"\n',
conf, problem1=(2, 10), problem2=(3, 10), problem3=(4, 10),
problem4=(6, 16), problem5=(7, 16), problem6=(8, 16))
'boolean2: !!bool boolstring\n'
'boolean3: !!bool "quotedboolstring"\n',
conf, problem1=(4, 10), problem2=(5, 10))
self.check('---\n'
'multiline string 1: |\n'
' line 1\n'
Expand All @@ -96,19 +96,19 @@ def test_quote_type_single(self):
def test_quote_type_double(self):
conf = 'quoted-strings: {quote-type: double}\n'
self.check('---\n'
'string1: "foo"\n'
'number1: 123\n' # fails
'string2: foo\n' # fails
'boolean1: true\n'
'number1: 123\n'
'string1: foo\n' # fails
'string2: "foo"\n'
'string3: \'bar\'\n' # fails
'string4: !!str genericstring\n' # fails
'string5: !!str 456\n' # fails
'string4: !!str genericstring\n'
'string5: !!str 456\n'
'string6: !!str "quotedgenericstring"\n'
'binary: !!binary binstring\n'
'integer: !!int intstring\n'
'boolean1: !!bool boolstring\n'
'boolean2: !!bool "quotedboolstring"\n',
conf, problem1=(3, 10), problem2=(4, 10), problem3=(5, 10),
problem4=(6, 16), problem5=(7, 16))
'boolean2: !!bool boolstring\n'
'boolean3: !!bool "quotedboolstring"\n',
conf, problem1=(4, 10), problem2=(6, 10))
self.check('---\n'
'multiline string 1: |\n'
' line 1\n'
Expand Down
45 changes: 24 additions & 21 deletions yamllint/rules/quoted_strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

"""
Use this rule to forbid any string values that are not quoted.
You can also enforce the type of the quote used - single or double - using the
``quote-type`` option.
You can also enforce the type of the quote used using the ``quote-type`` option
(``single``, ``double`` or ``any``).
**Note**: Multi-line strings (with ``|`` or ``>``) will not be checked.
Expand Down Expand Up @@ -51,24 +51,27 @@
def check(conf, token, prev, next, nextnext, context):
quote_type = conf['quote-type']

if prev and isinstance(prev, yaml.tokens.TagToken):
if prev.value[1] != "str":
# we ignore generic strings, e.g. somestring: !!str testtest
if (isinstance(token, yaml.tokens.ScalarToken) and
isinstance(prev, (yaml.ValueToken, yaml.TagToken))):
# Ignore explicit types, e.g. !!str testtest or !!int 42
if (prev and isinstance(prev, yaml.tokens.TagToken) and
prev.value[0] == '!!'):
return

if isinstance(token, yaml.tokens.ScalarToken):
if isinstance(prev, yaml.tokens.ValueToken) or \
isinstance(prev, yaml.tokens.TagToken):
if ((not token.plain) and
((token.style == "|") or (token.style == ">"))):
# we ignore multi-line strings
return

if ((quote_type == 'single' and token.style != "'") or
(quote_type == 'double' and token.style != '"') or
(quote_type == 'any' and token.style is None)):
yield LintProblem(
token.start_mark.line + 1,
token.start_mark.column + 1,
"string value is not quoted with %s quotes" % (quote_type)
)
# Ignore numbers, booleans, etc.
resolver = yaml.resolver.Resolver()
if resolver.resolve(yaml.nodes.ScalarNode, token.value,
(True, False)) != 'tag:yaml.org,2002:str':
return

# Ignore multi-line strings
if (not token.plain) and (token.style == "|" or token.style == ">"):
return

if ((quote_type == 'single' and token.style != "'") or
(quote_type == 'double' and token.style != '"') or
(quote_type == 'any' and token.style is None)):
yield LintProblem(
token.start_mark.line + 1,
token.start_mark.column + 1,
"string value is not quoted with %s quotes" % (quote_type))

0 comments on commit 71a2a50

Please sign in to comment.