summaryrefslogtreecommitdiff
path: root/pylint/pyreverse
diff options
context:
space:
mode:
authorClaudiu Popa <cpopa@cloudbasesolutions.com>2015-06-17 22:47:00 +0300
committerClaudiu Popa <cpopa@cloudbasesolutions.com>2015-06-17 22:47:00 +0300
commit992904d43055dd11dd22f43cd30d6265fe2eb2df (patch)
tree64c43bc465ba69d72678e03368323ce44960ffb3 /pylint/pyreverse
parent798a8aaac8b7b1d2517ae9d9b4ee72f8c5339f12 (diff)
downloadpylint-992904d43055dd11dd22f43cd30d6265fe2eb2df.tar.gz
astroid.utils.LocalsVisitor was moved to pylint.pyreverse.LocalsVisitor.
Diffstat (limited to 'pylint/pyreverse')
-rw-r--r--pylint/pyreverse/diadefslib.py2
-rw-r--r--pylint/pyreverse/inspector.py5
-rw-r--r--pylint/pyreverse/utils.py77
3 files changed, 81 insertions, 3 deletions
diff --git a/pylint/pyreverse/diadefslib.py b/pylint/pyreverse/diadefslib.py
index 89c77f3..ab6c946 100644
--- a/pylint/pyreverse/diadefslib.py
+++ b/pylint/pyreverse/diadefslib.py
@@ -19,9 +19,9 @@
from logilab.common.compat import builtins
import astroid
-from astroid.utils import LocalsVisitor
from pylint.pyreverse.diagrams import PackageDiagram, ClassDiagram
+from pylint.pyreverse.utils import LocalsVisitor
BUILTINS_NAME = builtins.__name__
diff --git a/pylint/pyreverse/inspector.py b/pylint/pyreverse/inspector.py
index 6671c71..3f31546 100644
--- a/pylint/pyreverse/inspector.py
+++ b/pylint/pyreverse/inspector.py
@@ -23,9 +23,10 @@ Try to resolve definitions (namespace) dictionary, relationship...
import os
import astroid
-from astroid import utils
from astroid import modutils
+from pylint.pyreverse import utils
+
class IdGeneratorMixIn(object):
"""Mixin adding the ability to generate integer uid."""
@@ -70,7 +71,7 @@ class Linker(IdGeneratorMixIn, utils.LocalsVisitor):
def __init__(self, project, inherited_interfaces=0, tag=False):
IdGeneratorMixIn.__init__(self)
- astroid.utils.LocalsVisitor.__init__(self)
+ utils.LocalsVisitor.__init__(self)
# take inherited interface in consideration or not
self.inherited_interfaces = inherited_interfaces
# tag nodes or not
diff --git a/pylint/pyreverse/utils.py b/pylint/pyreverse/utils.py
index 5d6d133..0127d27 100644
--- a/pylint/pyreverse/utils.py
+++ b/pylint/pyreverse/utils.py
@@ -130,3 +130,80 @@ class FilterMixIn(object):
visibility = get_visibility(getattr(node, 'name', node))
return not self.__mode & VIS_MOD[visibility]
+
+class ASTWalker(object):
+ """a walker visiting a tree in preorder, calling on the handler:
+
+ * visit_<class name> on entering a node, where class name is the class of
+ the node in lower case
+
+ * leave_<class name> on leaving a node, where class name is the class of
+ the node in lower case
+ """
+
+ def __init__(self, handler):
+ self.handler = handler
+ self._cache = {}
+
+ def walk(self, node, _done=None):
+ """walk on the tree from <node>, getting callbacks from handler"""
+ if _done is None:
+ _done = set()
+ if node in _done:
+ raise AssertionError((id(node), node, node.parent))
+ _done.add(node)
+ self.visit(node)
+ for child_node in node.get_children():
+ assert child_node is not node
+ self.walk(child_node, _done)
+ self.leave(node)
+ assert node.parent is not node
+
+ def get_callbacks(self, node):
+ """get callbacks from handler for the visited node"""
+ klass = node.__class__
+ methods = self._cache.get(klass)
+ if methods is None:
+ handler = self.handler
+ kid = klass.__name__.lower()
+ e_method = getattr(handler, 'visit_%s' % kid,
+ getattr(handler, 'visit_default', None))
+ l_method = getattr(handler, 'leave_%s' % kid,
+ getattr(handler, 'leave_default', None))
+ self._cache[klass] = (e_method, l_method)
+ else:
+ e_method, l_method = methods
+ return e_method, l_method
+
+ def visit(self, node):
+ """walk on the tree from <node>, getting callbacks from handler"""
+ method = self.get_callbacks(node)[0]
+ if method is not None:
+ method(node)
+
+ def leave(self, node):
+ """walk on the tree from <node>, getting callbacks from handler"""
+ method = self.get_callbacks(node)[1]
+ if method is not None:
+ method(node)
+
+
+class LocalsVisitor(ASTWalker):
+ """visit a project by traversing the locals dictionary"""
+ def __init__(self):
+ ASTWalker.__init__(self, self)
+ self._visited = {}
+
+ def visit(self, node):
+ """launch the visit starting from the given node"""
+ if node in self._visited:
+ return
+ self._visited[node] = 1 # FIXME: use set ?
+ methods = self.get_callbacks(node)
+ if methods[0] is not None:
+ methods[0](node)
+ if 'locals' in node.__dict__: # skip Instance and other proxy
+ for local_node in node.values():
+ self.visit(local_node)
+ if methods[1] is not None:
+ return methods[1](node)