diff options
author | Claudiu Popa <cpopa@cloudbasesolutions.com> | 2015-06-17 22:47:00 +0300 |
---|---|---|
committer | Claudiu Popa <cpopa@cloudbasesolutions.com> | 2015-06-17 22:47:00 +0300 |
commit | 992904d43055dd11dd22f43cd30d6265fe2eb2df (patch) | |
tree | 64c43bc465ba69d72678e03368323ce44960ffb3 /pylint/pyreverse | |
parent | 798a8aaac8b7b1d2517ae9d9b4ee72f8c5339f12 (diff) | |
download | pylint-992904d43055dd11dd22f43cd30d6265fe2eb2df.tar.gz |
astroid.utils.LocalsVisitor was moved to pylint.pyreverse.LocalsVisitor.
Diffstat (limited to 'pylint/pyreverse')
-rw-r--r-- | pylint/pyreverse/diadefslib.py | 2 | ||||
-rw-r--r-- | pylint/pyreverse/inspector.py | 5 | ||||
-rw-r--r-- | pylint/pyreverse/utils.py | 77 |
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) |