diff options
author | FELD Boris <lothiraldan@gmail.com> | 2012-09-19 14:39:05 +0200 |
---|---|---|
committer | FELD Boris <lothiraldan@gmail.com> | 2012-09-19 14:39:05 +0200 |
commit | 2c2d985aab13c3359c72fb04172ebe8e9a23e776 (patch) | |
tree | 06f5070b65ff7e5612e5670175f83e9148acdcc0 | |
parent | 1a8aa86961dd5d7a03066d81a7a44d17939ecb61 (diff) | |
download | pylint-git-2c2d985aab13c3359c72fb04172ebe8e9a23e776.tar.gz |
Add test and code for handling __all__ with pylint. Closes #4685.
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | checkers/variables.py | 18 | ||||
-rw-r--r-- | test/input/func_all.py | 45 | ||||
-rw-r--r-- | test/messages/func_all.txt | 4 |
4 files changed, 71 insertions, 5 deletions
@@ -5,12 +5,15 @@ ChangeLog for PyLint * #100707: check for boolop being used as exception class, introducing new W0711 message (patch by Tim Hatch) + * #4014: improve checking of metaclass methods first args, introducing + new C0204 message (patch by lothiraldan@gmail.com finalized by sthenault) + + * #4685: check for consistency of a module's __all__ variable, + introducing new E0603 message + * #100654: fix grammatical error for W0332 message (using 'l' as long int identifier) - * #4014: Improve checking of metaclass methods first args, introducing - new C0204 message (patch by lothiraldan@gmail.com finalized by sthenault) - * fix cross-interpreter issue (non compatible access to __builtins__) * stop including tests files in distribution, they causes crash when diff --git a/checkers/variables.py b/checkers/variables.py index f0abd1ba6..c6da73a6a 100644 --- a/checkers/variables.py +++ b/checkers/variables.py @@ -1,4 +1,4 @@ -# Copyright (c) 2003-2011 LOGILAB S.A. (Paris, FRANCE). +# Copyright (c) 2003-2012 LOGILAB S.A. (Paris, FRANCE). # http://www.logilab.fr/ -- mailto:contact@logilab.fr # # This program is free software; you can redistribute it and/or modify it under @@ -58,6 +58,8 @@ MSGS = { assignment.'), 'E0602': ('Undefined variable %r', 'Used when an undefined variable is accessed.'), + 'E0603': ('Undefined variable name %r in __all__', + 'Used when an undefined variable name is referenced in __all__.'), 'E0611': ('No name %r in module %r', 'Used when a name cannot be found in a module.'), @@ -105,6 +107,7 @@ class VariablesChecker(BaseChecker): * undefined variables * redefinition of variable from builtins or from an outer scope * use of variable before assignment + * __all__ consistency """ __implements__ = IASTNGChecker @@ -152,6 +155,17 @@ builtins. Remember that you should avoid to define new builtins when possible.' """ assert len(self._to_consume) == 1 not_consumed = self._to_consume.pop()[0] + # attempt to check for __all__ if defined + if '__all__' in node.locals: + assigned = node.igetattr('__all__').next() + for elt in getattr(assigned, 'elts', ()): + elt_name = elt.value + # If elt is in not_consumed, remove it from not_consumed + if elt_name in not_consumed: + del not_consumed[elt_name] + continue + if elt_name not in node.locals: + self.add_message('E0603', args=elt_name, node=elt) # don't check unused imports in __init__ files if not self.config.init_import and node.package: return @@ -375,7 +389,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' def visit_assname(self, node): if isinstance(node.ass_type(), astng.AugAssign): self.visit_name(node) - + def visit_delname(self, node): self.visit_name(node) diff --git a/test/input/func_all.py b/test/input/func_all.py new file mode 100644 index 000000000..e9f1fc8b5 --- /dev/null +++ b/test/input/func_all.py @@ -0,0 +1,45 @@ +"""Test Pylint's use of __all__. + +* NonExistant is not defined in this module, and it is listed in + __all__. An error is expected. + +* This module imports path and republished it in __all__. No errors + are expected. +""" +# pylint: disable=R0903,R0201,W0612 + +__revision__ = 0 + +from os import path + +__all__ = [ + 'Dummy', + 'NonExistant', + 'path', + 'func', + 'inner', + 'InnerKlass'] + + +class Dummy(object): + """A class defined in this module.""" + pass + +DUMMY = Dummy() + +def function(): + """Function docstring + """ + pass + +function() + +class Klass(object): + """A klass which contains a function""" + def func(self): + """A klass method""" + inner = None + + class InnerKlass(object): + """A inner klass""" + pass diff --git a/test/messages/func_all.txt b/test/messages/func_all.txt new file mode 100644 index 000000000..ba0e85571 --- /dev/null +++ b/test/messages/func_all.txt @@ -0,0 +1,4 @@ +E: 17: Undefined variable name 'NonExistant' in __all__ +E: 19: Undefined variable name 'func' in __all__ +E: 20: Undefined variable name 'inner' in __all__ +E: 21: Undefined variable name 'InnerKlass' in __all__ |