[Python-checkins] python/nondist/peps pep-0343.txt,1.1,1.2

gvanrossum@users.sourceforge.net gvanrossum at users.sourceforge.net
Sat May 14 04:02:42 CEST 2005


Update of /cvsroot/python/python/nondist/peps
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv25715

Modified Files:
	pep-0343.txt 
Log Message:
Don't be wishy-washy about the call to __exit__().

Fix the redirecting_stdout() example (remove the try/finally).


Index: pep-0343.txt
===================================================================
RCS file: /cvsroot/python/python/nondist/peps/pep-0343.txt,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- pep-0343.txt	14 May 2005 00:08:20 -0000	1.1
+++ pep-0343.txt	14 May 2005 02:02:40 -0000	1.2
@@ -46,23 +46,28 @@
     The translation of the above statement is:
 
         abc = EXPR
+        exc = ()  # Or (None, None, None) ?
         try:
-            VAR = abc.__enter__()
-            BLOCK
+            try:
+                VAR = abc.__enter__()
+                BLOCK
+            except:
+                exc = sys.exc_info()
+		raise
         finally:
-            abc.__exit__(*sys.exc_info())  # XXX See below
+            abc.__exit__(exc)
 
     If the "as VAR" part of the syntax is omitted, the "VAR =" part of
     the translation is omitted (but abc.__enter__() is still called).
 
-    The call to abc.__exit__() is only approximated as written.  The
-    actual calling convention is: If the finally-suite was reached
-    through normal completion of BLOCK or through a "non-local goto"
-    (a break, continue or return statement in BLOCK), abc.__exit__()
-    is called without arguments (or perhaps with three None
-    arguments).  If the finally-suite was reached through an exception
-    raised in BLOCK, abc.__exit__() is called with three arguments
-    representing the exception type, value, and traceback.
+    The calling convention for abc.__exit__() is: as follows.  If the
+    finally-suite was reached through normal completion of BLOCK or
+    through a "non-local goto" (a break, continue or return statement
+    in BLOCK), abc.__exit__() is called without arguments (or perhaps
+    with three None arguments?).  If the finally-suite was reached
+    through an exception raised in BLOCK, abc.__exit__() is called
+    with three arguments representing the exception type, value, and
+    traceback.
 
 Optional Generator Decorator
 
@@ -70,41 +75,41 @@
     a generator that yields exactly once to control a do-statement.
     Here's a sketch of such a decorator:
 
-	class Wrapper(object):
-	   def __init__(self, gen):
-	       self.gen = gen
-	       self.state = "initial"
-	   def __enter__(self):
-	       assert self.state == "initial"
-	       self.state = "entered"
-	       try:
-		   return self.gen.next()
-	       except StopIteration:
-		   self.state = "error"
-		   raise RuntimeError("template generator didn't yield")
-	   def __exit__(self, *args):
-	       assert self.state == "entered"
-	       self.state = "exited"
-	       try:
-		   self.gen.next()
-	       except StopIteration:
-		   return
-	       else:
-		   self.state = "error"
-		   raise RuntimeError("template generator didn't stop")
+        class Wrapper(object):
+           def __init__(self, gen):
+               self.gen = gen
+               self.state = "initial"
+           def __enter__(self):
+               assert self.state == "initial"
+               self.state = "entered"
+               try:
+                   return self.gen.next()
+               except StopIteration:
+                   self.state = "error"
+                   raise RuntimeError("template generator didn't yield")
+           def __exit__(self, *args):
+               assert self.state == "entered"
+               self.state = "exited"
+               try:
+                   self.gen.next()
+               except StopIteration:
+                   return
+               else:
+                   self.state = "error"
+                   raise RuntimeError("template generator didn't stop")
 
-	def do_template(func):
-	   def helper(*args, **kwds):
-	       return Wrapper(func(*args, **kwds))
-	   return helper
+        def do_template(func):
+           def helper(*args, **kwds):
+               return Wrapper(func(*args, **kwds))
+           return helper
 
     This decorator could be used as follows:
 
-	@do_template
-	def opening(filename):
-	   f = open(filename) # IOError here is untouched by Wrapper
-	   yield f
-	   f.close() # Ditto for errors here (however unlikely)
+        @do_template
+        def opening(filename):
+           f = open(filename) # IOError here is untouched by Wrapper
+           yield f
+           f.close() # Ditto for errors here (however unlikely)
 
     A robust implementation of such a decorator should be made part of
     the standard library.
@@ -151,14 +156,14 @@
 
         class transactional:
             def __init__(self, db):
-	        self.db = db
+                self.db = db
             def __enter__(self):
                 pass
-	    def __exit__(self, *args):
-	        if args and args[0] is not None:
-		    self.db.rollback()
-		else:
-		    self.db.commit()
+            def __exit__(self, *args):
+                if args and args[0] is not None:
+                    self.db.rollback()
+                else:
+                    self.db.commit()
 
     4. Example 1 rewritten without a generator:
 
@@ -166,9 +171,9 @@
            def __init__(self, lock):
                self.lock = lock
            def __enter__(self):
-	       self.lock.acquire()
+               self.lock.acquire()
            def __exit__(self, *args):
-	       self.lock.release()
+               self.lock.release()
 
        (This example is easily modified to implement the other
        examples; it shows how much simpler generators are for the same
@@ -179,11 +184,9 @@
         @do_template
         def redirecting_stdout(new_stdout):
             save_stdout = sys.stdout
-            try:
-                sys.stdout = new_stdout
-                yield None
-            finally:
-                sys.stdout = save_stdout
+            sys.stdout = new_stdout
+            yield None
+            sys.stdout = save_stdout
 
        Used as follows:
 
@@ -200,7 +203,7 @@
             except IOError, err:
                 yield None, err
             else:
-	        yield f, None
+                yield f, None
                 f.close()
 
        Used as follows:



More information about the Python-checkins mailing list