1# -*- coding: utf-8 -*-
2#
3# Copyright (C) 2008-2010 Edgewall Software
4# All rights reserved.
5#
6# This software is licensed as described in the file COPYING, which
7# you should have received as part of this distribution. The terms
8# are also available at http://genshi.edgewall.org/wiki/License.
9#
10# This software consists of voluntary contributions made by many
11# individuals. For the exact contribution history, see the revision
12# history and logs, available at http://genshi.edgewall.org/log/.
13
14"""Support classes for generating code from abstract syntax trees."""
15
16from genshi.compat import ast as _ast, _ast_Constant, IS_PYTHON2, isstring, \
17 _ast_Ellipsis, _ast_Ellipsis_value
18
19__docformat__ = 'restructuredtext en'
20
21def parse(source, mode):
22 return compile(source, '', mode, _ast.PyCF_ONLY_AST)
23
24
25class ASTCodeGenerator(object):
26 """General purpose base class for AST transformations.
27
28 Every visitor method can be overridden to return an AST node that has been
29 altered or replaced in some way.
30 """
31 def __init__(self, tree):
32 self.lines_info = []
33 self.line_info = None
34 self.code = ''
35 self.line = None
36 self.last = None
37 self.indent = 0
38 self.blame_stack = []
39 self.visit(tree)
40 if self.line.strip():
41 self.code += self.line + '\n'
42 self.lines_info.append(self.line_info)
43 self.line = None
44 self.line_info = None
45
46 def _change_indent(self, delta):
47 self.indent += delta
48
49 def _new_line(self):
50 if self.line is not None:
51 self.code += self.line + '\n'
52 self.lines_info.append(self.line_info)
53 self.line = ' '*4*self.indent
54 if len(self.blame_stack) == 0:
55 self.line_info = []
56 self.last = None
57 else:
58 self.line_info = [(0, self.blame_stack[-1],)]
59 self.last = self.blame_stack[-1]
60
61 def _write(self, s):
62 if len(s) == 0:
63 return
64 if len(self.blame_stack) == 0:
65 if self.last is not None:
66 self.last = None
67 self.line_info.append((len(self.line), self.last))
68 else:
69 if self.last != self.blame_stack[-1]:
70 self.last = self.blame_stack[-1]
71 self.line_info.append((len(self.line), self.last))
72 self.line += s
73
74 def visit(self, node):
75 if node is None:
76 return None
77 if type(node) is tuple:
78 return tuple([self.visit(n) for n in node])
79 try:
80 self.blame_stack.append((node.lineno, node.col_offset,))
81 info = True
82 except AttributeError:
83 info = False
84 if isinstance(node, (bool, bytes, float, int, str)):
85 # something['foo'] just returns 'foo' as str in Python 3.9 while
86 # Python 3.8 and earlier returned a Constant().
87 node = _ast_Constant(node)
88 visitor = getattr(self, 'visit_%s' % node.__class__.__name__, None)
89 if visitor is None:
90 raise Exception('Unhandled node type %r' % type(node))
91 ret = visitor(node)
92 if info:
93 self.blame_stack.pop()
94 return ret
95
96 def visit_Module(self, node):
97 for n in node.body:
98 self.visit(n)
99 visit_Interactive = visit_Module
100 visit_Suite = visit_Module
101
102 def visit_Expression(self, node):
103 self._new_line()
104 return self.visit(node.body)
105
106 # Python < 3.4
107 # arguments = (expr* args, identifier? vararg,
108 # identifier? kwarg, expr* defaults)
109 #
110 # Python >= 3.4
111 # arguments = (arg* args, arg? vararg, arg* kwonlyargs, expr* kw_defaults,
112 # arg? kwarg, expr* defaults)
113 def visit_arguments(self, node):
114 def write_possible_comma():
115 if _first[0]:
116 _first[0] = False
117 else:
118 self._write(', ')
119 _first = [True]
120
121 def write_args(args, defaults):
122 no_default_count = len(args) - len(defaults)
123 for i, arg in enumerate(args):
124 write_possible_comma()
125 self.visit(arg)
126 default_idx = i - no_default_count
127 if default_idx >= 0 and defaults[default_idx] is not None:
128 self._write('=')
129 self.visit(defaults[i - no_default_count])
130
131 write_args(node.args, node.defaults)
132 if getattr(node, 'vararg', None):
133 write_possible_comma()
134 self._write('*')
135 if isstring(node.vararg):
136 self._write(node.vararg)
137 else:
138 self.visit(node.vararg)
139 if getattr(node, 'kwonlyargs', None):
140 write_args(node.kwonlyargs, node.kw_defaults)
141 if getattr(node, 'kwarg', None):
142 write_possible_comma()
143 self._write('**')
144 if isstring(node.kwarg):
145 self._write(node.kwarg)
146 else:
147 self.visit(node.kwarg)
148
149 if not IS_PYTHON2:
150 # In Python 3 arguments get a special node
151 def visit_arg(self, node):
152 self._write(node.arg)
153
154 def visit_Starred(self, node):
155 self._write('*')
156 self.visit(node.value)
157
158 # FunctionDef(identifier name, arguments args,
159 # stmt* body, expr* decorator_list)
160 def visit_FunctionDef(self, node):
161 decarators = ()
162 if hasattr(node, 'decorator_list'):
163 decorators = getattr(node, 'decorator_list')
164 else: # different name in earlier Python versions
165 decorators = getattr(node, 'decorators', ())
166 for decorator in decorators:
167 self._new_line()
168 self._write('@')
169 self.visit(decorator)
170 self._new_line()
171 self._write('def ' + node.name + '(')
172 self.visit(node.args)
173 self._write('):')
174 self._change_indent(1)
175 for statement in node.body:
176 self.visit(statement)
177 self._change_indent(-1)
178
179 # ClassDef(identifier name, expr* bases, stmt* body)
180 def visit_ClassDef(self, node):
181 self._new_line()
182 self._write('class ' + node.name)
183 if node.bases:
184 self._write('(')
185 self.visit(node.bases[0])
186 for base in node.bases[1:]:
187 self._write(', ')
188 self.visit(base)
189 self._write(')')
190 self._write(':')
191 self._change_indent(1)
192 for statement in node.body:
193 self.visit(statement)
194 self._change_indent(-1)
195
196 # Return(expr? value)
197 def visit_Return(self, node):
198 self._new_line()
199 self._write('return')
200 if getattr(node, 'value', None):
201 self._write(' ')
202 self.visit(node.value)
203
204 # Delete(expr* targets)
205 def visit_Delete(self, node):
206 self._new_line()
207 self._write('del ')
208 self.visit(node.targets[0])
209 for target in node.targets[1:]:
210 self._write(', ')
211 self.visit(target)
212
213 # Assign(expr* targets, expr value)
214 def visit_Assign(self, node):
215 self._new_line()
216 for target in node.targets:
217 self.visit(target)
218 self._write(' = ')
219 self.visit(node.value)
220
221 # AugAssign(expr target, operator op, expr value)
222 def visit_AugAssign(self, node):
223 self._new_line()
224 self.visit(node.target)
225 self._write(' ' + self.binary_operators[node.op.__class__] + '= ')
226 self.visit(node.value)
227
228 # Print(expr? dest, expr* values, bool nl)
229 def visit_Print(self, node):
230 self._new_line()
231 self._write('print')
232 if getattr(node, 'dest', None):
233 self._write(' >> ')
234 self.visit(node.dest)
235 if getattr(node, 'values', None):
236 self._write(', ')
237 else:
238 self._write(' ')
239 if getattr(node, 'values', None):
240 self.visit(node.values[0])
241 for value in node.values[1:]:
242 self._write(', ')
243 self.visit(value)
244 if not node.nl:
245 self._write(',')
246
247 # For(expr target, expr iter, stmt* body, stmt* orelse)
248 def visit_For(self, node):
249 self._new_line()
250 self._write('for ')
251 self.visit(node.target)
252 self._write(' in ')
253 self.visit(node.iter)
254 self._write(':')
255 self._change_indent(1)
256 for statement in node.body:
257 self.visit(statement)
258 self._change_indent(-1)
259 if getattr(node, 'orelse', None):
260 self._new_line()
261 self._write('else:')
262 self._change_indent(1)
263 for statement in node.orelse:
264 self.visit(statement)
265 self._change_indent(-1)
266
267 # While(expr test, stmt* body, stmt* orelse)
268 def visit_While(self, node):
269 self._new_line()
270 self._write('while ')
271 self.visit(node.test)
272 self._write(':')
273 self._change_indent(1)
274 for statement in node.body:
275 self.visit(statement)
276 self._change_indent(-1)
277 if getattr(node, 'orelse', None):
278 self._new_line()
279 self._write('else:')
280 self._change_indent(1)
281 for statement in node.orelse:
282 self.visit(statement)
283 self._change_indent(-1)
284
285 # If(expr test, stmt* body, stmt* orelse)
286 def visit_If(self, node):
287 self._new_line()
288 self._write('if ')
289 self.visit(node.test)
290 self._write(':')
291 self._change_indent(1)
292 for statement in node.body:
293 self.visit(statement)
294 self._change_indent(-1)
295 if getattr(node, 'orelse', None):
296 self._new_line()
297 self._write('else:')
298 self._change_indent(1)
299 for statement in node.orelse:
300 self.visit(statement)
301 self._change_indent(-1)
302
303 # With(expr context_expr, expr? optional_vars, stmt* body)
304 # With(withitem* items, stmt* body) in Python >= 3.3
305 def visit_With(self, node):
306 self._new_line()
307 self._write('with ')
308 items = getattr(node, 'items', None)
309 first = True
310 if items is None:
311 items = [node]
312 for item in items:
313 if not first:
314 self._write(', ')
315 first = False
316 self.visit(item.context_expr)
317 if getattr(item, 'optional_vars', None):
318 self._write(' as ')
319 self.visit(item.optional_vars)
320 self._write(':')
321 self._change_indent(1)
322 for statement in node.body:
323 self.visit(statement)
324 self._change_indent(-1)
325
326 # Raise(expr? type, expr? inst, expr? tback)
327 def visit_Raise(self, node):
328 self._new_line()
329 self._write('raise')
330 if IS_PYTHON2:
331 if not node.type:
332 return
333 self._write(' ')
334 self.visit(node.type)
335 if not node.inst:
336 return
337 self._write(', ')
338 self.visit(node.inst)
339 if not node.tback:
340 return
341 self._write(', ')
342 self.visit(node.tback)
343 else:
344 if not node.exc:
345 return
346 self._write(' ')
347 self.visit(node.exc)
348 if not node.cause:
349 return
350 self._write(' from ')
351 self.visit(node.cause)
352
353 # TryExcept(stmt* body, excepthandler* handlers, stmt* orelse)
354 def visit_TryExcept(self, node):
355 self._new_line()
356 self._write('try:')
357 self._change_indent(1)
358 for statement in node.body:
359 self.visit(statement)
360 self._change_indent(-1)
361 if getattr(node, 'handlers', None):
362 for handler in node.handlers:
363 self.visit(handler)
364 self._new_line()
365 if getattr(node, 'orelse', None):
366 self._write('else:')
367 self._change_indent(1)
368 for statement in node.orelse:
369 self.visit(statement)
370 self._change_indent(-1)
371
372 # excepthandler = (expr? type, expr? name, stmt* body)
373 def visit_ExceptHandler(self, node):
374 self._new_line()
375 self._write('except')
376 if getattr(node, 'type', None):
377 self._write(' ')
378 self.visit(node.type)
379 if getattr(node, 'name', None):
380 self._write(', ')
381 self.visit(node.name)
382 self._write(':')
383 self._change_indent(1)
384 for statement in node.body:
385 self.visit(statement)
386 self._change_indent(-1)
387 visit_excepthandler = visit_ExceptHandler
388
389 # TryFinally(stmt* body, stmt* finalbody)
390 def visit_TryFinally(self, node):
391 self._new_line()
392 self._write('try:')
393 self._change_indent(1)
394 for statement in node.body:
395 self.visit(statement)
396 self._change_indent(-1)
397
398 if getattr(node, 'finalbody', None):
399 self._new_line()
400 self._write('finally:')
401 self._change_indent(1)
402 for statement in node.finalbody:
403 self.visit(statement)
404 self._change_indent(-1)
405
406 # New in Py3.3
407 # Try(stmt* body, excepthandler* handlers, stmt* orelse, stmt* finalbody)
408 def visit_Try(self, node):
409 self._new_line()
410 self._write('try:')
411 self._change_indent(1)
412 for statement in node.body:
413 self.visit(statement)
414 self._change_indent(-1)
415 if getattr(node, 'handlers', None):
416 for handler in node.handlers:
417 self.visit(handler)
418 self._new_line()
419 if getattr(node, 'orelse', None):
420 self._write('else:')
421 self._change_indent(1)
422 for statement in node.orelse:
423 self.visit(statement)
424 self._change_indent(-1)
425 if getattr(node, 'finalbody', None):
426 self._new_line()
427 self._write('finally:')
428 self._change_indent(1)
429 for statement in node.finalbody:
430 self.visit(statement)
431 self._change_indent(-1)
432
433 # Assert(expr test, expr? msg)
434 def visit_Assert(self, node):
435 self._new_line()
436 self._write('assert ')
437 self.visit(node.test)
438 if getattr(node, 'msg', None):
439 self._write(', ')
440 self.visit(node.msg)
441
442 def visit_alias(self, node):
443 self._write(node.name)
444 if getattr(node, 'asname', None):
445 self._write(' as ')
446 self._write(node.asname)
447
448 # Import(alias* names)
449 def visit_Import(self, node):
450 self._new_line()
451 self._write('import ')
452 self.visit(node.names[0])
453 for name in node.names[1:]:
454 self._write(', ')
455 self.visit(name)
456
457 # ImportFrom(identifier module, alias* names, int? level)
458 def visit_ImportFrom(self, node):
459 self._new_line()
460 self._write('from ')
461 if node.level:
462 self._write('.' * node.level)
463 self._write(node.module)
464 self._write(' import ')
465 self.visit(node.names[0])
466 for name in node.names[1:]:
467 self._write(', ')
468 self.visit(name)
469
470 # Exec(expr body, expr? globals, expr? locals)
471 def visit_Exec(self, node):
472 self._new_line()
473 self._write('exec ')
474 self.visit(node.body)
475 if not node.globals:
476 return
477 self._write(', ')
478 self.visit(node.globals)
479 if not node.locals:
480 return
481 self._write(', ')
482 self.visit(node.locals)
483
484 # Global(identifier* names)
485 def visit_Global(self, node):
486 self._new_line()
487 self._write('global ')
488 self.visit(node.names[0])
489 for name in node.names[1:]:
490 self._write(', ')
491 self.visit(name)
492
493 # Expr(expr value)
494 def visit_Expr(self, node):
495 self._new_line()
496 self.visit(node.value)
497
498 # Pass
499 def visit_Pass(self, node):
500 self._new_line()
501 self._write('pass')
502
503 # Break
504 def visit_Break(self, node):
505 self._new_line()
506 self._write('break')
507
508 # Continue
509 def visit_Continue(self, node):
510 self._new_line()
511 self._write('continue')
512
513 ### EXPRESSIONS
514 def with_parens(f):
515 def _f(self, node):
516 self._write('(')
517 f(self, node)
518 self._write(')')
519 return _f
520
521 bool_operators = {_ast.And: 'and', _ast.Or: 'or'}
522
523 # BoolOp(boolop op, expr* values)
524 @with_parens
525 def visit_BoolOp(self, node):
526 joiner = ' ' + self.bool_operators[node.op.__class__] + ' '
527 self.visit(node.values[0])
528 for value in node.values[1:]:
529 self._write(joiner)
530 self.visit(value)
531
532 binary_operators = {
533 _ast.Add: '+',
534 _ast.Sub: '-',
535 _ast.Mult: '*',
536 _ast.Div: '/',
537 _ast.Mod: '%',
538 _ast.Pow: '**',
539 _ast.LShift: '<<',
540 _ast.RShift: '>>',
541 _ast.BitOr: '|',
542 _ast.BitXor: '^',
543 _ast.BitAnd: '&',
544 _ast.FloorDiv: '//'
545 }
546
547 # BinOp(expr left, operator op, expr right)
548 @with_parens
549 def visit_BinOp(self, node):
550 self.visit(node.left)
551 self._write(' ' + self.binary_operators[node.op.__class__] + ' ')
552 self.visit(node.right)
553
554 unary_operators = {
555 _ast.Invert: '~',
556 _ast.Not: 'not',
557 _ast.UAdd: '+',
558 _ast.USub: '-',
559 }
560
561 # UnaryOp(unaryop op, expr operand)
562 def visit_UnaryOp(self, node):
563 self._write(self.unary_operators[node.op.__class__] + ' ')
564 self.visit(node.operand)
565
566 # Lambda(arguments args, expr body)
567 @with_parens
568 def visit_Lambda(self, node):
569 self._write('lambda ')
570 self.visit(node.args)
571 self._write(': ')
572 self.visit(node.body)
573
574 # IfExp(expr test, expr body, expr orelse)
575 @with_parens
576 def visit_IfExp(self, node):
577 self.visit(node.body)
578 self._write(' if ')
579 self.visit(node.test)
580 self._write(' else ')
581 self.visit(node.orelse)
582
583 # Dict(expr* keys, expr* values)
584 def visit_Dict(self, node):
585 self._write('{')
586 for key, value in zip(node.keys, node.values):
587 self.visit(key)
588 self._write(': ')
589 self.visit(value)
590 self._write(', ')
591 self._write('}')
592
593 # ListComp(expr elt, comprehension* generators)
594 def visit_ListComp(self, node):
595 self._write('[')
596 self.visit(node.elt)
597 for generator in node.generators:
598 # comprehension = (expr target, expr iter, expr* ifs)
599 self._write(' for ')
600 self.visit(generator.target)
601 self._write(' in ')
602 self.visit(generator.iter)
603 for ifexpr in generator.ifs:
604 self._write(' if ')
605 self.visit(ifexpr)
606 self._write(']')
607
608 # GeneratorExp(expr elt, comprehension* generators)
609 def visit_GeneratorExp(self, node):
610 self._write('(')
611 self.visit(node.elt)
612 for generator in node.generators:
613 # comprehension = (expr target, expr iter, expr* ifs)
614 self._write(' for ')
615 self.visit(generator.target)
616 self._write(' in ')
617 self.visit(generator.iter)
618 for ifexpr in generator.ifs:
619 self._write(' if ')
620 self.visit(ifexpr)
621 self._write(')')
622
623 # Yield(expr? value)
624 def visit_Yield(self, node):
625 self._write('yield')
626 if getattr(node, 'value', None):
627 self._write(' ')
628 self.visit(node.value)
629
630 comparision_operators = {
631 _ast.Eq: '==',
632 _ast.NotEq: '!=',
633 _ast.Lt: '<',
634 _ast.LtE: '<=',
635 _ast.Gt: '>',
636 _ast.GtE: '>=',
637 _ast.Is: 'is',
638 _ast.IsNot: 'is not',
639 _ast.In: 'in',
640 _ast.NotIn: 'not in',
641 }
642
643 # Compare(expr left, cmpop* ops, expr* comparators)
644 @with_parens
645 def visit_Compare(self, node):
646 self.visit(node.left)
647 for op, comparator in zip(node.ops, node.comparators):
648 self._write(' ' + self.comparision_operators[op.__class__] + ' ')
649 self.visit(comparator)
650
651 # Call(expr func, expr* args, keyword* keywords,
652 # expr? starargs, expr? kwargs)
653 def visit_Call(self, node):
654 self.visit(node.func)
655 self._write('(')
656 first = True
657 for arg in node.args:
658 if not first:
659 self._write(', ')
660 first = False
661 self.visit(arg)
662
663 for keyword in node.keywords:
664 if not first:
665 self._write(', ')
666 first = False
667 if not keyword.arg:
668 # Python 3.5+ star-star args
669 self._write('**')
670 else:
671 # keyword = (identifier arg, expr value)
672 self._write(keyword.arg)
673 self._write('=')
674 self.visit(keyword.value)
675 if getattr(node, 'starargs', None):
676 if not first:
677 self._write(', ')
678 first = False
679 self._write('*')
680 self.visit(node.starargs)
681
682 if getattr(node, 'kwargs', None):
683 if not first:
684 self._write(', ')
685 first = False
686 self._write('**')
687 self.visit(node.kwargs)
688 self._write(')')
689
690 # Repr(expr value)
691 def visit_Repr(self, node):
692 self._write('`')
693 self.visit(node.value)
694 self._write('`')
695
696 # Num(object n)
697 def visit_Num(self, node):
698 self._write(repr(node.n))
699
700 # Str(string s)
701 def visit_Str(self, node):
702 self._write(repr(node.s))
703
704 # Constant(object value)
705 def visit_Constant(self, node):
706 self._write(repr(node.value))
707
708 if not IS_PYTHON2:
709 # Bytes(bytes s)
710 def visit_Bytes(self, node):
711 self._write(repr(node.s))
712
713 # Attribute(expr value, identifier attr, expr_context ctx)
714 def visit_Attribute(self, node):
715 self.visit(node.value)
716 self._write('.')
717 self._write(node.attr)
718
719 # Subscript(expr value, slice slice, expr_context ctx)
720 def visit_Subscript(self, node):
721 self.visit(node.value)
722 self._write('[')
723 def _process_slice(node):
724 if (
725 isinstance(node, _ast_Ellipsis)
726 and _ast_Ellipsis_value(node) == Ellipsis
727 ):
728 self._write('...')
729 elif isinstance(node, _ast.Slice):
730 if getattr(node, 'lower', 'None'):
731 self.visit(node.lower)
732 self._write(':')
733 if getattr(node, 'upper', None):
734 self.visit(node.upper)
735 if getattr(node, 'step', None):
736 self._write(':')
737 self.visit(node.step)
738 elif isinstance(node, _ast.Index):
739 self.visit(node.value)
740 elif isinstance(node, _ast.ExtSlice):
741 self.visit(node.dims[0])
742 for dim in node.dims[1:]:
743 self._write(', ')
744 self.visit(dim)
745 else:
746 self.visit(node)
747 _process_slice(node.slice)
748 self._write(']')
749
750 # Name(identifier id, expr_context ctx)
751 def visit_Name(self, node):
752 self._write(node.id)
753
754 # NameConstant(singleton value)
755 def visit_NameConstant(self, node):
756 if node.value is None:
757 self._write('None')
758 elif node.value is True:
759 self._write('True')
760 elif node.value is False:
761 self._write('False')
762 else:
763 raise Exception("Unknown NameConstant %r" % (node.value,))
764
765 # List(expr* elts, expr_context ctx)
766 def visit_List(self, node):
767 self._write('[')
768 for elt in node.elts:
769 self.visit(elt)
770 self._write(', ')
771 self._write(']')
772
773 # Tuple(expr *elts, expr_context ctx)
774 def visit_Tuple(self, node):
775 self._write('(')
776 for elt in node.elts:
777 # In Python 3.9 simple types (which includes NoneType) are
778 # represented by their value in "subscription" expressions.
779 # However self.visit() returns None if elt is None leading to
780 # invalid generated code. So we deal with the special case here.
781 # Example code triggering this: value[None]
782 self.visit(elt) if (elt is not None) else self._write('None')
783 self._write(', ')
784 self._write(')')
785
786
787class ASTTransformer(object):
788 """General purpose base class for AST transformations.
789
790 Every visitor method can be overridden to return an AST node that has been
791 altered or replaced in some way.
792 """
793
794 def visit(self, node):
795 if node is None:
796 return None
797 if type(node) is tuple:
798 return tuple([self.visit(n) for n in node])
799 visitor = getattr(self, 'visit_%s' % node.__class__.__name__, None)
800 if visitor is None:
801 return node
802 return visitor(node)
803
804 def _clone(self, node):
805 clone = node.__class__()
806 for name in getattr(clone, '_attributes', ()):
807 try:
808 setattr(clone, name, getattr(node, name))
809 except AttributeError:
810 pass
811 for name in clone._fields:
812 try:
813 value = getattr(node, name)
814 except AttributeError:
815 pass
816 else:
817 if value is None:
818 pass
819 elif isinstance(value, list):
820 value = [self.visit(x) for x in value]
821 elif isinstance(value, tuple):
822 value = tuple(self.visit(x) for x in value)
823 else:
824 value = self.visit(value)
825 setattr(clone, name, value)
826 return clone
827
828 visit_Module = _clone
829 visit_Interactive = _clone
830 visit_Expression = _clone
831 visit_Suite = _clone
832
833 visit_FunctionDef = _clone
834 visit_ClassDef = _clone
835 visit_Return = _clone
836 visit_Delete = _clone
837 visit_Assign = _clone
838 visit_AugAssign = _clone
839 visit_Print = _clone
840 visit_For = _clone
841 visit_While = _clone
842 visit_If = _clone
843 visit_With = _clone
844 visit_Raise = _clone
845 visit_TryExcept = _clone
846 visit_TryFinally = _clone
847 visit_Try = _clone
848 visit_Assert = _clone
849 visit_ExceptHandler = _clone
850
851 visit_Import = _clone
852 visit_ImportFrom = _clone
853 visit_Exec = _clone
854 visit_Global = _clone
855 visit_Expr = _clone
856 # Pass, Break, Continue don't need to be copied
857
858 visit_BoolOp = _clone
859 visit_BinOp = _clone
860 visit_UnaryOp = _clone
861 visit_Lambda = _clone
862 visit_IfExp = _clone
863 visit_Dict = _clone
864 visit_ListComp = _clone
865 visit_GeneratorExp = _clone
866 visit_Yield = _clone
867 visit_Compare = _clone
868 visit_Call = _clone
869 visit_Repr = _clone
870 # Num, Str don't need to be copied
871
872 visit_Attribute = _clone
873 visit_Subscript = _clone
874 visit_Name = _clone
875 visit_NameConstant = _clone
876 visit_List = _clone
877 visit_Tuple = _clone
878
879 visit_comprehension = _clone
880 visit_excepthandler = _clone
881 visit_arguments = _clone
882 visit_keyword = _clone
883 visit_alias = _clone
884
885 visit_Slice = _clone
886 visit_ExtSlice = _clone
887 visit_Index = _clone
888
889 del _clone