Merge tag 'v1.15.0' into packaging

packaging
Philipp Huebner 6 years ago
commit d77cb4e2f6

@ -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': except EnvironmentError as e:
print(Format.parsable(problem, file)) print(e, file=sys.stderr)
elif args.format == 'colored' or \ sys.exit(-1)
(args.format == 'auto' and supports_color()): prob_level = show_problems(problems, file, args_format=args.format)
if first: max_level = max(max_level, prob_level)
print('\033[4m%s\033[0m' % file)
first = False # read yaml from stdin
if args.stdin:
print(Format.standard_color(problem, file)) try:
else: problems = linter.run(sys.stdin, conf, '')
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, '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

Loading…
Cancel
Save