]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Use our own copy of contextlib.nested (which no longer exists in py3)
authorBen Darnell <ben@bendarnell.com>
Thu, 24 Feb 2011 23:22:05 +0000 (15:22 -0800)
committerBen Darnell <ben@bendarnell.com>
Thu, 24 Feb 2011 23:22:05 +0000 (15:22 -0800)
tornado/stack_context.py

index 51d091ccdf2a294812f53ad59c4ae3260cf621ad..b2e41815806c225897e958013805836f1f7cf0f9 100644 (file)
@@ -52,6 +52,7 @@ import contextlib
 import functools
 import itertools
 import logging
+import sys
 import threading
 
 class _State(threading.local):
@@ -164,7 +165,7 @@ def wrap(fn):
             new_contexts = [cls(arg)
                             for (cls, arg) in contexts[len(_state.contexts):]]
         if len(new_contexts) > 1:
-            with contextlib.nested(*new_contexts):
+            with _nested(*new_contexts):
                 callback(*args, **kwargs)
         elif new_contexts:
             with new_contexts[0]:
@@ -178,3 +179,38 @@ def wrap(fn):
     result.stack_context_wrapped = True
     return result
 
+@contextlib.contextmanager
+def _nested(*managers):
+    """Support multiple context managers in a single with-statement.
+
+    Copied from the python 2.6 standard library.  It's no longer present
+    in python 3 because the with statement natively supports multiple
+    context managers, but that doesn't help if the list of context
+    managers is not known until runtime.
+    """
+    exits = []
+    vars = []
+    exc = (None, None, None)
+    try:
+        for mgr in managers:
+            exit = mgr.__exit__
+            enter = mgr.__enter__
+            vars.append(enter())
+            exits.append(exit)
+        yield vars
+    except:
+        exc = sys.exc_info()
+    finally:
+        while exits:
+            exit = exits.pop()
+            try:
+                if exit(*exc):
+                    exc = (None, None, None)
+            except:
+                exc = sys.exc_info()
+        if exc != (None, None, None):
+            # Don't rely on sys.exc_info() still containing
+            # the right information. Another exception may
+            # have been raised and caught by an exit method
+            raise exc[0], exc[1], exc[2]
+