]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
concurrent: Introduce future_set_exc_info function
authorBen Darnell <ben@bendarnell.com>
Mon, 5 Jun 2017 00:27:30 +0000 (20:27 -0400)
committerBen Darnell <ben@bendarnell.com>
Sun, 5 Nov 2017 16:17:50 +0000 (11:17 -0500)
This function is equivalent to future.set_exc_info for TracebackFuture
but also falls back to set_exception for other Futures.

tornado/auth.py
tornado/concurrent.py
tornado/gen.py
tornado/ioloop.py
tornado/platform/twisted.py

index f02d2898085f93f4087c2ecefc288cd6bbf8900f..93f771bc4bb42f5fd262130e70e7a20925446da8 100644 (file)
@@ -75,7 +75,7 @@ import hmac
 import time
 import uuid
 
-from tornado.concurrent import TracebackFuture, return_future, chain_future
+from tornado.concurrent import TracebackFuture, return_future, chain_future, future_set_exc_info
 from tornado import gen
 from tornado import httpclient
 from tornado import escape
@@ -127,7 +127,7 @@ def _auth_return_future(f):
             if future.done():
                 return False
             else:
-                future.set_exc_info((typ, value, tb))
+                future_set_exc_info(future, (typ, value, tb))
                 return True
         with ExceptionStackContext(handle_exception):
             f(*args, **kwargs)
index b1bcc56e2cf9a06c72610198f4e6b8c93838a14c..08c0e0b754a533d1d9aa6b348d78cc018c4778da 100644 (file)
@@ -362,7 +362,7 @@ class DummyExecutor(object):
         try:
             future.set_result(fn(*args, **kwargs))
         except Exception:
-            future.set_exc_info(sys.exc_info())
+            future_set_exc_info(future, sys.exc_info())
         return future
 
     def shutdown(self, wait=True):
@@ -466,7 +466,7 @@ def return_future(f):
             args, kwargs)
 
         def handle_error(typ, value, tb):
-            future.set_exc_info((typ, value, tb))
+            future_set_exc_info(future, (typ, value, tb))
             return True
         exc_info = None
         with ExceptionStackContext(handle_error):
@@ -513,12 +513,27 @@ def chain_future(a, b):
         assert future is a
         if b.done():
             return
-        if (isinstance(a, TracebackFuture) and
-                isinstance(b, TracebackFuture) and
+        if (hasattr(a, 'exc_info') and
                 a.exc_info() is not None):
-            b.set_exc_info(a.exc_info())
+            future_set_exc_info(b, a.exc_info())
         elif a.exception() is not None:
             b.set_exception(a.exception())
         else:
             b.set_result(a.result())
     a.add_done_callback(copy)
+
+
+def future_set_exc_info(future, exc_info):
+    """Set the given ``exc_info`` as the `Future`'s exception.
+
+    Understands both `asyncio.Future` and Tornado's extensions to
+    enable better tracebacks on Python 2.
+
+    .. versionadded:: 5.0
+    """
+    if hasattr(future, 'set_exc_info'):
+        # Tornado's Future
+        future.set_exc_info(exc_info)
+    else:
+        # asyncio.Future
+        future.set_exception(exc_info[1])
index 62fea303bc6ad33db3a665f56e05f63d357423e6..7368cb67c8d62e7b392d1e8c2a99b8ccd7e208ed 100644 (file)
@@ -85,7 +85,7 @@ import textwrap
 import types
 import weakref
 
-from tornado.concurrent import Future, TracebackFuture, is_future, chain_future
+from tornado.concurrent import Future, TracebackFuture, is_future, chain_future, future_set_exc_info
 from tornado.ioloop import IOLoop
 from tornado.log import app_log
 from tornado import stack_context
@@ -289,7 +289,7 @@ def _make_coroutine_wrapper(func, replace_callback):
         except (Return, StopIteration) as e:
             result = _value_from_stopiteration(e)
         except Exception:
-            future.set_exc_info(sys.exc_info())
+            future_set_exc_info(future, sys.exc_info())
             return future
         else:
             if isinstance(result, GeneratorType):
@@ -310,7 +310,7 @@ def _make_coroutine_wrapper(func, replace_callback):
                 except (StopIteration, Return) as e:
                     future.set_result(_value_from_stopiteration(e))
                 except Exception:
-                    future.set_exc_info(sys.exc_info())
+                    future_set_exc_info(future, sys.exc_info())
                 else:
                     _futures_to_runners[future] = Runner(result, future, yielded)
                 yielded = None
@@ -606,7 +606,7 @@ def Task(func, *args, **kwargs):
     def handle_exception(typ, value, tb):
         if future.done():
             return False
-        future.set_exc_info((typ, value, tb))
+        future_set_exc_info(future, (typ, value, tb))
         return True
 
     def set_result(result):
@@ -827,7 +827,7 @@ def multi_future(children, quiet_exceptions=()):
                             app_log.error("Multiple exceptions in yield list",
                                           exc_info=True)
                     else:
-                        future.set_exc_info(sys.exc_info())
+                        future_set_exc_info(future, sys.exc_info())
             if not future.done():
                 if keys is not None:
                     future.set_result(dict(zip(keys, result_list)))
@@ -1019,7 +1019,7 @@ class Runner(object):
             try:
                 self.future.set_result(self.yield_point.get_result())
             except:
-                self.future.set_exc_info(sys.exc_info())
+                future_set_exc_info(self.future, sys.exc_info())
             self.yield_point = None
             self.run()
 
@@ -1085,7 +1085,7 @@ class Runner(object):
                 except Exception:
                     self.finished = True
                     self.future = _null_future
-                    self.result_future.set_exc_info(sys.exc_info())
+                    future_set_exc_info(self.result_future, sys.exc_info())
                     self.result_future = None
                     self._deactivate_stack_context()
                     return
@@ -1115,8 +1115,8 @@ class Runner(object):
                     else:
                         self.yield_point = yielded
                 except Exception:
-                    self.future = TracebackFuture()
-                    self.future.set_exc_info(sys.exc_info())
+                    self.future = Future()
+                    future_set_exc_info(self.future, sys.exc_info())
 
             if self.stack_context_deactivate is None:
                 # Start a stack context if this is the first
@@ -1136,8 +1136,8 @@ class Runner(object):
             try:
                 self.future = convert_yielded(yielded)
             except BadYieldError:
-                self.future = TracebackFuture()
-                self.future.set_exc_info(sys.exc_info())
+                self.future = Future()
+                future_set_exc_info(self.future, sys.exc_info())
 
         if not self.future.done() or self.future is moment:
             def inner(f):
@@ -1155,8 +1155,8 @@ class Runner(object):
 
     def handle_exception(self, typ, value, tb):
         if not self.running and not self.finished:
-            self.future = TracebackFuture()
-            self.future.set_exc_info((typ, value, tb))
+            self.future = Future()
+            future_set_exc_info(self.future, (typ, value, tb))
             self.run()
             return True
         else:
index 481daeeb34df3395b9c50b5a5027f4eb1a5e3793..e64009df6d1d476df7043ff95f9811bb10e196ff 100644 (file)
@@ -44,7 +44,7 @@ import time
 import traceback
 import math
 
-from tornado.concurrent import TracebackFuture, is_future, chain_future
+from tornado.concurrent import TracebackFuture, is_future, chain_future, future_set_exc_info
 from tornado.log import app_log, gen_log
 from tornado.platform.auto import set_close_exec, Waker
 from tornado import stack_context
@@ -482,7 +482,7 @@ class IOLoop(Configurable):
                     result = convert_yielded(result)
             except Exception:
                 future_cell[0] = TracebackFuture()
-                future_cell[0].set_exc_info(sys.exc_info())
+                future_set_exc_info(future_cell[0], sys.exc_info())
             else:
                 if is_future(result):
                     future_cell[0] = result
index 7c337e8a59e042c16962eb449cc9d1130bf80f86..613e7b6dccad65bba217d05155ee1418206ac673 100644 (file)
@@ -42,7 +42,7 @@ import twisted.names.resolve  # type: ignore
 
 from zope.interface import implementer  # type: ignore
 
-from tornado.concurrent import Future
+from tornado.concurrent import Future, future_set_exc_info
 from tornado.escape import utf8
 from tornado import gen
 import tornado.ioloop
@@ -585,6 +585,6 @@ if hasattr(gen.convert_yielded, 'register'):
                 # Should never happen, but just in case
                 raise Exception("errback called without error")
             except:
-                f.set_exc_info(sys.exc_info())
+                future_set_exc_info(f, sys.exc_info())
         d.addCallbacks(f.set_result, errback)
         return f