diff --git a/tests/rules/test_quoted_strings.py b/tests/rules/test_quoted_strings.py index 5f148c0..487c20a 100644 --- a/tests/rules/test_quoted_strings.py +++ b/tests/rules/test_quoted_strings.py @@ -345,23 +345,98 @@ class QuotedTestCase(RuleTestCase): ' word 2"\n', conf, problem1=(9, 3)) - def test_needed_extra_regex(self): - conf1 = 'quoted-strings: {quote-type: single, ' + \ - 'required: only-when-needed, ' + \ - 'needed-extra-regex: ""}\n' + def test_needed_extra_regex_1(self): + conf = 'quoted-strings: {quote-type: single, ' + \ + 'required: only-when-needed, ' + \ + 'needed-extra-regex: ^%.*%$}\n' self.check('---\n' - 'string1: foo\n' - 'string2: \'foo\'\n' # fails - 'string3: \'%foo\'\n', # fails - conf1, problem1=(3, 10), problem2=(4, 10)) + 'string1: \'$foo$\'\n' # fails + 'string2: \'%foo%\'\n', + conf, problem1=(2, 10)) + self.check('---\n' + 'multiline string 1: |\n' + ' \'%line 1\n' + ' line 2%\'\n' + 'multiline string 2: >\n' + ' \'%word 1\n' + ' word 2%\'\n' + 'multiline string 3:\n' + ' \'%word 1\n' + ' word 2%\'\n' + 'multiline string 4:\n' + ' "\'%word 1\\\n' # fails + ' word 2%\'"\n', + conf, problem1=(12, 3)) - conf2 = 'quoted-strings: {quote-type: single, ' + \ - 'required: only-when-needed, ' + \ - 'needed-extra-regex: ^%.*$}\n' + def test_needed_extra_regex_2(self): + conf = 'quoted-strings: {quote-type: single, ' + \ + 'required: only-when-needed, ' + \ + 'needed-extra-regex: ^%}\n' self.check('---\n' - 'string1: foo\n' - 'string2: \'foo\'\n' # fails - 'string3: \'%foo\'\n', - conf2, problem1=(3, 10)) + 'string1: \'$foo\'\n' # fails + 'string2: \'%foo\'\n', + conf, problem1=(2, 10)) + self.check('---\n' + 'multiline string 1: |\n' + ' \'%line 1\n' + ' line 2\'\n' + 'multiline string 2: >\n' + ' \'%word 1\n' + ' word 2\'\n' + 'multiline string 3:\n' + ' \'%word 1\n' + ' word 2\'\n' + 'multiline string 4:\n' + ' "\'%word 1\\\n' # fails + ' word 2\'"\n', + conf, problem1=(12, 3)) + + def test_needed_extra_regex_3(self): + conf = 'quoted-strings: {quote-type: single, ' + \ + 'required: only-when-needed, ' + \ + 'needed-extra-regex: ;$}\n' + + self.check('---\n' + 'string1: \'foo,\'\n' # fails + 'string2: \'foo;\'\n', + conf, problem1=(2, 10)) + self.check('---\n' + 'multiline string 1: |\n' + ' \'line 1;\n' + ' line 2\'\n' + 'multiline string 2: >\n' + ' \'word 1;\n' + ' word 2\'\n' + 'multiline string 3:\n' + ' \'word 1;\n' # fails + ' word 2\'\n' + 'multiline string 4:\n' + ' "\'word 1;\\\n' # fails + ' word 2\'"\n', + conf, problem1=(9, 3), problem2=(12, 3)) + + def test_needed_extra_regex_4(self): + conf = 'quoted-strings: {quote-type: single, ' + \ + 'required: only-when-needed, ' + \ + 'needed-extra-regex: ".+ .+"}\n' + + self.check('---\n' + 'string1: \'foo\'\n' # fails + 'string2: \'foo bar\'\n', + conf, problem1=(2, 10)) + self.check('---\n' + 'multiline string 1: |\n' + ' \'line1\n' + ' line2\'\n' + 'multiline string 2: >\n' + ' \'word1\n' + ' word2\'\n' + 'multiline string 3:\n' + ' \'word1\n' + ' word2\'\n' + 'multiline string 4:\n' + ' "\'word1\\\n' # fails + ' word2\'"\n', + conf, problem1=(12, 3)) diff --git a/yamllint/rules/quoted_strings.py b/yamllint/rules/quoted_strings.py index 91c1623..5425e47 100644 --- a/yamllint/rules/quoted_strings.py +++ b/yamllint/rules/quoted_strings.py @@ -26,6 +26,8 @@ used. * ``required`` defines whether using quotes in string values is required (``true``, default) or not (``false``), or only allowed when really needed (``only-when-needed``). +* ``needed-extra-regex`` allows strings matching the given PCRE regex to be + quoted even when quoting is only allowed when really needed **Note**: Multi-line strings (with ``|`` or ``>``) will not be checked. @@ -63,9 +65,22 @@ used. :: foo: 'bar' + +#. With ``quoted-strings: {quote-type: single, required: only-when-needed, needed-extra-regex: ^%.*%$ }`` + + the following code snippet would **PASS**: + :: + + foo: '%bar%' + + the following code snippet would **FAIL**: + :: + + foo: 'bar' """ import re + import yaml from yamllint.linter import LintProblem @@ -137,7 +152,7 @@ def check(conf, token, prev, next, nextnext, context): and token.value[0] not in START_TOKENS): extra_regex = conf['needed-extra-regex'] - if extra_regex == '' or not re.match(extra_regex, token.value): + if extra_regex == '' or not re.search(extra_regex, token.value): msg = "string value is redundantly quoted with %s quotes" % ( quote_type)