diff --git a/tests/rules/test_quoted_strings.py b/tests/rules/test_quoted_strings.py index d848639..04ee492 100644 --- a/tests/rules/test_quoted_strings.py +++ b/tests/rules/test_quoted_strings.py @@ -34,19 +34,19 @@ class QuotedTestCase(RuleTestCase): 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' @@ -65,19 +65,19 @@ class QuotedTestCase(RuleTestCase): 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' @@ -96,19 +96,19 @@ class QuotedTestCase(RuleTestCase): 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' diff --git a/yamllint/rules/quoted_strings.py b/yamllint/rules/quoted_strings.py index 2380898..711a627 100644 --- a/yamllint/rules/quoted_strings.py +++ b/yamllint/rules/quoted_strings.py @@ -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. @@ -51,24 +51,27 @@ CONF = {'quote-type': ('any', 'single', 'double')} 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))