Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: third_party/logilab/astng/utils.py

Issue 739393004: Revert "Revert "pylint: upgrade to 1.3.1"" (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools/
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/logilab/astng/scoped_nodes.py ('k') | third_party/logilab/astroid/LICENSE.txt » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
3 # copyright 2003-2010 Sylvain Thenault, all rights reserved.
4 # contact mailto:thenault@gmail.com
5 #
6 # This file is part of logilab-astng.
7 #
8 # logilab-astng is free software: you can redistribute it and/or modify it
9 # under the terms of the GNU Lesser General Public License as published by the
10 # Free Software Foundation, either version 2.1 of the License, or (at your
11 # option) any later version.
12 #
13 # logilab-astng is distributed in the hope that it will be useful, but
14 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16 # for more details.
17 #
18 # You should have received a copy of the GNU Lesser General Public License along
19 # with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
20 """this module contains some utilities to navigate in the tree or to
21 extract information from it
22 """
23
24 __docformat__ = "restructuredtext en"
25
26 from logilab.astng.exceptions import ASTNGBuildingException
27
28
29 class ASTWalker:
30 """a walker visiting a tree in preorder, calling on the handler:
31
32 * visit_<class name> on entering a node, where class name is the class of
33 the node in lower case
34
35 * leave_<class name> on leaving a node, where class name is the class of
36 the node in lower case
37 """
38
39 def __init__(self, handler):
40 self.handler = handler
41 self._cache = {}
42
43 def walk(self, node, _done=None):
44 """walk on the tree from <node>, getting callbacks from handler"""
45 if _done is None:
46 _done = set()
47 if node in _done:
48 raise AssertionError((id(node), node, node.parent))
49 _done.add(node)
50 self.visit(node)
51 for child_node in node.get_children():
52 self.handler.set_context(node, child_node)
53 assert child_node is not node
54 self.walk(child_node, _done)
55 self.leave(node)
56 assert node.parent is not node
57
58 def get_callbacks(self, node):
59 """get callbacks from handler for the visited node"""
60 klass = node.__class__
61 methods = self._cache.get(klass)
62 if methods is None:
63 handler = self.handler
64 kid = klass.__name__.lower()
65 e_method = getattr(handler, 'visit_%s' % kid,
66 getattr(handler, 'visit_default', None))
67 l_method = getattr(handler, 'leave_%s' % kid,
68 getattr(handler, 'leave_default', None))
69 self._cache[klass] = (e_method, l_method)
70 else:
71 e_method, l_method = methods
72 return e_method, l_method
73
74 def visit(self, node):
75 """walk on the tree from <node>, getting callbacks from handler"""
76 method = self.get_callbacks(node)[0]
77 if method is not None:
78 method(node)
79
80 def leave(self, node):
81 """walk on the tree from <node>, getting callbacks from handler"""
82 method = self.get_callbacks(node)[1]
83 if method is not None:
84 method(node)
85
86
87 class LocalsVisitor(ASTWalker):
88 """visit a project by traversing the locals dictionary"""
89 def __init__(self):
90 ASTWalker.__init__(self, self)
91 self._visited = {}
92
93 def visit(self, node):
94 """launch the visit starting from the given node"""
95 if node in self._visited:
96 return
97 self._visited[node] = 1 # FIXME: use set ?
98 methods = self.get_callbacks(node)
99 if methods[0] is not None:
100 methods[0](node)
101 if 'locals' in node.__dict__: # skip Instance and other proxy
102 for name, local_node in node.items():
103 self.visit(local_node)
104 if methods[1] is not None:
105 return methods[1](node)
106
107
108 def _check_children(node):
109 """a helper function to check children - parent relations"""
110 for child in node.get_children():
111 ok = False
112 if child is None:
113 print "Hm, child of %s is None" % node
114 continue
115 if not hasattr(child, 'parent'):
116 print " ERROR: %s has child %s %x with no parent" % (node, child, id (child))
117 elif not child.parent:
118 print " ERROR: %s has child %s %x with parent %r" % (node, child, id (child), child.parent)
119 elif child.parent is not node:
120 print " ERROR: %s %x has child %s %x with wrong parent %s" % (node,
121 id(node), child, id(child), child.parent)
122 else:
123 ok = True
124 if not ok:
125 print "lines;", node.lineno, child.lineno
126 print "of module", node.root(), node.root().name
127 raise ASTNGBuildingException
128 _check_children(child)
129
130
131 from _ast import PyCF_ONLY_AST
132 def parse(string):
133 return compile(string, "<string>", 'exec', PyCF_ONLY_AST)
134
135 class TreeTester(object):
136 '''A helper class to see _ast tree and compare with astng tree
137
138 indent: string for tree indent representation
139 lineno: bool to tell if we should print the line numbers
140
141 >>> tester = TreeTester('print')
142 >>> print tester.native_tree_repr()
143
144 <Module>
145 . body = [
146 . <Print>
147 . . nl = True
148 . ]
149 >>> print tester.astng_tree_repr()
150 Module()
151 body = [
152 Print()
153 dest =
154 values = [
155 ]
156 ]
157 '''
158
159 indent = '. '
160 lineno = False
161
162 def __init__(self, sourcecode):
163 self._string = ''
164 self.sourcecode = sourcecode
165 self._ast_node = None
166 self.build_ast()
167
168 def build_ast(self):
169 """build the _ast tree from the source code"""
170 self._ast_node = parse(self.sourcecode)
171
172 def native_tree_repr(self, node=None, indent=''):
173 """get a nice representation of the _ast tree"""
174 self._string = ''
175 if node is None:
176 node = self._ast_node
177 self._native_repr_tree(node, indent)
178 return self._string
179
180
181 def _native_repr_tree(self, node, indent, _done=None):
182 """recursive method for the native tree representation"""
183 from _ast import Load as _Load, Store as _Store, Del as _Del
184 from _ast import AST as Node
185 if _done is None:
186 _done = set()
187 if node in _done:
188 self._string += '\nloop in tree: %r (%s)' % (node,
189 getattr(node, 'lineno', None))
190 return
191 _done.add(node)
192 self._string += '\n' + indent + '<%s>' % node.__class__.__name__
193 indent += self.indent
194 if not hasattr(node, '__dict__'):
195 self._string += '\n' + self.indent + " ** node has no __dict__ " + s tr(node)
196 return
197 node_dict = node.__dict__
198 if hasattr(node, '_attributes'):
199 for a in node._attributes:
200 attr = node_dict[a]
201 if attr is None:
202 continue
203 if a in ("lineno", "col_offset") and not self.lineno:
204 continue
205 self._string +='\n' + indent + a + " = " + repr(attr)
206 for field in node._fields or ():
207 attr = node_dict[field]
208 if attr is None:
209 continue
210 if isinstance(attr, list):
211 if not attr:
212 continue
213 self._string += '\n' + indent + field + ' = ['
214 for elt in attr:
215 self._native_repr_tree(elt, indent, _done)
216 self._string += '\n' + indent + ']'
217 continue
218 if isinstance(attr, (_Load, _Store, _Del)):
219 continue
220 if isinstance(attr, Node):
221 self._string += '\n' + indent + field + " = "
222 self._native_repr_tree(attr, indent, _done)
223 else:
224 self._string += '\n' + indent + field + " = " + repr(attr)
225
226
227 def build_astng_tree(self):
228 """build astng tree from the _ast tree
229 """
230 from logilab.astng.builder import ASTNGBuilder
231 tree = ASTNGBuilder().string_build(self.sourcecode)
232 return tree
233
234 def astng_tree_repr(self, ids=False):
235 """build the astng tree and return a nice tree representation"""
236 mod = self.build_astng_tree()
237 return mod.repr_tree(ids)
238
239
240 __all__ = ('LocalsVisitor', 'ASTWalker',)
241
OLDNEW
« no previous file with comments | « third_party/logilab/astng/scoped_nodes.py ('k') | third_party/logilab/astroid/LICENSE.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698