6
6
7
7
8
8
from collections import defaultdict
9
- from configparser import ConfigParser , NoSectionError , NoOptionError
9
+ from configparser import ConfigParser , NoOptionError , NoSectionError
10
10
from os import makedirs
11
- from os .path import getmtime , exists , join , dirname
11
+ from os .path import dirname , exists , getmtime , join
12
12
13
- from pylint import lint
14
- from pylint .config import PYLINTRC
15
13
import pytest
16
14
import toml
15
+ from pylint import lint
16
+ from pylint .config import PYLINTRC
17
17
18
18
from .pylint_util import ProgrammaticReporter
19
- from .util import get_rel_path , PyLintException , should_include_file
19
+ from .util import PyLintException , get_rel_path , should_include_file
20
20
21
- HISTKEY = ' pylint/mtimes'
22
- PYLINT_CONFIG_CACHE_KEY = ' pylintrc'
21
+ HISTKEY = " pylint/mtimes"
22
+ PYLINT_CONFIG_CACHE_KEY = " pylintrc"
23
23
FILL_CHARS = 80
24
- MARKER = ' pylint'
24
+ MARKER = " pylint"
25
25
26
26
27
27
def pytest_addoption (parser ):
28
28
"""Add all our command line options"""
29
29
group = parser .getgroup ("pylint" )
30
30
group .addoption (
31
- "--pylint" ,
32
- action = "store_true" , default = False ,
33
- help = "run pylint on all"
31
+ "--pylint" , action = "store_true" , default = False , help = "run pylint on all"
34
32
)
35
33
group .addoption (
36
34
"--no-pylint" ,
37
- action = "store_true" , default = False ,
38
- help = "disable running pylint "
35
+ action = "store_true" ,
36
+ default = False ,
37
+ help = "disable running pylint " ,
39
38
)
40
39
41
40
group .addoption (
42
- '--pylint-rcfile' ,
43
- default = None ,
44
- help = 'Location of RC file if not pylintrc'
41
+ "--pylint-rcfile" , default = None , help = "Location of RC file if not pylintrc"
45
42
)
46
43
group .addoption (
47
- ' --pylint-error-types' ,
48
- default = ' CRWEF' ,
49
- help = ' The types of pylint errors to consider failures by letter'
50
- ' , default is all of them (CRWEF).'
44
+ " --pylint-error-types" ,
45
+ default = " CRWEF" ,
46
+ help = " The types of pylint errors to consider failures by letter"
47
+ " , default is all of them (CRWEF)." ,
51
48
)
52
49
group .addoption (
53
- ' --pylint-jobs' ,
50
+ " --pylint-jobs" ,
54
51
default = None ,
55
- help = ' Specify number of processes to use for pylint'
52
+ help = " Specify number of processes to use for pylint" ,
56
53
)
57
54
group .addoption (
58
- ' --pylint-output-file' ,
55
+ " --pylint-output-file" ,
59
56
default = None ,
60
- help = ' Path to a file where Pylint report will be printed to.'
57
+ help = " Path to a file where Pylint report will be printed to." ,
61
58
)
62
59
group .addoption (
63
- '--pylint-ignore' ,
64
- default = None ,
65
- help = 'Files/directories that will be ignored'
60
+ "--pylint-ignore" , default = None , help = "Files/directories that will be ignored"
66
61
)
67
62
group .addoption (
68
- ' --pylint-ignore-patterns' ,
63
+ " --pylint-ignore-patterns" ,
69
64
default = None ,
70
- help = ' Files/directories patterns that will be ignored'
65
+ help = " Files/directories patterns that will be ignored" ,
71
66
)
72
67
73
68
@@ -77,10 +72,7 @@ def pytest_configure(config):
77
72
78
73
:param _pytest.config.Config config: pytest config object
79
74
"""
80
- config .addinivalue_line (
81
- 'markers' ,
82
- "{0}: Tests which run pylint." .format (MARKER )
83
- )
75
+ config .addinivalue_line ("markers" , "{0}: Tests which run pylint." .format (MARKER ))
84
76
if config .option .pylint and not config .option .no_pylint :
85
77
pylint_plugin = PylintPlugin (config )
86
78
config .pluginmanager .register (pylint_plugin )
@@ -90,9 +82,10 @@ class PylintPlugin:
90
82
"""
91
83
The core plugin for pylint
92
84
"""
85
+
93
86
# pylint: disable=too-many-instance-attributes
94
87
def __init__ (self , config ):
95
- if hasattr (config , ' cache' ):
88
+ if hasattr (config , " cache" ):
96
89
self .mtimes = config .cache .get (HISTKEY , {})
97
90
else :
98
91
self .mtimes = {}
@@ -136,36 +129,32 @@ def pytest_configure(self, config):
136
129
137
130
# Command line arguments take presedence over rcfile ones if set
138
131
if config .option .pylint_ignore is not None :
139
- self .pylint_ignore = config .option .pylint_ignore .split (',' )
132
+ self .pylint_ignore = config .option .pylint_ignore .split ("," )
140
133
if config .option .pylint_ignore_patterns is not None :
141
- self .pylint_ignore_patterns = (
142
- config . option . pylint_ignore_patterns . split ( ',' )
134
+ self .pylint_ignore_patterns = config . option . pylint_ignore_patterns . split (
135
+ ","
143
136
)
144
137
145
138
def _load_rc_file (self , pylintrc_file ):
146
139
self .pylint_config = ConfigParser ()
147
140
self .pylint_config .read (pylintrc_file )
148
141
149
142
try :
150
- ignore_string = self .pylint_config .get (' MASTER' , ' ignore' )
143
+ ignore_string = self .pylint_config .get (" MASTER" , " ignore" )
151
144
if ignore_string :
152
- self .pylint_ignore = ignore_string .split (',' )
145
+ self .pylint_ignore = ignore_string .split ("," )
153
146
except (NoSectionError , NoOptionError ):
154
147
pass
155
148
156
149
try :
157
- ignore_patterns = self .pylint_config .get (
158
- 'MASTER' , 'ignore-patterns'
159
- )
150
+ ignore_patterns = self .pylint_config .get ("MASTER" , "ignore-patterns" )
160
151
if ignore_patterns :
161
- self .pylint_ignore_patterns = ignore_patterns .split (',' )
152
+ self .pylint_ignore_patterns = ignore_patterns .split ("," )
162
153
except (NoSectionError , NoOptionError ):
163
154
pass
164
155
165
156
try :
166
- self .pylint_msg_template = self .pylint_config .get (
167
- 'REPORTS' , 'msg-template'
168
- )
157
+ self .pylint_msg_template = self .pylint_config .get ("REPORTS" , "msg-template" )
169
158
except (NoSectionError , NoOptionError ):
170
159
pass
171
160
@@ -192,13 +181,9 @@ def _load_pyproject_toml(self, pylintrc_file):
192
181
ignore = master_section .get ("ignore" )
193
182
if ignore :
194
183
self .pylint_ignore = (
195
- ignore .split ("," )
196
- if isinstance (ignore , str )
197
- else ignore
184
+ ignore .split ("," ) if isinstance (ignore , str ) else ignore
198
185
)
199
- self .pylint_ignore_patterns = (
200
- master_section .get ("ignore-patterns" ) or []
201
- )
186
+ self .pylint_ignore_patterns = master_section .get ("ignore-patterns" ) or []
202
187
self .pylint_msg_template = reports_section .get ("msg-template" )
203
188
204
189
def pytest_sessionfinish (self , session ):
@@ -207,7 +192,7 @@ def pytest_sessionfinish(self, session):
207
192
208
193
:param _pytest.main.Session session: the pytest session object
209
194
"""
210
- if hasattr (session .config , ' cache' ):
195
+ if hasattr (session .config , " cache" ):
211
196
session .config .cache .set (HISTKEY , self .mtimes )
212
197
213
198
def pytest_collect_file (self , path , parent ):
@@ -217,11 +202,9 @@ def pytest_collect_file(self, path, parent):
217
202
218
203
rel_path = get_rel_path (path .strpath , parent .session .fspath .strpath )
219
204
if should_include_file (
220
- rel_path , self .pylint_ignore , self .pylint_ignore_patterns
205
+ rel_path , self .pylint_ignore , self .pylint_ignore_patterns
221
206
):
222
- item = PylintFile .from_parent (
223
- parent , fspath = path , plugin = self
224
- )
207
+ item = PylintFile .from_parent (parent , fspath = path , plugin = self )
225
208
else :
226
209
return None
227
210
@@ -240,26 +223,20 @@ def pytest_collection_finish(self, session):
240
223
# Build argument list for pylint
241
224
args_list = list (self .pylint_files )
242
225
if self .pylintrc_file :
243
- args_list .append ('--rcfile={0}' .format (
244
- self .pylintrc_file
245
- ))
226
+ args_list .append ("--rcfile={0}" .format (self .pylintrc_file ))
246
227
if jobs is not None :
247
- args_list .append ('-j' )
228
+ args_list .append ("-j" )
248
229
args_list .append (jobs )
249
230
# These allow the user to override the pylint configuration's
250
231
# ignore list
251
232
if self .pylint_ignore :
252
- args_list .append (
253
- '--ignore={0}' .format (',' .join (self .pylint_ignore ))
254
- )
233
+ args_list .append ("--ignore={0}" .format ("," .join (self .pylint_ignore )))
255
234
if self .pylint_ignore_patterns :
256
235
args_list .append (
257
- '--ignore-patterns={0}' .format (
258
- ',' .join (self .pylint_ignore_patterns )
259
- )
236
+ "--ignore-patterns={0}" .format ("," .join (self .pylint_ignore_patterns ))
260
237
)
261
- print ('-' * FILL_CHARS )
262
- print (' Linting files' )
238
+ print ("-" * FILL_CHARS )
239
+ print (" Linting files" )
263
240
264
241
# Run pylint over the collected files.
265
242
@@ -275,11 +252,12 @@ def pytest_collection_finish(self, session):
275
252
# Stores the messages in a dictionary for lookup in tests.
276
253
for message in messages :
277
254
self .pylint_messages [message .path ].append (message )
278
- print ('-' * FILL_CHARS )
255
+ print ("-" * FILL_CHARS )
279
256
280
257
281
258
class PylintFile (pytest .File ):
282
259
"""File that pylint will run on."""
260
+
283
261
rel_path = None # : str
284
262
plugin = None # : PylintPlugin
285
263
should_skip = False # : bool
@@ -290,25 +268,19 @@ def from_parent(cls, parent, *, fspath, plugin):
290
268
# We add the ``plugin`` kwarg to get plugin level information so the
291
269
# signature differs
292
270
# pylint: disable=arguments-differ
293
- _self = getattr (super (), ' from_parent' , cls )(parent , fspath = fspath )
271
+ _self = getattr (super (), " from_parent" , cls )(parent , fspath = fspath )
294
272
_self .plugin = plugin
295
273
296
- _self .rel_path = get_rel_path (
297
- fspath .strpath ,
298
- parent .session .fspath .strpath
299
- )
274
+ _self .rel_path = get_rel_path (fspath .strpath , parent .session .fspath .strpath )
300
275
_self .mtime = fspath .mtime ()
301
276
prev_mtime = _self .plugin .mtimes .get (_self .rel_path , 0 )
302
- _self .should_skip = ( prev_mtime == _self .mtime )
277
+ _self .should_skip = prev_mtime == _self .mtime
303
278
304
279
return _self
305
280
306
281
def collect (self ):
307
282
"""Create a PyLintItem for the File."""
308
- yield PyLintItem .from_parent (
309
- parent = self ,
310
- name = 'PYLINT'
311
- )
283
+ yield PyLintItem .from_parent (parent = self , name = "PYLINT" )
312
284
313
285
314
286
class PyLintItem (pytest .Item ):
@@ -324,13 +296,13 @@ def __init__(self, *args, **kwargs):
324
296
325
297
msg_format = self .plugin .pylint_msg_template
326
298
if msg_format is None :
327
- self ._msg_format = ' {C}:{line:3d},{column:2d}: {msg} ({symbol})'
299
+ self ._msg_format = " {C}:{line:3d},{column:2d}: {msg} ({symbol})"
328
300
else :
329
301
self ._msg_format = msg_format
330
302
331
303
@classmethod
332
304
def from_parent (cls , parent , ** kw ):
333
- return getattr (super (), ' from_parent' , cls )(parent , ** kw )
305
+ return getattr (super (), " from_parent" , cls )(parent , ** kw )
334
306
335
307
def setup (self ):
336
308
"""Mark unchanged files as SKIPPED."""
@@ -343,18 +315,14 @@ def runtest(self):
343
315
344
316
def _loop_errors (writer ):
345
317
reported_errors = []
346
- for error in self .plugin .pylint_messages .get (
347
- self .parent .rel_path , []
348
- ):
318
+ for error in self .plugin .pylint_messages .get (self .parent .rel_path , []):
349
319
if error .C in self .config .option .pylint_error_types :
350
- reported_errors .append (
351
- error .format (self ._msg_format )
352
- )
320
+ reported_errors .append (error .format (self ._msg_format ))
353
321
354
322
writer (
355
- ' {error_path}:{error_line}: [{error_msg_id}'
356
- ' ({error_symbol}), {error_obj}] '
357
- ' {error_msg}\n ' .format (
323
+ " {error_path}:{error_line}: [{error_msg_id}"
324
+ " ({error_symbol}), {error_obj}] "
325
+ " {error_msg}\n " .format (
358
326
error_path = error .path ,
359
327
error_line = error .line ,
360
328
error_msg_id = error .msg_id ,
@@ -370,13 +338,13 @@ def _loop_errors(writer):
370
338
output_dir = dirname (pylint_output_file )
371
339
if output_dir :
372
340
makedirs (output_dir , exist_ok = True )
373
- with open (pylint_output_file , 'a' ) as _file :
341
+ with open (pylint_output_file , "a" ) as _file :
374
342
reported_errors = _loop_errors (writer = _file .write )
375
343
else :
376
344
reported_errors = _loop_errors (writer = lambda * args , ** kwargs : None )
377
345
378
346
if reported_errors :
379
- raise PyLintException (' \n ' .join (reported_errors ))
347
+ raise PyLintException (" \n " .join (reported_errors ))
380
348
381
349
# Update the cache if the item passed pylint.
382
350
self .plugin .mtimes [self .parent .rel_path ] = self .parent .mtime
0 commit comments