]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Simplify StackContext logic and behavior.
authorBen Darnell <ben@bendarnell.com>
Sat, 29 Sep 2012 21:29:22 +0000 (14:29 -0700)
committerBen Darnell <ben@bendarnell.com>
Sat, 29 Sep 2012 21:41:30 +0000 (14:41 -0700)
Previously, there was an optimization to avoid recreating contexts
that were already on the stack.  This optimization rarely mattered
(especially given the movement to run all callbacks through
IOLoop.add_callback), and sometimes caused surprising behavior as
other exception handlers could be inserted between stack contexts that
expected to be adjacent to each other or to the wrapped function.  Now
each wrapped function recreates its full stack of contexts, even if
some of those contexts were already on the stack.

This change allows a use of NullContext in testing.py to be
removed.

tornado/stack_context.py
tornado/testing.py

index 4b490e598cf80e88bde216af8fa799d42c9e4d9f..b0bf108acc6f3003ca496d06f25dc566964771d2 100644 (file)
@@ -70,7 +70,6 @@ from __future__ import absolute_import, division, with_statement
 
 import contextlib
 import functools
-import itertools
 import operator
 import sys
 import threading
@@ -198,31 +197,14 @@ def wrap(fn):
     def wrapped(*args, **kwargs):
         callback, contexts, args = args[0], args[1], args[2:]
 
-        if contexts is _state.contexts:
-            callback(*args, **kwargs)
-            return
-        if not _state.contexts:
-            new_contexts = [cls(arg, active_cell)
-                            for (cls, arg, active_cell) in contexts
-                            if active_cell[0]]
-        # If we're moving down the stack, _state.contexts is a prefix
-        # of contexts.  For each element of contexts not in that prefix,
-        # create a new StackContext object.
-        # If we're moving up the stack (or to an entirely different stack),
-        # _state.contexts will have elements not in contexts.  Use
-        # NullContext to clear the state and then recreate from contexts.
-        elif (len(_state.contexts) > len(contexts) or
-            any(a[1] is not b[1]
-                for a, b in itertools.izip(_state.contexts, contexts))):
-            # contexts have been removed or changed, so start over
-            new_contexts = ([NullContext()] +
-                            [cls(arg, active_cell)
-                             for (cls, arg, active_cell) in contexts
-                             if active_cell[0]])
+        if _state.contexts:
+            new_contexts = [NullContext()]
         else:
-            new_contexts = [cls(arg, active_cell)
-                            for (cls, arg, active_cell) in contexts[len(_state.contexts):]
-                            if active_cell[0]]
+            new_contexts = []
+        if contexts:
+            new_contexts.extend(cls(arg, active_cell)
+                                for (cls, arg, active_cell) in contexts
+                                if active_cell[0])
         if len(new_contexts) > 1:
             with _nested(*new_contexts):
                 callback(*args, **kwargs)
index 5b529a268c9eac88d98d0b532f4687980536053f..f6784116707f5a803bc3272f222e0282e0e7ae41 100644 (file)
@@ -36,7 +36,7 @@ except ImportError:
     netutil = None
     SimpleAsyncHTTPClient = None
 from tornado.log import gen_log
-from tornado.stack_context import StackContext, NullContext
+from tornado.stack_context import StackContext
 from tornado.util import raise_exc_info
 import contextlib
 import logging
@@ -223,11 +223,7 @@ class AsyncTestCase(unittest.TestCase):
                 self.__timeout = self.io_loop.add_timeout(time.time() + timeout, timeout_func)
             while True:
                 self.__running = True
-                with NullContext():
-                    # Wipe out the StackContext that was established in
-                    # self.run() so that all callbacks executed inside the
-                    # IOLoop will re-run it.
-                    self.io_loop.start()
+                self.io_loop.start()
                 if (self.__failure is not None or
                     condition is None or condition()):
                     break