summaryrefslogtreecommitdiff
path: root/checkers/variables.py
diff options
context:
space:
mode:
authorClaudiu Popa <pcmanticore@gmail.com>2014-07-23 13:32:22 +0200
committerClaudiu Popa <pcmanticore@gmail.com>2014-07-23 13:32:22 +0200
commitfc4fc60da1738c3597cfe29744cefb4279ec759e (patch)
tree68656a20d6eec20f83662a66f5ebf4f9601e7c16 /checkers/variables.py
parentbcefd3935e3b7d9a4b83465a99eef58b30dd78c7 (diff)
parent6c6a8364384049586ea9fd0820c59f48dde19193 (diff)
downloadpylint-git-fc4fc60da1738c3597cfe29744cefb4279ec759e.tar.gz
Merged in PCManticore/pylint/metaclass_undefined (pull request #111)
Emit 'undefined-variable' for undefined names used as metaclasses with Python 3 `metaclass=` syntax.
Diffstat (limited to 'checkers/variables.py')
-rw-r--r--checkers/variables.py50
1 files changed, 43 insertions, 7 deletions
diff --git a/checkers/variables.py b/checkers/variables.py
index 4150706e8..8f8ee87a0 100644
--- a/checkers/variables.py
+++ b/checkers/variables.py
@@ -841,16 +841,52 @@ class VariablesChecker3k(VariablesChecker):
""" Update consumption analysis variable
for metaclasses.
"""
+ module_locals = self._to_consume[0][0]
+ module_imports = self._to_consume[0][1]
+ consumed = {}
+
for klass in node.nodes_of_class(astroid.Class):
- if klass._metaclass:
- metaclass = klass.metaclass()
- module_locals = self._to_consume[0][0]
+ found = metaclass = name = None
+ if not klass._metaclass:
+ # Skip if this class doesn't use
+ # explictly a metaclass, but inherits it from ancestors
+ continue
+
+ metaclass = klass.metaclass()
+
+ # Look the name in the already found locals.
+ # If it's not found there, look in the module locals
+ # and in the imported modules.
+ if isinstance(klass._metaclass, astroid.Name):
+ name = klass._metaclass.name
+ elif metaclass:
+ # if it uses a `metaclass=module.Class`
+ name = metaclass.root().name
+
+ if name:
+ found = consumed.setdefault(name,
+ module_locals.get(name, module_imports.get(name))
+ )
+ if found is None and not metaclass:
+ name = None
if isinstance(klass._metaclass, astroid.Name):
- module_locals.pop(klass._metaclass.name, None)
- if metaclass:
- # if it uses a `metaclass=module.Class`
- module_locals.pop(metaclass.root().name, None)
+ name = klass._metaclass.name
+ elif isinstance(klass._metaclass, astroid.Getattr):
+ name = klass._metaclass.as_string()
+
+ if name is not None:
+ if not (name in astroid.Module.scope_attrs or
+ is_builtin(name) or
+ name in self.config.additional_builtins or
+ name in node.locals):
+ self.add_message('undefined-variable',
+ node=klass,
+ args=(name, ))
+ # Pop the consumed items, in order to
+ # avoid having unused-import false positives
+ for name in consumed:
+ module_locals.pop(name, None)
super(VariablesChecker3k, self).leave_module(node)
if sys.version_info >= (3, 0):