Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
318a12bbe6 | ||
|
|
66adaee66c | ||
|
|
5062b91cac | ||
|
|
3ef85739e3 |
@@ -1,6 +1,13 @@
|
|||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
1.13.0 (2018-11-14)
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
- Use `isinstance(x, y)` instead of `type(x) == y`
|
||||||
|
- Add a new `-f colored` option
|
||||||
|
- Update documentation about colored output when run from CLI
|
||||||
|
|
||||||
1.12.1 (2018-10-17)
|
1.12.1 (2018-10-17)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
|||||||
@@ -102,8 +102,8 @@ Errors and warnings
|
|||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
Problems detected by yamllint can be raised either as errors or as warnings.
|
Problems detected by yamllint can be raised either as errors or as warnings.
|
||||||
The CLI will output them (with different colors when using the ``standard``
|
The CLI will output them (with different colors when using the ``colored``
|
||||||
output format).
|
output format, or ``auto`` when run from a terminal).
|
||||||
|
|
||||||
By default the script will exit with a return code ``1`` *only when* there is one or
|
By default the script will exit with a return code ``1`` *only when* there is one or
|
||||||
more error(s).
|
more error(s).
|
||||||
|
|||||||
@@ -68,6 +68,10 @@ The output will look like (colors are not displayed here):
|
|||||||
10:1 error too many blank lines (4 > 2) (empty-lines)
|
10:1 error too many blank lines (4 > 2) (empty-lines)
|
||||||
11:4 error too many spaces inside braces (braces)
|
11:4 error too many spaces inside braces (braces)
|
||||||
|
|
||||||
|
By default, the output of yamllint is colored when run from a terminal, and pure
|
||||||
|
text in other cases. Add the ``-f standard`` arguments to force non-colored output.
|
||||||
|
Use the ``-f colored`` arguments to force colored output.
|
||||||
|
|
||||||
Add the ``-f parsable`` arguments if you need an output format parsable by a
|
Add the ``-f parsable`` arguments if you need an output format parsable by a
|
||||||
machine (for instance for :doc:`syntax highlighting in text editors
|
machine (for instance for :doc:`syntax highlighting in text editors
|
||||||
<text_editors>`). The output will then look like:
|
<text_editors>`). The output will then look like:
|
||||||
|
|||||||
@@ -351,7 +351,7 @@ class CommandLineTestCase(unittest.TestCase):
|
|||||||
'\n' % file))
|
'\n' % file))
|
||||||
self.assertEqual(err, '')
|
self.assertEqual(err, '')
|
||||||
|
|
||||||
def test_run_colored_output(self):
|
def test_run_default_format_output_in_tty(self):
|
||||||
file = os.path.join(self.wd, 'a.yaml')
|
file = os.path.join(self.wd, 'a.yaml')
|
||||||
|
|
||||||
# Create a pseudo-TTY and redirect stdout to it
|
# Create a pseudo-TTY and redirect stdout to it
|
||||||
@@ -383,3 +383,59 @@ class CommandLineTestCase(unittest.TestCase):
|
|||||||
'no new line character at the end of file '
|
'no new line character at the end of file '
|
||||||
'\033[2m(new-line-at-end-of-file)\033[0m\n'
|
'\033[2m(new-line-at-end-of-file)\033[0m\n'
|
||||||
'\n' % file))
|
'\n' % file))
|
||||||
|
|
||||||
|
def test_run_default_format_output_without_tty(self):
|
||||||
|
file = os.path.join(self.wd, 'a.yaml')
|
||||||
|
|
||||||
|
sys.stdout, sys.stderr = StringIO(), StringIO()
|
||||||
|
with self.assertRaises(SystemExit) as ctx:
|
||||||
|
cli.run((file, ))
|
||||||
|
|
||||||
|
self.assertEqual(ctx.exception.code, 1)
|
||||||
|
|
||||||
|
out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
|
||||||
|
self.assertEqual(out, (
|
||||||
|
'%s\n'
|
||||||
|
' 2:4 error trailing spaces (trailing-spaces)\n'
|
||||||
|
' 3:4 error no new line character at the end of file '
|
||||||
|
'(new-line-at-end-of-file)\n'
|
||||||
|
'\n' % file))
|
||||||
|
self.assertEqual(err, '')
|
||||||
|
|
||||||
|
def test_run_auto_output_without_tty_output(self):
|
||||||
|
file = os.path.join(self.wd, 'a.yaml')
|
||||||
|
|
||||||
|
sys.stdout, sys.stderr = StringIO(), StringIO()
|
||||||
|
with self.assertRaises(SystemExit) as ctx:
|
||||||
|
cli.run((file, '--format', 'auto'))
|
||||||
|
|
||||||
|
self.assertEqual(ctx.exception.code, 1)
|
||||||
|
|
||||||
|
out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
|
||||||
|
self.assertEqual(out, (
|
||||||
|
'%s\n'
|
||||||
|
' 2:4 error trailing spaces (trailing-spaces)\n'
|
||||||
|
' 3:4 error no new line character at the end of file '
|
||||||
|
'(new-line-at-end-of-file)\n'
|
||||||
|
'\n' % file))
|
||||||
|
self.assertEqual(err, '')
|
||||||
|
|
||||||
|
def test_run_format_colored(self):
|
||||||
|
file = os.path.join(self.wd, 'a.yaml')
|
||||||
|
|
||||||
|
sys.stdout, sys.stderr = StringIO(), StringIO()
|
||||||
|
with self.assertRaises(SystemExit) as ctx:
|
||||||
|
cli.run((file, '--format', 'colored'))
|
||||||
|
|
||||||
|
self.assertEqual(ctx.exception.code, 1)
|
||||||
|
|
||||||
|
out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
|
||||||
|
self.assertEqual(out, (
|
||||||
|
'\033[4m%s\033[0m\n'
|
||||||
|
' \033[2m2:4\033[0m \033[31merror\033[0m '
|
||||||
|
'trailing spaces \033[2m(trailing-spaces)\033[0m\n'
|
||||||
|
' \033[2m3:4\033[0m \033[31merror\033[0m '
|
||||||
|
'no new line character at the end of file '
|
||||||
|
'\033[2m(new-line-at-end-of-file)\033[0m\n'
|
||||||
|
'\n' % file))
|
||||||
|
self.assertEqual(err, '')
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ indentation, etc."""
|
|||||||
|
|
||||||
|
|
||||||
APP_NAME = 'yamllint'
|
APP_NAME = 'yamllint'
|
||||||
APP_VERSION = '1.12.1'
|
APP_VERSION = '1.13.0'
|
||||||
APP_DESCRIPTION = __doc__
|
APP_DESCRIPTION = __doc__
|
||||||
|
|
||||||
__author__ = u'Adrien Vergé'
|
__author__ = u'Adrien Vergé'
|
||||||
|
|||||||
@@ -96,8 +96,8 @@ def run(argv=None):
|
|||||||
action='store',
|
action='store',
|
||||||
help='custom configuration (as YAML source)')
|
help='custom configuration (as YAML source)')
|
||||||
parser.add_argument('-f', '--format',
|
parser.add_argument('-f', '--format',
|
||||||
choices=('parsable', 'standard'), default='standard',
|
choices=('parsable', 'standard', 'colored', 'auto'),
|
||||||
help='format for parsing output')
|
default='auto', help='format for parsing output')
|
||||||
parser.add_argument('-s', '--strict',
|
parser.add_argument('-s', '--strict',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='return non-zero exit code on warnings '
|
help='return non-zero exit code on warnings '
|
||||||
@@ -143,7 +143,8 @@ def run(argv=None):
|
|||||||
for problem in linter.run(f, conf, filepath):
|
for problem in linter.run(f, conf, filepath):
|
||||||
if args.format == 'parsable':
|
if args.format == 'parsable':
|
||||||
print(Format.parsable(problem, file))
|
print(Format.parsable(problem, file))
|
||||||
elif supports_color():
|
elif args.format == 'colored' or \
|
||||||
|
(args.format == 'auto' and supports_color()):
|
||||||
if first:
|
if first:
|
||||||
print('\033[4m%s\033[0m' % file)
|
print('\033[4m%s\033[0m' % file)
|
||||||
first = False
|
first = False
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ class YamlLintConfig(object):
|
|||||||
assert isinstance(base_config, YamlLintConfig)
|
assert isinstance(base_config, YamlLintConfig)
|
||||||
|
|
||||||
for rule in self.rules:
|
for rule in self.rules:
|
||||||
if (type(self.rules[rule]) == dict and
|
if (isinstance(self.rules[rule], dict) and
|
||||||
rule in base_config.rules and
|
rule in base_config.rules and
|
||||||
base_config.rules[rule] is not False):
|
base_config.rules[rule] is not False):
|
||||||
base_config.rules[rule].update(self.rules[rule])
|
base_config.rules[rule].update(self.rules[rule])
|
||||||
@@ -70,7 +70,7 @@ class YamlLintConfig(object):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
raise YamlLintConfigError('invalid config: %s' % e)
|
raise YamlLintConfigError('invalid config: %s' % e)
|
||||||
|
|
||||||
if type(conf) != dict:
|
if not isinstance(conf, dict):
|
||||||
raise YamlLintConfigError('invalid config: not a dict')
|
raise YamlLintConfigError('invalid config: not a dict')
|
||||||
|
|
||||||
self.rules = conf.get('rules', {})
|
self.rules = conf.get('rules', {})
|
||||||
@@ -85,7 +85,7 @@ class YamlLintConfig(object):
|
|||||||
raise YamlLintConfigError('invalid config: %s' % e)
|
raise YamlLintConfigError('invalid config: %s' % e)
|
||||||
|
|
||||||
if 'ignore' in conf:
|
if 'ignore' in conf:
|
||||||
if type(conf['ignore']) != str:
|
if not isinstance(conf['ignore'], str):
|
||||||
raise YamlLintConfigError(
|
raise YamlLintConfigError(
|
||||||
'invalid config: ignore should contain file patterns')
|
'invalid config: ignore should contain file patterns')
|
||||||
self.ignore = pathspec.PathSpec.from_lines(
|
self.ignore = pathspec.PathSpec.from_lines(
|
||||||
@@ -107,10 +107,10 @@ def validate_rule_conf(rule, conf):
|
|||||||
elif conf == 'enable':
|
elif conf == 'enable':
|
||||||
conf = {}
|
conf = {}
|
||||||
|
|
||||||
if type(conf) == dict:
|
if isinstance(conf, dict):
|
||||||
if ('ignore' in conf and
|
if ('ignore' in conf and
|
||||||
type(conf['ignore']) != pathspec.pathspec.PathSpec):
|
not isinstance(conf['ignore'], pathspec.pathspec.PathSpec)):
|
||||||
if type(conf['ignore']) != str:
|
if not isinstance(conf['ignore'], str):
|
||||||
raise YamlLintConfigError(
|
raise YamlLintConfigError(
|
||||||
'invalid config: ignore should contain file patterns')
|
'invalid config: ignore should contain file patterns')
|
||||||
conf['ignore'] = pathspec.PathSpec.from_lines(
|
conf['ignore'] = pathspec.PathSpec.from_lines(
|
||||||
@@ -130,14 +130,14 @@ def validate_rule_conf(rule, conf):
|
|||||||
raise YamlLintConfigError(
|
raise YamlLintConfigError(
|
||||||
'invalid config: unknown option "%s" for rule "%s"' %
|
'invalid config: unknown option "%s" for rule "%s"' %
|
||||||
(optkey, rule.ID))
|
(optkey, rule.ID))
|
||||||
if type(options[optkey]) == tuple:
|
if isinstance(options[optkey], tuple):
|
||||||
if (conf[optkey] not in options[optkey] and
|
if (conf[optkey] not in options[optkey] and
|
||||||
type(conf[optkey]) not in options[optkey]):
|
type(conf[optkey]) not in options[optkey]):
|
||||||
raise YamlLintConfigError(
|
raise YamlLintConfigError(
|
||||||
'invalid config: option "%s" of "%s" should be in %s'
|
'invalid config: option "%s" of "%s" should be in %s'
|
||||||
% (optkey, rule.ID, options[optkey]))
|
% (optkey, rule.ID, options[optkey]))
|
||||||
else:
|
else:
|
||||||
if type(conf[optkey]) != options[optkey]:
|
if not isinstance(conf[optkey], options[optkey]):
|
||||||
raise YamlLintConfigError(
|
raise YamlLintConfigError(
|
||||||
'invalid config: option "%s" of "%s" should be %s'
|
'invalid config: option "%s" of "%s" should be %s'
|
||||||
% (optkey, rule.ID, options[optkey].__name__))
|
% (optkey, rule.ID, options[optkey].__name__))
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ def run(input, conf, filepath=None):
|
|||||||
if conf.is_file_ignored(filepath):
|
if conf.is_file_ignored(filepath):
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
if type(input) in (type(b''), type(u'')): # compat with Python 2 & 3
|
if isinstance(input, (type(b''), type(u''))): # compat with Python 2 & 3
|
||||||
return _run(input, conf, filepath)
|
return _run(input, conf, filepath)
|
||||||
elif hasattr(input, 'read'): # Python 2's file or Python 3's io.IOBase
|
elif hasattr(input, 'read'): # Python 2's file or Python 3's io.IOBase
|
||||||
# We need to have everything in memory to parse correctly
|
# We need to have everything in memory to parse correctly
|
||||||
|
|||||||
@@ -86,14 +86,16 @@ CONF = {'present': bool}
|
|||||||
|
|
||||||
def check(conf, token, prev, next, nextnext, context):
|
def check(conf, token, prev, next, nextnext, context):
|
||||||
if conf['present']:
|
if conf['present']:
|
||||||
if (isinstance(token, yaml.StreamEndToken) and
|
is_stream_end = isinstance(token, yaml.StreamEndToken)
|
||||||
not (isinstance(prev, yaml.DocumentEndToken) or
|
is_start = isinstance(token, yaml.DocumentStartToken)
|
||||||
isinstance(prev, yaml.StreamStartToken))):
|
prev_is_end_or_stream_start = isinstance(
|
||||||
|
prev, (yaml.DocumentEndToken, yaml.StreamStartToken)
|
||||||
|
)
|
||||||
|
|
||||||
|
if is_stream_end and not prev_is_end_or_stream_start:
|
||||||
yield LintProblem(token.start_mark.line, 1,
|
yield LintProblem(token.start_mark.line, 1,
|
||||||
'missing document end "..."')
|
'missing document end "..."')
|
||||||
elif (isinstance(token, yaml.DocumentStartToken) and
|
elif is_start and not prev_is_end_or_stream_start:
|
||||||
not (isinstance(prev, yaml.DocumentEndToken) or
|
|
||||||
isinstance(prev, yaml.StreamStartToken))):
|
|
||||||
yield LintProblem(token.start_mark.line + 1, 1,
|
yield LintProblem(token.start_mark.line + 1, 1,
|
||||||
'missing document end "..."')
|
'missing document end "..."')
|
||||||
|
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ def check_scalar_indentation(conf, token, context):
|
|||||||
|
|
||||||
def compute_expected_indent(found_indent):
|
def compute_expected_indent(found_indent):
|
||||||
def detect_indent(base_indent):
|
def detect_indent(base_indent):
|
||||||
if type(context['spaces']) is not int:
|
if not isinstance(context['spaces'], int):
|
||||||
context['spaces'] = found_indent - base_indent
|
context['spaces'] = found_indent - base_indent
|
||||||
return base_indent + context['spaces']
|
return base_indent + context['spaces']
|
||||||
|
|
||||||
@@ -312,7 +312,7 @@ def _check(conf, token, prev, next, nextnext, context):
|
|||||||
token.start_mark.line + 1 > context['cur_line'])
|
token.start_mark.line + 1 > context['cur_line'])
|
||||||
|
|
||||||
def detect_indent(base_indent, next):
|
def detect_indent(base_indent, next):
|
||||||
if type(context['spaces']) is not int:
|
if not isinstance(context['spaces'], int):
|
||||||
context['spaces'] = next.start_mark.column - base_indent
|
context['spaces'] = next.start_mark.column - base_indent
|
||||||
return base_indent + context['spaces']
|
return base_indent + context['spaces']
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user