quoted-strings: Fix broken rule

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.
pull/140/head
Adrien Vergé 6 years ago
parent 524d721f0d
commit 8354d50016

@ -34,19 +34,19 @@ class QuotedTestCase(RuleTestCase):
def test_quote_type_any(self): def test_quote_type_any(self):
conf = 'quoted-strings: {quote-type: any}\n' conf = 'quoted-strings: {quote-type: any}\n'
self.check('---\n' self.check('---\n'
'string1: "foo"\n' 'boolean1: true\n'
'number1: 123\n' # fails 'number1: 123\n'
'string2: foo\n' # fails 'string1: foo\n' # fails
'string2: "foo"\n'
'string3: \'bar\'\n' 'string3: \'bar\'\n'
'string4: !!str genericstring\n' # fails 'string4: !!str genericstring\n'
'string5: !!str 456\n' # fails 'string5: !!str 456\n'
'string6: !!str "quotedgenericstring"\n' 'string6: !!str "quotedgenericstring"\n'
'binary: !!binary binstring\n' 'binary: !!binary binstring\n'
'integer: !!int intstring\n' 'integer: !!int intstring\n'
'boolean1: !!bool boolstring\n' 'boolean2: !!bool boolstring\n'
'boolean2: !!bool "quotedboolstring"\n', 'boolean3: !!bool "quotedboolstring"\n',
conf, problem1=(3, 10), problem2=(4, 10), conf, problem=(4, 10))
problem3=(6, 16), problem4=(7, 16))
self.check('---\n' self.check('---\n'
'multiline string 1: |\n' 'multiline string 1: |\n'
' line 1\n' ' line 1\n'
@ -65,19 +65,19 @@ class QuotedTestCase(RuleTestCase):
def test_quote_type_single(self): def test_quote_type_single(self):
conf = 'quoted-strings: {quote-type: single}\n' conf = 'quoted-strings: {quote-type: single}\n'
self.check('---\n' self.check('---\n'
'string1: "foo"\n' # fails 'boolean1: true\n'
'number1: 123\n' # fails 'number1: 123\n'
'string2: foo\n' # fails 'string1: foo\n' # fails
'string2: "foo"\n' # fails
'string3: \'bar\'\n' 'string3: \'bar\'\n'
'string4: !!str genericstring\n' # fails 'string4: !!str genericstring\n'
'string5: !!str 456\n' # fails 'string5: !!str 456\n'
'string6: !!str "quotedgenericstring"\n' # fails 'string6: !!str "quotedgenericstring"\n'
'binary: !!binary binstring\n' 'binary: !!binary binstring\n'
'integer: !!int intstring\n' 'integer: !!int intstring\n'
'boolean1: !!bool boolstring\n' 'boolean2: !!bool boolstring\n'
'boolean2: !!bool "quotedboolstring"\n', 'boolean3: !!bool "quotedboolstring"\n',
conf, problem1=(2, 10), problem2=(3, 10), problem3=(4, 10), conf, problem1=(4, 10), problem2=(5, 10))
problem4=(6, 16), problem5=(7, 16), problem6=(8, 16))
self.check('---\n' self.check('---\n'
'multiline string 1: |\n' 'multiline string 1: |\n'
' line 1\n' ' line 1\n'
@ -96,19 +96,19 @@ class QuotedTestCase(RuleTestCase):
def test_quote_type_double(self): def test_quote_type_double(self):
conf = 'quoted-strings: {quote-type: double}\n' conf = 'quoted-strings: {quote-type: double}\n'
self.check('---\n' self.check('---\n'
'string1: "foo"\n' 'boolean1: true\n'
'number1: 123\n' # fails 'number1: 123\n'
'string2: foo\n' # fails 'string1: foo\n' # fails
'string2: "foo"\n'
'string3: \'bar\'\n' # fails 'string3: \'bar\'\n' # fails
'string4: !!str genericstring\n' # fails 'string4: !!str genericstring\n'
'string5: !!str 456\n' # fails 'string5: !!str 456\n'
'string6: !!str "quotedgenericstring"\n' 'string6: !!str "quotedgenericstring"\n'
'binary: !!binary binstring\n' 'binary: !!binary binstring\n'
'integer: !!int intstring\n' 'integer: !!int intstring\n'
'boolean1: !!bool boolstring\n' 'boolean2: !!bool boolstring\n'
'boolean2: !!bool "quotedboolstring"\n', 'boolean3: !!bool "quotedboolstring"\n',
conf, problem1=(3, 10), problem2=(4, 10), problem3=(5, 10), conf, problem1=(4, 10), problem2=(6, 10))
problem4=(6, 16), problem5=(7, 16))
self.check('---\n' self.check('---\n'
'multiline string 1: |\n' 'multiline string 1: |\n'
' line 1\n' ' line 1\n'

@ -16,8 +16,8 @@
""" """
Use this rule to forbid any string values that are not quoted. 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 You can also enforce the type of the quote used using the ``quote-type`` option
``quote-type`` option. (``single``, ``double`` or ``any``).
**Note**: Multi-line strings (with ``|`` or ``>``) will not be checked. **Note**: Multi-line strings (with ``|`` or ``>``) will not be checked.
@ -51,17 +51,21 @@ CONF = {'quote-type': ('any', 'single', 'double')}
def check(conf, token, prev, next, nextnext, context): def check(conf, token, prev, next, nextnext, context):
quote_type = conf['quote-type'] quote_type = conf['quote-type']
if prev and isinstance(prev, yaml.tokens.TagToken): if (isinstance(token, yaml.tokens.ScalarToken) and
if prev.value[1] != "str": isinstance(prev, (yaml.ValueToken, yaml.TagToken))):
# we ignore generic strings, e.g. somestring: !!str testtest # Ignore explicit types, e.g. !!str testtest or !!int 42
if (prev and isinstance(prev, yaml.tokens.TagToken) and
prev.value[0] == '!!'):
return return
if isinstance(token, yaml.tokens.ScalarToken): # Ignore numbers, booleans, etc.
if isinstance(prev, yaml.tokens.ValueToken) or \ resolver = yaml.resolver.Resolver()
isinstance(prev, yaml.tokens.TagToken): if resolver.resolve(yaml.nodes.ScalarNode, token.value,
if ((not token.plain) and (True, False)) != 'tag:yaml.org,2002:str':
((token.style == "|") or (token.style == ">"))): return
# we ignore multi-line strings
# Ignore multi-line strings
if (not token.plain) and (token.style == "|" or token.style == ">"):
return return
if ((quote_type == 'single' and token.style != "'") or if ((quote_type == 'single' and token.style != "'") or
@ -70,5 +74,4 @@ def check(conf, token, prev, next, nextnext, context):
yield LintProblem( yield LintProblem(
token.start_mark.line + 1, token.start_mark.line + 1,
token.start_mark.column + 1, token.start_mark.column + 1,
"string value is not quoted with %s quotes" % (quote_type) "string value is not quoted with %s quotes" % (quote_type))
)

Loading…
Cancel
Save