diff options
author | Sylvain Th?nault <sylvain.thenault@logilab.fr> | 2014-07-25 17:23:37 +0200 |
---|---|---|
committer | Sylvain Th?nault <sylvain.thenault@logilab.fr> | 2014-07-25 17:23:37 +0200 |
commit | 94809f51eb4bc1d46e573be6763271f05558b80a (patch) | |
tree | e9b9f51e0ce1b56227b37207178cdd3f5f319f01 | |
parent | 331732cc5019f19a323e1176b58c1d8c82c5ced4 (diff) | |
download | pylint-94809f51eb4bc1d46e573be6763271f05558b80a.tar.gz |
linting pylint
-rw-r--r-- | checkers/base.py | 407 | ||||
-rw-r--r-- | checkers/classes.py | 80 | ||||
-rw-r--r-- | checkers/design_analysis.py | 22 | ||||
-rw-r--r-- | checkers/exceptions.py | 12 | ||||
-rw-r--r-- | checkers/format.py | 94 | ||||
-rw-r--r-- | checkers/imports.py | 18 | ||||
-rw-r--r-- | checkers/logging.py | 42 | ||||
-rw-r--r-- | checkers/newstyle.py | 4 | ||||
-rw-r--r-- | checkers/similar.py | 10 | ||||
-rw-r--r-- | checkers/stdlib.py | 7 | ||||
-rw-r--r-- | checkers/strings.py | 11 | ||||
-rw-r--r-- | checkers/typecheck.py | 31 | ||||
-rw-r--r-- | checkers/utils.py | 29 | ||||
-rw-r--r-- | checkers/variables.py | 41 | ||||
-rwxr-xr-x | epylint.py | 2 | ||||
-rw-r--r-- | gui.py | 33 | ||||
-rw-r--r-- | lint.py | 120 | ||||
-rw-r--r-- | pyreverse/main.py | 73 | ||||
-rw-r--r-- | pyreverse/writer.py | 6 | ||||
-rw-r--r-- | setup.py | 18 | ||||
-rw-r--r-- | testutils.py | 8 | ||||
-rw-r--r-- | utils.py | 6 |
22 files changed, 534 insertions, 540 deletions
diff --git a/checkers/base.py b/checkers/base.py index 1a41f59..fb63c51 100644 --- a/checkers/base.py +++ b/checkers/base.py @@ -124,8 +124,8 @@ def _determine_function_name_type(node): # If the function is a property (decorated with @property # or @abc.abstractproperty), the name type is 'attr'. if (isinstance(decorator, astroid.Name) or - (isinstance(decorator, astroid.Getattr) and - decorator.attrname == 'abstractproperty')): + (isinstance(decorator, astroid.Getattr) and + decorator.attrname == 'abstractproperty')): infered = safe_infer(decorator) if infered and infered.qname() in PROPERTY_CLASSES: return 'attr' @@ -208,7 +208,7 @@ def redefined_by_decorator(node): if node.decorators: for decorator in node.decorators.nodes: if (isinstance(decorator, astroid.Getattr) and - getattr(decorator.expr, 'name', None) == node.name): + getattr(decorator.expr, 'name', None) == node.name): return True return False @@ -218,57 +218,53 @@ class _BasicChecker(BaseChecker): class BasicErrorChecker(_BasicChecker): msgs = { - 'E0100': ('__init__ method is a generator', - 'init-is-generator', - 'Used when the special class method __init__ is turned into a ' - 'generator by a yield in its body.'), - 'E0101': ('Explicit return in __init__', - 'return-in-init', - 'Used when the special class method __init__ has an explicit \ - return value.'), - 'E0102': ('%s already defined line %s', - 'function-redefined', - 'Used when a function / class / method is redefined.'), - 'E0103': ('%r not properly in loop', - 'not-in-loop', - 'Used when break or continue keywords are used outside a loop.'), - - 'E0104': ('Return outside function', - 'return-outside-function', - 'Used when a "return" statement is found outside a function or ' - 'method.'), - 'E0105': ('Yield outside function', - 'yield-outside-function', - 'Used when a "yield" statement is found outside a function or ' - 'method.'), - 'E0106': ('Return with argument inside generator', - 'return-arg-in-generator', - 'Used when a "return" statement with an argument is found ' - 'outside in a generator function or method (e.g. with some ' - '"yield" statements).', - {'maxversion': (3, 3)}), - 'E0107': ("Use of the non-existent %s operator", - 'nonexistent-operator', - "Used when you attempt to use the C-style pre-increment or" - "pre-decrement operator -- and ++, which doesn't exist in Python."), - 'E0108': ('Duplicate argument name %s in function definition', - 'duplicate-argument-name', - 'Duplicate argument names in function definitions are syntax' - ' errors.'), - 'E0110': ('Abstract class with abstract methods instantiated', - 'abstract-class-instantiated', - 'Used when an abstract class with `abc.ABCMeta` as metaclass ' - 'has abstract methods and is instantiated.', - {'minversion': (3, 0)}), - 'W0120': ('Else clause on loop without a break statement', - 'useless-else-on-loop', - 'Loops should only have an else clause if they can exit early ' - 'with a break statement, otherwise the statements under else ' - 'should be on the same scope as the loop itself.'), - } - - def __init__(self, linter): - _BasicChecker.__init__(self, linter) + 'E0100': ('__init__ method is a generator', + 'init-is-generator', + 'Used when the special class method __init__ is turned into a ' + 'generator by a yield in its body.'), + 'E0101': ('Explicit return in __init__', + 'return-in-init', + 'Used when the special class method __init__ has an explicit ' + 'return value.'), + 'E0102': ('%s already defined line %s', + 'function-redefined', + 'Used when a function / class / method is redefined.'), + 'E0103': ('%r not properly in loop', + 'not-in-loop', + 'Used when break or continue keywords are used outside a loop.'), + 'E0104': ('Return outside function', + 'return-outside-function', + 'Used when a "return" statement is found outside a function or ' + 'method.'), + 'E0105': ('Yield outside function', + 'yield-outside-function', + 'Used when a "yield" statement is found outside a function or ' + 'method.'), + 'E0106': ('Return with argument inside generator', + 'return-arg-in-generator', + 'Used when a "return" statement with an argument is found ' + 'outside in a generator function or method (e.g. with some ' + '"yield" statements).', + {'maxversion': (3, 3)}), + 'E0107': ("Use of the non-existent %s operator", + 'nonexistent-operator', + "Used when you attempt to use the C-style pre-increment or" + "pre-decrement operator -- and ++, which doesn't exist in Python."), + 'E0108': ('Duplicate argument name %s in function definition', + 'duplicate-argument-name', + 'Duplicate argument names in function definitions are syntax' + ' errors.'), + 'E0110': ('Abstract class with abstract methods instantiated', + 'abstract-class-instantiated', + 'Used when an abstract class with `abc.ABCMeta` as metaclass ' + 'has abstract methods and is instantiated.', + {'minversion': (3, 0)}), + 'W0120': ('Else clause on loop without a break statement', + 'useless-else-on-loop', + 'Loops should only have an else clause if they can exit early ' + 'with a break statement, otherwise the statements under else ' + 'should be on the same scope as the loop itself.'), + } @check_messages('function-redefined') def visit_class(self, node): @@ -289,11 +285,11 @@ class BasicErrorChecker(_BasicChecker): else: values = [r.value for r in returns] # Are we returning anything but None from constructors - if [v for v in values if - not (v is None or - (isinstance(v, astroid.Const) and v.value is None) or - (isinstance(v, astroid.Name) and v.name == 'None') - )]: + if [v for v in values + if not (v is None or + (isinstance(v, astroid.Const) and v.value is None) or + (isinstance(v, astroid.Name) and v.name == 'None') + )]: self.add_message('return-in-init', node=node) elif node.is_generator(): # make sure we don't mix non-None returns and yields @@ -342,8 +338,8 @@ class BasicErrorChecker(_BasicChecker): def visit_unaryop(self, node): """check use of the non-existent ++ and -- operator operator""" if ((node.op in '+-') and - isinstance(node.operand, astroid.UnaryOp) and - (node.operand.op == node.op)): + isinstance(node.operand, astroid.UnaryOp) and + (node.operand.op == node.op)): self.add_message('nonexistent-operator', node=node, args=node.op*2) @check_messages('abstract-class-instantiated') @@ -364,14 +360,12 @@ class BasicErrorChecker(_BasicChecker): # by ClassNode.metaclass() for ancestor in infered.ancestors(): if (ancestor.qname() == 'abc.ABC' and - has_abstract_methods(infered)): - + has_abstract_methods(infered)): self.add_message('abstract-class-instantiated', node=node) break return if (metaclass.qname() == 'abc.ABCMeta' and - has_abstract_methods(infered)): - + has_abstract_methods(infered)): self.add_message('abstract-class-instantiated', node=node) def _check_else_on_loop(self, node): @@ -417,88 +411,88 @@ functions, methods name = 'basic' msgs = { - 'W0101': ('Unreachable code', - 'unreachable', - 'Used when there is some code behind a "return" or "raise" \ - statement, which will never be accessed.'), - 'W0102': ('Dangerous default value %s as argument', - 'dangerous-default-value', - 'Used when a mutable value as list or dictionary is detected in \ - a default value for an argument.'), - 'W0104': ('Statement seems to have no effect', - 'pointless-statement', - 'Used when a statement doesn\'t have (or at least seems to) \ - any effect.'), - 'W0105': ('String statement has no effect', - 'pointless-string-statement', - 'Used when a string is used as a statement (which of course \ - has no effect). This is a particular case of W0104 with its \ - own message so you can easily disable it if you\'re using \ - those strings as documentation, instead of comments.'), - 'W0106': ('Expression "%s" is assigned to nothing', - 'expression-not-assigned', - 'Used when an expression that is not a function call is assigned\ - to nothing. Probably something else was intended.'), - 'W0108': ('Lambda may not be necessary', - 'unnecessary-lambda', - 'Used when the body of a lambda expression is a function call \ - on the same argument list as the lambda itself; such lambda \ - expressions are in all but a few cases replaceable with the \ - function being called in the body of the lambda.'), - 'W0109': ("Duplicate key %r in dictionary", - 'duplicate-key', - "Used when a dictionary expression binds the same key multiple \ - times."), - 'W0122': ('Use of exec', - 'exec-used', - 'Used when you use the "exec" statement (function for Python 3), to discourage its \ - usage. That doesn\'t mean you can not use it !'), - 'W0123': ('Use of eval', - 'eval-used', - 'Used when you use the "eval" function, to discourage its ' - 'usage. Consider using `ast.literal_eval` for safely evaluating ' - 'strings containing Python expressions ' - 'from untrusted sources. '), - 'W0141': ('Used builtin function %r', - 'bad-builtin', - 'Used when a black listed builtin function is used (see the ' - 'bad-function option). Usual black listed functions are the ones ' - 'like map, or filter , where Python offers now some cleaner ' - 'alternative like list comprehension.'), - 'W0142': ('Used * or ** magic', - 'star-args', - 'Used when a function or method is called using `*args` or ' - '`**kwargs` to dispatch arguments. This doesn\'t improve ' - 'readability and should be used with care.'), - 'W0150': ("%s statement in finally block may swallow exception", - 'lost-exception', - "Used when a break or a return statement is found inside the \ - finally clause of a try...finally block: the exceptions raised \ - in the try clause will be silently swallowed instead of being \ - re-raised."), - 'W0199': ('Assert called on a 2-uple. Did you mean \'assert x,y\'?', - 'assert-on-tuple', - 'A call of assert on a tuple will always evaluate to true if ' - 'the tuple is not empty, and will always evaluate to false if ' - 'it is.'), - 'W0121': ('Use raise ErrorClass(args) instead of raise ErrorClass, args.', - 'old-raise-syntax', - "Used when the alternate raise syntax 'raise foo, bar' is used " - "instead of 'raise foo(bar)'.", - {'maxversion': (3, 0)}), - - 'C0121': ('Missing required attribute "%s"', # W0103 - 'missing-module-attribute', - 'Used when an attribute required for modules is missing.'), - - 'E0109': ('Missing argument to reversed()', - 'missing-reversed-argument', - 'Used when reversed() builtin didn\'t receive an argument.'), - 'E0111': ('The first reversed() argument is not a sequence', - 'bad-reversed-sequence', - 'Used when the first argument to reversed() builtin ' - 'isn\'t a sequence (does not implement __reversed__, ' - 'nor __getitem__ and __len__'), + 'W0101': ('Unreachable code', + 'unreachable', + 'Used when there is some code behind a "return" or "raise" ' + 'statement, which will never be accessed.'), + 'W0102': ('Dangerous default value %s as argument', + 'dangerous-default-value', + 'Used when a mutable value as list or dictionary is detected in ' + 'a default value for an argument.'), + 'W0104': ('Statement seems to have no effect', + 'pointless-statement', + 'Used when a statement doesn\'t have (or at least seems to) ' + 'any effect.'), + 'W0105': ('String statement has no effect', + 'pointless-string-statement', + 'Used when a string is used as a statement (which of course ' + 'has no effect). This is a particular case of W0104 with its ' + 'own message so you can easily disable it if you\'re using ' + 'those strings as documentation, instead of comments.'), + 'W0106': ('Expression "%s" is assigned to nothing', + 'expression-not-assigned', + 'Used when an expression that is not a function call is assigned ' + 'to nothing. Probably something else was intended.'), + 'W0108': ('Lambda may not be necessary', + 'unnecessary-lambda', + 'Used when the body of a lambda expression is a function call ' + 'on the same argument list as the lambda itself; such lambda ' + 'expressions are in all but a few cases replaceable with the ' + 'function being called in the body of the lambda.'), + 'W0109': ("Duplicate key %r in dictionary", + 'duplicate-key', + 'Used when a dictionary expression binds the same key multiple ' + 'times.'), + 'W0122': ('Use of exec', + 'exec-used', + 'Used when you use the "exec" statement (function for Python 3), to discourage its ' + 'usage. That doesn\'t mean you can not use it !'), + 'W0123': ('Use of eval', + 'eval-used', + 'Used when you use the "eval" function, to discourage its ' + 'usage. Consider using `ast.literal_eval` for safely evaluating ' + 'strings containing Python expressions ' + 'from untrusted sources. '), + 'W0141': ('Used builtin function %r', + 'bad-builtin', + 'Used when a black listed builtin function is used (see the ' + 'bad-function option). Usual black listed functions are the ones ' + 'like map, or filter , where Python offers now some cleaner ' + 'alternative like list comprehension.'), + 'W0142': ('Used * or ** magic', + 'star-args', + 'Used when a function or method is called using `*args` or ' + '`**kwargs` to dispatch arguments. This doesn\'t improve ' + 'readability and should be used with care.'), + 'W0150': ("%s statement in finally block may swallow exception", + 'lost-exception', + 'Used when a break or a return statement is found inside the ' + 'finally clause of a try...finally block: the exceptions raised ' + 'in the try clause will be silently swallowed instead of being ' + 're-raised.'), + 'W0199': ('Assert called on a 2-uple. Did you mean \'assert x,y\'?', + 'assert-on-tuple', + 'A call of assert on a tuple will always evaluate to true if ' + 'the tuple is not empty, and will always evaluate to false if ' + 'it is.'), + 'W0121': ('Use raise ErrorClass(args) instead of raise ErrorClass, args.', + 'old-raise-syntax', + "Used when the alternate raise syntax 'raise foo, bar' is used " + "instead of 'raise foo(bar)'.", + {'maxversion': (3, 0)}), + + 'C0121': ('Missing required attribute "%s"', # W0103 + 'missing-module-attribute', + 'Used when an attribute required for modules is missing.'), + + 'E0109': ('Missing argument to reversed()', + 'missing-reversed-argument', + 'Used when reversed() builtin didn\'t receive an argument.'), + 'E0111': ('The first reversed() argument is not a sequence', + 'bad-reversed-sequence', + 'Used when the first argument to reversed() builtin ' + 'isn\'t a sequence (does not implement __reversed__, ' + 'nor __getitem__ and __len__'), } @@ -507,14 +501,14 @@ functions, methods 'metavar' : '<attributes>', 'help' : 'Required attributes for module, separated by a ' 'comma'} - ), + ), ('bad-functions', {'default' : BAD_FUNCTIONS, 'type' :'csv', 'metavar' : '<builtin function names>', 'help' : 'List of builtins function names that should not be ' 'used, separated by a comma'} - ), - ) + ), + ) reports = (('RP0101', 'Statistics by type', report_by_type_stats),) def __init__(self, linter): @@ -549,7 +543,7 @@ functions, methods """check for various kind of statements without effect""" expr = node.value if isinstance(expr, astroid.Const) and isinstance(expr.value, - basestring): + basestring): # treat string statement in a separated message # Handle PEP-257 attribute docstrings. # An attribute docstring is defined as being a string right after @@ -561,7 +555,7 @@ functions, methods else: sibling = expr.previous_sibling() if (sibling.scope() is scope and - isinstance(sibling, astroid.Assign)): + isinstance(sibling, astroid.Assign)): return self.add_message('pointless-string-statement', node=node) return @@ -572,11 +566,12 @@ functions, methods # warn W0106 if we have any underlying function call (we can't predict # side effects), else pointless-statement if (isinstance(expr, (astroid.Yield, astroid.CallFunc)) or - (isinstance(node.parent, astroid.TryExcept) and - node.parent.body == [node])): + (isinstance(node.parent, astroid.TryExcept) and + node.parent.body == [node])): return if any(expr.nodes_of_class(astroid.CallFunc)): - self.add_message('expression-not-assigned', node=node, args=expr.as_string()) + self.add_message('expression-not-assigned', node=node, + args=expr.as_string()) else: self.add_message('pointless-statement', node=node) @@ -609,15 +604,15 @@ functions, methods ordinary_args = list(node.args.args) if node.args.kwarg: if (not call.kwargs - or not isinstance(call.kwargs, astroid.Name) - or node.args.kwarg != call.kwargs.name): + or not isinstance(call.kwargs, astroid.Name) + or node.args.kwarg != call.kwargs.name): return elif call.kwargs: return if node.args.vararg: if (not call.starargs - or not isinstance(call.starargs, astroid.Name) - or node.args.vararg != call.starargs.name): + or not isinstance(call.starargs, astroid.Name) + or node.args.vararg != call.starargs.name): return elif call.starargs: return @@ -651,7 +646,7 @@ functions, methods continue builtins = astroid.bases.BUILTINS if (isinstance(value, astroid.Instance) and - value.qname() in ['.'.join([builtins, x]) for x in ('set', 'dict', 'list')]): + value.qname() in ['.'.join([builtins, x]) for x in ('set', 'dict', 'list')]): if value is default: msg = default.as_string() elif type(value) is astroid.Instance: @@ -707,7 +702,7 @@ functions, methods self.add_message('exec-used', node=node) @check_messages('bad-builtin', 'star-args', 'eval-used', - 'exec-used', 'missing-reversed-argument', + 'exec-used', 'missing-reversed-argument', 'bad-reversed-sequence') def visit_callfunc(self, node): """visit a CallFunc node -> check if this is not a blacklisted builtin @@ -744,7 +739,7 @@ functions, methods def visit_assert(self, node): """check the use of an assert statement on a tuple.""" if node.fail is None and isinstance(node.test, astroid.Tuple) and \ - len(node.test.elts) == 2: + len(node.test.elts) == 2: self.add_message('assert-on-tuple', node=node) @check_messages('duplicate-key') @@ -789,7 +784,7 @@ functions, methods return _node = _parent _parent = _node.parent - + def _check_reversed(self, node): """ check that the argument to `reversed` is a sequence """ try: @@ -808,17 +803,17 @@ functions, methods except InferenceError: return if (getattr(func, 'name', None) == 'iter' and - is_builtin_object(func)): + is_builtin_object(func)): self.add_message('bad-reversed-sequence', node=node) return if isinstance(argument, astroid.Instance): - if (argument._proxied.name == 'dict' and - is_builtin_object(argument._proxied)): - self.add_message('bad-reversed-sequence', node=node) - return + if (argument._proxied.name == 'dict' and + is_builtin_object(argument._proxied)): + self.add_message('bad-reversed-sequence', node=node) + return elif any(ancestor.name == 'dict' and is_builtin_object(ancestor) - for ancestor in argument._proxied.ancestors()): + for ancestor in argument._proxied.ancestors()): # mappings aren't accepted by reversed() self.add_message('bad-reversed-sequence', node=node) return @@ -831,10 +826,10 @@ functions, methods break else: break - else: + else: # check if it is a .deque. It doesn't seem that - # we can retrieve special methods - # from C implemented constructs + # we can retrieve special methods + # from C implemented constructs if argument._proxied.qname().endswith(".deque"): return self.add_message('bad-reversed-sequence', node=node) @@ -860,53 +855,51 @@ def _create_naming_options(): for name_type, (rgx, human_readable_name) in _NAME_TYPES.iteritems(): name_type = name_type.replace('_', '-') name_options.append(( - '%s-rgx' % (name_type,), + '%s-rgx' % (name_type,), {'default': rgx, 'type': 'regexp', 'metavar': '<regexp>', 'help': 'Regular expression matching correct %s names' % (human_readable_name,)})) name_options.append(( - '%s-name-hint' % (name_type,), + '%s-name-hint' % (name_type,), {'default': rgx.pattern, 'type': 'string', 'metavar': '<string>', 'help': 'Naming hint for %s names' % (human_readable_name,)})) - - return tuple(name_options) + return tuple(name_options) class NameChecker(_BasicChecker): msgs = { - 'C0102': ('Black listed name "%s"', - 'blacklisted-name', - 'Used when the name is listed in the black list (unauthorized \ - names).'), - 'C0103': ('Invalid %s name "%s"%s', - 'invalid-name', - 'Used when the name doesn\'t match the regular expression \ - associated to its type (constant, variable, class...).'), + 'C0102': ('Black listed name "%s"', + 'blacklisted-name', + 'Used when the name is listed in the black list (unauthorized ' + 'names).'), + 'C0103': ('Invalid %s name "%s"%s', + 'invalid-name', + 'Used when the name doesn\'t match the regular expression ' + 'associated to its type (constant, variable, class...).'), } - options = (# XXX use set - ('good-names', + options = (('good-names', {'default' : ('i', 'j', 'k', 'ex', 'Run', '_'), 'type' :'csv', 'metavar' : '<names>', 'help' : 'Good variable names which should always be accepted,' ' separated by a comma'} - ), + ), ('bad-names', {'default' : ('foo', 'bar', 'baz', 'toto', 'tutu', 'tata'), 'type' :'csv', 'metavar' : '<names>', 'help' : 'Bad variable names which should always be refused, ' 'separated by a comma'} - ), + ), ('name-group', {'default' : (), 'type' :'csv', 'metavar' : '<name1:name2>', 'help' : ('Colon-delimited sets of names that determine each' ' other\'s naming style when the name regexes' ' allow several styles.')} - ), + ), ('include-naming-hint', {'default': False, 'type' : 'yn', 'metavar' : '<y_or_n>', 'help': 'Include a hint for the correct naming format with invalid-name'} - ), - ) + _create_naming_options() + ), + ) + _create_naming_options() def __init__(self, linter): @@ -1028,30 +1021,30 @@ class NameChecker(_BasicChecker): class DocStringChecker(_BasicChecker): msgs = { - 'C0111': ('Missing %s docstring', # W0131 - 'missing-docstring', - 'Used when a module, function, class or method has no docstring.\ - Some special methods like __init__ doesn\'t necessary require a \ - docstring.'), - 'C0112': ('Empty %s docstring', # W0132 - 'empty-docstring', - 'Used when a module, function, class or method has an empty \ - docstring (it would be too easy ;).'), - } + 'C0111': ('Missing %s docstring', # W0131 + 'missing-docstring', + 'Used when a module, function, class or method has no docstring.' + 'Some special methods like __init__ doesn\'t necessary require a ' + 'docstring.'), + 'C0112': ('Empty %s docstring', # W0132 + 'empty-docstring', + 'Used when a module, function, class or method has an empty ' + 'docstring (it would be too easy ;).'), + } options = (('no-docstring-rgx', {'default' : NO_REQUIRED_DOC_RGX, 'type' : 'regexp', 'metavar' : '<regexp>', 'help' : 'Regular expression which should only match ' 'function or class names that do not require a ' 'docstring.'} - ), + ), ('docstring-min-length', {'default' : -1, 'type' : 'int', 'metavar' : '<int>', 'help': ('Minimum line length for functions/classes that' ' require docstrings, shorter ones are exempt.')} - ), - ) + ), + ) def open(self): @@ -1111,7 +1104,7 @@ class PassChecker(_BasicChecker): 'unnecessary-pass', 'Used when a "pass" statement that can be avoided is ' 'encountered.'), - } + } @check_messages('unnecessary-pass') def visit_pass(self, node): if len(node.parent.child_sequence(node)) > 1: @@ -1131,7 +1124,7 @@ class LambdaForComprehensionChecker(_BasicChecker): '"filter". It could be clearer as a list ' 'comprehension or generator expression.', {'maxversion': (3, 0)}), - } + } @check_messages('deprecated-lambda') def visit_callfunc(self, node): @@ -1144,7 +1137,7 @@ class LambdaForComprehensionChecker(_BasicChecker): return infered = safe_infer(node.func) if (is_builtin_object(infered) - and infered.name in ['map', 'filter']): + and infered.name in ['map', 'filter']): self.add_message('deprecated-lambda', node=node) diff --git a/checkers/classes.py b/checkers/classes.py index 170bb19..61769f2 100644 --- a/checkers/classes.py +++ b/checkers/classes.py @@ -25,9 +25,9 @@ from astroid.bases import Generator from pylint.interfaces import IAstroidChecker from pylint.checkers import BaseChecker -from pylint.checkers.utils import (PYMETHODS, overrides_a_method, - check_messages, is_attr_private, is_attr_protected, node_frame_class, - safe_infer) +from pylint.checkers.utils import ( + PYMETHODS, overrides_a_method, check_messages, is_attr_private, + is_attr_protected, node_frame_class, safe_infer) if sys.version_info >= (3, 0): NEXT_METHOD = '__next__' @@ -106,12 +106,12 @@ MSGS = { 'Used when a static method has "self" or a value specified in ' 'valid-classmethod-first-arg option or ' 'valid-metaclass-classmethod-first-arg option as first argument.' - ), + ), 'R0201': ('Method could be a function', 'no-self-use', 'Used when a method doesn\'t use its bound instance, and so could\ be written as a function.' - ), + ), 'E0221': ('Interface resolved to %s is not a class', 'interface-is-not-class', @@ -133,7 +133,7 @@ MSGS = { 'abstract-method', 'Used when an abstract method (i.e. raise NotImplementedError) is \ not overridden in concrete class.' - ), + ), 'F0220': ('failed to resolve interfaces implemented by %s (%s)', # W0224 'unresolved-interface', 'Used when a PyLint as failed to find interfaces implemented by \ @@ -198,45 +198,43 @@ class ClassChecker(BaseChecker): # configuration options options = (('ignore-iface-methods', {'default' : (#zope interface - 'isImplementedBy', 'deferred', 'extends', 'names', - 'namesAndDescriptions', 'queryDescriptionFor', 'getBases', - 'getDescriptionFor', 'getDoc', 'getName', 'getTaggedValue', - 'getTaggedValueTags', 'isEqualOrExtendedBy', 'setTaggedValue', - 'isImplementedByInstancesOf', - # twisted - 'adaptWith', - # logilab.common interface - 'is_implemented_by'), + 'isImplementedBy', 'deferred', 'extends', 'names', + 'namesAndDescriptions', 'queryDescriptionFor', 'getBases', + 'getDescriptionFor', 'getDoc', 'getName', 'getTaggedValue', + 'getTaggedValueTags', 'isEqualOrExtendedBy', 'setTaggedValue', + 'isImplementedByInstancesOf', + # twisted + 'adaptWith', + # logilab.common interface + 'is_implemented_by'), 'type' : 'csv', 'metavar' : '<method names>', 'help' : 'List of interface methods to ignore, \ separated by a comma. This is used for instance to not check methods defines \ in Zope\'s Interface base class.'} - ), - + ), ('defining-attr-methods', {'default' : ('__init__', '__new__', 'setUp'), 'type' : 'csv', 'metavar' : '<method names>', 'help' : 'List of method names used to declare (i.e. assign) \ instance attributes.'} - ), + ), ('valid-classmethod-first-arg', {'default' : ('cls',), 'type' : 'csv', 'metavar' : '<argument names>', 'help' : 'List of valid names for the first argument in \ a class method.'} - ), + ), ('valid-metaclass-classmethod-first-arg', {'default' : ('mcs',), 'type' : 'csv', 'metavar' : '<argument names>', 'help' : 'List of valid names for the first argument in \ a metaclass class method.'} - ), - - ) + ), + ) def __init__(self, linter=None): BaseChecker.__init__(self, linter) @@ -400,7 +398,7 @@ a metaclass class method.'} if infered is YES: continue if (not isinstance(infered, astroid.Const) or - not isinstance(infered.value, str)): + not isinstance(infered.value, str)): self.add_message('invalid-slots-object', args=infered.as_string(), node=elt) @@ -418,7 +416,7 @@ a metaclass class method.'} for infered_node in infered: if (infered_node is YES - or isinstance(infered_node, Generator)): + or isinstance(infered_node, Generator)): continue if isinstance(infered_node, astroid.Instance): try: @@ -451,10 +449,10 @@ a metaclass class method.'} return class_node = node.parent.frame() if (self._meth_could_be_func and node.type == 'method' - and not node.name in PYMETHODS - and not (node.is_abstract() or - overrides_a_method(class_node, node.name)) - and class_node.type != 'interface'): + and not node.name in PYMETHODS + and not (node.is_abstract() or + overrides_a_method(class_node, node.name)) + and class_node.type != 'interface'): self.add_message('no-self-use', node=node) def visit_getattr(self, node): @@ -629,8 +627,8 @@ a metaclass class method.'} # static method if node.type == 'staticmethod': if (first_arg == 'self' or - first_arg in self.config.valid_classmethod_first_arg or - first_arg in self.config.valid_metaclass_classmethod_first_arg): + first_arg in self.config.valid_classmethod_first_arg or + first_arg in self.config.valid_metaclass_classmethod_first_arg): self.add_message('bad-staticmethod-argument', args=first, node=node) return self._first_attrs[-1] = None @@ -641,19 +639,22 @@ a metaclass class method.'} elif metaclass: # metaclass __new__ or classmethod if node.type == 'classmethod': - self._check_first_arg_config(first, + self._check_first_arg_config( + first, self.config.valid_metaclass_classmethod_first_arg, node, 'bad-mcs-classmethod-argument', node.name) # metaclass regular method else: - self._check_first_arg_config(first, + self._check_first_arg_config( + first, self.config.valid_classmethod_first_arg, node, 'bad-mcs-method-argument', node.name) # regular class else: # class method if node.type == 'classmethod': - self._check_first_arg_config(first, + self._check_first_arg_config( + first, self.config.valid_classmethod_first_arg, node, 'bad-classmethod-argument', node.name) # regular method without self as argument @@ -666,11 +667,8 @@ a metaclass class method.'} if len(config) == 1: valid = repr(config[0]) else: - valid = ', '.join( - repr(v) - for v in config[:-1]) - valid = '%s or %r' % ( - valid, config[-1]) + valid = ', '.join(repr(v) for v in config[:-1]) + valid = '%s or %r' % (valid, config[-1]) self.add_message(message, args=(method_name, valid), node=node) def _check_bases_classes(self, node): @@ -727,7 +725,7 @@ a metaclass class method.'} continue # check signature self._check_signature(method, imethod, - '%s interface' % iface.name) + '%s interface' % iface.name) except astroid.InferenceError: if e0221_hack[0]: return @@ -746,7 +744,7 @@ a metaclass class method.'} method """ if (not self.linter.is_message_enabled('super-init-not-called') and - not self.linter.is_message_enabled('non-parent-init-called')): + not self.linter.is_message_enabled('non-parent-init-called')): return klass_node = node.parent.frame() to_call = _ancestors_to_call(klass_node) @@ -758,7 +756,7 @@ a metaclass class method.'} continue # skip the test if using super if isinstance(expr.expr, astroid.CallFunc) and \ - isinstance(expr.expr.func, astroid.Name) and \ + isinstance(expr.expr.func, astroid.Name) and \ expr.expr.func.name == 'super': return try: diff --git a/checkers/design_analysis.py b/checkers/design_analysis.py index c9ef4df..0725ccf 100644 --- a/checkers/design_analysis.py +++ b/checkers/design_analysis.py @@ -105,59 +105,59 @@ class MisdesignChecker(BaseChecker): options = (('max-args', {'default' : 5, 'type' : 'int', 'metavar' : '<int>', 'help': 'Maximum number of arguments for function / method'} - ), + ), ('ignored-argument-names', {'default' : IGNORED_ARGUMENT_NAMES, 'type' :'regexp', 'metavar' : '<regexp>', 'help' : 'Argument names that match this expression will be ' 'ignored. Default to name with leading underscore'} - ), + ), ('max-locals', {'default' : 15, 'type' : 'int', 'metavar' : '<int>', 'help': 'Maximum number of locals for function / method body'} - ), + ), ('max-returns', {'default' : 6, 'type' : 'int', 'metavar' : '<int>', 'help': 'Maximum number of return / yield for function / ' 'method body'} - ), + ), ('max-branches', {'default' : 12, 'type' : 'int', 'metavar' : '<int>', 'help': 'Maximum number of branch for function / method body'} - ), + ), ('max-statements', {'default' : 50, 'type' : 'int', 'metavar' : '<int>', 'help': 'Maximum number of statements in function / method ' 'body'} - ), + ), ('max-parents', {'default' : 7, 'type' : 'int', 'metavar' : '<num>', 'help' : 'Maximum number of parents for a class (see R0901).'} - ), + ), ('max-attributes', {'default' : 7, 'type' : 'int', 'metavar' : '<num>', 'help' : 'Maximum number of attributes for a class \ (see R0902).'} - ), + ), ('min-public-methods', {'default' : 2, 'type' : 'int', 'metavar' : '<num>', 'help' : 'Minimum number of public methods for a class \ (see R0903).'} - ), + ), ('max-public-methods', {'default' : 20, 'type' : 'int', 'metavar' : '<num>', 'help' : 'Maximum number of public methods for a class \ (see R0904).'} - ), - ) + ), + ) def __init__(self, linter=None): BaseChecker.__init__(self, linter) diff --git a/checkers/exceptions.py b/checkers/exceptions.py index c91c95d..94186eb 100644 --- a/checkers/exceptions.py +++ b/checkers/exceptions.py @@ -137,8 +137,8 @@ class ExceptionsChecker(BaseChecker): 'help' : 'Exceptions that will emit a warning ' 'when being caught. Defaults to "%s"' % ( ', '.join(OVERGENERAL_EXCEPTIONS),)} - ), - ) + ), + ) @check_messages('raising-string', 'nonstandard-exception', 'raising-bad-type', 'raising-non-exception', 'notimplemented-raised', 'bad-exception-context') @@ -162,7 +162,7 @@ class ExceptionsChecker(BaseChecker): elif (not isinstance(cause, astroid.Class) and not inherit_from_std_ex(cause)): self.add_message('bad-exception-context', - node=node) + node=node) expr = node.exc if self._check_raise_value(node, expr): return @@ -269,12 +269,12 @@ class ExceptionsChecker(BaseChecker): previous_exc.name, exc.name) self.add_message('bad-except-order', node=handler.type, args=msg) if (exc.name in self.config.overgeneral_exceptions - and exc.root().name == EXCEPTIONS_MODULE - and not is_raising(handler.body)): + and exc.root().name == EXCEPTIONS_MODULE + and not is_raising(handler.body)): self.add_message('broad-except', args=exc.name, node=handler.type) if (not inherit_from_std_ex(exc) and - exc.root().name != BUILTINS_NAME): + exc.root().name != BUILTINS_NAME): # try to see if the exception is based on a C based # exception, by infering all the base classes and # looking for inference errors diff --git a/checkers/format.py b/checkers/format.py index c07ff32..7b5eb64 100644 --- a/checkers/format.py +++ b/checkers/format.py @@ -68,7 +68,7 @@ MSGS = { 'C0302': ('Too many lines in module (%s)', # was W0302 'too-many-lines', 'Used when a module has too much lines, reducing its readability.' - ), + ), 'C0303': ('Trailing whitespace', 'trailing-whitespace', 'Used when there is whitespace between the end of a line and the ' @@ -111,20 +111,20 @@ MSGS = { if sys.version_info < (3, 0): MSGS.update({ - 'W0331': ('Use of the <> operator', - 'old-ne-operator', - 'Used when the deprecated "<>" operator is used instead \ - of "!=".'), - 'W0332': ('Use of "l" as long integer identifier', - 'lowercase-l-suffix', - 'Used when a lower case "l" is used to mark a long integer. You ' - 'should use a upper case "L" since the letter "l" looks too much ' - 'like the digit "1"'), - 'W0333': ('Use of the `` operator', - 'backtick', - 'Used when the deprecated "``" (backtick) operator is used ' - 'instead of the str() function.', - {'scope': WarningScope.NODE}), + 'W0331': ('Use of the <> operator', + 'old-ne-operator', + 'Used when the deprecated "<>" operator is used instead ' + 'of "!=".'), + 'W0332': ('Use of "l" as long integer identifier', + 'lowercase-l-suffix', + 'Used when a lower case "l" is used to mark a long integer. You ' + 'should use a upper case "L" since the letter "l" looks too much ' + 'like the digit "1"'), + 'W0333': ('Use of the `` operator', + 'backtick', + 'Used when the deprecated "``" (backtick) operator is used ' + 'instead of the str() function.', + {'scope': WarningScope.NODE}), }) @@ -145,29 +145,28 @@ def _column_distance(token1, token2): def _last_token_on_line_is(tokens, line_end, token): - return ( - line_end > 0 and tokens.token(line_end-1) == token or - line_end > 1 and tokens.token(line_end-2) == token - and tokens.type(line_end-1) == tokenize.COMMENT) + return (line_end > 0 and tokens.token(line_end-1) == token or + line_end > 1 and tokens.token(line_end-2) == token + and tokens.type(line_end-1) == tokenize.COMMENT) def _token_followed_by_eol(tokens, position): - return (tokens.type(position+1) == tokenize.NL or - tokens.type(position+1) == tokenize.COMMENT and - tokens.type(position+2) == tokenize.NL) + return (tokens.type(position+1) == tokenize.NL or + tokens.type(position+1) == tokenize.COMMENT and + tokens.type(position+2) == tokenize.NL) def _get_indent_length(line): - """Return the length of the indentation on the given token's line.""" - result = 0 - for char in line: - if char == ' ': - result += 1 - elif char == '\t': - result += _TAB_LENGTH - else: - break - return result + """Return the length of the indentation on the given token's line.""" + result = 0 + for char in line: + if char == ' ': + result += 1 + elif char == '\t': + result += _TAB_LENGTH + else: + break + return result def _get_indent_hint_line(bar_positions, bad_position): @@ -426,9 +425,9 @@ class FormatChecker(BaseTokenChecker): 'help': ('Regexp for a line that is allowed to be longer than ' 'the limit.')}), ('single-line-if-stmt', - {'default': False, 'type' : 'yn', 'metavar' : '<y_or_n>', - 'help' : ('Allow the body of an if to be on the same ' - 'line as the test if there is no else.')}), + {'default': False, 'type' : 'yn', 'metavar' : '<y_or_n>', + 'help' : ('Allow the body of an if to be on the same ' + 'line as the test if there is no else.')}), ('no-space-check', {'default': ','.join(_NO_SPACE_CHECK_CHOICES), 'type': 'multiple_choice', @@ -438,16 +437,16 @@ class FormatChecker(BaseTokenChecker): ('max-module-lines', {'default' : 1000, 'type' : 'int', 'metavar' : '<int>', 'help': 'Maximum number of lines in a module'} - ), + ), ('indent-string', {'default' : ' ', 'type' : "string", 'metavar' : '<string>', - 'help' : 'String used as indentation unit. This is usually \ -" " (4 spaces) or "\\t" (1 tab).'}), + 'help' : 'String used as indentation unit. This is usually ' + '" " (4 spaces) or "\\t" (1 tab).'}), ('indent-after-paren', {'type': 'int', 'metavar': '<int>', 'default': 4, 'help': 'Number of spaces of indent required inside a hanging ' ' or continued line.'}), - ) + ) def __init__(self, linter=None): BaseTokenChecker.__init__(self, linter) @@ -515,8 +514,9 @@ class FormatChecker(BaseTokenChecker): if not depth: # ')' can't happen after if (foo), since it would be a syntax error. if (tokens[i+1][1] in (':', ')', ']', '}', 'in') or - tokens[i+1][0] in (tokenize.NEWLINE, tokenize.ENDMARKER, - tokenize.COMMENT)): + tokens[i+1][0] in (tokenize.NEWLINE, + tokenize.ENDMARKER, + tokenize.COMMENT)): # The empty tuple () is always accepted. if i == start + 2: return @@ -593,7 +593,7 @@ class FormatChecker(BaseTokenChecker): if self._inside_brackets('['): return if (self._inside_brackets('{') and - _DICT_SEPARATOR in self.config.no_space_check): + _DICT_SEPARATOR in self.config.no_space_check): policy = (_IGNORE, _IGNORE) else: policy = (_MUST_NOT, _MUST) @@ -731,7 +731,7 @@ class FormatChecker(BaseTokenChecker): self.new_line(TokenWrapper(tokens), idx-1, idx+1) else: self.new_line(TokenWrapper(tokens), idx-1, idx) - + if tok_type == tokenize.NEWLINE: # a program statement, or ENDMARKER, will eventually follow, # after some (possibly empty) run of tokens of the form @@ -804,7 +804,7 @@ class FormatChecker(BaseTokenChecker): return state, valid_offsets = self._current_line.get_valid_offsets(next_idx) - # Special handling for hanging comments and strings. If the last line ended + # Special handling for hanging comments and strings. If the last line ended # with a comment (string) and the new line contains only a comment, the line # may also be indented to the start of the previous token. if same_token_around_nl(tokenize.COMMENT) or same_token_around_nl(tokenize.STRING): @@ -844,7 +844,7 @@ class FormatChecker(BaseTokenChecker): # by taking the last line of the body and adding 1, which # should be the line of finally: if (isinstance(node.parent, nodes.TryFinally) - and node in node.parent.finalbody): + and node in node.parent.finalbody): prev_line = node.parent.body[0].tolineno + 1 else: prev_line = node.parent.statement().fromlineno @@ -877,10 +877,10 @@ class FormatChecker(BaseTokenChecker): # For try... except... finally..., the two nodes # appear to be on the same line due to how the AST is built. if (isinstance(node, nodes.TryExcept) and - isinstance(node.parent, nodes.TryFinally)): + isinstance(node.parent, nodes.TryFinally)): return if (isinstance(node.parent, nodes.If) and not node.parent.orelse - and self.config.single_line_if_stmt): + and self.config.single_line_if_stmt): return self.add_message('multiple-statements', node=node) self._visited_lines[line] = 2 diff --git a/checkers/imports.py b/checkers/imports.py index 9ae3935..3242b75 100644 --- a/checkers/imports.py +++ b/checkers/imports.py @@ -48,7 +48,8 @@ def get_first_import(node, context, name, base, level): break elif isinstance(first, astroid.From): if level == first.level and any( - fullname == '%s.%s' % (first.modname, iname[0]) for iname in first.names): + fullname == '%s.%s' % (first.modname, iname[0]) + for iname in first.names): found = True break if found and not are_exclusive(first, node): @@ -178,30 +179,29 @@ class ImportsChecker(BaseChecker): 'metavar' : '<modules>', 'help' : 'Deprecated modules which should not be used, \ separated by a comma'} - ), + ), ('import-graph', {'default' : '', 'type' : 'string', 'metavar' : '<file.dot>', 'help' : 'Create a graph of every (i.e. internal and \ external) dependencies in the given file (report RP0402 must not be disabled)'} - ), + ), ('ext-import-graph', {'default' : '', 'type' : 'string', 'metavar' : '<file.dot>', 'help' : 'Create a graph of external dependencies in the \ given file (report RP0402 must not be disabled)'} - ), + ), ('int-import-graph', {'default' : '', 'type' : 'string', 'metavar' : '<file.dot>', 'help' : 'Create a graph of internal dependencies in the \ given file (report RP0402 must not be disabled)'} - ), - - ) + ), + ) def __init__(self, linter=None): BaseChecker.__init__(self, linter) @@ -212,7 +212,7 @@ given file (report RP0402 must not be disabled)'} self.report_external_dependencies), ('RP0402', 'Modules dependencies graph', self.report_dependencies_graph), - ) + ) def open(self): """called before visiting project (i.e set of modules)""" @@ -252,7 +252,7 @@ given file (report RP0402 must not be disabled)'} if prev: # consecutive future statements are possible if not (isinstance(prev, astroid.From) - and prev.modname == '__future__'): + and prev.modname == '__future__'): self.add_message('misplaced-future', node=node) return for name, _ in node.names: diff --git a/checkers/logging.py b/checkers/logging.py index cbdf0f2..d82d74b 100644 --- a/checkers/logging.py +++ b/checkers/logging.py @@ -22,16 +22,16 @@ from pylint.checkers.utils import check_messages MSGS = { 'W1201': ('Specify string format arguments as logging function parameters', - 'logging-not-lazy', - 'Used when a logging statement has a call form of ' - '"logging.<logging method>(format_string % (format_args...))". ' - 'Such calls should leave string interpolation to the logging ' - 'method itself and be written ' - '"logging.<logging method>(format_string, format_args...)" ' - 'so that the program may avoid incurring the cost of the ' - 'interpolation in those cases in which no message will be ' - 'logged. For more, see ' - 'http://www.python.org/dev/peps/pep-0282/.'), + 'logging-not-lazy', + 'Used when a logging statement has a call form of ' + '"logging.<logging method>(format_string % (format_args...))". ' + 'Such calls should leave string interpolation to the logging ' + 'method itself and be written ' + '"logging.<logging method>(format_string, format_args...)" ' + 'so that the program may avoid incurring the cost of the ' + 'interpolation in those cases in which no message will be ' + 'logged. For more, see ' + 'http://www.python.org/dev/peps/pep-0282/.'), 'E1200': ('Unsupported logging format character %r (%#02x) at index %d', 'logging-unsupported-format', 'Used when an unsupported format character is used in a logging\ @@ -65,10 +65,10 @@ class LoggingChecker(checkers.BaseChecker): {'default' : ('logging',), 'type' : 'csv', 'metavar' : '<comma separated list>', - 'help' : ('Logging modules to check that the string format ' - 'arguments are in logging function parameter format')} - ), - ) + 'help' : 'Logging modules to check that the string format ' + 'arguments are in logging function parameter format'} + ), + ) def visit_module(self, unused_node): """Clears any state left in this checker from last module checked.""" @@ -105,19 +105,19 @@ class LoggingChecker(checkers.BaseChecker): def visit_callfunc(self, node): """Checks calls to logging methods.""" def is_logging_name(): - return (isinstance(node.func, astroid.Getattr) and - isinstance(node.func.expr, astroid.Name) and - node.func.expr.name in self._logging_names) + return (isinstance(node.func, astroid.Getattr) and + isinstance(node.func.expr, astroid.Name) and + node.func.expr.name in self._logging_names) def is_logger_class(): try: for inferred in node.func.infer(): if isinstance(inferred, astroid.BoundMethod): parent = inferred._proxied.parent - if (isinstance(parent, astroid.Class) and - (parent.qname() == 'logging.Logger' or - any(ancestor.qname() == 'logging.Logger' - for ancestor in parent.ancestors()))): + if (isinstance(parent, astroid.Class) and + (parent.qname() == 'logging.Logger' or + any(ancestor.qname() == 'logging.Logger' + for ancestor in parent.ancestors()))): return True, inferred._proxied.name except astroid.exceptions.InferenceError: pass diff --git a/checkers/newstyle.py b/checkers/newstyle.py index f801c44..cc8f640 100644 --- a/checkers/newstyle.py +++ b/checkers/newstyle.py @@ -89,8 +89,8 @@ class NewStyleConflictChecker(BaseChecker): """check property usage""" parent = node.parent.frame() if (isinstance(parent, astroid.Class) and - not parent.newstyle and - isinstance(node.func, astroid.Name)): + not parent.newstyle and + isinstance(node.func, astroid.Name)): name = node.func.name if name == 'property': self.add_message('property-on-old-class', node=node) diff --git a/checkers/similar.py b/checkers/similar.py index cf671bf..e5c9300 100644 --- a/checkers/similar.py +++ b/checkers/similar.py @@ -107,7 +107,7 @@ class Similar(object): for index2 in find(lineset1[index1]): non_blank = 0 for num, ((_, line1), (_, line2)) in enumerate( - izip(lines1(index1), lines2(index2))): + izip(lines1(index1), lines2(index2))): if line1 != line2: if non_blank > min_lines: yield num, lineset1, index1, lineset2, index2 @@ -249,16 +249,16 @@ class SimilarChecker(BaseChecker, Similar): ('ignore-comments', {'default' : True, 'type' : 'yn', 'metavar' : '<y or n>', 'help': 'Ignore comments when computing similarities.'} - ), + ), ('ignore-docstrings', {'default' : True, 'type' : 'yn', 'metavar' : '<y or n>', 'help': 'Ignore docstrings when computing similarities.'} - ), + ), ('ignore-imports', {'default' : False, 'type' : 'yn', 'metavar' : '<y or n>', 'help': 'Ignore imports when computing similarities.'} - ), - ) + ), + ) # reports reports = (('RP0801', 'Duplication', report_similarities),) diff --git a/checkers/stdlib.py b/checkers/stdlib.py index a1c3133..9913e99 100644 --- a/checkers/stdlib.py +++ b/checkers/stdlib.py @@ -24,7 +24,7 @@ from pylint.interfaces import IAstroidChecker from pylint.checkers import BaseChecker from pylint.checkers import utils -_VALID_OPEN_MODE_REGEX = r'^(r?U|[rwa]\+?b?)$' +_VALID_OPEN_MODE_REGEX = re.compile(r'^(r?U|[rwa]\+?b?)$') if sys.version_info >= (3, 0): OPEN_MODULE = '_io' @@ -58,8 +58,9 @@ class OpenModeChecker(BaseChecker): if mode_arg: mode_arg = utils.safe_infer(mode_arg) if (isinstance(mode_arg, astroid.Const) - and not re.match(_VALID_OPEN_MODE_REGEX, mode_arg.value)): - self.add_message('bad-open-mode', node=node, args=(mode_arg.value)) + and not _VALID_OPEN_MODE_REGEX.match(mode_arg.value)): + self.add_message('bad-open-mode', node=node, + args=(mode_arg.value)) except (utils.NoSuchArgumentError, TypeError): pass diff --git a/checkers/strings.py b/checkers/strings.py index af2ceea..8251a80 100644 --- a/checkers/strings.py +++ b/checkers/strings.py @@ -211,7 +211,7 @@ class StringFormatChecker(BaseChecker): args = node.right if not (isinstance(left, astroid.Const) - and isinstance(left.value, basestring)): + and isinstance(left.value, basestring)): return format_string = left.value try: @@ -298,9 +298,8 @@ class StringMethodsChecker(BaseChecker): def visit_callfunc(self, node): func = utils.safe_infer(node.func) if (isinstance(func, astroid.BoundMethod) - and isinstance(func.bound, astroid.Instance) - and func.bound.name in ('str', 'unicode', 'bytes')): - + and isinstance(func.bound, astroid.Instance) + and func.bound.name in ('str', 'unicode', 'bytes')): if func.name in ('strip', 'lstrip', 'rstrip') and node.args: arg = utils.safe_infer(node.args[0]) if not isinstance(arg, astroid.Const): @@ -413,7 +412,7 @@ class StringMethodsChecker(BaseChecker): previous = previous.getattr(specifier)[0] except astroid.NotFoundError: if (hasattr(previous, 'has_dynamic_getattr') and - previous.has_dynamic_getattr()): + previous.has_dynamic_getattr()): # Don't warn if the object has a custom __getattr__ break path = get_access_path(key, parsed) @@ -504,7 +503,7 @@ class StringConstantChecker(BaseTokenChecker): # No special checks on raw strings at the moment. if 'r' not in prefix: self.process_non_raw_string_token(prefix, string_body, - start_row, start_col) + start_row, start_col) def process_non_raw_string_token(self, prefix, string_body, start_row, start_col): diff --git a/checkers/typecheck.py b/checkers/typecheck.py index 09caa86..fb8f3c6 100644 --- a/checkers/typecheck.py +++ b/checkers/typecheck.py @@ -146,39 +146,38 @@ class TypeChecker(BaseChecker): 'help' : 'Tells whether missing members accessed in mixin \ class should be ignored. A mixin class is detected if its name ends with \ "mixin" (case insensitive).'} - ), - ('ignored-modules', - {'default': (), - 'type': 'csv', - 'metavar': '<module names>', - 'help': 'List of module names for which member attributes \ + ), + ('ignored-modules', + {'default': (), + 'type': 'csv', + 'metavar': '<module names>', + 'help': 'List of module names for which member attributes \ should not be checked (useful for modules/projects where namespaces are \ manipulated during runtime and thus existing member attributes cannot be \ deduced by static analysis'}, - ), + ), ('ignored-classes', {'default' : ('SQLObject',), 'type' : 'csv', 'metavar' : '<members names>', 'help' : 'List of classes names for which member attributes \ should not be checked (useful for classes with attributes dynamically set).'} - ), + ), ('zope', {'default' : False, 'type' : 'yn', 'metavar': '<y_or_n>', 'help' : 'When zope mode is activated, add a predefined set \ of Zope acquired attributes to generated-members.'} - ), + ), ('generated-members', - {'default' : ( - 'REQUEST', 'acl_users', 'aq_parent'), + {'default' : ('REQUEST', 'acl_users', 'aq_parent'), 'type' : 'string', 'metavar' : '<members names>', 'help' : 'List of members which are set dynamically and \ missed by pylint inference system, and so shouldn\'t trigger E0201 when \ accessed. Python regular expressions are accepted.'} - ), - ) + ), + ) def open(self): # do this in open since config not fully initialized in __init__ @@ -326,7 +325,7 @@ accessed. Python regular expressions are accepted.'} expr = node.func.expr klass = safe_infer(expr) if (klass is None or klass is astroid.YES or - not isinstance(klass, astroid.Instance)): + not isinstance(klass, astroid.Instance)): return try: @@ -354,12 +353,12 @@ accessed. Python regular expressions are accepted.'} property_like = False if isinstance(infered, astroid.Class): if (infered.root().name == BUILTINS and - infered.name == 'property'): + infered.name == 'property'): property_like = True else: for ancestor in infered.ancestors(): if (ancestor.name == 'property' and - ancestor.root().name == BUILTINS): + ancestor.root().name == BUILTINS): property_like = True break if property_like: diff --git a/checkers/utils.py b/checkers/utils.py index 01989be..d88d620 100644 --- a/checkers/utils.py +++ b/checkers/utils.py @@ -67,11 +67,10 @@ def clobber_in_except(node): if is_builtin(name): return (True, (name, 'builtins')) else: - scope, stmts = node.lookup(name) - if (stmts and - not isinstance(stmts[0].ass_type(), - (astroid.Assign, astroid.AugAssign, - astroid.ExceptHandler))): + stmts = node.lookup(name)[1] + if (stmts and not isinstance(stmts[0].ass_type(), + (astroid.Assign, astroid.AugAssign, + astroid.ExceptHandler))): return (True, (name, 'outer scope (line %s)' % stmts[0].fromlineno)) return (False, None) @@ -155,10 +154,10 @@ def is_defined_before(var_node): elif isinstance(_node, astroid.With): for expr, vars in _node.items: if expr.parent_of(var_node): - break + break if (vars and - isinstance(vars, astroid.AssName) and - vars.name == varname): + isinstance(vars, astroid.AssName) and + vars.name == varname): return True elif isinstance(_node, (astroid.Lambda, astroid.Function)): if _node.args.is_argument(varname): @@ -205,9 +204,9 @@ def is_func_decorator(node): if isinstance(parent, astroid.Decorators): return True if (parent.is_statement or - isinstance(parent, astroid.Lambda) or - isinstance(parent, (scoped_nodes.ComprehensionScope, - scoped_nodes.ListComp))): + isinstance(parent, astroid.Lambda) or + isinstance(parent, (scoped_nodes.ComprehensionScope, + scoped_nodes.ListComp))): break parent = parent.parent return False @@ -269,7 +268,7 @@ PYMETHODS = set(('__new__', '__init__', '__del__', '__hash__', '__or__', '__ior__', '__ror__', '__xor__', '__ixor__', '__rxor__', # XXX To be continued - )) + )) def check_messages(*messages): """decorator to store messages that are handled by a checker method""" @@ -365,7 +364,7 @@ def is_attr_protected(attrname): details), False otherwise. """ return attrname[0] == '_' and not attrname == '_' and not ( - attrname.startswith('__') and attrname.endswith('__')) + attrname.startswith('__') and attrname.endswith('__')) def node_frame_class(node): """return klass node for a method node (or a staticmethod or a @@ -386,8 +385,8 @@ def is_super_call(expr): is super. Check before that you're in a method. """ return (isinstance(expr, astroid.CallFunc) and - isinstance(expr.func, astroid.Name) and - expr.func.name == 'super') + isinstance(expr.func, astroid.Name) and + expr.func.name == 'super') def is_attr_private(attrname): """Check that attribute name is private (at least two leading underscores, diff --git a/checkers/variables.py b/checkers/variables.py index 3b9bcda..fc4c99e 100644 --- a/checkers/variables.py +++ b/checkers/variables.py @@ -27,10 +27,11 @@ from logilab.common.modutils import file_from_modpath from pylint.interfaces import IAstroidChecker from pylint.utils import get_global_option 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, check_messages, is_inside_except, clobber_in_except, - get_all_elements) +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, is_inside_except, clobber_in_except, + get_all_elements) def in_for_else_branch(parent, stmt): @@ -102,7 +103,7 @@ def _detect_global_scope(node, frame, defframe): (astroid.Function, astroid.Arguments)): return False elif any(not isinstance(f, (astroid.Class, astroid.Module)) - for f in (frame, defframe)): + for f in (frame, defframe)): # Not interested in other frames, since they are already # not in a global scope. return False @@ -234,8 +235,7 @@ class VariablesChecker(BaseChecker): name = 'variables' msgs = MSGS priority = -1 - options = ( - ("init-import", + options = (("init-import", {'default': 0, 'type' : 'yn', 'metavar' : '<y_or_n>', 'help' : 'Tells whether we should check for unused import in \ __init__ files.'}), @@ -249,8 +249,8 @@ variables (i.e. expectedly not used).'}), 'metavar' : '<comma separated list>', 'help' : 'List of additional names supposed to be defined in \ builtins. Remember that you should avoid to define new builtins when possible.' - }), - ) + }), + ) def __init__(self, linter=None): BaseChecker.__init__(self, linter) self._to_consume = None @@ -306,7 +306,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' self.add_message('undefined-all-variable', args=elt_name, node=elt) - except SyntaxError, exc: + except SyntaxError: # don't yield an syntax-error warning, # because it will be later yielded # when the file will be checked @@ -545,7 +545,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' def _is_direct_lambda_call(): return (isinstance(node_scope.parent, astroid.CallFunc) and node_scope.parent.func is node_scope) - + node_scope = node.scope() if not isinstance(node_scope, (astroid.Lambda, astroid.Function)): return @@ -594,7 +594,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' _astmts = astmts[:1] for i, stmt in enumerate(astmts[1:]): if (astmts[i].statement().parent_of(stmt) - and not in_for_else_branch(astmts[i].statement(), stmt)): + and not in_for_else_branch(astmts[i].statement(), stmt)): continue _astmts.append(stmt) astmts = _astmts @@ -634,7 +634,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' # a decorator, then start from the parent frame of the function instead # of the function frame - and thus open an inner class scope if (is_func_default(node) or is_func_decorator(node) - or is_ancestor_name(frame, node)): + or is_ancestor_name(frame, node)): start_index = len(self._to_consume) - 2 else: start_index = len(self._to_consume) - 1 @@ -648,7 +648,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' # names. The only exception is when the starting scope is a # comprehension and its direct outer scope is a class if scope_type == 'class' and i != start_index and not ( - base_scope_type == 'comprehension' and i == start_index-1): + base_scope_type == 'comprehension' and i == start_index-1): # XXX find a way to handle class scope in a smoother way continue # the name has already been consumed, only check it's not a loop @@ -690,9 +690,11 @@ builtins. Remember that you should avoid to define new builtins when possible.' and name in child.names for child in defframe.get_children()) if (maybee0601 - and stmt.fromlineno <= defstmt.fromlineno - and not is_defined_before(node) - and not are_exclusive(stmt, defstmt, ('NameError', 'Exception', 'BaseException'))): + and stmt.fromlineno <= defstmt.fromlineno + and not is_defined_before(node) + and not are_exclusive(stmt, defstmt, ('NameError', + 'Exception', + 'BaseException'))): if defstmt is stmt and isinstance(node, (astroid.DelName, astroid.AssName)): self.add_message('undefined-variable', args=name, node=node) @@ -872,9 +874,8 @@ class VariablesChecker3k(VariablesChecker): name = metaclass.root().name if name: - found = consumed.setdefault(name, - module_locals.get(name, module_imports.get(name)) - ) + found = consumed.setdefault( + name, module_locals.get(name, module_imports.get(name))) if found is None and not metaclass: name = None @@ -46,7 +46,7 @@ You may also use py_run to run pylint with desired options and get back (or not) its output. """ -import sys, os, re +import sys, os import os.path as osp from subprocess import Popen, PIPE @@ -171,10 +171,11 @@ class LintGui(object): rightscrollbar.pack(side=RIGHT, fill=Y) bottomscrollbar = Scrollbar(msg_frame, orient=HORIZONTAL) bottomscrollbar.pack(side=BOTTOM, fill=X) - self.lb_messages = Listbox(msg_frame, - yscrollcommand=rightscrollbar.set, - xscrollcommand=bottomscrollbar.set, - bg="white") + self.lb_messages = Listbox( + msg_frame, + yscrollcommand=rightscrollbar.set, + xscrollcommand=bottomscrollbar.set, + bg="white") self.lb_messages.bind("<Double-Button-1>", self.show_sourcefile) self.lb_messages.pack(expand=True, fill=BOTH) rightscrollbar.config(command=self.lb_messages.yview) @@ -185,10 +186,11 @@ class LintGui(object): rightscrollbar2.pack(side=RIGHT, fill=Y) bottomscrollbar2 = Scrollbar(history_frame, orient=HORIZONTAL) bottomscrollbar2.pack(side=BOTTOM, fill=X) - self.showhistory = Listbox(history_frame, - yscrollcommand=rightscrollbar2.set, - xscrollcommand=bottomscrollbar2.set, - bg="white") + self.showhistory = Listbox( + history_frame, + yscrollcommand=rightscrollbar2.set, + xscrollcommand=bottomscrollbar2.set, + bg="white") self.showhistory.pack(expand=True, fill=BOTH) rightscrollbar2.config(command=self.showhistory.yview) bottomscrollbar2.config(command=self.showhistory.xview) @@ -217,10 +219,11 @@ class LintGui(object): rightscrollbar.pack(side=RIGHT, fill=Y) bottomscrollbar = Scrollbar(res_frame, orient=HORIZONTAL) bottomscrollbar.pack(side=BOTTOM, fill=X) - self.results = Listbox(res_frame, - yscrollcommand=rightscrollbar.set, - xscrollcommand=bottomscrollbar.set, - bg="white", font="Courier") + self.results = Listbox( + res_frame, + yscrollcommand=rightscrollbar.set, + xscrollcommand=bottomscrollbar.set, + bg="white", font="Courier") self.results.pack(expand=True, fill=BOTH, side=BOTTOM) rightscrollbar.config(command=self.results.yview) bottomscrollbar.config(command=self.results.xview) @@ -399,8 +402,10 @@ class LintGui(object): def file_open(self, package=False, _=None): """launch a file browser""" if not package: - filename = askopenfilename(parent=self.root, filetypes=[('pythonfiles', '*.py'), - ('allfiles', '*')], title='Select Module') + filename = askopenfilename(parent=self.root, + filetypes=[('pythonfiles', '*.py'), + ('allfiles', '*')], + title='Select Module') else: filename = askdirectory(title="Select A Folder", mustexist=1) @@ -27,9 +27,8 @@ """ # import this first to avoid builtin namespace pollution -from pylint.checkers import utils +from pylint.checkers import utils #pylint: disable=unused-import -import functools import sys import os import tokenize @@ -43,14 +42,14 @@ from logilab.common.textutils import splitstrip, unquote from logilab.common.ureports import Table, Text, Section from logilab.common.__pkginfo__ import version as common_version -from astroid import MANAGER, nodes, AstroidBuildingException +from astroid import MANAGER, AstroidBuildingException from astroid.__pkginfo__ import version as astroid_version from astroid.modutils import load_module_from_name, get_module_part from pylint.utils import ( MSG_TYPES, OPTION_RGX, PyLintASTWalker, UnknownMessage, MessagesHandlerMixIn, ReportsHandlerMixIn, - MessagesStore, FileState, EmptyReport, WarningScope, + MessagesStore, FileState, EmptyReport, expand_modules, tokenize_module) from pylint.interfaces import IRawChecker, ITokenChecker, IAstroidChecker from pylint.checkers import (BaseTokenChecker, @@ -65,7 +64,7 @@ from pylint.__pkginfo__ import version def _get_python_path(filepath): dirname = os.path.dirname(os.path.realpath( - os.path.expanduser(filepath))) + os.path.expanduser(filepath))) while True: if not os.path.exists(os.path.join(dirname, "__init__.py")): return dirname @@ -94,7 +93,7 @@ MSGS = { 'F0010': ('error while code parsing: %s', 'parse-error', 'Used when an exception occured while building the Astroid ' - 'representation which could be handled by astroid.'), + 'representation which could be handled by astroid.'), 'I0001': ('Unable to run raw checkers on built-in module %s', 'raw-checker-failed', @@ -183,7 +182,7 @@ class PyLinter(OptionsManagerMixIn, MessagesHandlerMixIn, ReportsHandlerMixIn, {'type' : 'csv', 'metavar' : '<file>[,<file>...]', 'dest' : 'black_list', 'default' : ('CVS',), 'help' : 'Add files or directories to the blacklist. ' - 'They should be base names, not paths.'}), + 'They should be base names, not paths.'}), ('persistent', {'default': True, 'type' : 'yn', 'metavar' : '<y_or_n>', 'level': 1, @@ -193,85 +192,86 @@ class PyLinter(OptionsManagerMixIn, MessagesHandlerMixIn, ReportsHandlerMixIn, {'type' : 'csv', 'metavar' : '<modules>', 'default' : (), 'level': 1, 'help' : 'List of plugins (as comma separated values of ' - 'python modules names) to load, usually to register ' - 'additional checkers.'}), + 'python modules names) to load, usually to register ' + 'additional checkers.'}), ('output-format', {'default': 'text', 'type': 'string', 'metavar' : '<format>', 'short': 'f', 'group': 'Reports', 'help' : 'Set the output format. Available formats are text,' - ' parseable, colorized, msvs (visual studio) and html. You ' - 'can also give a reporter class, eg mypackage.mymodule.' - 'MyReporterClass.'}), + ' parseable, colorized, msvs (visual studio) and html. You ' + 'can also give a reporter class, eg mypackage.mymodule.' + 'MyReporterClass.'}), ('files-output', {'default': 0, 'type' : 'yn', 'metavar' : '<y_or_n>', 'group': 'Reports', 'level': 1, 'help' : 'Put messages in a separate file for each module / ' - 'package specified on the command line instead of printing ' - 'them on stdout. Reports (if any) will be written in a file ' - 'name "pylint_global.[txt|html]".'}), + 'package specified on the command line instead of printing ' + 'them on stdout. Reports (if any) will be written in a file ' + 'name "pylint_global.[txt|html]".'}), ('reports', {'default': 1, 'type' : 'yn', 'metavar' : '<y_or_n>', 'short': 'r', 'group': 'Reports', 'help' : 'Tells whether to display a full report or only the ' - 'messages'}), + 'messages'}), ('evaluation', {'type' : 'string', 'metavar' : '<python_expression>', 'group': 'Reports', 'level': 1, 'default': '10.0 - ((float(5 * error + warning + refactor + ' - 'convention) / statement) * 10)', - 'help' : 'Python expression which should return a note less \ -than 10 (10 is the highest note). You have access to the variables errors \ -warning, statement which respectively contain the number of errors / warnings\ - messages and the total number of statements analyzed. This is used by the \ - global evaluation report (RP0004).'}), + 'convention) / statement) * 10)', + 'help' : 'Python expression which should return a note less ' + 'than 10 (10 is the highest note). You have access ' + 'to the variables errors warning, statement which ' + 'respectively contain the number of errors / ' + 'warnings messages and the total number of ' + 'statements analyzed. This is used by the global ' + 'evaluation report (RP0004).'}), ('comment', {'default': 0, 'type' : 'yn', 'metavar' : '<y_or_n>', 'group': 'Reports', 'level': 1, 'help' : 'Add a comment according to your evaluation note. ' - 'This is used by the global evaluation report (RP0004).'}), + 'This is used by the global evaluation report (RP0004).'}), ('enable', {'type' : 'csv', 'metavar': '<msg ids>', 'short': 'e', 'group': 'Messages control', 'help' : 'Enable the message, report, category or checker with the ' - 'given id(s). You can either give multiple identifier ' - 'separated by comma (,) or put this option multiple time. ' - 'See also the "--disable" option for examples. '}), + 'given id(s). You can either give multiple identifier ' + 'separated by comma (,) or put this option multiple time. ' + 'See also the "--disable" option for examples. '}), ('disable', {'type' : 'csv', 'metavar': '<msg ids>', 'short': 'd', 'group': 'Messages control', 'help' : 'Disable the message, report, category or checker ' - 'with the given id(s). You can either give multiple identifiers' - ' separated by comma (,) or put this option multiple times ' - '(only on the command line, not in the configuration file ' - 'where it should appear only once).' - 'You can also use "--disable=all" to disable everything first ' - 'and then reenable specific checks. For example, if you want ' - 'to run only the similarities checker, you can use ' - '"--disable=all --enable=similarities". ' - 'If you want to run only the classes checker, but have no ' - 'Warning level messages displayed, use' - '"--disable=all --enable=classes --disable=W"'}), + 'with the given id(s). You can either give multiple identifiers' + ' separated by comma (,) or put this option multiple times ' + '(only on the command line, not in the configuration file ' + 'where it should appear only once).' + 'You can also use "--disable=all" to disable everything first ' + 'and then reenable specific checks. For example, if you want ' + 'to run only the similarities checker, you can use ' + '"--disable=all --enable=similarities". ' + 'If you want to run only the classes checker, but have no ' + 'Warning level messages displayed, use' + '"--disable=all --enable=classes --disable=W"'}), ('msg-template', {'type' : 'string', 'metavar': '<template>', - #'short': 't', 'group': 'Reports', 'help' : ('Template used to display messages. ' 'This is a python new-style format string ' 'used to format the message information. ' 'See doc for all details') - }), + }), ('include-ids', _deprecated_option('i', 'yn')), ('symbols', _deprecated_option('s', 'yn')), @@ -323,7 +323,7 @@ warning, statement which respectively contain the number of errors / warnings\ report_messages_stats), ('RP0004', 'Global evaluation', self.report_evaluation), - ) + ) self.register_checker(self) self._dynamic_plugins = set() self.load_provider_defaults() @@ -516,7 +516,7 @@ warning, statement which respectively contain the number of errors / warnings\ messages = set(msg for msg in checker.msgs if msg[0] != 'F' and self.is_message_enabled(msg)) if (messages or - any(self.report_is_enabled(r[0]) for r in checker.reports)): + any(self.report_is_enabled(r[0]) for r in checker.reports)): neededcheckers.append(checker) # Sort checkers by priority neededcheckers = sorted(neededcheckers, key=attrgetter('priority'), @@ -668,7 +668,7 @@ warning, statement which respectively contain the number of errors / warnings\ """initialize counters""" self.stats = {'by_module' : {}, 'by_msg' : {}, - } + } for msg_cat in MSG_TYPES.itervalues(): self.stats[msg_cat] = 0 @@ -844,11 +844,11 @@ group are mutually exclusive.'), self._plugins = [] try: preprocess_options(args, { - # option: (callback, takearg) - 'init-hook': (cb_init_hook, True), - 'rcfile': (self.cb_set_rcfile, True), - 'load-plugins': (self.cb_add_plugins, True), - }) + # option: (callback, takearg) + 'init-hook': (cb_init_hook, True), + 'rcfile': (self.cb_set_rcfile, True), + 'load-plugins': (self.cb_add_plugins, True), + }) except ArgumentPreprocessingError, ex: print >> sys.stderr, ex sys.exit(32) @@ -863,15 +863,15 @@ group are mutually exclusive.'), {'action' : 'callback', 'callback' : lambda *args: 1, 'type' : 'string', 'metavar': '<code>', 'level': 1, - 'help' : 'Python code to execute, usually for sys.path \ -manipulation such as pygtk.require().'}), + 'help' : 'Python code to execute, usually for sys.path ' + 'manipulation such as pygtk.require().'}), ('help-msg', {'action' : 'callback', 'type' : 'string', 'metavar': '<msg-id>', 'callback' : self.cb_help_message, 'group': 'Commands', - 'help' : '''Display a help message for the given message id and \ -exit. The value may be a comma separated list of message ids.'''}), + 'help' : 'Display a help message for the given message id and ' + 'exit. The value may be a comma separated list of message ids.'}), ('list-msgs', {'action' : 'callback', 'metavar': '<msg-id>', @@ -888,9 +888,10 @@ exit. The value may be a comma separated list of message ids.'''}), ('generate-rcfile', {'action' : 'callback', 'callback' : self.cb_generate_config, 'group': 'Commands', - 'help' : '''Generate a sample configuration file according to \ -the current configuration. You can put other options before this one to get \ -them in the generated configuration.'''}), + 'help' : 'Generate a sample configuration file according to ' + 'the current configuration. You can put other options ' + 'before this one to get them in the generated ' + 'configuration.'}), ('generate-man', {'action' : 'callback', 'callback' : self.cb_generate_manpage, @@ -900,9 +901,9 @@ them in the generated configuration.'''}), ('errors-only', {'action' : 'callback', 'callback' : self.cb_error_mode, 'short': 'E', - 'help' : '''In error mode, checkers without error messages are \ -disabled and for others, only the ERROR messages are displayed, and no reports \ -are done by default'''}), + 'help' : 'In error mode, checkers without error messages are ' + 'disabled and for others, only the ERROR messages are ' + 'displayed, and no reports are done by default'''}), ('profile', {'type' : 'yn', 'metavar' : '<y_or_n>', @@ -916,6 +917,7 @@ are done by default'''}), linter.load_plugin_modules(self._plugins) # add some help section linter.add_help_section('Environment variables', config.ENV_HELP, level=1) + # pylint: disable=bad-continuation linter.add_help_section('Output', 'Using the default text output, the message format is : \n' ' \n' @@ -928,7 +930,7 @@ are done by default'''}), ' * (E) error, for probable bugs in the code \n' ' * (F) fatal, if an error occurred which prevented pylint from doing further\n' 'processing.\n' - , level=1) + , level=1) linter.add_help_section('Output status code', 'Pylint should leave with following status code: \n' ' * 0 if everything went fine \n' @@ -941,7 +943,7 @@ are done by default'''}), ' \n' 'status 1 to 16 will be bit-ORed so you can know which different categories has\n' 'been issued by analysing pylint output status code\n', - level=1) + level=1) # read configuration linter.disable('pointless-except') linter.disable('suppressed-message') diff --git a/pyreverse/main.py b/pyreverse/main.py index 7801835..d4991b5 100644 --- a/pyreverse/main.py +++ b/pyreverse/main.py @@ -29,10 +29,10 @@ from pylint.pyreverse import writer from pylint.pyreverse.utils import insert_default_options OPTIONS = ( -("filter-mode", - dict(short='f', default='PUB_ONLY', dest='mode', type='string', - action='store', metavar='<mode>', - help="""filter attributes and functions according to + ("filter-mode", + dict(short='f', default='PUB_ONLY', dest='mode', type='string', + action='store', metavar='<mode>', + help="""filter attributes and functions according to <mode>. Correct modes are : 'PUB_ONLY' filter all non public attributes [DEFAULT], equivalent to PRIVATE+SPECIAL_A @@ -42,43 +42,42 @@ OPTIONS = ( 'OTHER' filter protected and private attributes""")), -("class", -dict(short='c', action="append", metavar="<class>", dest="classes", default=[], - help="create a class diagram with all classes related to <class>;\ + ("class", + dict(short='c', action="append", metavar="<class>", dest="classes", default=[], + help="create a class diagram with all classes related to <class>;\ this uses by default the options -ASmy")), -("show-ancestors", -dict(short="a", action="store", metavar='<ancestor>', type='int', - help='show <ancestor> generations of ancestor classes not in <projects>')), -("all-ancestors", -dict(short="A", default=None, - help="show all ancestors off all classes in <projects>")), -("show-associated", -dict(short='s', action="store", metavar='<ass_level>', type='int', - help='show <ass_level> levels of associated classes not in <projects>')), -("all-associated", -dict(short='S', default=None, - help='show recursively all associated off all associated classes')), + ("show-ancestors", + dict(short="a", action="store", metavar='<ancestor>', type='int', + help='show <ancestor> generations of ancestor classes not in <projects>')), + ("all-ancestors", + dict(short="A", default=None, + help="show all ancestors off all classes in <projects>")), + ("show-associated", + dict(short='s', action="store", metavar='<ass_level>', type='int', + help='show <ass_level> levels of associated classes not in <projects>')), + ("all-associated", + dict(short='S', default=None, + help='show recursively all associated off all associated classes')), + ("show-builtin", + dict(short="b", action="store_true", default=False, + help='include builtin objects in representation of classes')), -("show-builtin", -dict(short="b", action="store_true", default=False, - help='include builtin objects in representation of classes')), - -("module-names", -dict(short="m", default=None, type='yn', metavar='[yn]', - help='include module name in representation of classes')), -# TODO : generate dependencies like in pylint -#("package-dependencies", -#dict(short="M", action="store", metavar='<package_depth>', type='int', - #help='show <package_depth> module dependencies beyond modules in \ -#<projects> (for the package diagram)')), -("only-classnames", -dict(short='k', action="store_true", default=False, - help="don't show attributes and methods in the class boxes; \ + ("module-names", + dict(short="m", default=None, type='yn', metavar='[yn]', + help='include module name in representation of classes')), + # TODO : generate dependencies like in pylint + # ("package-dependencies", + # dict(short="M", action="store", metavar='<package_depth>', type='int', + # help='show <package_depth> module dependencies beyond modules in \ + # <projects> (for the package diagram)')), + ("only-classnames", + dict(short='k', action="store_true", default=False, + help="don't show attributes and methods in the class boxes; \ this disables -f values")), -("output", dict(short="o", dest="output_format", action="store", - default="dot", metavar="<format>", - help="create a *.<format> output file if format available.")), + ("output", dict(short="o", dest="output_format", action="store", + default="dot", metavar="<format>", + help="create a *.<format> output file if format available.")), ) # FIXME : quiet mode #( ('quiet', diff --git a/pyreverse/writer.py b/pyreverse/writer.py index 6b35548..8628a8c 100644 --- a/pyreverse/writer.py +++ b/pyreverse/writer.py @@ -51,7 +51,7 @@ class DiagramWriter(object): # package dependencies for rel in diagram.get_relationships('depends'): self.printer.emit_edge(rel.from_object.fig_id, rel.to_object.fig_id, - **self.pkg_edges) + **self.pkg_edges) def write_classes(self, diagram): """write a class diagram""" @@ -99,7 +99,7 @@ class DotWriter(DiagramWriter): dict(arrowtail='node', arrowhead='empty', style='dashed'), dict(fontcolor='green', arrowtail='none', arrowhead='diamond', style='solid'), - ] + ] DiagramWriter.__init__(self, config, styles) def set_printer(self, file_name, basename): @@ -147,7 +147,7 @@ class VCGWriter(DiagramWriter): linestyle='dotted', backarrowsize=10), dict(arrowstyle='solid', backarrowstyle='none', textcolor='green'), - ] + ] DiagramWriter.__init__(self, config, styles) def set_printer(self, file_name, basename): @@ -135,7 +135,7 @@ class MyInstallLib(install_lib.install_lib): # since python2.5's copytree doesn't support the ignore # parameter, the following loop to remove the exclude set # was added - for (dirpath, dirnames, filenames) in os.walk(dest): + for (dirpath, _, filenames) in os.walk(dest): for n in filenames: if n in exclude: os.remove(os.path.join(dirpath, n)) @@ -176,12 +176,12 @@ def install(**kwargs): kwargs['install_requires'] = install_requires kwargs['dependency_links'] = dependency_links kwargs['entry_points'] = {'console_scripts': [ - 'pylint = pylint:run_pylint', - 'pylint-gui = pylint:run_pylint_gui', - 'epylint = pylint:run_epylint', - 'pyreverse = pylint:run_pyreverse', - 'symilar = pylint:run_symilar', - ]} + 'pylint = pylint:run_pylint', + 'pylint-gui = pylint:run_pylint_gui', + 'epylint = pylint:run_epylint', + 'pyreverse = pylint:run_pyreverse', + 'symilar = pylint:run_symilar', + ]} kwargs['packages'] = packages return setup(name=distname, version=version, @@ -196,8 +196,8 @@ def install(**kwargs): data_files=data_files, ext_modules=ext_modules, cmdclass={'install_lib': MyInstallLib, - 'build_py': build_py}, + 'build_py': build_py}, **kwargs) -if __name__ == '__main__' : +if __name__ == '__main__': install() diff --git a/testutils.py b/testutils.py index ef423c5..1dd083f 100644 --- a/testutils.py +++ b/testutils.py @@ -99,7 +99,7 @@ class TestReporter(BaseReporter): def add_message(self, msg_id, location, msg): """manage message of different type and in the context of path """ - fpath, module, obj, line, _ = location + _, _, obj, line, _ = location self.message_ids[msg_id] = 1 if obj: obj = ':%s' % obj @@ -282,7 +282,7 @@ class LintTestUsingModule(testlib.TestCase): tocheck = [self.package+'.'+self.module] if self.depends: tocheck += [self.package+'.%s' % name.replace('.py', '') - for name, file in self.depends] + for name, _ in self.depends] self._test(tocheck) def _check_result(self, got): @@ -380,9 +380,7 @@ def make_tests(input_dir, msg_dir, filter_rgx, callbacks): for callback in callbacks: test = callback(input_dir, msg_dir, module_file, messages_file, - dependencies) + dependencies) if test: tests.append(test) - - return tests @@ -106,7 +106,7 @@ def tokenize_module(module): if sys.version_info < (3, 0): if module.file_encoding is not None: readline = lambda: stream.readline().decode(module.file_encoding, - 'replace') + 'replace') return list(tokenize.generate_tokens(readline)) return list(tokenize.tokenize(readline)) @@ -285,7 +285,7 @@ class MessagesHandlerMixIn(object): msgid may be either a numeric or symbolic message id. """ try: - msgid = self.msgs_store.check_message_id(msg_descr).msgid + msgid = self.msgs_store.check_message_id(msg_descr).msgid except UnknownMessage: # The linter checks for messages that are not registered # due to version mismatch, just treat them as message IDs @@ -818,7 +818,7 @@ def register_plugins(linter, directory): if base in imported or base == '__pycache__': continue if extension in PY_EXTS and base != '__init__' or ( - not extension and isdir(join(directory, base))): + not extension and isdir(join(directory, base))): try: module = load_module_from_file(join(directory, filename)) except ValueError: |