summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--checkers/base.py89
-rw-r--r--checkers/format.py3
-rw-r--r--checkers/newstyle.py9
-rw-r--r--checkers/typecheck.py3
-rw-r--r--checkers/variables.py8
5 files changed, 58 insertions, 54 deletions
diff --git a/checkers/base.py b/checkers/base.py
index f415c9f41..6e48b8a16 100644
--- a/checkers/base.py
+++ b/checkers/base.py
@@ -23,6 +23,7 @@ from logilab.astng import are_exclusive
from pylint.interfaces import IASTNGChecker
from pylint.reporters import diff_string
from pylint.checkers import BaseChecker, EmptyReport
+from pylint.checkers.utils import check_messages
import re
@@ -134,23 +135,17 @@ class BasicErrorChecker(_BasicChecker):
def __init__(self, linter):
_BasicChecker.__init__(self, linter)
- self._returns = None
-
- def open(self):
- self._returns = []
+ @check_messages('E0102')
def visit_class(self, node):
self._check_redefinition('class', node)
+ @check_messages('E0100', 'E0101', 'E0102', 'E0106')
def visit_function(self, node):
- self._returns.append([])
self._check_redefinition(node.is_method() and 'method' or 'function', node)
-
- def leave_function(self, node):
- """most of the work is done here on close:
- checks for max returns, branch, return in __init__
- """
- returns = self._returns.pop()
+ # checks for max returns, branch, return in __init__
+ returns = node.nodes_of_class(astng.Return,
+ skip_klass=(astng.Function, astng.Class))
if node.is_method() and node.name == '__init__':
if node.is_generator():
self.add_message('E0100', node=node)
@@ -163,32 +158,30 @@ class BasicErrorChecker(_BasicChecker):
elif node.is_generator():
# make sure we don't mix non-None returns and yields
for retnode in returns:
- if isinstance(retnode, astng.Return) and \
- isinstance(retnode.value, astng.Const) and \
+ if isinstance(retnode.value, astng.Const) and \
retnode.value.value is not None:
self.add_message('E0106', node=node,
line=retnode.fromlineno)
+ @check_messages('E0104')
def visit_return(self, node):
- # if self._returns is empty, we're outside a function
- if not self._returns:
+ if not isinstance(node.frame(), astng.Function):
self.add_message('E0104', node=node)
- return
- self._returns[-1].append(node)
+ @check_messages('E0105')
def visit_yield(self, node):
- # if self._returns is empty, we're outside a function
- if not self._returns:
+ if not isinstance(node.frame(), astng.Function):
self.add_message('E0105', node=node)
- return
- self._returns[-1].append(node)
+ @check_messages('E0103')
def visit_continue(self, node):
self._check_in_loop(node, 'continue')
+ @check_messages('E0103')
def visit_break(self, node):
self._check_in_loop(node, 'break')
+ @check_messages('E0107')
def visit_unaryop(self, node):
"""check use of the non-existent ++ adn -- operator operator"""
if ((node.op in '+-') and
@@ -312,7 +305,9 @@ functions, methods
"""check module name, docstring and required arguments
"""
self.stats['module'] += 1
- self._check_required_attributes(node, self.config.required_attributes)
+ for attr in self.config.required_attributes:
+ if attr not in node:
+ self.add_message('C0121', node=node, args=attr)
def visit_class(self, node):
"""check module name, docstring and redefinition
@@ -320,6 +315,7 @@ functions, methods
"""
self.stats['class'] += 1
+ @check_messages('W0104', 'W0105')
def visit_discard(self, node):
"""check for various kind of statements without effect"""
expr = node.value
@@ -335,6 +331,7 @@ functions, methods
or isinstance(node.parent, astng.TryExcept) and node.parent.body == [node]):
self.add_message('W0104', node=node)
+ @check_messages('W0108')
def visit_lambda(self, node):
"""check whether or not the lambda is suspicious
"""
@@ -391,9 +388,20 @@ functions, methods
variable names, max locals
"""
self.stats[node.is_method() and 'method' or 'function'] += 1
- # check default arguments'value
- self._check_defaults(node)
+ # check for dangerous default values as arguments
+ for default in node.args.defaults:
+ try:
+ value = default.infer().next()
+ except astng.InferenceError:
+ continue
+ if isinstance(value, (astng.Dict, astng.List)):
+ if value is default:
+ msg = default.as_string()
+ else:
+ msg = '%s (%s)' % (default.as_string(), value.as_string())
+ self.add_message('W0102', node=node, args=(msg,))
+ @check_messages('W0101', 'W0150')
def visit_return(self, node):
"""1 - check is the node has a right sibling (if so, that's some
unreachable code)
@@ -404,12 +412,14 @@ functions, methods
# Is it inside final body of a try...finally bloc ?
self._check_not_in_finally(node, 'return', (astng.Function,))
+ @check_messages('W0101')
def visit_continue(self, node):
"""check is the node has a right sibling (if so, that's some unreachable
code)
"""
self._check_unreachable(node)
+ @check_messages('W0101', 'W0150')
def visit_break(self, node):
"""1 - check is the node has a right sibling (if so, that's some
unreachable code)
@@ -421,16 +431,19 @@ functions, methods
# 2 - Is it inside final body of a try...finally bloc ?
self._check_not_in_finally(node, 'break', (astng.For, astng.While,))
+ @check_messages('W0101')
def visit_raise(self, node):
"""check is the node has a right sibling (if so, that's some unreachable
code)
"""
self._check_unreachable(node)
+ @check_messages('W0122')
def visit_exec(self, node):
"""just print a warning on exec statements"""
self.add_message('W0122', node=node)
+ @check_messages('W0141', 'W0142')
def visit_callfunc(self, node):
"""visit a CallFunc node -> check if this is not a blacklisted builtin
call and check for * or ** use
@@ -456,12 +469,14 @@ functions, methods
return # W0142 can be skipped
self.add_message('W0142', node=node.func)
+ @check_messages('W0199')
def visit_assert(self, node):
"""check the use of an assert statement on a tuple."""
if node.fail is None and isinstance(node.test, astng.Tuple) and \
len(node.test.elts) == 2:
self.add_message('W0199', line=node.fromlineno, node=node)
+ @check_messages('W0109')
def visit_dict(self, node):
"""check duplicate key in dictionary"""
keys = set()
@@ -480,33 +495,12 @@ functions, methods
"""update try...finally flag"""
self._tryfinallys.pop()
-
def _check_unreachable(self, node):
"""check unreachable code"""
unreach_stmt = node.next_sibling()
if unreach_stmt is not None:
self.add_message('W0101', node=unreach_stmt)
- def _check_defaults(self, node):
- """check for dangerous default values as arguments"""
- for default in node.args.defaults:
- try:
- value = default.infer().next()
- except astng.InferenceError:
- continue
- if isinstance(value, (astng.Dict, astng.List)):
- if value is default:
- msg = default.as_string()
- else:
- msg = '%s (%s)' % (default.as_string(), value.as_string())
- self.add_message('W0102', node=node, args=(msg,))
-
- def _check_required_attributes(self, node, attributes):
- """check for required attributes"""
- for attr in attributes:
- if attr not in node:
- self.add_message('C0121', node=node, args=attr)
-
def _check_not_in_finally(self, node, node_name, breaker_classes=()):
"""check that a node is not inside a finally clause of a
try...finally statement.
@@ -615,14 +609,17 @@ class NameChecker(_BasicChecker):
badname_inlinevar=0,
badname_argument=0)
+ @check_messages('C0102', 'C0103')
def visit_module(self, node):
self._check_name('module', node.name.split('.')[-1], node)
+ @check_messages('C0102', 'C0103')
def visit_class(self, node):
self._check_name('class', node.name, node)
for attr, anodes in node.instance_attrs.items():
self._check_name('attr', attr, anodes[0])
+ @check_messages('C0102', 'C0103')
def visit_function(self, node):
self._check_name(node.is_method() and 'method' or 'function',
node.name, node)
@@ -631,6 +628,7 @@ class NameChecker(_BasicChecker):
if args is not None:
self._recursive_check_names(args, node)
+ @check_messages('C0102', 'C0103')
def visit_assname(self, node):
"""check module level assigned names"""
frame = node.frame()
@@ -648,7 +646,6 @@ class NameChecker(_BasicChecker):
def _recursive_check_names(self, args, node):
"""check names in a possibly recursive list <arg>"""
for arg in args:
- #if type(arg) is type(''):
if isinstance(arg, astng.AssName):
self._check_name('argument', arg.name, node)
else:
diff --git a/checkers/format.py b/checkers/format.py
index c21363094..8c874fa3d 100644
--- a/checkers/format.py
+++ b/checkers/format.py
@@ -32,6 +32,7 @@ from logilab.astng import nodes
from pylint.interfaces import IRawChecker, IASTNGChecker
from pylint.checkers import BaseRawChecker
from pylint.checkers.misc import guess_encoding, is_ascii
+from pylint.checkers.utils import check_messages
MSGS = {
'C0301': ('Line too long (%s/%s)',
@@ -274,6 +275,7 @@ class FormatChecker(BaseRawChecker):
if line_num > self.config.max_module_lines:
self.add_message('C0302', args=line_num, line=1)
+ @check_messages('C0321' ,'C03232', 'C0323', 'C0324')
def visit_default(self, node):
"""check the node line number and check it if not yet done"""
if not node.is_statement:
@@ -317,6 +319,7 @@ class FormatChecker(BaseRawChecker):
# FIXME: internal error !
pass
+ @check_messages('W0333')
def visit_backquote(self, node):
self.add_message('W0333', node=node)
diff --git a/checkers/newstyle.py b/checkers/newstyle.py
index 16d17c0ff..29721d0e2 100644
--- a/checkers/newstyle.py
+++ b/checkers/newstyle.py
@@ -20,6 +20,7 @@ from logilab import astng
from pylint.interfaces import IASTNGChecker
from pylint.checkers import BaseChecker
+from pylint.checkers.utils import check_messages
MSGS = {
'E1001': ('Use __slots__ on an old style class',
@@ -53,15 +54,14 @@ class NewStyleConflictChecker(BaseChecker):
# configuration options
options = ()
-# def __init__(self, linter=None):
-# BaseChecker.__init__(self, linter)
-
+ @check_messages('E1001')
def visit_class(self, node):
"""check __slots__ usage
"""
if '__slots__' in node and not node.newstyle:
self.add_message('E1001', node=node)
-
+
+ @check_messages('W1001')
def visit_callfunc(self, node):
"""check property usage"""
parent = node.parent.frame()
@@ -72,6 +72,7 @@ class NewStyleConflictChecker(BaseChecker):
if name == 'property':
self.add_message('W1001', node=node)
+ @check_messages('E1002', 'E1003')
def visit_function(self, node):
"""check use of super"""
# ignore actual functions or method within a new style class
diff --git a/checkers/typecheck.py b/checkers/typecheck.py
index 1ed47134e..bb1086d3b 100644
--- a/checkers/typecheck.py
+++ b/checkers/typecheck.py
@@ -21,7 +21,7 @@ from logilab.astng import InferenceError, NotFoundError, YES, Instance
from pylint.interfaces import IASTNGChecker
from pylint.checkers import BaseChecker
-from pylint.checkers.utils import safe_infer, is_super
+from pylint.checkers.utils import safe_infer, is_super, check_messages
MSGS = {
'E1101': ('%s %r has no %r member',
@@ -113,6 +113,7 @@ accessed.'}
def visit_delattr(self, node):
self.visit_getattr(node)
+ @check_messages('E1101', 'E1103')
def visit_getattr(self, node):
"""check that the accessed attribute exists
diff --git a/checkers/variables.py b/checkers/variables.py
index b292a2103..d7ebcc8e8 100644
--- a/checkers/variables.py
+++ b/checkers/variables.py
@@ -23,9 +23,9 @@ from logilab.astng import are_exclusive, builtin_lookup
from pylint.interfaces import IASTNGChecker
from pylint.checkers import BaseChecker
-from pylint.checkers.utils import PYMETHODS, is_ancestor_name, is_builtin, \
- is_defined_before, is_error, is_func_default, is_func_decorator, assign_parent
-
+from pylint.checkers.utils import (PYMETHODS, is_ancestor_name, is_builtin,
+ is_defined_before, is_error, is_func_default, is_func_decorator,
+ assign_parent, check_messages)
def overridden_method(klass, name):
"""get overridden method if any"""
@@ -136,6 +136,7 @@ builtins. Remember that you should avoid to define new builtins when possible.'
# do not print Redefining builtin for additional builtins
self.add_message('W0622', args=name, node=stmts[0])
+ @check_messages('W0611', 'W0614')
def leave_module(self, node):
"""leave module: check globals
"""
@@ -269,6 +270,7 @@ builtins. Remember that you should avoid to define new builtins when possible.'
else:
self.add_message('W0612', args=name, node=stmt)
+ @check_messages('W0601', 'W0602', 'W0603', 'W0604', 'W0622')
def visit_global(self, node):
"""check names imported exists in the global scope"""
frame = node.frame()