1"""Pylama's shell support."""
2
3from __future__ import absolute_import, with_statement
4
5import sys
6from os import walk, path as op
7
8from .config import parse_options, CURDIR, setup_logger
9from .core import LOGGER, run
10from .check_async import check_async
11
12
13def check_path(options, rootdir=None, candidates=None, code=None):
14    """Check path.
15
16    :param rootdir: Root directory (for making relative file paths)
17    :param options: Parsed pylama options (from pylama.config.parse_options)
18
19    :returns: (list) Errors list
20
21    """
22    if not candidates:
23        candidates = []
24        for path_ in options.paths:
25            path = op.abspath(path_)
26            if op.isdir(path):
27                for root, _, files in walk(path):
28                    candidates += [op.relpath(op.join(root, f), CURDIR)
29                                   for f in files]
30            else:
31                candidates.append(path)
32
33    if rootdir is None:
34        rootdir = path if op.isdir(path) else op.dirname(path)
35
36    paths = []
37    for path in candidates:
38
39        if not options.force and not any(l.allow(path)
40                                         for _, l in options.linters):
41            continue
42
43        if not op.exists(path):
44            continue
45
46        paths.append(path)
47
48    if options.concurrent:
49        return check_async(paths, options, rootdir)
50
51    errors = []
52    for path in paths:
53        errors += run(path=path, code=code, rootdir=rootdir, options=options)
54    return errors
55
56
57def shell(args=None, error=True):
58    """Endpoint for console.
59
60    Parse a command arguments, configuration files and run a checkers.
61
62    :return list: list of errors
63    :raise SystemExit:
64
65    """
66    if args is None:
67        args = sys.argv[1:]
68
69    options = parse_options(args)
70    setup_logger(options)
71    LOGGER.info(options)
72
73    # Install VSC hook
74    if options.hook:
75        from .hook import install_hook
76        for path in options.paths:
77            return install_hook(path)
78
79    return process_paths(options, error=error)
80
81
82def process_paths(options, candidates=None, error=True):
83    """Process files and log errors."""
84    errors = check_path(options, rootdir=CURDIR, candidates=candidates)
85
86    if options.format in ['pycodestyle', 'pep8']:
87        pattern = "%(filename)s:%(lnum)s:%(col)s: %(text)s"
88    elif options.format == 'pylint':
89        pattern = "%(filename)s:%(lnum)s: [%(type)s] %(text)s"
90    else:  # 'parsable'
91        pattern = "%(filename)s:%(lnum)s:%(col)s: [%(type)s] %(text)s"
92
93    for er in errors:
94        if options.abspath:
95            er._info['filename'] = op.abspath(er.filename)
96        LOGGER.warning(pattern, er._info)
97
98    if error:
99        sys.exit(int(bool(errors)))
100
101    return errors
102
103
104if __name__ == '__main__':
105    shell()
106
107# pylama:ignore=F0001
108