10000 Update pylama to version 3.3.2 · python-mode/python-mode@d610ccd · GitHub
[go: up one dir, main page]

Skip to content

Commit d610ccd

Browse files
committed
Update pylama to version 3.3.2
1 parent 80dddfe commit d610ccd

File tree

15 files changed

+192
-108
lines changed

15 files changed

+192
-108
lines changed

pymode/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
def auto():
1010
""" Fix PEP8 erorrs in current buffer. """
11-
1211
from .autopep8 import fix_file
1312

1413
class Options(object):
@@ -30,7 +29,6 @@ class Options(object):
3029

3130
def get_documentation():
3231
""" Search documentation and append to current buffer. """
33-
3432
try:
3533
from StringIO import StringIO
3634
except ImportError:

pymode/async.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
""" Python-mode async support. """
2+
23
try:
34
from Queue import Queue
45
except ImportError:

pymode/environment.py

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,19 @@ class VimPymodeEnviroment(object):
1717
prefix = '[Pymode]'
1818

1919
def __init__(self):
20+
""" Init VIM environment. """
2021
self.current = vim.current
2122
self.options = dict(encoding=vim.eval('&enc'))
2223
self.options['debug'] = self.var('g:pymode_debug', True)
2324

2425
@property
2526
def curdir(self):
2627
""" Return current working directory. """
27-
2828
return self.var('getcwd()')
2929

3030
@property
3131
def curbuf(self):
3232
""" Return current buffer. """
33-
3433
return self.current.buffer
3534

3635
@property
@@ -45,7 +44,6 @@ def cursor(self):
4544
@property
4645
def source(self):
4746
""" Return source of current buffer. """
48-
4947
return "\n".join(self.lines)
5048

5149
@property
@@ -66,7 +64,6 @@ def var(self, name, to_bool=False):
6664
:return vimobj:
6765
6866
"""
69-
7067
value = vim.eval(name)
7168

7269
if to_bool:
@@ -82,7 +79,6 @@ def message(self, msg, history=False):
8279
:return: :None
8380
8481
"""
85-
8682
if history:
8783
return vim.command('echom "%s"' % str(msg))
8884

@@ -149,16 +145,14 @@ def error(self, msg):
149145

150146
def debug(self, msg, *args):
151147
""" Print debug information. """
152-
153148
if self.options.get('debug'):
154149
print("%s %s [%s]" % (
155150
int(time.time()), msg, ', '.join([str(a) for a in args])))
156151

157152
def stop(self, value=None):
158153
""" Break Vim function. """
159-
160154
cmd = 'return'
161-
if not value is None:
155+
if value is not None:
162156
cmd += ' ' + self.prepare_value(value)
163157
vim.command(cmd)
164158

@@ -168,7 +162,6 @@ def catch_exceptions(self, func):
168162
:return func:
169163
170164
"""
171-
172165
def _wrapper(*args, **kwargs):
173166
try:
174167
return func(*args, **kwargs)
@@ -181,7 +174,6 @@ def _wrapper(*args, **kwargs):
181174

182175
def run(self, name, *args):
183176
""" Run vim function. """
184-
185177
vim.command('call %s(%s)' % (name, ", ".join([
186178
self.prepare_value(a) for a in args
187179
])))
@@ -198,7 +190,6 @@ def prepare_value(self, value, dumps=True):
198190
:return unicode string:
199191
200192
"""
201-
202193
if dumps:
203194
value = json.dumps(value)
204195

@@ -229,12 +220,10 @@ def get_offset_params(self, cursor=None, base=""):
229220

230221
def goto_line(self, line):
231222
""" Go to line. """
232-
233223
vim.command('normal %sggzz' % line)
234224

235225
def goto_file(self, path, cmd='e', force=False):
236226
""" Function description. """
237-
238227
if force or os.path.abspath(path) != self.curbuf.name:
239228
self.debug('read', path)
240229
vim.command("%s %s" % (cmd, path))

pymode/libs/pylama/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
66
"""
77

8-
__version__ = "3.2.0"
8+
__version__ = "3.3.2"
99
__project__ = "pylama"
1010
__author__ = "Kirill Klenov <horneds@gmail.com>"
1111
__license__ = "GNU LGPL"

pymode/libs/pylama/config.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ def __init__(self, value=None):
3333
def __str__(self):
3434
return str(self.value)
3535

36-
__repr__ = lambda s: "<_Default [%s]>" % s.value
36+
def __repr__(self):
37+
return "<_Default [%s]>" % self.value
3738

3839

3940
def split_csp_str(s):

pymode/libs/pylama/core.py

Lines changed: 60 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
import re
77

88
import logging
9+
from collections import defaultdict
910

1011
from .config import process_value, LOGGER
1112
from .lint.extensions import LINTERS
13+
from .errors import DUPLICATES, Error
1214

1315

1416
#: The skip pattern
@@ -20,18 +22,24 @@
2022
re.I | re.M)
2123

2224

23-
def run(path, code=None, options=None):
25+
def run(path='', code=None, options=None):
2426
""" Run a code checkers with given params.
2527
2628
:return errors: list of dictionaries with error's information
2729
2830
"""
2931
errors = []
30-
params = dict(ignore=options.ignore, select=options.select)
3132
fileconfig = dict()
32-
for mask in options.file_params:
33-
if mask.match(path):
34-
fileconfig.update(options.file_params[mask])
33+
params = dict()
34+
linters = LINTERS
35+
linter_params = dict()
36+
37+
if options:
38+
linters = options.linters
39+
linter_params = options.linter_params
40+
for mask in options.file_params:
41+
if mask.match(path):
42+
fileconfig.update(options.file_params[mask])
3543

3644
try:
3745
with CodeContext(code, path) as ctx:
@@ -41,51 +49,43 @@ def run(path, code=None, options=None):
4149
if params.get('skip'):
4250
return errors
4351

44-
for item in options.linters:
52+
for item in linters:
4553

4654
if not isinstance(item, tuple):
4755
item = (item, LINTERS.get(item))
4856

49-
name, linter = item
57+
lname, linter = item
5058

51-
if not linter or not linter.allow(path):
59+
if not linter or path and not linter.allow(path):
5260
continue
5361

54-
LOGGER.info("Run %s", name)
55-
meta = options.linter_params.get(name, dict())
56-
result = linter.run(path, code=code, **meta)
57-
for e in result:
58-
e['linter'] = name
59-
e['col'] = e.get('col') or 0
60-
e['lnum'] = e.get('lnum') or 0
61-
e['type'] = e.get('type') or 'E'
62-
e['text'] = "%s [%s]" % (
63-
e.get('text', '').strip().split('\n')[0], name)
64-
e['filename'] = path or ''
65-
errors.append(e)
62+
LOGGER.info("Run %s", lname)
63+
meta = linter_params.get(lname, dict())
64+
errors += [Error(filename=path, linter=lname, **e)
65+
for e in linter.run(path, code=code, **meta)]
6666

6767
except IOError as e:
6868
LOGGER.debug("IOError %s", e)
69-
errors.append(dict(
70-
lnum=0, type='E', col=0, text=str(e), filename=path or ''))
69+
errors.append(Error(text=str(e), filename=path, linter=lname))
7170

7271
except SyntaxError as e:
7372
LOGGER.debug("SyntaxError %s", e)
74-
errors.append(dict(
75-
lnum=e.lineno or 0, type='E', col=e.offset or 0,
76-
text=e.args[0] + ' [%s]' % name, filename=path or ''
77-
))
73+
errors.append(
74+
Error(linter=lname, lnum=e.lineno, col=e.offset, text=e.args[0],
75+
filename=path))
7876

7977
except Exception as e:
8078
import traceback
8179
LOGGER.info(traceback.format_exc())
8280

83-
errors = [er for er in errors if filter_errors(er, **params)]
81+
errors = filter_errors(errors, **params)
82+
83+
errors = list(remove_duplicates(errors))
8484

8585
if code and errors:
8686
errors = filter_skiplines(code, errors)
8787

88-
return sorted(errors, key=lambda x: x['lnum'])
88+
return sorted(errors, key=lambda e: e.lnum)
8989

9090

9191
def parse_modeline(code):
@@ -107,7 +107,10 @@ def prepare_params(modeline, fileconfig, options):
107107
:return dict:
108108
109109
"""
110-
params = dict(ignore=options.ignore, select=options.select, skip=False)
110+
params = dict(skip=False, ignore=[], select=[])
111+
if options:
112+
params['ignore'] = options.ignore
113+
params['select'] = options.select
111114

112115
for config in filter(None, [modeline, fileconfig]):
113116
for key in ('ignore', 'select'):
@@ -120,23 +123,26 @@ def prepare_params(modeline, fileconfig, options):
120123
return params
121124

122125

123-
def filter_errors(e, select=None, ignore=None, **params):
126+
def filter_errors(errors, select=None, ignore=None, **params):
124127
""" Filter a erros by select and ignore options.
125128
126129
:return bool:
127130
128131
"""
129-
if select:
130-
for s in select:
131-
if e['text'].startswith(s):
132-
return True
133-
134-
if ignore:
135-
for s in ignore:
136-
if e['text'].startswith(s):
137-
return False
132+
select = select or []
133+
ignore = ignore or []
138134

139-
return True
135+
for e in errors:
136+
for s in select:
137+
if e.number.startswith(s):
138+
yield e
139+
break
140+
else:
141+
for s in ignore:
142+
if e.number.startswith(s):
143+
break
144+
else:
145+
yield e
140146

141147

142148
def filter_skiplines(code, errors):
@@ -148,18 +154,30 @@ def filter_skiplines(code, errors):
148154
if not errors:
149155
return errors
150156

151-
enums = set(er['lnum'] for er in errors)
157+
enums = set(er.lnum for er in errors)
152158
removed = set([
153159
num for num, l in enumerate(code.split('\n'), 1)
154160
if num in enums and SKIP_PATTERN(l)
155161
])
156162

157163
if removed:
158-
errors = [er for er in errors if not er['lnum'] in removed]
164+
errors = [er for er in errors if er.lnum not in removed]
159165

160166
return errors
161167

162168

169+
def remove_duplicates(errors):
170+
""" Remove same errors from others linters. """
171+
passed = defaultdict(list)
172+
for error in errors:
173+
key = error.linter, error.number
174+
if key in DUPLICATES:
175+
if key in passed[error.lnum]:
176+
continue
177+
passed[error.lnum] = DUPLICATES[key]
178+
yield error
179+
180+
163181
class CodeContext(object):
164182

165183
""" Read file if code is None. """

pymode/libs/pylama/errors.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
""" Dont duplicate errors same type. """
2+
3+
DUPLICATES = (
4+
5+
# multiple statements on one line
6+
[('pep8', 'E701'), ('pylint', 'C0321')],
7+
8+
# missing whitespace around operator
9+
[('pep8', 'E225'), ('pylint', 'C0326')],
10+
11+
# unused variable
12+
[('pylint', 'W0612'), ('pyflakes', 'W0612')],
13+
14+
# undefined variable
15+
[('pylint', 'E0602'), ('pyflakes', 'E0602')],
16+
17+
# unused import
18+
[('pylint', 'W0611'), ('pyflakes', 'W0611')],
19+
20+
# unexpected spaces
21+
[('pylint', 'C0326'), ('pep8', 'E251')],
22+
23+
# long lines
24+
[('pylint', 'C0301'), ('pep8', 'E501')],
25+
26+
# whitespace before '('
27+
[('pylint', 'C0326'), ('pep8', 'E211')],
28+
29+
# statement ends with a semicolon
30+
[('pylint', 'W0301'), ('pep8', 'E703')],
31+
32+
# multiple statements on one line
33+
[('pylint', 'C0321'), ('pep8', 'E702')],
34+
35+
)
36+
37+
DUPLICATES = dict((key, values) for values in DUPLICATES for key in values)
38+
39+
40+
class Error(object):
41+
42+
""" Store error information. """
43+
44+
def __init__(self, linter="", col=1, lnum=1, type="E",
45+
text="unknown error", filename="", **kwargs):
46+
""" Init error information with default values. """
47+
text = ' '.join(str(text).strip().split('\n'))
48+
if linter:
49+
text = "%s [%s]" % (text, linter)
50+
number = text.split(' ', 1)[0]
51+
self._info = dict(linter=linter, col=col, lnum=lnum, type=type,
52+
text=text, filename=filename, number=number)
53+
54+
def __getattr__(self, name):
55+
return self._info[name]
56+
57+
def __getitem__(self, name):
58+
return self._info[name]
59+
60+
def __repr__(self):
61+
return "<Error: %s %s>" % (self.number, self.linter)
62+
63+
# pylama:ignore=W0622,D

0 commit comments

Comments
 (0)
0