Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
483a8d89a5 | ||
|
|
fa87913566 |
@@ -1,6 +1,11 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
1.22.1 (2020-04-15)
|
||||
-------------------
|
||||
|
||||
- Fix ``quoted-strings`` rule with ``only-when-needed`` on corner cases
|
||||
|
||||
1.22.0 (2020-04-13)
|
||||
-------------------
|
||||
|
||||
|
||||
@@ -316,3 +316,44 @@ class QuotedTestCase(RuleTestCase):
|
||||
' "word 1\\\n' # fails
|
||||
' word 2"\n',
|
||||
conf, problem1=(12, 3))
|
||||
|
||||
def test_only_when_needed_corner_cases(self):
|
||||
conf = 'quoted-strings: {required: only-when-needed}\n'
|
||||
|
||||
self.check('---\n'
|
||||
'- ""\n'
|
||||
'- "- item"\n'
|
||||
'- "key: value"\n'
|
||||
'- "%H:%M:%S"\n'
|
||||
'- "%wheel ALL=(ALL) NOPASSWD: ALL"\n'
|
||||
'- \'"quoted"\'\n'
|
||||
'- "\'foo\' == \'bar\'"\n'
|
||||
'- "\'Mac\' in ansible_facts.product_name"\n',
|
||||
conf)
|
||||
self.check('---\n'
|
||||
'k1: ""\n'
|
||||
'k2: "- item"\n'
|
||||
'k3: "key: value"\n'
|
||||
'k4: "%H:%M:%S"\n'
|
||||
'k5: "%wheel ALL=(ALL) NOPASSWD: ALL"\n'
|
||||
'k6: \'"quoted"\'\n'
|
||||
'k7: "\'foo\' == \'bar\'"\n'
|
||||
'k8: "\'Mac\' in ansible_facts.product_name"\n',
|
||||
conf)
|
||||
|
||||
self.check('---\n'
|
||||
'- ---\n'
|
||||
'- "---"\n' # fails
|
||||
'- ----------\n'
|
||||
'- "----------"\n' # fails
|
||||
'- :wq\n'
|
||||
'- ":wq"\n', # fails
|
||||
conf, problem1=(3, 3), problem2=(5, 3), problem3=(7, 3))
|
||||
self.check('---\n'
|
||||
'k1: ---\n'
|
||||
'k2: "---"\n' # fails
|
||||
'k3: ----------\n'
|
||||
'k4: "----------"\n' # fails
|
||||
'k5: :wq\n'
|
||||
'k6: ":wq"\n', # fails
|
||||
conf, problem1=(3, 5), problem2=(5, 5), problem3=(7, 5))
|
||||
|
||||
@@ -22,7 +22,7 @@ indentation, etc."""
|
||||
|
||||
|
||||
APP_NAME = 'yamllint'
|
||||
APP_VERSION = '1.22.0'
|
||||
APP_VERSION = '1.22.1'
|
||||
APP_DESCRIPTION = __doc__
|
||||
|
||||
__author__ = u'Adrien Vergé'
|
||||
|
||||
@@ -77,16 +77,30 @@ DEFAULT = {'quote-type': 'any',
|
||||
'required': True}
|
||||
|
||||
DEFAULT_SCALAR_TAG = u'tag:yaml.org,2002:str'
|
||||
START_TOKENS = {'#', '*', '!', '?', '@', '`', '&',
|
||||
',', '-', '{', '}', '[', ']', ':'}
|
||||
|
||||
|
||||
def quote_match(quote_type, token_style):
|
||||
def _quote_match(quote_type, token_style):
|
||||
return ((quote_type == 'any') or
|
||||
(quote_type == 'single' and token_style == "'") or
|
||||
(quote_type == 'double' and token_style == '"'))
|
||||
|
||||
|
||||
def _quotes_are_needed(string):
|
||||
loader = yaml.BaseLoader('key: ' + string)
|
||||
# Remove the 5 first tokens corresponding to 'key: ' (StreamStartToken,
|
||||
# BlockMappingStartToken, KeyToken, ScalarToken(value=key), ValueToken)
|
||||
for _ in range(5):
|
||||
loader.get_token()
|
||||
try:
|
||||
a, b = loader.get_token(), loader.get_token()
|
||||
if (isinstance(a, yaml.ScalarToken) and a.style is None and
|
||||
isinstance(b, yaml.BlockEndToken)):
|
||||
return False
|
||||
return True
|
||||
except yaml.scanner.ScannerError:
|
||||
return True
|
||||
|
||||
|
||||
def check(conf, token, prev, next, nextnext, context):
|
||||
if not (isinstance(token, yaml.tokens.ScalarToken) and
|
||||
isinstance(prev, (yaml.BlockEntryToken, yaml.FlowEntryToken,
|
||||
@@ -121,25 +135,25 @@ def check(conf, token, prev, next, nextnext, context):
|
||||
if required is True:
|
||||
|
||||
# Quotes are mandatory and need to match config
|
||||
if token.style is None or not quote_match(quote_type, token.style):
|
||||
if token.style is None or not _quote_match(quote_type, token.style):
|
||||
msg = "string value is not quoted with %s quotes" % (quote_type)
|
||||
|
||||
elif required is False:
|
||||
|
||||
# Quotes are not mandatory but when used need to match config
|
||||
if token.style and not quote_match(quote_type, token.style):
|
||||
if token.style and not _quote_match(quote_type, token.style):
|
||||
msg = "string value is not quoted with %s quotes" % (quote_type)
|
||||
|
||||
elif not token.plain:
|
||||
|
||||
# Quotes are disallowed when not needed
|
||||
if (tag == DEFAULT_SCALAR_TAG and token.value
|
||||
and token.value[0] not in START_TOKENS):
|
||||
if (tag == DEFAULT_SCALAR_TAG and token.value and
|
||||
not _quotes_are_needed(token.value)):
|
||||
msg = "string value is redundantly quoted with %s quotes" % (
|
||||
quote_type)
|
||||
|
||||
# But when used need to match config
|
||||
elif token.style and not quote_match(quote_type, token.style):
|
||||
elif token.style and not _quote_match(quote_type, token.style):
|
||||
msg = "string value is not quoted with %s quotes" % (quote_type)
|
||||
|
||||
if msg is not None:
|
||||
|
||||
Reference in New Issue
Block a user