1*4882a593Smuzhiyun# -*- coding: utf-8 -*- 2*4882a593Smuzhiyun""" 3*4882a593Smuzhiyun codegen 4*4882a593Smuzhiyun ~~~~~~~ 5*4882a593Smuzhiyun 6*4882a593Smuzhiyun Extension to ast that allow ast -> python code generation. 7*4882a593Smuzhiyun 8*4882a593Smuzhiyun :copyright: Copyright 2008 by Armin Ronacher. 9*4882a593Smuzhiyun :license: BSD. 10*4882a593Smuzhiyun""" 11*4882a593Smuzhiyunfrom ast import * 12*4882a593Smuzhiyun 13*4882a593SmuzhiyunBOOLOP_SYMBOLS = { 14*4882a593Smuzhiyun And: 'and', 15*4882a593Smuzhiyun Or: 'or' 16*4882a593Smuzhiyun} 17*4882a593Smuzhiyun 18*4882a593SmuzhiyunBINOP_SYMBOLS = { 19*4882a593Smuzhiyun Add: '+', 20*4882a593Smuzhiyun Sub: '-', 21*4882a593Smuzhiyun Mult: '*', 22*4882a593Smuzhiyun Div: '/', 23*4882a593Smuzhiyun FloorDiv: '//', 24*4882a593Smuzhiyun Mod: '%', 25*4882a593Smuzhiyun LShift: '<<', 26*4882a593Smuzhiyun RShift: '>>', 27*4882a593Smuzhiyun BitOr: '|', 28*4882a593Smuzhiyun BitAnd: '&', 29*4882a593Smuzhiyun BitXor: '^' 30*4882a593Smuzhiyun} 31*4882a593Smuzhiyun 32*4882a593SmuzhiyunCMPOP_SYMBOLS = { 33*4882a593Smuzhiyun Eq: '==', 34*4882a593Smuzhiyun Gt: '>', 35*4882a593Smuzhiyun GtE: '>=', 36*4882a593Smuzhiyun In: 'in', 37*4882a593Smuzhiyun Is: 'is', 38*4882a593Smuzhiyun IsNot: 'is not', 39*4882a593Smuzhiyun Lt: '<', 40*4882a593Smuzhiyun LtE: '<=', 41*4882a593Smuzhiyun NotEq: '!=', 42*4882a593Smuzhiyun NotIn: 'not in' 43*4882a593Smuzhiyun} 44*4882a593Smuzhiyun 45*4882a593SmuzhiyunUNARYOP_SYMBOLS = { 46*4882a593Smuzhiyun Invert: '~', 47*4882a593Smuzhiyun Not: 'not', 48*4882a593Smuzhiyun UAdd: '+', 49*4882a593Smuzhiyun USub: '-' 50*4882a593Smuzhiyun} 51*4882a593Smuzhiyun 52*4882a593SmuzhiyunALL_SYMBOLS = {} 53*4882a593SmuzhiyunALL_SYMBOLS.update(BOOLOP_SYMBOLS) 54*4882a593SmuzhiyunALL_SYMBOLS.update(BINOP_SYMBOLS) 55*4882a593SmuzhiyunALL_SYMBOLS.update(CMPOP_SYMBOLS) 56*4882a593SmuzhiyunALL_SYMBOLS.update(UNARYOP_SYMBOLS) 57*4882a593Smuzhiyun 58*4882a593Smuzhiyundef to_source(node, indent_with=' ' * 4, add_line_information=False): 59*4882a593Smuzhiyun """This function can convert a node tree back into python sourcecode. 60*4882a593Smuzhiyun This is useful for debugging purposes, especially if you're dealing with 61*4882a593Smuzhiyun custom asts not generated by python itself. 62*4882a593Smuzhiyun 63*4882a593Smuzhiyun It could be that the sourcecode is evaluable when the AST itself is not 64*4882a593Smuzhiyun compilable / evaluable. The reason for this is that the AST contains some 65*4882a593Smuzhiyun more data than regular sourcecode does, which is dropped during 66*4882a593Smuzhiyun conversion. 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun Each level of indentation is replaced with `indent_with`. Per default this 69*4882a593Smuzhiyun parameter is equal to four spaces as suggested by PEP 8, but it might be 70*4882a593Smuzhiyun adjusted to match the application's styleguide. 71*4882a593Smuzhiyun 72*4882a593Smuzhiyun If `add_line_information` is set to `True` comments for the line numbers 73*4882a593Smuzhiyun of the nodes are added to the output. This can be used to spot wrong line 74*4882a593Smuzhiyun number information of statement nodes. 75*4882a593Smuzhiyun """ 76*4882a593Smuzhiyun generator = SourceGenerator(indent_with, add_line_information) 77*4882a593Smuzhiyun generator.visit(node) 78*4882a593Smuzhiyun return ''.join(generator.result) 79*4882a593Smuzhiyun 80*4882a593Smuzhiyun 81*4882a593Smuzhiyunclass SourceGenerator(NodeVisitor): 82*4882a593Smuzhiyun """This visitor is able to transform a well formed syntax tree into python 83*4882a593Smuzhiyun sourcecode. For more details have a look at the docstring of the 84*4882a593Smuzhiyun `node_to_source` function. 85*4882a593Smuzhiyun """ 86*4882a593Smuzhiyun 87*4882a593Smuzhiyun def __init__(self, indent_with, add_line_information=False): 88*4882a593Smuzhiyun self.result = [] 89*4882a593Smuzhiyun self.indent_with = indent_with 90*4882a593Smuzhiyun self.add_line_information = add_line_information 91*4882a593Smuzhiyun self.indentation = 0 92*4882a593Smuzhiyun self.new_lines = 0 93*4882a593Smuzhiyun 94*4882a593Smuzhiyun def write(self, x): 95*4882a593Smuzhiyun if self.new_lines: 96*4882a593Smuzhiyun if self.result: 97*4882a593Smuzhiyun self.result.append('\n' * self.new_lines) 98*4882a593Smuzhiyun self.result.append(self.indent_with * self.indentation) 99*4882a593Smuzhiyun self.new_lines = 0 100*4882a593Smuzhiyun self.result.append(x) 101*4882a593Smuzhiyun 102*4882a593Smuzhiyun def newline(self, node=None, extra=0): 103*4882a593Smuzhiyun self.new_lines = max(self.new_lines, 1 + extra) 104*4882a593Smuzhiyun if node is not None and self.add_line_information: 105*4882a593Smuzhiyun self.write('# line: %s' % node.lineno) 106*4882a593Smuzhiyun self.new_lines = 1 107*4882a593Smuzhiyun 108*4882a593Smuzhiyun def body(self, statements): 109*4882a593Smuzhiyun self.new_line = True 110*4882a593Smuzhiyun self.indentation += 1 111*4882a593Smuzhiyun for stmt in statements: 112*4882a593Smuzhiyun self.visit(stmt) 113*4882a593Smuzhiyun self.indentation -= 1 114*4882a593Smuzhiyun 115*4882a593Smuzhiyun def body_or_else(self, node): 116*4882a593Smuzhiyun self.body(node.body) 117*4882a593Smuzhiyun if node.orelse: 118*4882a593Smuzhiyun self.newline() 119*4882a593Smuzhiyun self.write('else:') 120*4882a593Smuzhiyun self.body(node.orelse) 121*4882a593Smuzhiyun 122*4882a593Smuzhiyun def signature(self, node): 123*4882a593Smuzhiyun want_comma = [] 124*4882a593Smuzhiyun def write_comma(): 125*4882a593Smuzhiyun if want_comma: 126*4882a593Smuzhiyun self.write(', ') 127*4882a593Smuzhiyun else: 128*4882a593Smuzhiyun want_comma.append(True) 129*4882a593Smuzhiyun 130*4882a593Smuzhiyun padding = [None] * (len(node.args) - len(node.defaults)) 131*4882a593Smuzhiyun for arg, default in zip(node.args, padding + node.defaults): 132*4882a593Smuzhiyun write_comma() 133*4882a593Smuzhiyun self.visit(arg) 134*4882a593Smuzhiyun if default is not None: 135*4882a593Smuzhiyun self.write('=') 136*4882a593Smuzhiyun self.visit(default) 137*4882a593Smuzhiyun if node.vararg is not None: 138*4882a593Smuzhiyun write_comma() 139*4882a593Smuzhiyun self.write('*' + node.vararg) 140*4882a593Smuzhiyun if node.kwarg is not None: 141*4882a593Smuzhiyun write_comma() 142*4882a593Smuzhiyun self.write('**' + node.kwarg) 143*4882a593Smuzhiyun 144*4882a593Smuzhiyun def decorators(self, node): 145*4882a593Smuzhiyun for decorator in node.decorator_list: 146*4882a593Smuzhiyun self.newline(decorator) 147*4882a593Smuzhiyun self.write('@') 148*4882a593Smuzhiyun self.visit(decorator) 149*4882a593Smuzhiyun 150*4882a593Smuzhiyun # Statements 151*4882a593Smuzhiyun 152*4882a593Smuzhiyun def visit_Assign(self, node): 153*4882a593Smuzhiyun self.newline(node) 154*4882a593Smuzhiyun for idx, target in enumerate(node.targets): 155*4882a593Smuzhiyun if idx: 156*4882a593Smuzhiyun self.write(', ') 157*4882a593Smuzhiyun self.visit(target) 158*4882a593Smuzhiyun self.write(' = ') 159*4882a593Smuzhiyun self.visit(node.value) 160*4882a593Smuzhiyun 161*4882a593Smuzhiyun def visit_AugAssign(self, node): 162*4882a593Smuzhiyun self.newline(node) 163*4882a593Smuzhiyun self.visit(node.target) 164*4882a593Smuzhiyun self.write(BINOP_SYMBOLS[type(node.op)] + '=') 165*4882a593Smuzhiyun self.visit(node.value) 166*4882a593Smuzhiyun 167*4882a593Smuzhiyun def visit_ImportFrom(self, node): 168*4882a593Smuzhiyun self.newline(node) 169*4882a593Smuzhiyun self.write('from %s%s import ' % ('.' * node.level, node.module)) 170*4882a593Smuzhiyun for idx, item in enumerate(node.names): 171*4882a593Smuzhiyun if idx: 172*4882a593Smuzhiyun self.write(', ') 173*4882a593Smuzhiyun self.write(item) 174*4882a593Smuzhiyun 175*4882a593Smuzhiyun def visit_Import(self, node): 176*4882a593Smuzhiyun self.newline(node) 177*4882a593Smuzhiyun for item in node.names: 178*4882a593Smuzhiyun self.write('import ') 179*4882a593Smuzhiyun self.visit(item) 180*4882a593Smuzhiyun 181*4882a593Smuzhiyun def visit_Expr(self, node): 182*4882a593Smuzhiyun self.newline(node) 183*4882a593Smuzhiyun self.generic_visit(node) 184*4882a593Smuzhiyun 185*4882a593Smuzhiyun def visit_FunctionDef(self, node): 186*4882a593Smuzhiyun self.newline(extra=1) 187*4882a593Smuzhiyun self.decorators(node) 188*4882a593Smuzhiyun self.newline(node) 189*4882a593Smuzhiyun self.write('def %s(' % node.name) 190*4882a593Smuzhiyun self.signature(node.args) 191*4882a593Smuzhiyun self.write('):') 192*4882a593Smuzhiyun self.body(node.body) 193*4882a593Smuzhiyun 194*4882a593Smuzhiyun def visit_ClassDef(self, node): 195*4882a593Smuzhiyun have_args = [] 196*4882a593Smuzhiyun def paren_or_comma(): 197*4882a593Smuzhiyun if have_args: 198*4882a593Smuzhiyun self.write(', ') 199*4882a593Smuzhiyun else: 200*4882a593Smuzhiyun have_args.append(True) 201*4882a593Smuzhiyun self.write('(') 202*4882a593Smuzhiyun 203*4882a593Smuzhiyun self.newline(extra=2) 204*4882a593Smuzhiyun self.decorators(node) 205*4882a593Smuzhiyun self.newline(node) 206*4882a593Smuzhiyun self.write('class %s' % node.name) 207*4882a593Smuzhiyun for base in node.bases: 208*4882a593Smuzhiyun paren_or_comma() 209*4882a593Smuzhiyun self.visit(base) 210*4882a593Smuzhiyun # XXX: the if here is used to keep this module compatible 211*4882a593Smuzhiyun # with python 2.6. 212*4882a593Smuzhiyun if hasattr(node, 'keywords'): 213*4882a593Smuzhiyun for keyword in node.keywords: 214*4882a593Smuzhiyun paren_or_comma() 215*4882a593Smuzhiyun self.write(keyword.arg + '=') 216*4882a593Smuzhiyun self.visit(keyword.value) 217*4882a593Smuzhiyun if hasattr(node, 'starargs') and node.starargs is not None: 218*4882a593Smuzhiyun paren_or_comma() 219*4882a593Smuzhiyun self.write('*') 220*4882a593Smuzhiyun self.visit(node.starargs) 221*4882a593Smuzhiyun if hasattr(node, 'kwargs') and node.kwargs is not None: 222*4882a593Smuzhiyun paren_or_comma() 223*4882a593Smuzhiyun self.write('**') 224*4882a593Smuzhiyun self.visit(node.kwargs) 225*4882a593Smuzhiyun self.write(have_args and '):' or ':') 226*4882a593Smuzhiyun self.body(node.body) 227*4882a593Smuzhiyun 228*4882a593Smuzhiyun def visit_If(self, node): 229*4882a593Smuzhiyun self.newline(node) 230*4882a593Smuzhiyun self.write('if ') 231*4882a593Smuzhiyun self.visit(node.test) 232*4882a593Smuzhiyun self.write(':') 233*4882a593Smuzhiyun self.body(node.body) 234*4882a593Smuzhiyun while True: 235*4882a593Smuzhiyun else_ = node.orelse 236*4882a593Smuzhiyun if len(else_) == 1 and isinstance(else_[0], If): 237*4882a593Smuzhiyun node = else_[0] 238*4882a593Smuzhiyun self.newline() 239*4882a593Smuzhiyun self.write('elif ') 240*4882a593Smuzhiyun self.visit(node.test) 241*4882a593Smuzhiyun self.write(':') 242*4882a593Smuzhiyun self.body(node.body) 243*4882a593Smuzhiyun else: 244*4882a593Smuzhiyun self.newline() 245*4882a593Smuzhiyun self.write('else:') 246*4882a593Smuzhiyun self.body(else_) 247*4882a593Smuzhiyun break 248*4882a593Smuzhiyun 249*4882a593Smuzhiyun def visit_For(self, node): 250*4882a593Smuzhiyun self.newline(node) 251*4882a593Smuzhiyun self.write('for ') 252*4882a593Smuzhiyun self.visit(node.target) 253*4882a593Smuzhiyun self.write(' in ') 254*4882a593Smuzhiyun self.visit(node.iter) 255*4882a593Smuzhiyun self.write(':') 256*4882a593Smuzhiyun self.body_or_else(node) 257*4882a593Smuzhiyun 258*4882a593Smuzhiyun def visit_While(self, node): 259*4882a593Smuzhiyun self.newline(node) 260*4882a593Smuzhiyun self.write('while ') 261*4882a593Smuzhiyun self.visit(node.test) 262*4882a593Smuzhiyun self.write(':') 263*4882a593Smuzhiyun self.body_or_else(node) 264*4882a593Smuzhiyun 265*4882a593Smuzhiyun def visit_With(self, node): 266*4882a593Smuzhiyun self.newline(node) 267*4882a593Smuzhiyun self.write('with ') 268*4882a593Smuzhiyun self.visit(node.context_expr) 269*4882a593Smuzhiyun if node.optional_vars is not None: 270*4882a593Smuzhiyun self.write(' as ') 271*4882a593Smuzhiyun self.visit(node.optional_vars) 272*4882a593Smuzhiyun self.write(':') 273*4882a593Smuzhiyun self.body(node.body) 274*4882a593Smuzhiyun 275*4882a593Smuzhiyun def visit_Pass(self, node): 276*4882a593Smuzhiyun self.newline(node) 277*4882a593Smuzhiyun self.write('pass') 278*4882a593Smuzhiyun 279*4882a593Smuzhiyun def visit_Print(self, node): 280*4882a593Smuzhiyun # XXX: python 2.6 only 281*4882a593Smuzhiyun self.newline(node) 282*4882a593Smuzhiyun self.write('print ') 283*4882a593Smuzhiyun want_comma = False 284*4882a593Smuzhiyun if node.dest is not None: 285*4882a593Smuzhiyun self.write(' >> ') 286*4882a593Smuzhiyun self.visit(node.dest) 287*4882a593Smuzhiyun want_comma = True 288*4882a593Smuzhiyun for value in node.values: 289*4882a593Smuzhiyun if want_comma: 290*4882a593Smuzhiyun self.write(', ') 291*4882a593Smuzhiyun self.visit(value) 292*4882a593Smuzhiyun want_comma = True 293*4882a593Smuzhiyun if not node.nl: 294*4882a593Smuzhiyun self.write(',') 295*4882a593Smuzhiyun 296*4882a593Smuzhiyun def visit_Delete(self, node): 297*4882a593Smuzhiyun self.newline(node) 298*4882a593Smuzhiyun self.write('del ') 299*4882a593Smuzhiyun for idx, target in enumerate(node): 300*4882a593Smuzhiyun if idx: 301*4882a593Smuzhiyun self.write(', ') 302*4882a593Smuzhiyun self.visit(target) 303*4882a593Smuzhiyun 304*4882a593Smuzhiyun def visit_TryExcept(self, node): 305*4882a593Smuzhiyun self.newline(node) 306*4882a593Smuzhiyun self.write('try:') 307*4882a593Smuzhiyun self.body(node.body) 308*4882a593Smuzhiyun for handler in node.handlers: 309*4882a593Smuzhiyun self.visit(handler) 310*4882a593Smuzhiyun 311*4882a593Smuzhiyun def visit_TryFinally(self, node): 312*4882a593Smuzhiyun self.newline(node) 313*4882a593Smuzhiyun self.write('try:') 314*4882a593Smuzhiyun self.body(node.body) 315*4882a593Smuzhiyun self.newline(node) 316*4882a593Smuzhiyun self.write('finally:') 317*4882a593Smuzhiyun self.body(node.finalbody) 318*4882a593Smuzhiyun 319*4882a593Smuzhiyun def visit_Global(self, node): 320*4882a593Smuzhiyun self.newline(node) 321*4882a593Smuzhiyun self.write('global ' + ', '.join(node.names)) 322*4882a593Smuzhiyun 323*4882a593Smuzhiyun def visit_Nonlocal(self, node): 324*4882a593Smuzhiyun self.newline(node) 325*4882a593Smuzhiyun self.write('nonlocal ' + ', '.join(node.names)) 326*4882a593Smuzhiyun 327*4882a593Smuzhiyun def visit_Return(self, node): 328*4882a593Smuzhiyun self.newline(node) 329*4882a593Smuzhiyun self.write('return ') 330*4882a593Smuzhiyun self.visit(node.value) 331*4882a593Smuzhiyun 332*4882a593Smuzhiyun def visit_Break(self, node): 333*4882a593Smuzhiyun self.newline(node) 334*4882a593Smuzhiyun self.write('break') 335*4882a593Smuzhiyun 336*4882a593Smuzhiyun def visit_Continue(self, node): 337*4882a593Smuzhiyun self.newline(node) 338*4882a593Smuzhiyun self.write('continue') 339*4882a593Smuzhiyun 340*4882a593Smuzhiyun def visit_Raise(self, node): 341*4882a593Smuzhiyun # XXX: Python 2.6 / 3.0 compatibility 342*4882a593Smuzhiyun self.newline(node) 343*4882a593Smuzhiyun self.write('raise') 344*4882a593Smuzhiyun if hasattr(node, 'exc') and node.exc is not None: 345*4882a593Smuzhiyun self.write(' ') 346*4882a593Smuzhiyun self.visit(node.exc) 347*4882a593Smuzhiyun if node.cause is not None: 348*4882a593Smuzhiyun self.write(' from ') 349*4882a593Smuzhiyun self.visit(node.cause) 350*4882a593Smuzhiyun elif hasattr(node, 'type') and node.type is not None: 351*4882a593Smuzhiyun self.visit(node.type) 352*4882a593Smuzhiyun if node.inst is not None: 353*4882a593Smuzhiyun self.write(', ') 354*4882a593Smuzhiyun self.visit(node.inst) 355*4882a593Smuzhiyun if node.tback is not None: 356*4882a593Smuzhiyun self.write(', ') 357*4882a593Smuzhiyun self.visit(node.tback) 358*4882a593Smuzhiyun 359*4882a593Smuzhiyun # Expressions 360*4882a593Smuzhiyun 361*4882a593Smuzhiyun def visit_Attribute(self, node): 362*4882a593Smuzhiyun self.visit(node.value) 363*4882a593Smuzhiyun self.write('.' + node.attr) 364*4882a593Smuzhiyun 365*4882a593Smuzhiyun def visit_Call(self, node): 366*4882a593Smuzhiyun want_comma = [] 367*4882a593Smuzhiyun def write_comma(): 368*4882a593Smuzhiyun if want_comma: 369*4882a593Smuzhiyun self.write(', ') 370*4882a593Smuzhiyun else: 371*4882a593Smuzhiyun want_comma.append(True) 372*4882a593Smuzhiyun 373*4882a593Smuzhiyun self.visit(node.func) 374*4882a593Smuzhiyun self.write('(') 375*4882a593Smuzhiyun for arg in node.args: 376*4882a593Smuzhiyun write_comma() 377*4882a593Smuzhiyun self.visit(arg) 378*4882a593Smuzhiyun for keyword in node.keywords: 379*4882a593Smuzhiyun write_comma() 380*4882a593Smuzhiyun self.write(keyword.arg + '=') 381*4882a593Smuzhiyun self.visit(keyword.value) 382*4882a593Smuzhiyun if hasattr(node, 'starargs') and node.starargs is not None: 383*4882a593Smuzhiyun write_comma() 384*4882a593Smuzhiyun self.write('*') 385*4882a593Smuzhiyun self.visit(node.starargs) 386*4882a593Smuzhiyun if hasattr(node, 'kwargs') and node.kwargs is not None: 387*4882a593Smuzhiyun write_comma() 388*4882a593Smuzhiyun self.write('**') 389*4882a593Smuzhiyun self.visit(node.kwargs) 390*4882a593Smuzhiyun self.write(')') 391*4882a593Smuzhiyun 392*4882a593Smuzhiyun def visit_Name(self, node): 393*4882a593Smuzhiyun self.write(node.id) 394*4882a593Smuzhiyun 395*4882a593Smuzhiyun def visit_Str(self, node): 396*4882a593Smuzhiyun self.write(repr(node.s)) 397*4882a593Smuzhiyun 398*4882a593Smuzhiyun def visit_Bytes(self, node): 399*4882a593Smuzhiyun self.write(repr(node.s)) 400*4882a593Smuzhiyun 401*4882a593Smuzhiyun def visit_Num(self, node): 402*4882a593Smuzhiyun self.write(repr(node.n)) 403*4882a593Smuzhiyun 404*4882a593Smuzhiyun def visit_Constant(self, node): 405*4882a593Smuzhiyun # Python 3.8 deprecated visit_Num(), visit_Str(), visit_Bytes(), 406*4882a593Smuzhiyun # visit_NameConstant() and visit_Ellipsis(). They can be removed once we 407*4882a593Smuzhiyun # require 3.8+. 408*4882a593Smuzhiyun self.write(repr(node.value)) 409*4882a593Smuzhiyun 410*4882a593Smuzhiyun def visit_Tuple(self, node): 411*4882a593Smuzhiyun self.write('(') 412*4882a593Smuzhiyun idx = -1 413*4882a593Smuzhiyun for idx, item in enumerate(node.elts): 414*4882a593Smuzhiyun if idx: 415*4882a593Smuzhiyun self.write(', ') 416*4882a593Smuzhiyun self.visit(item) 417*4882a593Smuzhiyun self.write(idx and ')' or ',)') 418*4882a593Smuzhiyun 419*4882a593Smuzhiyun def sequence_visit(left, right): 420*4882a593Smuzhiyun def visit(self, node): 421*4882a593Smuzhiyun self.write(left) 422*4882a593Smuzhiyun for idx, item in enumerate(node.elts): 423*4882a593Smuzhiyun if idx: 424*4882a593Smuzhiyun self.write(', ') 425*4882a593Smuzhiyun self.visit(item) 426*4882a593Smuzhiyun self.write(right) 427*4882a593Smuzhiyun return visit 428*4882a593Smuzhiyun 429*4882a593Smuzhiyun visit_List = sequence_visit('[', ']') 430*4882a593Smuzhiyun visit_Set = sequence_visit('{', '}') 431*4882a593Smuzhiyun del sequence_visit 432*4882a593Smuzhiyun 433*4882a593Smuzhiyun def visit_Dict(self, node): 434*4882a593Smuzhiyun self.write('{') 435*4882a593Smuzhiyun for idx, (key, value) in enumerate(zip(node.keys, node.values)): 436*4882a593Smuzhiyun if idx: 437*4882a593Smuzhiyun self.write(', ') 438*4882a593Smuzhiyun self.visit(key) 439*4882a593Smuzhiyun self.write(': ') 440*4882a593Smuzhiyun self.visit(value) 441*4882a593Smuzhiyun self.write('}') 442*4882a593Smuzhiyun 443*4882a593Smuzhiyun def visit_BinOp(self, node): 444*4882a593Smuzhiyun self.visit(node.left) 445*4882a593Smuzhiyun self.write(' %s ' % BINOP_SYMBOLS[type(node.op)]) 446*4882a593Smuzhiyun self.visit(node.right) 447*4882a593Smuzhiyun 448*4882a593Smuzhiyun def visit_BoolOp(self, node): 449*4882a593Smuzhiyun self.write('(') 450*4882a593Smuzhiyun for idx, value in enumerate(node.values): 451*4882a593Smuzhiyun if idx: 452*4882a593Smuzhiyun self.write(' %s ' % BOOLOP_SYMBOLS[type(node.op)]) 453*4882a593Smuzhiyun self.visit(value) 454*4882a593Smuzhiyun self.write(')') 455*4882a593Smuzhiyun 456*4882a593Smuzhiyun def visit_Compare(self, node): 457*4882a593Smuzhiyun self.write('(') 458*4882a593Smuzhiyun self.write(node.left) 459*4882a593Smuzhiyun for op, right in zip(node.ops, node.comparators): 460*4882a593Smuzhiyun self.write(' %s %%' % CMPOP_SYMBOLS[type(op)]) 461*4882a593Smuzhiyun self.visit(right) 462*4882a593Smuzhiyun self.write(')') 463*4882a593Smuzhiyun 464*4882a593Smuzhiyun def visit_UnaryOp(self, node): 465*4882a593Smuzhiyun self.write('(') 466*4882a593Smuzhiyun op = UNARYOP_SYMBOLS[type(node.op)] 467*4882a593Smuzhiyun self.write(op) 468*4882a593Smuzhiyun if op == 'not': 469*4882a593Smuzhiyun self.write(' ') 470*4882a593Smuzhiyun self.visit(node.operand) 471*4882a593Smuzhiyun self.write(')') 472*4882a593Smuzhiyun 473*4882a593Smuzhiyun def visit_Subscript(self, node): 474*4882a593Smuzhiyun self.visit(node.value) 475*4882a593Smuzhiyun self.write('[') 476*4882a593Smuzhiyun self.visit(node.slice) 477*4882a593Smuzhiyun self.write(']') 478*4882a593Smuzhiyun 479*4882a593Smuzhiyun def visit_Slice(self, node): 480*4882a593Smuzhiyun if node.lower is not None: 481*4882a593Smuzhiyun self.visit(node.lower) 482*4882a593Smuzhiyun self.write(':') 483*4882a593Smuzhiyun if node.upper is not None: 484*4882a593Smuzhiyun self.visit(node.upper) 485*4882a593Smuzhiyun if node.step is not None: 486*4882a593Smuzhiyun self.write(':') 487*4882a593Smuzhiyun if not (isinstance(node.step, Name) and node.step.id == 'None'): 488*4882a593Smuzhiyun self.visit(node.step) 489*4882a593Smuzhiyun 490*4882a593Smuzhiyun def visit_ExtSlice(self, node): 491*4882a593Smuzhiyun for idx, item in node.dims: 492*4882a593Smuzhiyun if idx: 493*4882a593Smuzhiyun self.write(', ') 494*4882a593Smuzhiyun self.visit(item) 495*4882a593Smuzhiyun 496*4882a593Smuzhiyun def visit_Yield(self, node): 497*4882a593Smuzhiyun self.write('yield ') 498*4882a593Smuzhiyun self.visit(node.value) 499*4882a593Smuzhiyun 500*4882a593Smuzhiyun def visit_Lambda(self, node): 501*4882a593Smuzhiyun self.write('lambda ') 502*4882a593Smuzhiyun self.signature(node.args) 503*4882a593Smuzhiyun self.write(': ') 504*4882a593Smuzhiyun self.visit(node.body) 505*4882a593Smuzhiyun 506*4882a593Smuzhiyun def visit_Ellipsis(self, node): 507*4882a593Smuzhiyun self.write('Ellipsis') 508*4882a593Smuzhiyun 509*4882a593Smuzhiyun def generator_visit(left, right): 510*4882a593Smuzhiyun def visit(self, node): 511*4882a593Smuzhiyun self.write(left) 512*4882a593Smuzhiyun self.visit(node.elt) 513*4882a593Smuzhiyun for comprehension in node.generators: 514*4882a593Smuzhiyun self.visit(comprehension) 515*4882a593Smuzhiyun self.write(right) 516*4882a593Smuzhiyun return visit 517*4882a593Smuzhiyun 518*4882a593Smuzhiyun visit_ListComp = generator_visit('[', ']') 519*4882a593Smuzhiyun visit_GeneratorExp = generator_visit('(', ')') 520*4882a593Smuzhiyun visit_SetComp = generator_visit('{', '}') 521*4882a593Smuzhiyun del generator_visit 522*4882a593Smuzhiyun 523*4882a593Smuzhiyun def visit_DictComp(self, node): 524*4882a593Smuzhiyun self.write('{') 525*4882a593Smuzhiyun self.visit(node.key) 526*4882a593Smuzhiyun self.write(': ') 527*4882a593Smuzhiyun self.visit(node.value) 528*4882a593Smuzhiyun for comprehension in node.generators: 529*4882a593Smuzhiyun self.visit(comprehension) 530*4882a593Smuzhiyun self.write('}') 531*4882a593Smuzhiyun 532*4882a593Smuzhiyun def visit_IfExp(self, node): 533*4882a593Smuzhiyun self.visit(node.body) 534*4882a593Smuzhiyun self.write(' if ') 535*4882a593Smuzhiyun self.visit(node.test) 536*4882a593Smuzhiyun self.write(' else ') 537*4882a593Smuzhiyun self.visit(node.orelse) 538*4882a593Smuzhiyun 539*4882a593Smuzhiyun def visit_Starred(self, node): 540*4882a593Smuzhiyun self.write('*') 541*4882a593Smuzhiyun self.visit(node.value) 542*4882a593Smuzhiyun 543*4882a593Smuzhiyun def visit_Repr(self, node): 544*4882a593Smuzhiyun # XXX: python 2.6 only 545*4882a593Smuzhiyun self.write('`') 546*4882a593Smuzhiyun self.visit(node.value) 547*4882a593Smuzhiyun self.write('`') 548*4882a593Smuzhiyun 549*4882a593Smuzhiyun # Helper Nodes 550*4882a593Smuzhiyun 551*4882a593Smuzhiyun def visit_alias(self, node): 552*4882a593Smuzhiyun self.write(node.name) 553*4882a593Smuzhiyun if node.asname is not None: 554*4882a593Smuzhiyun self.write(' as ' + node.asname) 555*4882a593Smuzhiyun 556*4882a593Smuzhiyun def visit_comprehension(self, node): 557*4882a593Smuzhiyun self.write(' for ') 558*4882a593Smuzhiyun self.visit(node.target) 559*4882a593Smuzhiyun self.write(' in ') 560*4882a593Smuzhiyun self.visit(node.iter) 561*4882a593Smuzhiyun if node.ifs: 562*4882a593Smuzhiyun for if_ in node.ifs: 563*4882a593Smuzhiyun self.write(' if ') 564*4882a593Smuzhiyun self.visit(if_) 565*4882a593Smuzhiyun 566*4882a593Smuzhiyun def visit_excepthandler(self, node): 567*4882a593Smuzhiyun self.newline(node) 568*4882a593Smuzhiyun self.write('except') 569*4882a593Smuzhiyun if node.type is not None: 570*4882a593Smuzhiyun self.write(' ') 571*4882a593Smuzhiyun self.visit(node.type) 572*4882a593Smuzhiyun if node.name is not None: 573*4882a593Smuzhiyun self.write(' as ') 574*4882a593Smuzhiyun self.visit(node.name) 575*4882a593Smuzhiyun self.write(':') 576*4882a593Smuzhiyun self.body(node.body) 577