Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37700ab3e6 | ||
|
|
f66661e36d | ||
|
|
d6b89e94e4 | ||
|
|
05dfcbc109 |
@@ -1,6 +1,11 @@
|
|||||||
Changelog
|
Changelog
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
1.15.0 (2019-02-11)
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
- Allow linting from standard input with ``yamllint -``
|
||||||
|
|
||||||
1.14.0 (2019-01-14)
|
1.14.0 (2019-01-14)
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ man_pages = [
|
|||||||
class Mock(MagicMock):
|
class Mock(MagicMock):
|
||||||
@classmethod
|
@classmethod
|
||||||
def __getattr__(cls, name):
|
def __getattr__(cls, name):
|
||||||
return MagicMock()
|
return MagicMock()
|
||||||
|
|
||||||
|
|
||||||
MOCK_MODULES = ['pathspec', 'yaml']
|
MOCK_MODULES = ['pathspec', 'yaml']
|
||||||
|
|||||||
@@ -50,6 +50,12 @@ You can also lint all YAML files in a whole directory:
|
|||||||
|
|
||||||
yamllint .
|
yamllint .
|
||||||
|
|
||||||
|
Or lint a YAML stream from standard input:
|
||||||
|
|
||||||
|
.. code:: bash
|
||||||
|
|
||||||
|
echo -e 'this: is\nvalid: YAML' | yamllint -
|
||||||
|
|
||||||
The output will look like (colors are not displayed here):
|
The output will look like (colors are not displayed here):
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|||||||
@@ -140,6 +140,17 @@ class CommandLineTestCase(unittest.TestCase):
|
|||||||
r'not allowed with argument -c\/--config-file$'
|
r'not allowed with argument -c\/--config-file$'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# checks if reading from stdin and files are mutually exclusive
|
||||||
|
sys.stdout, sys.stderr = StringIO(), StringIO()
|
||||||
|
with self.assertRaises(SystemExit) as ctx:
|
||||||
|
cli.run(('-', 'file'))
|
||||||
|
|
||||||
|
self.assertNotEqual(ctx.exception.code, 0)
|
||||||
|
|
||||||
|
out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
|
||||||
|
self.assertEqual(out, '')
|
||||||
|
self.assertRegexpMatches(err, r'^usage')
|
||||||
|
|
||||||
def test_run_with_bad_config(self):
|
def test_run_with_bad_config(self):
|
||||||
sys.stdout, sys.stderr = StringIO(), StringIO()
|
sys.stdout, sys.stderr = StringIO(), StringIO()
|
||||||
with self.assertRaises(SystemExit) as ctx:
|
with self.assertRaises(SystemExit) as ctx:
|
||||||
@@ -434,3 +445,22 @@ class CommandLineTestCase(unittest.TestCase):
|
|||||||
'\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))
|
||||||
self.assertEqual(err, '')
|
self.assertEqual(err, '')
|
||||||
|
|
||||||
|
def test_run_read_from_stdin(self):
|
||||||
|
# prepares stdin with an invalid yaml string so that we can check
|
||||||
|
# for its specific error, and be assured that stdin was read
|
||||||
|
sys.stdout, sys.stderr = StringIO(), StringIO()
|
||||||
|
sys.stdin = StringIO(
|
||||||
|
'I am a string\n'
|
||||||
|
'therefore: I am an error\n')
|
||||||
|
|
||||||
|
with self.assertRaises(SystemExit) as ctx:
|
||||||
|
cli.run(('-', '-f', 'parsable'))
|
||||||
|
|
||||||
|
self.assertNotEqual(ctx.exception.code, 0)
|
||||||
|
|
||||||
|
out, err = sys.stdout.getvalue(), sys.stderr.getvalue()
|
||||||
|
self.assertEqual(out, (
|
||||||
|
'stdin:2:10: [error] syntax error: '
|
||||||
|
'mapping values are not allowed here\n'))
|
||||||
|
self.assertEqual(err, '')
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ indentation, etc."""
|
|||||||
|
|
||||||
|
|
||||||
APP_NAME = 'yamllint'
|
APP_NAME = 'yamllint'
|
||||||
APP_VERSION = '1.14.0'
|
APP_VERSION = '1.15.0'
|
||||||
APP_DESCRIPTION = __doc__
|
APP_DESCRIPTION = __doc__
|
||||||
|
|
||||||
__author__ = u'Adrien Vergé'
|
__author__ = u'Adrien Vergé'
|
||||||
|
|||||||
@@ -83,11 +83,41 @@ class Format(object):
|
|||||||
return line
|
return line
|
||||||
|
|
||||||
|
|
||||||
|
def show_problems(problems, file, args_format):
|
||||||
|
max_level = 0
|
||||||
|
first = True
|
||||||
|
|
||||||
|
for problem in problems:
|
||||||
|
if args_format == 'parsable':
|
||||||
|
print(Format.parsable(problem, file))
|
||||||
|
elif args_format == 'colored' or \
|
||||||
|
(args_format == 'auto' and supports_color()):
|
||||||
|
if first:
|
||||||
|
print('\033[4m%s\033[0m' % file)
|
||||||
|
first = False
|
||||||
|
print(Format.standard_color(problem, file))
|
||||||
|
else:
|
||||||
|
if first:
|
||||||
|
print(file)
|
||||||
|
first = False
|
||||||
|
print(Format.standard(problem, file))
|
||||||
|
max_level = max(max_level, PROBLEM_LEVELS[problem.level])
|
||||||
|
|
||||||
|
if not first and args_format != 'parsable':
|
||||||
|
print('')
|
||||||
|
|
||||||
|
return max_level
|
||||||
|
|
||||||
|
|
||||||
def run(argv=None):
|
def run(argv=None):
|
||||||
parser = argparse.ArgumentParser(prog=APP_NAME,
|
parser = argparse.ArgumentParser(prog=APP_NAME,
|
||||||
description=APP_DESCRIPTION)
|
description=APP_DESCRIPTION)
|
||||||
parser.add_argument('files', metavar='FILE_OR_DIR', nargs='+',
|
files_group = parser.add_mutually_exclusive_group(required=True)
|
||||||
help='files to check')
|
files_group.add_argument('files', metavar='FILE_OR_DIR', nargs='*',
|
||||||
|
default=(),
|
||||||
|
help='files to check')
|
||||||
|
files_group.add_argument('-', action='store_true', dest='stdin',
|
||||||
|
help='read from standard input')
|
||||||
config_group = parser.add_mutually_exclusive_group()
|
config_group = parser.add_mutually_exclusive_group()
|
||||||
config_group.add_argument('-c', '--config-file', dest='config_file',
|
config_group.add_argument('-c', '--config-file', dest='config_file',
|
||||||
action='store',
|
action='store',
|
||||||
@@ -105,8 +135,6 @@ def run(argv=None):
|
|||||||
parser.add_argument('-v', '--version', action='version',
|
parser.add_argument('-v', '--version', action='version',
|
||||||
version='{} {}'.format(APP_NAME, APP_VERSION))
|
version='{} {}'.format(APP_NAME, APP_VERSION))
|
||||||
|
|
||||||
# TODO: read from stdin when no filename?
|
|
||||||
|
|
||||||
args = parser.parse_args(argv)
|
args = parser.parse_args(argv)
|
||||||
|
|
||||||
# User-global config is supposed to be in ~/.config/yamllint/config
|
# User-global config is supposed to be in ~/.config/yamllint/config
|
||||||
@@ -138,32 +166,23 @@ def run(argv=None):
|
|||||||
for file in find_files_recursively(args.files):
|
for file in find_files_recursively(args.files):
|
||||||
filepath = file[2:] if file.startswith('./') else file
|
filepath = file[2:] if file.startswith('./') else file
|
||||||
try:
|
try:
|
||||||
first = True
|
|
||||||
with open(file) as f:
|
with open(file) as f:
|
||||||
for problem in linter.run(f, conf, filepath):
|
problems = linter.run(f, conf, filepath)
|
||||||
if args.format == 'parsable':
|
|
||||||
print(Format.parsable(problem, file))
|
|
||||||
elif args.format == 'colored' or \
|
|
||||||
(args.format == 'auto' and supports_color()):
|
|
||||||
if first:
|
|
||||||
print('\033[4m%s\033[0m' % file)
|
|
||||||
first = False
|
|
||||||
|
|
||||||
print(Format.standard_color(problem, file))
|
|
||||||
else:
|
|
||||||
if first:
|
|
||||||
print(file)
|
|
||||||
first = False
|
|
||||||
|
|
||||||
print(Format.standard(problem, file))
|
|
||||||
|
|
||||||
max_level = max(max_level, PROBLEM_LEVELS[problem.level])
|
|
||||||
|
|
||||||
if not first and args.format != 'parsable':
|
|
||||||
print('')
|
|
||||||
except EnvironmentError as e:
|
except EnvironmentError as e:
|
||||||
print(e, file=sys.stderr)
|
print(e, file=sys.stderr)
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
prob_level = show_problems(problems, file, args_format=args.format)
|
||||||
|
max_level = max(max_level, prob_level)
|
||||||
|
|
||||||
|
# read yaml from stdin
|
||||||
|
if args.stdin:
|
||||||
|
try:
|
||||||
|
problems = linter.run(sys.stdin, conf, '')
|
||||||
|
except EnvironmentError as e:
|
||||||
|
print(e, file=sys.stderr)
|
||||||
|
sys.exit(-1)
|
||||||
|
prob_level = show_problems(problems, 'stdin', args_format=args.format)
|
||||||
|
max_level = max(max_level, prob_level)
|
||||||
|
|
||||||
if max_level == PROBLEM_LEVELS['error']:
|
if max_level == PROBLEM_LEVELS['error']:
|
||||||
return_code = 1
|
return_code = 1
|
||||||
|
|||||||
Reference in New Issue
Block a user