Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: third_party/pylint/pylint/checkers/python3.py

Issue 1920403002: [content/test/gpu] Run pylint check of gpu tests in unittest instead of PRESUBMIT (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Update path to LICENSE.txt of logilab/README.chromium Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2014 Google Inc.
2 # This program is free software; you can redistribute it and/or modify it under
3 # the terms of the GNU General Public License as published by the Free Software
4 # Foundation; either version 2 of the License, or (at your option) any later
5 # version.
6 #
7 # This program is distributed in the hope that it will be useful, but WITHOUT
8 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
10 #
11 # You should have received a copy of the GNU General Public License along with
12 # this program; if not, write to the Free Software Foundation, Inc.,
13 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
14 """Check Python 2 code for Python 2/3 source-compatible issues."""
15 from __future__ import absolute_import
16
17 import re
18 import tokenize
19
20 import astroid
21 from pylint import checkers, interfaces
22 from pylint.utils import WarningScope
23 from pylint.checkers import utils
24
25
26 _ZERO = re.compile("^0+$")
27
28 def _is_old_octal(literal):
29 if _ZERO.match(literal):
30 return False
31 if re.match('0\d+', literal):
32 try:
33 int(literal, 8)
34 except ValueError:
35 return False
36 return True
37
38 def _check_dict_node(node):
39 inferred_types = set()
40 try:
41 inferred = node.infer()
42 for inferred_node in inferred:
43 inferred_types.add(inferred_node)
44 except (astroid.InferenceError, astroid.UnresolvableName):
45 pass
46 return (not inferred_types
47 or any(isinstance(x, astroid.Dict) for x in inferred_types))
48
49
50 class Python3Checker(checkers.BaseChecker):
51
52 __implements__ = interfaces.IAstroidChecker
53 enabled = False
54 name = 'python3'
55
56 msgs = {
57 # Errors for what will syntactically break in Python 3, warnings for
58 # everything else.
59 'E1601': ('print statement used',
60 'print-statement',
61 'Used when a print statement is used '
62 '(`print` is a function in Python 3)',
63 {'maxversion': (3, 0)}),
64 'E1602': ('Parameter unpacking specified',
65 'parameter-unpacking',
66 'Used when parameter unpacking is specified for a function'
67 "(Python 3 doesn't allow it)",
68 {'maxversion': (3, 0)}),
69 'E1603': ('Implicit unpacking of exceptions is not supported '
70 'in Python 3',
71 'unpacking-in-except',
72 'Python3 will not allow implicit unpacking of '
73 'exceptions in except clauses. '
74 'See http://www.python.org/dev/peps/pep-3110/',
75 {'maxversion': (3, 0),
76 'old_names': [('W0712', 'unpacking-in-except')]}),
77 'E1604': ('Use raise ErrorClass(args) instead of '
78 'raise ErrorClass, args.',
79 'old-raise-syntax',
80 "Used when the alternate raise syntax "
81 "'raise foo, bar' is used "
82 "instead of 'raise foo(bar)'.",
83 {'maxversion': (3, 0),
84 'old_names': [('W0121', 'old-raise-syntax')]}),
85 'E1605': ('Use of the `` operator',
86 'backtick',
87 'Used when the deprecated "``" (backtick) operator is used '
88 'instead of the str() function.',
89 {'scope': WarningScope.NODE,
90 'maxversion': (3, 0),
91 'old_names': [('W0333', 'backtick')]}),
92 'W1601': ('apply built-in referenced',
93 'apply-builtin',
94 'Used when the apply built-in function is referenced '
95 '(missing from Python 3)',
96 {'maxversion': (3, 0)}),
97 'W1602': ('basestring built-in referenced',
98 'basestring-builtin',
99 'Used when the basestring built-in function is referenced '
100 '(missing from Python 3)',
101 {'maxversion': (3, 0)}),
102 'W1603': ('buffer built-in referenced',
103 'buffer-builtin',
104 'Used when the buffer built-in function is referenced '
105 '(missing from Python 3)',
106 {'maxversion': (3, 0)}),
107 'W1604': ('cmp built-in referenced',
108 'cmp-builtin',
109 'Used when the cmp built-in function is referenced '
110 '(missing from Python 3)',
111 {'maxversion': (3, 0)}),
112 'W1605': ('coerce built-in referenced',
113 'coerce-builtin',
114 'Used when the coerce built-in function is referenced '
115 '(missing from Python 3)',
116 {'maxversion': (3, 0)}),
117 'W1606': ('execfile built-in referenced',
118 'execfile-builtin',
119 'Used when the execfile built-in function is referenced '
120 '(missing from Python 3)',
121 {'maxversion': (3, 0)}),
122 'W1607': ('file built-in referenced',
123 'file-builtin',
124 'Used when the file built-in function is referenced '
125 '(missing from Python 3)',
126 {'maxversion': (3, 0)}),
127 'W1608': ('long built-in referenced',
128 'long-builtin',
129 'Used when the long built-in function is referenced '
130 '(missing from Python 3)',
131 {'maxversion': (3, 0)}),
132 'W1609': ('raw_input built-in referenced',
133 'raw_input-builtin',
134 'Used when the raw_input built-in function is referenced '
135 '(missing from Python 3)',
136 {'maxversion': (3, 0)}),
137 'W1610': ('reduce built-in referenced',
138 'reduce-builtin',
139 'Used when the reduce built-in function is referenced '
140 '(missing from Python 3)',
141 {'maxversion': (3, 0)}),
142 'W1611': ('StandardError built-in referenced',
143 'standarderror-builtin',
144 'Used when the StandardError built-in function is referenced '
145 '(missing from Python 3)',
146 {'maxversion': (3, 0)}),
147 'W1612': ('unicode built-in referenced',
148 'unicode-builtin',
149 'Used when the unicode built-in function is referenced '
150 '(missing from Python 3)',
151 {'maxversion': (3, 0)}),
152 'W1613': ('xrange built-in referenced',
153 'xrange-builtin',
154 'Used when the xrange built-in function is referenced '
155 '(missing from Python 3)',
156 {'maxversion': (3, 0)}),
157 'W1614': ('__coerce__ method defined',
158 'coerce-method',
159 'Used when a __coerce__ method is defined '
160 '(method is not used by Python 3)',
161 {'maxversion': (3, 0)}),
162 'W1615': ('__delslice__ method defined',
163 'delslice-method',
164 'Used when a __delslice__ method is defined '
165 '(method is not used by Python 3)',
166 {'maxversion': (3, 0)}),
167 'W1616': ('__getslice__ method defined',
168 'getslice-method',
169 'Used when a __getslice__ method is defined '
170 '(method is not used by Python 3)',
171 {'maxversion': (3, 0)}),
172 'W1617': ('__setslice__ method defined',
173 'setslice-method',
174 'Used when a __setslice__ method is defined '
175 '(method is not used by Python 3)',
176 {'maxversion': (3, 0)}),
177 'W1618': ('import missing `from __future__ import absolute_import`',
178 'no-absolute-import',
179 'Used when an import is not accompanied by '
180 '`from __future__ import absolute_import`'
181 ' (default behaviour in Python 3)',
182 {'maxversion': (3, 0)}),
183 'W1619': ('division w/o __future__ statement',
184 'old-division',
185 'Used for non-floor division w/o a float literal or '
186 '``from __future__ import division``'
187 '(Python 3 returns a float for int division unconditionally)',
188 {'maxversion': (3, 0)}),
189 'W1620': ('Calling a dict.iter*() method',
190 'dict-iter-method',
191 'Used for calls to dict.iterkeys(), itervalues() or iteritems( ) '
192 '(Python 3 lacks these methods)',
193 {'maxversion': (3, 0)}),
194 'W1621': ('Calling a dict.view*() method',
195 'dict-view-method',
196 'Used for calls to dict.viewkeys(), viewvalues() or viewitems( ) '
197 '(Python 3 lacks these methods)',
198 {'maxversion': (3, 0)}),
199 'W1622': ('Called a next() method on an object',
200 'next-method-called',
201 "Used when an object's next() method is called "
202 '(Python 3 uses the next() built-in function)',
203 {'maxversion': (3, 0)}),
204 'W1623': ("Assigning to a class' __metaclass__ attribute",
205 'metaclass-assignment',
206 "Used when a metaclass is specified by assigning to __metaclas s__ "
207 '(Python 3 specifies the metaclass as a class statement argume nt)',
208 {'maxversion': (3, 0)}),
209 'W1624': ('Indexing exceptions will not work on Python 3',
210 'indexing-exception',
211 'Indexing exceptions will not work on Python 3. Use '
212 '`exception.args[index]` instead.',
213 {'maxversion': (3, 0),
214 'old_names': [('W0713', 'indexing-exception')]}),
215 'W1625': ('Raising a string exception',
216 'raising-string',
217 'Used when a string exception is raised. This will not '
218 'work on Python 3.',
219 {'maxversion': (3, 0),
220 'old_names': [('W0701', 'raising-string')]}),
221 'W1626': ('reload built-in referenced',
222 'reload-builtin',
223 'Used when the reload built-in function is referenced '
224 '(missing from Python 3). You can use instead imp.reload '
225 'or importlib.reload.',
226 {'maxversion': (3, 0)}),
227 'W1627': ('__oct__ method defined',
228 'oct-method',
229 'Used when a __oct__ method is defined '
230 '(method is not used by Python 3)',
231 {'maxversion': (3, 0)}),
232 'W1628': ('__hex__ method defined',
233 'hex-method',
234 'Used when a __hex__ method is defined '
235 '(method is not used by Python 3)',
236 {'maxversion': (3, 0)}),
237 'W1629': ('__nonzero__ method defined',
238 'nonzero-method',
239 'Used when a __nonzero__ method is defined '
240 '(method is not used by Python 3)',
241 {'maxversion': (3, 0)}),
242 'W1630': ('__cmp__ method defined',
243 'cmp-method',
244 'Used when a __cmp__ method is defined '
245 '(method is not used by Python 3)',
246 {'maxversion': (3, 0)}),
247 'W1631': ('map is used as implicitly evaluated call',
248 'implicit-map-evaluation',
249 'Used when the map builtin is used as implicitly '
250 'evaluated call, as in "map(func, args)" on a single line. '
251 'This behaviour will not work in Python 3, where '
252 'map is a generator and must be evaluated. '
253 'Prefer a for-loop as alternative.',
254 {'maxversion': (3, 0)}),
255 'W1632': ('input built-in referenced',
256 'input-builtin',
257 'Used when the input built-in is referenced '
258 '(backwards-incompatible semantics in Python 3)',
259 {'maxversion': (3, 0)}),
260 'W1633': ('round built-in referenced',
261 'round-builtin',
262 'Used when the round built-in is referenced '
263 '(backwards-incompatible semantics in Python 3)',
264 {'maxversion': (3, 0)}),
265 }
266
267 _bad_builtins = frozenset([
268 'apply',
269 'basestring',
270 'buffer',
271 'cmp',
272 'coerce',
273 'execfile',
274 'file',
275 'input', # Not missing, but incompatible semantics
276 'long',
277 'raw_input',
278 'reduce',
279 'round', # Not missing, but incompatible semantics
280 'StandardError',
281 'unicode',
282 'xrange',
283 'reload',
284 ])
285
286 _unused_magic_methods = frozenset([
287 '__coerce__',
288 '__delslice__',
289 '__getslice__',
290 '__setslice__',
291 '__oct__',
292 '__hex__',
293 '__nonzero__',
294 '__cmp__',
295 ])
296
297 def __init__(self, *args, **kwargs):
298 self._future_division = False
299 self._future_absolute_import = False
300 super(Python3Checker, self).__init__(*args, **kwargs)
301
302 def visit_function(self, node):
303 if node.is_method() and node.name in self._unused_magic_methods:
304 method_name = node.name
305 if node.name.startswith('__'):
306 method_name = node.name[2:-2]
307 self.add_message(method_name + '-method', node=node)
308
309 @utils.check_messages('parameter-unpacking')
310 def visit_arguments(self, node):
311 for arg in node.args:
312 if isinstance(arg, astroid.Tuple):
313 self.add_message('parameter-unpacking', node=arg)
314
315 @utils.check_messages('implicit-map-evaluation')
316 def visit_discard(self, node):
317 if (isinstance(node.value, astroid.CallFunc) and
318 isinstance(node.value.func, astroid.Name) and
319 node.value.func.name == 'map'):
320 module = node.value.func.lookup('map')[0]
321 if getattr(module, 'name', None) == '__builtin__':
322 self.add_message('implicit-map-evaluation', node=node)
323
324 def visit_name(self, node):
325 """Detect when a "bad" built-in is referenced."""
326 found_node = node.lookup(node.name)[0]
327 if getattr(found_node, 'name', None) == '__builtin__':
328 if node.name in self._bad_builtins:
329 message = node.name.lower() + '-builtin'
330 self.add_message(message, node=node)
331
332 @utils.check_messages('print-statement')
333 def visit_print(self, node):
334 self.add_message('print-statement', node=node)
335
336 @utils.check_messages('no-absolute-import')
337 def visit_from(self, node):
338 if node.modname == '__future__':
339 for name, _ in node.names:
340 if name == 'division':
341 self._future_division = True
342 elif name == 'absolute_import':
343 self._future_absolute_import = True
344 elif not self._future_absolute_import:
345 self.add_message('no-absolute-import', node=node)
346
347 @utils.check_messages('no-absolute-import')
348 def visit_import(self, node):
349 if not self._future_absolute_import:
350 self.add_message('no-absolute-import', node=node)
351
352 @utils.check_messages('metaclass-assignment')
353 def visit_class(self, node):
354 if '__metaclass__' in node.locals:
355 self.add_message('metaclass-assignment', node=node)
356
357 @utils.check_messages('old-division')
358 def visit_binop(self, node):
359 if not self._future_division and node.op == '/':
360 for arg in (node.left, node.right):
361 if isinstance(arg, astroid.Const) and isinstance(arg.value, floa t):
362 break
363 else:
364 self.add_message('old-division', node=node)
365
366 @utils.check_messages('next-method-called',
367 'dict-iter-method',
368 'dict-view-method')
369 def visit_callfunc(self, node):
370 if not isinstance(node.func, astroid.Getattr):
371 return
372 if any([node.args, node.starargs, node.kwargs]):
373 return
374 if node.func.attrname == 'next':
375 self.add_message('next-method-called', node=node)
376 else:
377 if _check_dict_node(node.func.expr):
378 if node.func.attrname in ('iterkeys', 'itervalues', 'iteritems') :
379 self.add_message('dict-iter-method', node=node)
380 elif node.func.attrname in ('viewkeys', 'viewvalues', 'viewitems '):
381 self.add_message('dict-view-method', node=node)
382
383 @utils.check_messages('indexing-exception')
384 def visit_subscript(self, node):
385 """ Look for indexing exceptions. """
386 try:
387 for infered in node.value.infer():
388 if not isinstance(infered, astroid.Instance):
389 continue
390 if utils.inherit_from_std_ex(infered):
391 self.add_message('indexing-exception', node=node)
392 except astroid.InferenceError:
393 return
394
395 @utils.check_messages('unpacking-in-except')
396 def visit_excepthandler(self, node):
397 """Visit an except handler block and check for exception unpacking."""
398 if isinstance(node.name, (astroid.Tuple, astroid.List)):
399 self.add_message('unpacking-in-except', node=node)
400
401 @utils.check_messages('backtick')
402 def visit_backquote(self, node):
403 self.add_message('backtick', node=node)
404
405 @utils.check_messages('raising-string', 'old-raise-syntax')
406 def visit_raise(self, node):
407 """Visit a raise statement and check for raising
408 strings or old-raise-syntax.
409 """
410 if (node.exc is not None and
411 node.inst is not None and
412 node.tback is None):
413 self.add_message('old-raise-syntax', node=node)
414
415 # Ignore empty raise.
416 if node.exc is None:
417 return
418 expr = node.exc
419 if self._check_raise_value(node, expr):
420 return
421 else:
422 try:
423 value = next(astroid.unpack_infer(expr))
424 except astroid.InferenceError:
425 return
426 self._check_raise_value(node, value)
427
428 def _check_raise_value(self, node, expr):
429 if isinstance(expr, astroid.Const):
430 value = expr.value
431 if isinstance(value, str):
432 self.add_message('raising-string', node=node)
433 return True
434
435
436 class Python3TokenChecker(checkers.BaseTokenChecker):
437 __implements__ = interfaces.ITokenChecker
438 name = 'python3'
439 enabled = False
440
441 msgs = {
442 'E1606': ('Use of long suffix',
443 'long-suffix',
444 'Used when "l" or "L" is used to mark a long integer. '
445 'This will not work in Python 3, since `int` and `long` '
446 'types have merged.',
447 {'maxversion': (3, 0)}),
448 'E1607': ('Use of the <> operator',
449 'old-ne-operator',
450 'Used when the deprecated "<>" operator is used instead '
451 'of "!=". This is removed in Python 3.',
452 {'maxversion': (3, 0),
453 'old_names': [('W0331', 'old-ne-operator')]}),
454 'E1608': ('Use of old octal literal',
455 'old-octal-literal',
456 'Usen when encountering the old octal syntax, '
457 'removed in Python 3. To use the new syntax, '
458 'prepend 0o on the number.',
459 {'maxversion': (3, 0)}),
460 }
461
462 def process_tokens(self, tokens):
463 for idx, (tok_type, token, start, _, _) in enumerate(tokens):
464 if tok_type == tokenize.NUMBER:
465 if token.lower().endswith('l'):
466 # This has a different semantic than lowercase-l-suffix.
467 self.add_message('long-suffix', line=start[0])
468 elif _is_old_octal(token):
469 self.add_message('old-octal-literal', line=start[0])
470 if tokens[idx][1] == '<>':
471 self.add_message('old-ne-operator', line=tokens[idx][2][0])
472
473
474 def register(linter):
475 linter.register_checker(Python3Checker(linter))
476 linter.register_checker(Python3TokenChecker(linter))
OLDNEW
« no previous file with comments | « third_party/pylint/pylint/checkers/newstyle.py ('k') | third_party/pylint/pylint/checkers/raw_metrics.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698