[Python-checkins] r82347 - in python/branches/py3k/Demo/parser: test_unparse.py unparse.py

mark.dickinson python-checkins at python.org
Mon Jun 28 23:14:17 CEST 2010


Author: mark.dickinson
Date: Mon Jun 28 23:14:17 2010
New Revision: 82347

Log:
Update Demo/parser/unparse.py to current Python 3.x syntax.  Additions:
 - relative imports
 - keyword-only arguments
 - function annotations
 - class decorators
 - raise ... from ...
 - except ... as ...
 - nonlocal
 - bytes literals
 - set literals
 - set comprehensions
 - dict comprehensions
Removals:
 - print statement.

Some of this should be backported to 2.x.



Modified:
   python/branches/py3k/Demo/parser/test_unparse.py
   python/branches/py3k/Demo/parser/unparse.py

Modified: python/branches/py3k/Demo/parser/test_unparse.py
==============================================================================
--- python/branches/py3k/Demo/parser/test_unparse.py	(original)
+++ python/branches/py3k/Demo/parser/test_unparse.py	Mon Jun 28 23:14:17 2010
@@ -6,7 +6,7 @@
 import _ast
 import unparse
 
-forelse = """\
+for_else = """\
 def f():
     for x in range(10):
         break
@@ -15,7 +15,7 @@
     z = 3
 """
 
-whileelse = """\
+while_else = """\
 def g():
     while True:
         break
@@ -24,6 +24,37 @@
     z = 3
 """
 
+relative_import = """\
+from . import fred
+from .. import barney
+from .australia import shrimp as prawns
+"""
+
+nonlocal_ex = """\
+def f():
+    x = 1
+    def g():
+        nonlocal x
+        x = 2
+        y = 7
+        def h():
+            nonlocal x, y
+"""
+
+# also acts as test for 'except ... as ...'
+raise_from = """\
+try:
+    1 / 0
+except ZeroDivisionError as e:
+    raise ArithmeticError from e
+"""
+
+class_decorator = """\
+ at f1(arg)
+ at f2
+class Foo: pass
+"""
+
 class UnparseTestCase(unittest.TestCase):
     # Tests for specific bugs found in earlier versions of unparse
 
@@ -43,10 +74,10 @@
         self.check_roundtrip("13 >> 7")
 
     def test_for_else(self):
-        self.check_roundtrip(forelse)
+        self.check_roundtrip(for_else)
 
     def test_while_else(self):
-        self.check_roundtrip(whileelse)
+        self.check_roundtrip(while_else)
 
     def test_unary_parens(self):
         self.check_roundtrip("(-1)**7")
@@ -57,6 +88,50 @@
         self.check_roundtrip("1 < 4 <= 5")
         self.check_roundtrip("a is b is c is not d")
 
+    def test_function_arguments(self):
+        self.check_roundtrip("def f(): pass")
+        self.check_roundtrip("def f(a): pass")
+        self.check_roundtrip("def f(b = 2): pass")
+        self.check_roundtrip("def f(a, b): pass")
+        self.check_roundtrip("def f(a, b = 2): pass")
+        self.check_roundtrip("def f(a = 5, b = 2): pass")
+        self.check_roundtrip("def f(*, a = 1, b = 2): pass")
+        self.check_roundtrip("def f(*, a = 1, b): pass")
+        self.check_roundtrip("def f(*, a, b = 2): pass")
+        self.check_roundtrip("def f(a, b = None, *, c, **kwds): pass")
+        self.check_roundtrip("def f(a=2, *args, c=5, d, **kwds): pass")
+        self.check_roundtrip("def f(*args, **kwargs): pass")
+
+    def test_relative_import(self):
+        self.check_roundtrip(relative_import)
+
+    def test_nonlocal(self):
+        self.check_roundtrip(nonlocal_ex)
+
+    def test_raise_from(self):
+        self.check_roundtrip(raise_from)
+
+    def test_bytes(self):
+        self.check_roundtrip("b'123'")
+
+    def test_annotations(self):
+        self.check_roundtrip("def f(a : int): pass")
+        self.check_roundtrip("def f(a: int = 5): pass")
+        self.check_roundtrip("def f(*args: [int]): pass")
+        self.check_roundtrip("def f(**kwargs: dict): pass")
+        self.check_roundtrip("def f() -> None: pass")
+
+    def test_set_literal(self):
+        self.check_roundtrip("{'a', 'b', 'c'}")
+
+    def test_set_comprehension(self):
+        self.check_roundtrip("{x for x in range(5)}")
+
+    def test_dict_comprehension(self):
+        self.check_roundtrip("{x: x*x for x in range(10)}")
+
+    def test_class_decorators(self):
+        self.check_roundtrip(class_decorator)
 
 def test_main():
     test.support.run_unittest(UnparseTestCase)

Modified: python/branches/py3k/Demo/parser/unparse.py
==============================================================================
--- python/branches/py3k/Demo/parser/unparse.py	(original)
+++ python/branches/py3k/Demo/parser/unparse.py	Mon Jun 28 23:14:17 2010
@@ -1,6 +1,6 @@
 "Usage: unparse.py <path to source file>"
 import sys
-import _ast
+import ast
 import io
 import os
 
@@ -20,7 +20,7 @@
 class Unparser:
     """Methods in this class recursively traverse an AST and
     output source code for the abstract syntax; original formatting
-    is disregarged. """
+    is disregarded. """
 
     def __init__(self, tree, file = sys.stdout):
         """Unparser(tree, file=sys.stdout) -> None.
@@ -80,10 +80,11 @@
 
     def _ImportFrom(self, t):
         self.fill("from ")
-        self.write(t.module)
+        self.write("." * t.level)
+        if t.module:
+            self.write(t.module)
         self.write(" import ")
         interleave(lambda: self.write(", "), self.dispatch, t.names)
-        # XXX(jpe) what is level for?
 
     def _Assign(self, t):
         self.fill()
@@ -124,24 +125,14 @@
             self.write(", ")
             self.dispatch(t.msg)
 
-    def _Print(self, t):
-        self.fill("print ")
-        do_comma = False
-        if t.dest:
-            self.write(">>")
-            self.dispatch(t.dest)
-            do_comma = True
-        for e in t.values:
-            if do_comma:self.write(", ")
-            else:do_comma=True
-            self.dispatch(e)
-        if not t.nl:
-            self.write(",")
-
     def _Global(self, t):
         self.fill("global ")
         interleave(lambda: self.write(", "), self.write, t.names)
 
+    def _Nonlocal(self, t):
+        self.fill("nonlocal ")
+        interleave(lambda: self.write(", "), self.write, t.names)
+
     def _Yield(self, t):
         self.write("(")
         self.write("yield")
@@ -151,15 +142,15 @@
         self.write(")")
 
     def _Raise(self, t):
-        self.fill('raise ')
-        if t.type:
-            self.dispatch(t.type)
-        if t.inst:
-            self.write(", ")
-            self.dispatch(t.inst)
-        if t.tback:
-            self.write(", ")
-            self.dispatch(t.tback)
+        self.fill("raise")
+        if not t.exc:
+            assert not t.cause
+            return
+        self.write(" ")
+        self.dispatch(t.exc)
+        if t.cause:
+            self.write(" from ")
+            self.dispatch(t.cause)
 
     def _TryExcept(self, t):
         self.fill("try")
@@ -192,21 +183,40 @@
             self.write(" ")
             self.dispatch(t.type)
         if t.name:
-            self.write(", ")
-            self.dispatch(t.name)
+            self.write(" as ")
+            self.write(t.name)
         self.enter()
         self.dispatch(t.body)
         self.leave()
 
     def _ClassDef(self, t):
         self.write("\n")
+        for deco in t.decorator_list:
+            self.fill("@")
+            self.dispatch(deco)
         self.fill("class "+t.name)
-        if t.bases:
-            self.write("(")
-            for a in t.bases:
-                self.dispatch(a)
-                self.write(", ")
-            self.write(")")
+        self.write("(")
+        comma = False
+        for e in t.bases:
+            if comma: self.write(", ")
+            else: comma = True
+            self.dispatch(e)
+        for e in t.keywords:
+            if comma: self.write(", ")
+            else: comma = True
+            self.dispatch(e)
+        if t.starargs:
+            if comma: self.write(", ")
+            else: comma = True
+            self.write("*")
+            self.dispatch(t.starargs)
+        if t.kwargs:
+            if comma: self.write(", ")
+            else: comma = True
+            self.write("*")
+            self.dispatch(t.kwargs)
+        self.write(")")
+
         self.enter()
         self.dispatch(t.body)
         self.leave()
@@ -219,6 +229,9 @@
         self.fill("def "+t.name + "(")
         self.dispatch(t.args)
         self.write(")")
+        if t.returns:
+            self.write(" -> ")
+            self.dispatch(t.returns)
         self.enter()
         self.dispatch(t.body)
         self.leave()
@@ -273,6 +286,9 @@
         self.leave()
 
     # expr
+    def _Bytes(self, t):
+        self.write(repr(t.s))
+
     def _Str(self, tree):
         self.write(repr(tree.s))
 
@@ -294,7 +310,7 @@
             self.write(strnum)
             self.write(")")
         else:
-            self.write(repr(t.n))
+            self.write(strnum)
 
     def _List(self, t):
         self.write("[")
@@ -315,6 +331,22 @@
             self.dispatch(gen)
         self.write(")")
 
+    def _SetComp(self, t):
+        self.write("{")
+        self.dispatch(t.elt)
+        for gen in t.generators:
+            self.dispatch(gen)
+        self.write("}")
+
+    def _DictComp(self, t):
+        self.write("{")
+        self.dispatch(t.key)
+        self.write(": ")
+        self.dispatch(t.value)
+        for gen in t.generators:
+            self.dispatch(gen)
+        self.write("}")
+
     def _comprehension(self, t):
         self.write(" for ")
         self.dispatch(t.target)
@@ -333,14 +365,20 @@
         self.dispatch(t.orelse)
         self.write(")")
 
+    def _Set(self, t):
+        assert(t.elts) # should be at least one element
+        self.write("{")
+        interleave(lambda: self.write(", "), self.dispatch, t.elts)
+        self.write("}")
+
     def _Dict(self, t):
         self.write("{")
-        def writem(xxx_todo_changeme):
-            (k, v) = xxx_todo_changeme
+        def write_pair(pair):
+            (k, v) = pair
             self.dispatch(k)
             self.write(": ")
             self.dispatch(v)
-        interleave(lambda: self.write(", "), writem, zip(t.keys, t.values))
+        interleave(lambda: self.write(", "), write_pair, zip(t.keys, t.values))
         self.write("}")
 
     def _Tuple(self, t):
@@ -381,7 +419,7 @@
             self.dispatch(e)
         self.write(")")
 
-    boolops = {_ast.And: 'and', _ast.Or: 'or'}
+    boolops = {ast.And: 'and', ast.Or: 'or'}
     def _BoolOp(self, t):
         self.write("(")
         s = " %s " % self.boolops[t.op.__class__]
@@ -443,28 +481,55 @@
     def _ExtSlice(self, t):
         interleave(lambda: self.write(', '), self.dispatch, t.dims)
 
+    # argument
+    def _arg(self, t):
+        self.write(t.arg)
+        if t.annotation:
+            self.write(": ")
+            self.dispatch(t.annotation)
+
     # others
     def _arguments(self, t):
         first = True
-        nonDef = len(t.args)-len(t.defaults)
-        for a in t.args[0:nonDef]:
+        # normal arguments
+        defaults = [None] * (len(t.args) - len(t.defaults)) + t.defaults
+        for a, d in zip(t.args, defaults):
             if first:first = False
             else: self.write(", ")
             self.dispatch(a)
-        for a,d in zip(t.args[nonDef:], t.defaults):
-            if first:first = False
-            else: self.write(", ")
-            self.dispatch(a),
-            self.write("=")
-            self.dispatch(d)
-        if t.vararg:
+            if d:
+                self.write("=")
+                self.dispatch(d)
+
+        # varargs, or bare '*' if no varargs but keyword-only arguments present
+        if t.vararg or t.kwonlyargs:
             if first:first = False
             else: self.write(", ")
-            self.write("*"+t.vararg)
+            self.write("*")
+            if t.vararg:
+                self.write(t.vararg)
+                if t.varargannotation:
+                    self.write(": ")
+                    self.dispatch(t.varargannotation)
+
+        # keyword-only arguments
+        if t.kwonlyargs:
+            for a, d in zip(t.kwonlyargs, t.kw_defaults):
+                if first:first = False
+                else: self.write(", ")
+                self.dispatch(a),
+                if d:
+                    self.write("=")
+                    self.dispatch(d)
+
+        # kwargs
         if t.kwarg:
             if first:first = False
             else: self.write(", ")
             self.write("**"+t.kwarg)
+            if t.kwargannotation:
+                self.write(": ")
+                self.dispatch(t.kwargannotation)
 
     def _keyword(self, t):
         self.write(t.arg)


More information about the Python-checkins mailing list