[Python-checkins] r42697 - peps/trunk/pep-0343.txt

guido.van.rossum python-checkins at python.org
Tue Feb 28 23:49:19 CET 2006


Author: guido.van.rossum
Date: Tue Feb 28 23:49:15 2006
New Revision: 42697

Modified:
   peps/trunk/pep-0343.txt
Log:
Fix two examples that were broken by the new semantics.


Modified: peps/trunk/pep-0343.txt
==============================================================================
--- peps/trunk/pep-0343.txt	(original)
+++ peps/trunk/pep-0343.txt	Tue Feb 28 23:49:15 2006
@@ -576,7 +576,7 @@
     The tense used in the names of the example context managers is not
     arbitrary. Past tense ("-ed") is used when the name refers to an
     action which is done in the __enter__ method and undone in the
-    __exit__ method. Progressive tense  ("-ing") is used when the name
+    __exit__ method. Progressive tense ("-ing") is used when the name
     refers to an action which is to be done in the __exit__ method.
 
     1. A template for ensuring that a lock, acquired at the start of a
@@ -643,6 +643,8 @@
                self.lock.acquire()
            def __exit__(self, type, value, tb):
                self.lock.release()
+               if type is not None:
+                   raise type, value, tb
 
        (This example is easily modified to implement the other
        relatively stateless examples; it shows that it is easy to avoid
@@ -769,34 +771,35 @@
                  # General Decimal Arithmetic Specification
              return +s # Convert result to normal context
 
-    10. A generic "object-closing" template:
+     10. A generic "object-closing" template:
 
-        @contextmanager
-        def closing(obj):
-            try:
-                yield obj
-            finally:
-                try:
-                    close = obj.close
-                except AttributeError:
-                    pass
-                else:
-                    close()
-
-        This can be used to deterministically close anything with a
-        close method, be it file, generator, or something else. It can
-        even be used when the object isn't guaranteed to require
-        closing (e.g., a function that accepts an arbitrary iterable):
-
-        # emulate opening():
-        with closing(open("argument.txt")) as contradiction:
-           for line in contradiction:
-               print line
-
-        # deterministically finalize an iterator:
-        with closing(iter(data_source)) as data:
-           for datum in data:
-               process(datum)
+         @contextmanager
+         def closing(obj):
+             try:
+                 yield obj
+             finally:
+                 try:
+                     close = obj.close
+                 except AttributeError:
+                     pass
+                 else:
+                     close()
+
+         This can be used to deterministically close anything with a
+         close method, be it file, generator, or something else. It
+         can even be used when the object isn't guaranteed to require
+         closing (e.g., a function that accepts an arbitrary
+         iterable):
+
+         # emulate opening():
+         with closing(open("argument.txt")) as contradiction:
+            for line in contradiction:
+                print line
+
+         # deterministically finalize an iterator:
+         with closing(iter(data_source)) as data:
+            for datum in data:
+                process(datum)
 
      11. Native contexts for objects with acquire/release methods:
 
@@ -807,7 +810,7 @@
          def released(self):
              return unlocked(self)
 
-        Sample usage:
+         Sample usage:
 
          with my_lock:
              # Operations with the lock held
@@ -820,54 +823,43 @@
          supplied contexts from left-to-right to avoid excessive
          indentation:
 
-         class nested(object):
-             def __init__(self, *contexts):
-                 self.contexts = contexts
-                 self.entered = None
-
-             def __context__(self):
-                 return self
-
-             def __enter__(self):
-                 if self.entered is not None:
-                     raise RuntimeError("Context is not reentrant")
-                 self.entered = deque()
-                 vars = []
+         @contextmanager
+         def nested(*contexts):
+             exits = []
+             vars = []
+             exc = (None, None, None)
+             try:
                  try:
-                     for context in self.contexts:
+                     for context in contexts:
                          mgr = context.__context__()
-                         vars.append(mgr.__enter__())
-                         self.entered.appendleft(mgr)
+                         exit = mgr.__exit__
+                         enter = mgr.__enter__
+                         vars.append(enter())
+                         exits.append(exit)
+                     yield vars
                  except:
-                     self.__exit__(*sys.exc_info())
-                     raise
-                 return vars
-
-             def __exit__(self, *exc_info):
-                 # Behave like nested with statements
-                 # first in, last out
-                 # New exceptions override old ones
-                 ex = exc_info
-                 for mgr in self.entered:
+                     exc = sys.exc_info()
+             finally:
+                 while exits:
+                     exit = exits.pop()
                      try:
-                         mgr.__exit__(*ex)
+                         exit(*exc)
                      except:
-                         ex = sys.exc_info()
-                 self.entered = None
-                 if ex is not exc_info:
-                     raise ex[0], ex[1], ex[2]
+                         exc = sys.exc_info()
+                 if exc != (None, None, None):
+                     raise
 
-        Sample usage:
+         Sample usage:
 
-          with nested(a, b, c) as (x, y, z):
-              # Perform operation
+         with nested(a, b, c) as (x, y, z):
+             # Perform operation
 
-        Is equivalent to:
+         Is equivalent to:
 
-           with a as x:
-               with b as y:
-                   with c as z:
-                       # Perform operation
+          with a as x:
+              with b as y:
+                  with c as z:
+                      # Perform operation
 
 
 Reference Implementation
@@ -911,6 +903,8 @@
     [12]
     http://sourceforge.net/tracker/index.php?func=detail&aid=1223381&group_id=5470&atid=305470
 
+    [13]
+    http://mail.python.org/pipermail/python-dev/2006-February/061903.html
 
 Copyright
 


More information about the Python-checkins mailing list