diff options
| author | Claudiu Popa <pcmanticore@gmail.com> | 2014-07-23 13:32:22 +0200 |
|---|---|---|
| committer | Claudiu Popa <pcmanticore@gmail.com> | 2014-07-23 13:32:22 +0200 |
| commit | fc4fc60da1738c3597cfe29744cefb4279ec759e (patch) | |
| tree | 68656a20d6eec20f83662a66f5ebf4f9601e7c16 /checkers/variables.py | |
| parent | bcefd3935e3b7d9a4b83465a99eef58b30dd78c7 (diff) | |
| parent | 6c6a8364384049586ea9fd0820c59f48dde19193 (diff) | |
| download | pylint-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.py | 50 |
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): |
