Skip to content

Commit 63d9271

Browse files
committed
Update pylama
1 parent 6ce0fe1 commit 63d9271

File tree

8 files changed

+247
-218
lines changed

8 files changed

+247
-218
lines changed

pylibs/pylama/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
:license: BSD, see LICENSE for more details.
66
"""
77

8-
version_info = 1, 3, 0
8+
version_info = 1, 3, 3
99

1010
__version__ = version = '.'.join(map(str, version_info))
1111
__project__ = __name__

pylibs/pylama/config.py

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
""" Parse arguments from command line and configuration files. """
2+
import fnmatch
3+
import logging
4+
from argparse import ArgumentParser, Namespace as Options
5+
from os import getcwd, path
6+
from re import compile as re
7+
8+
from . import version, utils
9+
from .core import DEFAULT_LINTERS, LOGGER, STREAM
10+
from .inirama import Namespace
11+
12+
13+
DEFAULT_COMPLEXITY = 10
14+
CURDIR = getcwd()
15+
DEFAULT_INI_PATH = path.join(CURDIR, 'pylama.ini')
16+
17+
18+
def parse_options(
19+
args=None, async=False, select='', ignore='', linters=DEFAULT_LINTERS,
20+
complexity=DEFAULT_COMPLEXITY, options=DEFAULT_INI_PATH):
21+
""" Parse options from command line and configuration files.
22+
23+
:return argparse.Namespace:
24+
25+
"""
26+
parser = get_parser()
27+
actions = dict((a.dest, a) for a in parser._actions)
28+
options = Options(
29+
async=_Default(async), format=_Default('pep8'),
30+
select=_Default(select), ignore=_Default(ignore),
31+
report=_Default(None), verbose=_Default(False),
32+
linters=_Default(linters), complexity=_Default(complexity),
33+
options=_Default(options))
34+
35+
if not (args is None):
36+
options = parser.parse_args(args)
37+
38+
config = get_config(str(options.options))
39+
40+
for k, v in config.default.items():
41+
value = getattr(options, k, _Default(None))
42+
if not isinstance(value, _Default):
43+
continue
44+
45+
action = actions.get(k)
46+
LOGGER.info('Find option %s (%s)', k, v)
47+
name, value = action.dest, action.type(v)\
48+
if callable(action.type) else v
49+
if action.const:
50+
value = bool(int(value))
51+
setattr(options, name, value)
52+
53+
opts = dict(options.__dict__.items())
54+
for name, value in opts.items():
55+
if isinstance(value, _Default):
56+
action = actions.get(name)
57+
if action and callable(action.type):
58+
value.value = action.type(value.value)
59+
60+
setattr(options, name, value.value)
61+
62+
options.file_params = dict()
63+
for k, s in config.sections.items():
64+
if k != config.default_section:
65+
mask = re(fnmatch.translate(k))
66+
options.file_params[mask] = dict(s)
67+
options.file_params[mask]['lint'] = int(
68+
options.file_params[mask].get('lint', 1)
69+
)
70+
71+
return options
72+
73+
74+
def setup_logger(options):
75+
""" Setup logger with options. """
76+
77+
LOGGER.setLevel(logging.INFO if options.verbose else logging.WARN)
78+
if options.report:
79+
LOGGER.removeHandler(STREAM)
80+
LOGGER.addHandler(logging.FileHandler(options.report, mode='w'))
81+
LOGGER.info('Try to read configuration from: ' + options.options)
82+
83+
84+
def get_parser():
85+
""" Make command parser for pylama.
86+
87+
:return ArgumentParser:
88+
89+
"""
90+
split_csp_str = lambda s: list(
91+
set(i for i in s.strip().split(',') if i))
92+
93+
parser = ArgumentParser(description="Code audit tool for python.")
94+
parser.add_argument(
95+
"path", nargs='?', default=_Default(CURDIR),
96+
help="Path on file or directory.")
97+
98+
parser.add_argument(
99+
"--verbose", "-v", action='store_true', help="Verbose mode.")
100+
101+
parser.add_argument('--version', action='version',
102+
version='%(prog)s ' + version)
103+
104+
parser.add_argument(
105+
"--format", "-f", default=_Default('pep8'), choices=['pep8', 'pylint'],
106+
help="Error format.")
107+
108+
parser.add_argument(
109+
"--select", "-s", default=_Default(''), type=split_csp_str,
110+
help="Select errors and warnings. (comma-separated)")
111+
112+
parser.add_argument(
113+
"--linters", "-l", default=_Default(','.join(DEFAULT_LINTERS)),
114+
type=split_csp_str,
115+
help=(
116+
"Select linters. (comma-separated). Choices are %s."
117+
% ','.join(s for s in utils.__all__)
118+
))
119+
120+
parser.add_argument(
121+
"--ignore", "-i", default=_Default(''), type=split_csp_str,
122+
help="Ignore errors and warnings. (comma-separated)")
123+
124+
parser.add_argument(
125+
"--skip", default=_Default(''),
126+
type=lambda s: [re(fnmatch.translate(p)) for p in s.split(',') if p],
127+
help="Skip files by masks (comma-separated, Ex. */messages.py)")
128+
129+
parser.add_argument(
130+
"--complexity", "-c", default=_Default(DEFAULT_COMPLEXITY), type=int,
131+
help="Set mccabe complexity.")
132+
133+
parser.add_argument("--report", "-r", help="Filename for report.")
134+
parser.add_argument(
135+
"--hook", action="store_true", help="Install Git (Mercurial) hook.")
136+
137+
parser.add_argument(
138+
"--async", action="store_true",
139+
help="Enable async mode. Usefull for checking a lot of files. "
140+
"Dont supported with pylint.")
141+
142+
parser.add_argument(
143+
"--options", "-o", default=_Default(DEFAULT_INI_PATH),
144+
help="Select configuration file. By default is '<CURDIR>/pylama.ini'")
145+
146+
return parser
147+
148+
149+
def get_config(ini_path=DEFAULT_INI_PATH):
150+
""" Load configuration from INI.
151+
152+
:return Namespace:
153+
154+
"""
155+
config = Namespace()
156+
config.default_section = 'main'
157+
config.read(ini_path)
158+
159+
return config
160+
161+
162+
class _Default(object):
163+
164+
def __init__(self, value):
165+
self.value = value
166+
167+
def __getattr__(self, name):
168+
return getattr(self.value, name)
169+
170+
def __str__(self):
171+
return str(self.value)
172+
173+
174+
# lint_ignore=R0914,W0212,E1103,C901

pylibs/pylama/core.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
""" Pylama core functionality. Get params and runs the checkers.
1+
""" Pylama's core functionality. Prepare params, check a modeline and run the
2+
checkers.
23
"""
34
import logging
45
import re
@@ -24,12 +25,13 @@
2425

2526
def run(path, ignore=None, select=None, linters=DEFAULT_LINTERS, config=None,
2627
**meta):
27-
""" Run code checking for path.
28+
""" Run a code checkers with given params.
2829
2930
:return errors: list of dictionaries with error's information
3031
3132
"""
3233
errors = []
34+
params = dict(ignore=ignore, select=select)
3335

3436
try:
3537
with open(path, 'rU') as f:
@@ -92,7 +94,7 @@ def run(path, ignore=None, select=None, linters=DEFAULT_LINTERS, config=None,
9294

9395

9496
def parse_modeline(code):
95-
""" Parse modeline params from file.
97+
""" Parse params from file's modeline.
9698
9799
:return dict: Linter params.
98100
@@ -105,7 +107,7 @@ def parse_modeline(code):
105107

106108

107109
def prepare_params(*configs, **params):
108-
""" Prepare and merge a params from modeline or config.
110+
""" Prepare and merge a params from modelines and configs.
109111
110112
:return dict:
111113
@@ -129,7 +131,7 @@ def prepare_params(*configs, **params):
129131

130132

131133
def filter_errors(e, select=None, ignore=None, **params):
132-
""" Filter a erros by select and ignore lists.
134+
""" Filter a erros by select and ignore options.
133135
134136
:return bool:
135137

pylibs/pylama/hook.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from subprocess import Popen, PIPE
88

99
from .main import LOGGER
10+
from .config import parse_options, setup_logger
1011

1112

1213
try:
@@ -32,8 +33,12 @@ def git_hook():
3233

3334
from .main import check_files
3435
_, files_modified, _ = run("git diff-index --cached --name-only HEAD")
35-
LOGGER.setLevel('WARN')
36-
check_files([f for f in map(str, files_modified) if f.endswith('.py')])
36+
37+
options = parse_options()
38+
setup_logger(options)
39+
check_files(
40+
[f for f in map(str, files_modified) if f.endswith('.py')], options
41+
)
3742

3843

3944
def hg_hook(ui, repo, node=None, **kwargs):
@@ -51,8 +56,10 @@ def hg_hook(ui, repo, node=None, **kwargs):
5156
seen.add(file_)
5257
if file_.endswith('.py'):
5358
paths.append(file_)
54-
LOGGER.setLevel('WARN')
55-
check_files(paths)
59+
60+
options = parse_options()
61+
setup_logger(options)
62+
check_files(paths, options)
5663

5764

5865
def install_git(path):

pylibs/pylama/inirama.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,6 @@
11
"""
22
Inirama is a python module that parses INI files.
33
4-
.. _badges:
5-
.. include:: ../README.rst
6-
:start-after: .. _badges:
7-
:end-before: .. _contents:
8-
9-
.. _description:
10-
.. include:: ../README.rst
11-
:start-after: .. _description:
12-
:end-before: .. _badges:
13-
144
:copyright: 2013 by Kirill Klenov.
155
:license: BSD, see LICENSE for more details.
166
"""

0 commit comments

Comments
 (0)