OLD | NEW |
1 # copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved. | 1 # copyright 2003-2011 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
2 # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr | 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 |
3 # | 5 # |
4 # This file is part of astroid. | 6 # This file is part of logilab-astng. |
5 # | 7 # |
6 # astroid is free software: you can redistribute it and/or modify it | 8 # logilab-astng is free software: you can redistribute it and/or modify it |
7 # under the terms of the GNU Lesser General Public License as published by the | 9 # under the terms of the GNU Lesser General Public License as published by the |
8 # Free Software Foundation, either version 2.1 of the License, or (at your | 10 # Free Software Foundation, either version 2.1 of the License, or (at your |
9 # option) any later version. | 11 # option) any later version. |
10 # | 12 # |
11 # astroid is distributed in the hope that it will be useful, but | 13 # logilab-astng is distributed in the hope that it will be useful, but |
12 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | 14 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
13 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License | 15 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License |
14 # for more details. | 16 # for more details. |
15 # | 17 # |
16 # You should have received a copy of the GNU Lesser General Public License along | 18 # You should have received a copy of the GNU Lesser General Public License along |
17 # with astroid. If not, see <http://www.gnu.org/licenses/>. | 19 # with logilab-astng. If not, see <http://www.gnu.org/licenses/>. |
18 """This module renders Astroid nodes as string: | 20 """This module renders ASTNG nodes to string representation. |
19 | 21 |
20 * :func:`to_code` function return equivalent (hopefuly valid) python string | 22 It will probably not work on bare _ast trees. |
| 23 """ |
| 24 import sys |
21 | 25 |
22 * :func:`dump` function return an internal representation of nodes found | |
23 in the tree, useful for debugging or understanding the tree structure | |
24 """ | |
25 | |
26 import sys | |
27 | 26 |
28 INDENT = ' ' # 4 spaces ; keep indentation variable | 27 INDENT = ' ' # 4 spaces ; keep indentation variable |
29 | 28 |
30 | 29 |
31 def dump(node, ids=False): | 30 def _import_string(names): |
32 """print a nice astroid tree representation. | 31 """return a list of (name, asname) formatted as a string""" |
33 | 32 _names = [] |
34 :param ids: if true, we also print the ids (usefull for debugging) | 33 for name, asname in names: |
35 """ | 34 if asname is not None: |
36 result = [] | 35 _names.append('%s as %s' % (name, asname)) |
37 _repr_tree(node, result, ids=ids) | |
38 return "\n".join(result) | |
39 | |
40 def _repr_tree(node, result, indent='', _done=None, ids=False): | |
41 """built a tree representation of a node as a list of lines""" | |
42 if _done is None: | |
43 _done = set() | |
44 if not hasattr(node, '_astroid_fields'): # not a astroid node | |
45 return | |
46 if node in _done: | |
47 result.append(indent + 'loop in tree: %s' % node) | |
48 return | |
49 _done.add(node) | |
50 node_str = str(node) | |
51 if ids: | |
52 node_str += ' . \t%x' % id(node) | |
53 result.append(indent + node_str) | |
54 indent += INDENT | |
55 for field in node._astroid_fields: | |
56 value = getattr(node, field) | |
57 if isinstance(value, (list, tuple)): | |
58 result.append(indent + field + " = [") | |
59 for child in value: | |
60 if isinstance(child, (list, tuple)): | |
61 # special case for Dict # FIXME | |
62 _repr_tree(child[0], result, indent, _done, ids) | |
63 _repr_tree(child[1], result, indent, _done, ids) | |
64 result.append(indent + ',') | |
65 else: | |
66 _repr_tree(child, result, indent, _done, ids) | |
67 result.append(indent + "]") | |
68 else: | 36 else: |
69 result.append(indent + field + " = ") | 37 _names.append(name) |
70 _repr_tree(value, result, indent, _done, ids) | 38 return ', '.join(_names) |
71 | 39 |
72 | 40 |
73 class AsStringVisitor(object): | 41 class AsStringVisitor(object): |
74 """Visitor to render an Astroid node as a valid python code string""" | 42 """Visitor to render an ASTNG node as string """ |
75 | 43 |
76 def __call__(self, node): | 44 def __call__(self, node): |
77 """Makes this visitor behave as a simple function""" | 45 """Makes this visitor behave as a simple function""" |
78 return node.accept(self) | 46 return node.accept(self) |
79 | 47 |
80 def _stmt_list(self, stmts): | 48 def _stmt_list(self, stmts): |
81 """return a list of nodes to string""" | 49 """return a list of nodes to string""" |
82 stmts = '\n'.join([nstr for nstr in [n.accept(self) for n in stmts] if n
str]) | 50 stmts = '\n'.join([nstr for nstr in [n.accept(self) for n in stmts] if n
str]) |
83 return INDENT + stmts.replace('\n', '\n'+INDENT) | 51 return INDENT + stmts.replace('\n', '\n'+INDENT) |
84 | 52 |
85 | 53 |
86 ## visit_<node> methods ########################################### | 54 ## visit_<node> methods ########################################### |
87 | 55 |
88 def visit_arguments(self, node): | 56 def visit_arguments(self, node): |
89 """return an astroid.Function node as string""" | 57 """return an astng.Function node as string""" |
90 return node.format_args() | 58 return node.format_args() |
91 | 59 |
92 def visit_assattr(self, node): | 60 def visit_assattr(self, node): |
93 """return an astroid.AssAttr node as string""" | 61 """return an astng.AssAttr node as string""" |
94 return self.visit_getattr(node) | 62 return self.visit_getattr(node) |
95 | 63 |
96 def visit_assert(self, node): | 64 def visit_assert(self, node): |
97 """return an astroid.Assert node as string""" | 65 """return an astng.Assert node as string""" |
98 if node.fail: | 66 if node.fail: |
99 return 'assert %s, %s' % (node.test.accept(self), | 67 return 'assert %s, %s' % (node.test.accept(self), |
100 node.fail.accept(self)) | 68 node.fail.accept(self)) |
101 return 'assert %s' % node.test.accept(self) | 69 return 'assert %s' % node.test.accept(self) |
102 | 70 |
103 def visit_assname(self, node): | 71 def visit_assname(self, node): |
104 """return an astroid.AssName node as string""" | 72 """return an astng.AssName node as string""" |
105 return node.name | 73 return node.name |
106 | 74 |
107 def visit_assign(self, node): | 75 def visit_assign(self, node): |
108 """return an astroid.Assign node as string""" | 76 """return an astng.Assign node as string""" |
109 lhs = ' = '.join([n.accept(self) for n in node.targets]) | 77 lhs = ' = '.join([n.accept(self) for n in node.targets]) |
110 return '%s = %s' % (lhs, node.value.accept(self)) | 78 return '%s = %s' % (lhs, node.value.accept(self)) |
111 | 79 |
112 def visit_augassign(self, node): | 80 def visit_augassign(self, node): |
113 """return an astroid.AugAssign node as string""" | 81 """return an astng.AugAssign node as string""" |
114 return '%s %s %s' % (node.target.accept(self), node.op, node.value.accep
t(self)) | 82 return '%s %s %s' % (node.target.accept(self), node.op, node.value.accep
t(self)) |
115 | 83 |
116 def visit_backquote(self, node): | 84 def visit_backquote(self, node): |
117 """return an astroid.Backquote node as string""" | 85 """return an astng.Backquote node as string""" |
118 return '`%s`' % node.value.accept(self) | 86 return '`%s`' % node.value.accept(self) |
119 | 87 |
120 def visit_binop(self, node): | 88 def visit_binop(self, node): |
121 """return an astroid.BinOp node as string""" | 89 """return an astng.BinOp node as string""" |
122 return '(%s) %s (%s)' % (node.left.accept(self), node.op, node.right.acc
ept(self)) | 90 return '(%s) %s (%s)' % (node.left.accept(self), node.op, node.right.acc
ept(self)) |
123 | 91 |
124 def visit_boolop(self, node): | 92 def visit_boolop(self, node): |
125 """return an astroid.BoolOp node as string""" | 93 """return an astng.BoolOp node as string""" |
126 return (' %s ' % node.op).join(['(%s)' % n.accept(self) | 94 return (' %s ' % node.op).join(['(%s)' % n.accept(self) |
127 for n in node.values]) | 95 for n in node.values]) |
128 | 96 |
129 def visit_break(self, node): | 97 def visit_break(self, node): |
130 """return an astroid.Break node as string""" | 98 """return an astng.Break node as string""" |
131 return 'break' | 99 return 'break' |
132 | 100 |
133 def visit_callfunc(self, node): | 101 def visit_callfunc(self, node): |
134 """return an astroid.CallFunc node as string""" | 102 """return an astng.CallFunc node as string""" |
135 expr_str = node.func.accept(self) | 103 expr_str = node.func.accept(self) |
136 args = [arg.accept(self) for arg in node.args] | 104 args = [arg.accept(self) for arg in node.args] |
137 if node.starargs: | 105 if node.starargs: |
138 args.append('*' + node.starargs.accept(self)) | 106 args.append( '*' + node.starargs.accept(self)) |
139 if node.kwargs: | 107 if node.kwargs: |
140 args.append('**' + node.kwargs.accept(self)) | 108 args.append( '**' + node.kwargs.accept(self)) |
141 return '%s(%s)' % (expr_str, ', '.join(args)) | 109 return '%s(%s)' % (expr_str, ', '.join(args)) |
142 | 110 |
143 def visit_class(self, node): | 111 def visit_class(self, node): |
144 """return an astroid.Class node as string""" | 112 """return an astng.Class node as string""" |
145 decorate = node.decorators and node.decorators.accept(self) or '' | 113 decorate = node.decorators and node.decorators.accept(self) or '' |
146 bases = ', '.join([n.accept(self) for n in node.bases]) | 114 bases = ', '.join([n.accept(self) for n in node.bases]) |
147 if sys.version_info[0] == 2: | 115 bases = bases and '(%s)' % bases or '' |
148 bases = bases and '(%s)' % bases or '' | |
149 else: | |
150 metaclass = node.metaclass() | |
151 if metaclass: | |
152 if bases: | |
153 bases = '(%s, metaclass=%s)' % (bases, metaclass.name) | |
154 else: | |
155 bases = '(metaclass=%s)' % metaclass.name | |
156 else: | |
157 bases = bases and '(%s)' % bases or '' | |
158 docs = node.doc and '\n%s"""%s"""' % (INDENT, node.doc) or '' | 116 docs = node.doc and '\n%s"""%s"""' % (INDENT, node.doc) or '' |
159 return '\n\n%sclass %s%s:%s\n%s\n' % (decorate, node.name, bases, docs, | 117 return '\n\n%sclass %s%s:%s\n%s\n' % (decorate, node.name, bases, docs, |
160 self._stmt_list(node.body)) | 118 self._stmt_list( node.body)) |
161 | 119 |
162 def visit_compare(self, node): | 120 def visit_compare(self, node): |
163 """return an astroid.Compare node as string""" | 121 """return an astng.Compare node as string""" |
164 rhs_str = ' '.join(['%s %s' % (op, expr.accept(self)) | 122 rhs_str = ' '.join(['%s %s' % (op, expr.accept(self)) |
165 for op, expr in node.ops]) | 123 for op, expr in node.ops]) |
166 return '%s %s' % (node.left.accept(self), rhs_str) | 124 return '%s %s' % (node.left.accept(self), rhs_str) |
167 | 125 |
168 def visit_comprehension(self, node): | 126 def visit_comprehension(self, node): |
169 """return an astroid.Comprehension node as string""" | 127 """return an astng.Comprehension node as string""" |
170 ifs = ''.join([' if %s' % n.accept(self) for n in node.ifs]) | 128 ifs = ''.join([ ' if %s' % n.accept(self) for n in node.ifs]) |
171 return 'for %s in %s%s' % (node.target.accept(self), | 129 return 'for %s in %s%s' % (node.target.accept(self), |
172 node.iter.accept(self), ifs) | 130 node.iter.accept(self), ifs ) |
173 | 131 |
174 def visit_const(self, node): | 132 def visit_const(self, node): |
175 """return an astroid.Const node as string""" | 133 """return an astng.Const node as string""" |
176 return repr(node.value) | 134 return repr(node.value) |
177 | 135 |
178 def visit_continue(self, node): | 136 def visit_continue(self, node): |
179 """return an astroid.Continue node as string""" | 137 """return an astng.Continue node as string""" |
180 return 'continue' | 138 return 'continue' |
181 | 139 |
182 def visit_delete(self, node): # XXX check if correct | 140 def visit_delete(self, node): # XXX check if correct |
183 """return an astroid.Delete node as string""" | 141 """return an astng.Delete node as string""" |
184 return 'del %s' % ', '.join([child.accept(self) | 142 return 'del %s' % ', '.join([child.accept(self) |
185 for child in node.targets]) | 143 for child in node.targets]) |
186 | 144 |
187 def visit_delattr(self, node): | 145 def visit_delattr(self, node): |
188 """return an astroid.DelAttr node as string""" | 146 """return an astng.DelAttr node as string""" |
189 return self.visit_getattr(node) | 147 return self.visit_getattr(node) |
190 | 148 |
191 def visit_delname(self, node): | 149 def visit_delname(self, node): |
192 """return an astroid.DelName node as string""" | 150 """return an astng.DelName node as string""" |
193 return node.name | 151 return node.name |
194 | 152 |
195 def visit_decorators(self, node): | 153 def visit_decorators(self, node): |
196 """return an astroid.Decorators node as string""" | 154 """return an astng.Decorators node as string""" |
197 return '@%s\n' % '\n@'.join([item.accept(self) for item in node.nodes]) | 155 return '@%s\n' % '\n@'.join([item.accept(self) for item in node.nodes]) |
198 | 156 |
199 def visit_dict(self, node): | 157 def visit_dict(self, node): |
200 """return an astroid.Dict node as string""" | 158 """return an astng.Dict node as string""" |
201 return '{%s}' % ', '.join(['%s: %s' % (key.accept(self), | 159 return '{%s}' % ', '.join(['%s: %s' % (key.accept(self), |
202 value.accept(self)) | 160 value.accept(self)) for key, value in node.items]) |
203 for key, value in node.items]) | |
204 | 161 |
205 def visit_dictcomp(self, node): | 162 def visit_dictcomp(self, node): |
206 """return an astroid.DictComp node as string""" | 163 """return an astng.DictComp node as string""" |
207 return '{%s: %s %s}' % (node.key.accept(self), node.value.accept(self), | 164 return '{%s: %s %s}' % (node.key.accept(self), node.value.accept(self), |
208 ' '.join([n.accept(self) for n in node.generator
s])) | 165 ' '.join([n.accept(self) for n in node.generators])) |
209 | 166 |
210 def visit_discard(self, node): | 167 def visit_discard(self, node): |
211 """return an astroid.Discard node as string""" | 168 """return an astng.Discard node as string""" |
212 return node.value.accept(self) | 169 return node.value.accept(self) |
213 | 170 |
214 def visit_emptynode(self, node): | 171 def visit_emptynode(self, node): |
215 """dummy method for visiting an Empty node""" | 172 """dummy method for visiting an Empty node""" |
216 return '' | 173 return '' |
217 | 174 |
218 def visit_excepthandler(self, node): | 175 def visit_excepthandler(self, node): |
219 if node.type: | 176 if node.type: |
220 if node.name: | 177 if node.name: |
221 excs = 'except %s, %s' % (node.type.accept(self), | 178 excs = 'except %s, %s' % (node.type.accept(self), |
222 node.name.accept(self)) | 179 node.name.accept(self)) |
223 else: | 180 else: |
224 excs = 'except %s' % node.type.accept(self) | 181 excs = 'except %s' % node.type.accept(self) |
225 else: | 182 else: |
226 excs = 'except' | 183 excs = 'except' |
227 return '%s:\n%s' % (excs, self._stmt_list(node.body)) | 184 return '%s:\n%s' % (excs, self._stmt_list(node.body)) |
228 | 185 |
229 def visit_ellipsis(self, node): | 186 def visit_ellipsis(self, node): |
230 """return an astroid.Ellipsis node as string""" | 187 """return an astng.Ellipsis node as string""" |
231 return '...' | 188 return '...' |
232 | 189 |
233 def visit_empty(self, node): | 190 def visit_empty(self, node): |
234 """return an Empty node as string""" | 191 """return an Empty node as string""" |
235 return '' | 192 return '' |
236 | 193 |
237 def visit_exec(self, node): | 194 def visit_exec(self, node): |
238 """return an astroid.Exec node as string""" | 195 """return an astng.Exec node as string""" |
239 if node.locals: | 196 if node.locals: |
240 return 'exec %s in %s, %s' % (node.expr.accept(self), | 197 return 'exec %s in %s, %s' % (node.expr.accept(self), |
241 node.locals.accept(self), | 198 node.locals.accept(self), |
242 node.globals.accept(self)) | 199 node.globals.accept(self)) |
243 if node.globals: | 200 if node.globals: |
244 return 'exec %s in %s' % (node.expr.accept(self), | 201 return 'exec %s in %s' % (node.expr.accept(self), |
245 node.globals.accept(self)) | 202 node.globals.accept(self)) |
246 return 'exec %s' % node.expr.accept(self) | 203 return 'exec %s' % node.expr.accept(self) |
247 | 204 |
248 def visit_extslice(self, node): | 205 def visit_extslice(self, node): |
249 """return an astroid.ExtSlice node as string""" | 206 """return an astng.ExtSlice node as string""" |
250 return ','.join([dim.accept(self) for dim in node.dims]) | 207 return ','.join( [dim.accept(self) for dim in node.dims] ) |
251 | 208 |
252 def visit_for(self, node): | 209 def visit_for(self, node): |
253 """return an astroid.For node as string""" | 210 """return an astng.For node as string""" |
254 fors = 'for %s in %s:\n%s' % (node.target.accept(self), | 211 fors = 'for %s in %s:\n%s' % (node.target.accept(self), |
255 node.iter.accept(self), | 212 node.iter.accept(self), |
256 self._stmt_list(node.body)) | 213 self._stmt_list( node.body)) |
257 if node.orelse: | 214 if node.orelse: |
258 fors = '%s\nelse:\n%s' % (fors, self._stmt_list(node.orelse)) | 215 fors = '%s\nelse:\n%s' % (fors, self._stmt_list(node.orelse)) |
259 return fors | 216 return fors |
260 | 217 |
261 def visit_from(self, node): | 218 def visit_from(self, node): |
262 """return an astroid.From node as string""" | 219 """return an astng.From node as string""" |
263 return 'from %s import %s' % ('.' * (node.level or 0) + node.modname, | 220 return 'from %s import %s' % ('.' * (node.level or 0) + node.modname, |
264 _import_string(node.names)) | 221 _import_string(node.names)) |
265 | 222 |
266 def visit_function(self, node): | 223 def visit_function(self, node): |
267 """return an astroid.Function node as string""" | 224 """return an astng.Function node as string""" |
268 decorate = node.decorators and node.decorators.accept(self) or '' | 225 decorate = node.decorators and node.decorators.accept(self) or '' |
269 docs = node.doc and '\n%s"""%s"""' % (INDENT, node.doc) or '' | 226 docs = node.doc and '\n%s"""%s"""' % (INDENT, node.doc) or '' |
270 return '\n%sdef %s(%s):%s\n%s' % (decorate, node.name, node.args.accept(
self), | 227 return '\n%sdef %s(%s):%s\n%s' % (decorate, node.name, node.args.accept(
self), |
271 docs, self._stmt_list(node.body)) | 228 docs, self._stmt_list(node.body)) |
272 | 229 |
273 def visit_genexpr(self, node): | 230 def visit_genexpr(self, node): |
274 """return an astroid.GenExpr node as string""" | 231 """return an astng.GenExpr node as string""" |
275 return '(%s %s)' % (node.elt.accept(self), | 232 return '(%s %s)' % (node.elt.accept(self), ' '.join([n.accept(self) |
276 ' '.join([n.accept(self) for n in node.generators])) | 233 for n in node.generators])) |
277 | 234 |
278 def visit_getattr(self, node): | 235 def visit_getattr(self, node): |
279 """return an astroid.Getattr node as string""" | 236 """return an astng.Getattr node as string""" |
280 return '%s.%s' % (node.expr.accept(self), node.attrname) | 237 return '%s.%s' % (node.expr.accept(self), node.attrname) |
281 | 238 |
282 def visit_global(self, node): | 239 def visit_global(self, node): |
283 """return an astroid.Global node as string""" | 240 """return an astng.Global node as string""" |
284 return 'global %s' % ', '.join(node.names) | 241 return 'global %s' % ', '.join(node.names) |
285 | 242 |
286 def visit_if(self, node): | 243 def visit_if(self, node): |
287 """return an astroid.If node as string""" | 244 """return an astng.If node as string""" |
288 ifs = ['if %s:\n%s' % (node.test.accept(self), self._stmt_list(node.body
))] | 245 ifs = ['if %s:\n%s' % (node.test.accept(self), self._stmt_list(node.body
))] |
289 if node.orelse:# XXX use elif ??? | 246 if node.orelse:# XXX use elif ??? |
290 ifs.append('else:\n%s' % self._stmt_list(node.orelse)) | 247 ifs.append('else:\n%s' % self._stmt_list(node.orelse)) |
291 return '\n'.join(ifs) | 248 return '\n'.join(ifs) |
292 | 249 |
293 def visit_ifexp(self, node): | 250 def visit_ifexp(self, node): |
294 """return an astroid.IfExp node as string""" | 251 """return an astng.IfExp node as string""" |
295 return '%s if %s else %s' % (node.body.accept(self), | 252 return '%s if %s else %s' % (node.body.accept(self), |
296 node.test.accept(self), | 253 node.test.accept(self), node.orelse.accept(self)) |
297 node.orelse.accept(self)) | |
298 | 254 |
299 def visit_import(self, node): | 255 def visit_import(self, node): |
300 """return an astroid.Import node as string""" | 256 """return an astng.Import node as string""" |
301 return 'import %s' % _import_string(node.names) | 257 return 'import %s' % _import_string(node.names) |
302 | 258 |
303 def visit_keyword(self, node): | 259 def visit_keyword(self, node): |
304 """return an astroid.Keyword node as string""" | 260 """return an astng.Keyword node as string""" |
305 return '%s=%s' % (node.arg, node.value.accept(self)) | 261 return '%s=%s' % (node.arg, node.value.accept(self)) |
306 | 262 |
307 def visit_lambda(self, node): | 263 def visit_lambda(self, node): |
308 """return an astroid.Lambda node as string""" | 264 """return an astng.Lambda node as string""" |
309 return 'lambda %s: %s' % (node.args.accept(self), | 265 return 'lambda %s: %s' % (node.args.accept(self), node.body.accept(self)
) |
310 node.body.accept(self)) | |
311 | 266 |
312 def visit_list(self, node): | 267 def visit_list(self, node): |
313 """return an astroid.List node as string""" | 268 """return an astng.List node as string""" |
314 return '[%s]' % ', '.join([child.accept(self) for child in node.elts]) | 269 return '[%s]' % ', '.join([child.accept(self) for child in node.elts]) |
315 | 270 |
316 def visit_listcomp(self, node): | 271 def visit_listcomp(self, node): |
317 """return an astroid.ListComp node as string""" | 272 """return an astng.ListComp node as string""" |
318 return '[%s %s]' % (node.elt.accept(self), | 273 return '[%s %s]' % (node.elt.accept(self), ' '.join([n.accept(self) |
319 ' '.join([n.accept(self) for n in node.generators])) | 274 for n in node.generators])) |
320 | 275 |
321 def visit_module(self, node): | 276 def visit_module(self, node): |
322 """return an astroid.Module node as string""" | 277 """return an astng.Module node as string""" |
323 docs = node.doc and '"""%s"""\n\n' % node.doc or '' | 278 docs = node.doc and '"""%s"""\n\n' % node.doc or '' |
324 return docs + '\n'.join([n.accept(self) for n in node.body]) + '\n\n' | 279 return docs + '\n'.join([n.accept(self) for n in node.body]) + '\n\n' |
325 | 280 |
326 def visit_name(self, node): | 281 def visit_name(self, node): |
327 """return an astroid.Name node as string""" | 282 """return an astng.Name node as string""" |
328 return node.name | 283 return node.name |
329 | 284 |
330 def visit_pass(self, node): | 285 def visit_pass(self, node): |
331 """return an astroid.Pass node as string""" | 286 """return an astng.Pass node as string""" |
332 return 'pass' | 287 return 'pass' |
333 | 288 |
334 def visit_print(self, node): | 289 def visit_print(self, node): |
335 """return an astroid.Print node as string""" | 290 """return an astng.Print node as string""" |
336 nodes = ', '.join([n.accept(self) for n in node.values]) | 291 nodes = ', '.join([n.accept(self) for n in node.values]) |
337 if not node.nl: | 292 if not node.nl: |
338 nodes = '%s,' % nodes | 293 nodes = '%s,' % nodes |
339 if node.dest: | 294 if node.dest: |
340 return 'print >> %s, %s' % (node.dest.accept(self), nodes) | 295 return 'print >> %s, %s' % (node.dest.accept(self), nodes) |
341 return 'print %s' % nodes | 296 return 'print %s' % nodes |
342 | 297 |
343 def visit_raise(self, node): | 298 def visit_raise(self, node): |
344 """return an astroid.Raise node as string""" | 299 """return an astng.Raise node as string""" |
345 if node.exc: | 300 if node.exc: |
346 if node.inst: | 301 if node.inst: |
347 if node.tback: | 302 if node.tback: |
348 return 'raise %s, %s, %s' % (node.exc.accept(self), | 303 return 'raise %s, %s, %s' % (node.exc.accept(self), |
349 node.inst.accept(self), | 304 node.inst.accept(self), |
350 node.tback.accept(self)) | 305 node.tback.accept(self)) |
351 return 'raise %s, %s' % (node.exc.accept(self), | 306 return 'raise %s, %s' % (node.exc.accept(self), |
352 node.inst.accept(self)) | 307 node.inst.accept(self)) |
353 return 'raise %s' % node.exc.accept(self) | 308 return 'raise %s' % node.exc.accept(self) |
354 return 'raise' | 309 return 'raise' |
355 | 310 |
356 def visit_return(self, node): | 311 def visit_return(self, node): |
357 """return an astroid.Return node as string""" | 312 """return an astng.Return node as string""" |
358 if node.value: | 313 if node.value: |
359 return 'return %s' % node.value.accept(self) | 314 return 'return %s' % node.value.accept(self) |
360 else: | 315 else: |
361 return 'return' | 316 return 'return' |
362 | 317 |
363 def visit_index(self, node): | 318 def visit_index(self, node): |
364 """return a astroid.Index node as string""" | 319 """return a astng.Index node as string""" |
365 return node.value.accept(self) | 320 return node.value.accept(self) |
366 | 321 |
367 def visit_set(self, node): | 322 def visit_set(self, node): |
368 """return an astroid.Set node as string""" | 323 """return an astng.Set node as string""" |
369 return '{%s}' % ', '.join([child.accept(self) for child in node.elts]) | 324 return '{%s}' % ', '.join([child.accept(self) for child in node.elts]) |
370 | 325 |
371 def visit_setcomp(self, node): | 326 def visit_setcomp(self, node): |
372 """return an astroid.SetComp node as string""" | 327 """return an astng.SetComp node as string""" |
373 return '{%s %s}' % (node.elt.accept(self), | 328 return '{%s %s}' % (node.elt.accept(self), ' '.join([n.accept(self) |
374 ' '.join([n.accept(self) for n in node.generators])) | 329 for n in node.generators])) |
375 | 330 |
376 def visit_slice(self, node): | 331 def visit_slice(self, node): |
377 """return a astroid.Slice node as string""" | 332 """return a astng.Slice node as string""" |
378 lower = node.lower and node.lower.accept(self) or '' | 333 lower = node.lower and node.lower.accept(self) or '' |
379 upper = node.upper and node.upper.accept(self) or '' | 334 upper = node.upper and node.upper.accept(self) or '' |
380 step = node.step and node.step.accept(self) or '' | 335 step = node.step and node.step.accept(self) or '' |
381 if step: | 336 if step: |
382 return '%s:%s:%s' % (lower, upper, step) | 337 return '%s:%s:%s' % (lower, upper, step) |
383 return '%s:%s' % (lower, upper) | 338 return '%s:%s' % (lower, upper) |
384 | 339 |
385 def visit_subscript(self, node): | 340 def visit_subscript(self, node): |
386 """return an astroid.Subscript node as string""" | 341 """return an astng.Subscript node as string""" |
387 return '%s[%s]' % (node.value.accept(self), node.slice.accept(self)) | 342 return '%s[%s]' % (node.value.accept(self), node.slice.accept(self)) |
388 | 343 |
389 def visit_tryexcept(self, node): | 344 def visit_tryexcept(self, node): |
390 """return an astroid.TryExcept node as string""" | 345 """return an astng.TryExcept node as string""" |
391 trys = ['try:\n%s' % self._stmt_list(node.body)] | 346 trys = ['try:\n%s' % self._stmt_list( node.body)] |
392 for handler in node.handlers: | 347 for handler in node.handlers: |
393 trys.append(handler.accept(self)) | 348 trys.append(handler.accept(self)) |
394 if node.orelse: | 349 if node.orelse: |
395 trys.append('else:\n%s' % self._stmt_list(node.orelse)) | 350 trys.append('else:\n%s' % self._stmt_list(node.orelse)) |
396 return '\n'.join(trys) | 351 return '\n'.join(trys) |
397 | 352 |
398 def visit_tryfinally(self, node): | 353 def visit_tryfinally(self, node): |
399 """return an astroid.TryFinally node as string""" | 354 """return an astng.TryFinally node as string""" |
400 return 'try:\n%s\nfinally:\n%s' % (self._stmt_list(node.body), | 355 return 'try:\n%s\nfinally:\n%s' % (self._stmt_list( node.body), |
401 self._stmt_list(node.finalbody)) | 356 self._stmt_list(node.finalbody)) |
402 | 357 |
403 def visit_tuple(self, node): | 358 def visit_tuple(self, node): |
404 """return an astroid.Tuple node as string""" | 359 """return an astng.Tuple node as string""" |
405 if len(node.elts) == 1: | |
406 return '(%s, )' % node.elts[0].accept(self) | |
407 return '(%s)' % ', '.join([child.accept(self) for child in node.elts]) | 360 return '(%s)' % ', '.join([child.accept(self) for child in node.elts]) |
408 | 361 |
409 def visit_unaryop(self, node): | 362 def visit_unaryop(self, node): |
410 """return an astroid.UnaryOp node as string""" | 363 """return an astng.UnaryOp node as string""" |
411 if node.op == 'not': | 364 if node.op == 'not': |
412 operator = 'not ' | 365 operator = 'not ' |
413 else: | 366 else: |
414 operator = node.op | 367 operator = node.op |
415 return '%s%s' % (operator, node.operand.accept(self)) | 368 return '%s%s' % (operator, node.operand.accept(self)) |
416 | 369 |
417 def visit_while(self, node): | 370 def visit_while(self, node): |
418 """return an astroid.While node as string""" | 371 """return an astng.While node as string""" |
419 whiles = 'while %s:\n%s' % (node.test.accept(self), | 372 whiles = 'while %s:\n%s' % (node.test.accept(self), |
420 self._stmt_list(node.body)) | 373 self._stmt_list(node.body)) |
421 if node.orelse: | 374 if node.orelse: |
422 whiles = '%s\nelse:\n%s' % (whiles, self._stmt_list(node.orelse)) | 375 whiles = '%s\nelse:\n%s' % (whiles, self._stmt_list(node.orelse)) |
423 return whiles | 376 return whiles |
424 | 377 |
425 def visit_with(self, node): # 'with' without 'as' is possible | 378 def visit_with(self, node): # 'with' without 'as' is possible |
426 """return an astroid.With node as string""" | 379 """return an astng.With node as string""" |
427 items = ', '.join(('(%s)' % expr.accept(self)) + | 380 as_var = node.vars and " as (%s)" % (node.vars.accept(self)) or "" |
428 (vars and ' as (%s)' % (vars.accept(self)) or '') | 381 withs = 'with (%s)%s:\n%s' % (node.expr.accept(self), as_var, |
429 for expr, vars in node.items) | 382 self._stmt_list( node.body)) |
430 return 'with %s:\n%s' % (items, self._stmt_list(node.body)) | 383 return withs |
431 | 384 |
432 def visit_yield(self, node): | 385 def visit_yield(self, node): |
433 """yield an ast.Yield node as string""" | 386 """yield an ast.Yield node as string""" |
434 yi_val = node.value and (" " + node.value.accept(self)) or "" | 387 yi_val = node.value and (" " + node.value.accept(self)) or "" |
435 expr = 'yield' + yi_val | 388 return 'yield' + yi_val |
436 if node.parent.is_statement: | |
437 return expr | |
438 else: | |
439 return "(%s)" % (expr,) | |
440 | 389 |
441 | 390 |
442 class AsStringVisitor3k(AsStringVisitor): | 391 class AsStringVisitor3k(AsStringVisitor): |
443 """AsStringVisitor3k overwrites some AsStringVisitor methods""" | 392 """AsStringVisitor3k overwrites some AsStringVisitor methods""" |
444 | 393 |
445 def visit_excepthandler(self, node): | 394 def visit_excepthandler(self, node): |
446 if node.type: | 395 if node.type: |
447 if node.name: | 396 if node.name: |
448 excs = 'except %s as %s' % (node.type.accept(self), | 397 excs = 'except %s as %s' % (node.type.accept(self), |
449 node.name.accept(self)) | 398 node.name.accept(self)) |
450 else: | 399 else: |
451 excs = 'except %s' % node.type.accept(self) | 400 excs = 'except %s' % node.type.accept(self) |
452 else: | 401 else: |
453 excs = 'except' | 402 excs = 'except' |
454 return '%s:\n%s' % (excs, self._stmt_list(node.body)) | 403 return '%s:\n%s' % (excs, self._stmt_list(node.body)) |
455 | 404 |
456 def visit_nonlocal(self, node): | 405 def visit_nonlocal(self, node): |
457 """return an astroid.Nonlocal node as string""" | 406 """return an astng.Nonlocal node as string""" |
458 return 'nonlocal %s' % ', '.join(node.names) | 407 return 'nonlocal %s' % ', '.join(node.names) |
459 | 408 |
460 def visit_raise(self, node): | 409 def visit_raise(self, node): |
461 """return an astroid.Raise node as string""" | 410 """return an astng.Raise node as string""" |
462 if node.exc: | 411 if node.exc: |
463 if node.cause: | 412 if node.cause: |
464 return 'raise %s from %s' % (node.exc.accept(self), | 413 return 'raise %s from %s' % (node.exc.accept(self), |
465 node.cause.accept(self)) | 414 node.cause.accept(self)) |
466 return 'raise %s' % node.exc.accept(self) | 415 return 'raise %s' % node.exc.accept(self) |
467 return 'raise' | 416 return 'raise' |
468 | 417 |
469 def visit_starred(self, node): | 418 def visit_starred(self, node): |
470 """return Starred node as string""" | 419 """return Starred node as string""" |
471 return "*" + node.value.accept(self) | 420 return "*" + node.value.accept(self) |
472 | 421 |
473 def visit_yieldfrom(self, node): | |
474 """ Return an astroid.YieldFrom node as string. """ | |
475 yi_val = node.value and (" " + node.value.accept(self)) or "" | |
476 expr = 'yield from' + yi_val | |
477 if node.parent.is_statement: | |
478 return expr | |
479 else: | |
480 return "(%s)" % (expr,) | |
481 | |
482 | |
483 def _import_string(names): | |
484 """return a list of (name, asname) formatted as a string""" | |
485 _names = [] | |
486 for name, asname in names: | |
487 if asname is not None: | |
488 _names.append('%s as %s' % (name, asname)) | |
489 else: | |
490 _names.append(name) | |
491 return ', '.join(_names) | |
492 | |
493 | |
494 if sys.version_info >= (3, 0): | 422 if sys.version_info >= (3, 0): |
495 AsStringVisitor = AsStringVisitor3k | 423 AsStringVisitor = AsStringVisitor3k |
496 | 424 |
497 # this visitor is stateless, thus it can be reused | 425 # this visitor is stateless, thus it can be reused |
498 to_code = AsStringVisitor() | 426 as_string = AsStringVisitor() |
499 | 427 |
OLD | NEW |