Changeset 391 for python/trunk/Demo/parser/unparse.py
- Timestamp:
- Mar 19, 2014, 11:31:01 PM (11 years ago)
- Location:
- python/trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
python/trunk
-
Property svn:mergeinfo
set to
/python/vendor/Python-2.7.6 merged eligible /python/vendor/current merged eligible
-
Property svn:mergeinfo
set to
-
python/trunk/Demo/parser/unparse.py
r2 r391 1 1 "Usage: unparse.py <path to source file>" 2 2 import sys 3 import _ast3 import ast 4 4 import cStringIO 5 5 import os 6 7 # Large float and imaginary literals get turned into infinities in the AST. 8 # We unparse those infinities to INFSTR. 9 INFSTR = "1e" + repr(sys.float_info.max_10_exp + 1) 6 10 7 11 def interleave(inter, f, seq): … … 10 14 seq = iter(seq) 11 15 try: 12 f( seq.next())16 f(next(seq)) 13 17 except StopIteration: 14 18 pass … … 21 25 """Methods in this class recursively traverse an AST and 22 26 output source code for the abstract syntax; original formatting 23 is disregar ged. """27 is disregarded. """ 24 28 25 29 def __init__(self, tree, file = sys.stdout): … … 27 31 Print the source for tree to file.""" 28 32 self.f = file 33 self.future_imports = [] 29 34 self._indent = 0 30 35 self.dispatch(tree) 31 print >>self.f,""36 self.f.write("") 32 37 self.f.flush() 33 38 … … 80 85 81 86 def _ImportFrom(self, t): 87 # A from __future__ import may affect unparsing, so record it. 88 if t.module and t.module == '__future__': 89 self.future_imports.extend(n.name for n in t.names) 90 82 91 self.fill("from ") 83 self.write(t.module) 92 self.write("." * t.level) 93 if t.module: 94 self.write(t.module) 84 95 self.write(" import ") 85 96 interleave(lambda: self.write(", "), self.dispatch, t.names) 86 # XXX(jpe) what is level for?87 97 88 98 def _Assign(self, t): … … 116 126 def _Delete(self, t): 117 127 self.fill("del ") 118 self.dispatch(t.targets)128 interleave(lambda: self.write(", "), self.dispatch, t.targets) 119 129 120 130 def _Assert(self, t): … … 187 197 188 198 def _TryFinally(self, t): 189 self.fill("try") 190 self.enter() 191 self.dispatch(t.body) 192 self.leave() 199 if len(t.body) == 1 and isinstance(t.body[0], ast.TryExcept): 200 # try-except-finally 201 self.dispatch(t.body) 202 else: 203 self.fill("try") 204 self.enter() 205 self.dispatch(t.body) 206 self.leave() 193 207 194 208 self.fill("finally") … … 203 217 self.dispatch(t.type) 204 218 if t.name: 205 self.write(" ,")219 self.write(" as ") 206 220 self.dispatch(t.name) 207 221 self.enter() … … 211 225 def _ClassDef(self, t): 212 226 self.write("\n") 227 for deco in t.decorator_list: 228 self.fill("@") 229 self.dispatch(deco) 213 230 self.fill("class "+t.name) 214 231 if t.bases: … … 246 263 self.enter() 247 264 self.dispatch(t.orelse) 248 self.leave 265 self.leave() 249 266 250 267 def _If(self, t): … … 252 269 self.dispatch(t.test) 253 270 self.enter() 254 # XXX elif? 255 self.dispatch(t.body) 256 self.leave() 271 self.dispatch(t.body) 272 self.leave() 273 # collapse nested ifs into equivalent elifs. 274 while (t.orelse and len(t.orelse) == 1 and 275 isinstance(t.orelse[0], ast.If)): 276 t = t.orelse[0] 277 self.fill("elif ") 278 self.dispatch(t.test) 279 self.enter() 280 self.dispatch(t.body) 281 self.leave() 282 # final else 257 283 if t.orelse: 258 284 self.fill("else") … … 271 297 self.enter() 272 298 self.dispatch(t.orelse) 273 self.leave 299 self.leave() 274 300 275 301 def _With(self, t): … … 285 311 # expr 286 312 def _Str(self, tree): 287 self.write(repr(tree.s)) 313 # if from __future__ import unicode_literals is in effect, 314 # then we want to output string literals using a 'b' prefix 315 # and unicode literals with no prefix. 316 if "unicode_literals" not in self.future_imports: 317 self.write(repr(tree.s)) 318 elif isinstance(tree.s, str): 319 self.write("b" + repr(tree.s)) 320 elif isinstance(tree.s, unicode): 321 self.write(repr(tree.s).lstrip("u")) 322 else: 323 assert False, "shouldn't get here" 288 324 289 325 def _Name(self, t): … … 296 332 297 333 def _Num(self, t): 298 self.write(repr(t.n)) 334 repr_n = repr(t.n) 335 # Parenthesize negative numbers, to avoid turning (-1)**2 into -1**2. 336 if repr_n.startswith("-"): 337 self.write("(") 338 # Substitute overflowing decimal literal for AST infinities. 339 self.write(repr_n.replace("inf", INFSTR)) 340 if repr_n.startswith("-"): 341 self.write(")") 299 342 300 343 def _List(self, t): … … 316 359 self.dispatch(gen) 317 360 self.write(")") 361 362 def _SetComp(self, t): 363 self.write("{") 364 self.dispatch(t.elt) 365 for gen in t.generators: 366 self.dispatch(gen) 367 self.write("}") 368 369 def _DictComp(self, t): 370 self.write("{") 371 self.dispatch(t.key) 372 self.write(": ") 373 self.dispatch(t.value) 374 for gen in t.generators: 375 self.dispatch(gen) 376 self.write("}") 318 377 319 378 def _comprehension(self, t): … … 335 394 self.write(")") 336 395 396 def _Set(self, t): 397 assert(t.elts) # should be at least one element 398 self.write("{") 399 interleave(lambda: self.write(", "), self.dispatch, t.elts) 400 self.write("}") 401 337 402 def _Dict(self, t): 338 403 self.write("{") 339 def writem((k, v)): 404 def write_pair(pair): 405 (k, v) = pair 340 406 self.dispatch(k) 341 407 self.write(": ") 342 408 self.dispatch(v) 343 interleave(lambda: self.write(", "), write m, zip(t.keys, t.values))409 interleave(lambda: self.write(", "), write_pair, zip(t.keys, t.values)) 344 410 self.write("}") 345 411 … … 356 422 unop = {"Invert":"~", "Not": "not", "UAdd":"+", "USub":"-"} 357 423 def _UnaryOp(self, t): 424 self.write("(") 358 425 self.write(self.unop[t.op.__class__.__name__]) 359 self.write("(") 360 self.dispatch(t.operand) 426 self.write(" ") 427 # If we're applying unary minus to a number, parenthesize the number. 428 # This is necessary: -2147483648 is different from -(2147483648) on 429 # a 32-bit machine (the first is an int, the second a long), and 430 # -7j is different from -(7j). (The first has real part 0.0, the second 431 # has real part -0.0.) 432 if isinstance(t.op, ast.USub) and isinstance(t.operand, ast.Num): 433 self.write("(") 434 self.dispatch(t.operand) 435 self.write(")") 436 else: 437 self.dispatch(t.operand) 361 438 self.write(")") 362 439 363 440 binop = { "Add":"+", "Sub":"-", "Mult":"*", "Div":"/", "Mod":"%", 364 "LShift":" >>", "RShift":"<<", "BitOr":"|", "BitXor":"^", "BitAnd":"&",441 "LShift":"<<", "RShift":">>", "BitOr":"|", "BitXor":"^", "BitAnd":"&", 365 442 "FloorDiv":"//", "Pow": "**"} 366 443 def _BinOp(self, t): … … 379 456 self.write(" " + self.cmpops[o.__class__.__name__] + " ") 380 457 self.dispatch(e) 381 382 383 boolops = { _ast.And: 'and', _ast.Or: 'or'}458 self.write(")") 459 460 boolops = {ast.And: 'and', ast.Or: 'or'} 384 461 def _BoolOp(self, t): 385 462 self.write("(") … … 390 467 def _Attribute(self,t): 391 468 self.dispatch(t.value) 469 # Special case: 3.__abs__() is a syntax error, so if t.value 470 # is an integer literal then we need to either parenthesize 471 # it or add an extra space to get 3 .__abs__(). 472 if isinstance(t.value, ast.Num) and isinstance(t.value.n, int): 473 self.write(" ") 392 474 self.write(".") 393 475 self.write(t.attr) … … 446 528 def _arguments(self, t): 447 529 first = True 448 nonDef = len(t.args)-len(t.defaults) 449 for a in t.args[0:nonDef]: 450 if first:first = False 451 else: self.write(", ") 452 self.dispatch(a) 453 for a,d in zip(t.args[nonDef:], t.defaults): 530 # normal arguments 531 defaults = [None] * (len(t.args) - len(t.defaults)) + t.defaults 532 for a,d in zip(t.args, defaults): 454 533 if first:first = False 455 534 else: self.write(", ") 456 535 self.dispatch(a), 457 self.write("=") 458 self.dispatch(d) 536 if d: 537 self.write("=") 538 self.dispatch(d) 539 540 # varargs 459 541 if t.vararg: 460 542 if first:first = False 461 543 else: self.write(", ") 462 self.write("*"+t.vararg) 544 self.write("*") 545 self.write(t.vararg) 546 547 # kwargs 463 548 if t.kwarg: 464 549 if first:first = False … … 472 557 473 558 def _Lambda(self, t): 559 self.write("(") 474 560 self.write("lambda ") 475 561 self.dispatch(t.args) 476 562 self.write(": ") 477 563 self.dispatch(t.body) 564 self.write(")") 478 565 479 566 def _alias(self, t): … … 483 570 484 571 def roundtrip(filename, output=sys.stdout): 485 source = open(filename).read() 486 tree = compile(source, filename, "exec", _ast.PyCF_ONLY_AST) 572 with open(filename, "r") as pyfile: 573 source = pyfile.read() 574 tree = compile(source, filename, "exec", ast.PyCF_ONLY_AST) 487 575 Unparser(tree, output) 488 576 … … 493 581 names = [n for n in os.listdir(a) if n.endswith('.py')] 494 582 except OSError: 495 print >> sys.stderr, "Directory not readable: %s" % a583 sys.stderr.write("Directory not readable: %s" % a) 496 584 else: 497 585 for n in names: … … 502 590 try: 503 591 roundtrip(fullname, output) 504 except Exception ,e:592 except Exception as e: 505 593 print ' Failed to compile, exception is %s' % repr(e) 506 594 elif os.path.isdir(fullname):
Note:
See TracChangeset
for help on using the changeset viewer.