From: Ben Darnell Date: Mon, 17 Feb 2014 01:29:37 +0000 (-0500) Subject: Fold TracebackFuture into Future. X-Git-Tag: v4.0.0b1~125 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8e07f3d86524b5f0fb5c3f4057085f3dd9c83b95;p=thirdparty%2Ftornado.git Fold TracebackFuture into Future. Since it is no longer possible for TracebackFuture to modify concurrent.futures.Future instead, there is no need for separate classes. Removing the subclass speeds things up a bit by removing a level of indirection. Also microoptimized a few methods of Future. --- diff --git a/tornado/concurrent.py b/tornado/concurrent.py index a1b2d57c8..ab7b65c3a 100644 --- a/tornado/concurrent.py +++ b/tornado/concurrent.py @@ -41,10 +41,23 @@ class ReturnValueIgnoredError(Exception): class Future(object): + """Placeholder for an asynchronous result. + + Similar to `concurrent.futures.Future`, but not thread-safe (and + therefore faster for use with single-threaded event loops. + + In addition to ``exception`` and ``set_exception``, methods ``exc_info`` + and ``set_exc_info`` are supported to capture tracebacks in Python 2. + The traceback is automatically available in Python 3, but in the + Python 2 futures backport this information is discarded. + This functionality was previously available in a separate class + ``TracebackFuture``, which is now a deprecated alias for this class. + """ def __init__(self): self._done = False self._result = None self._exception = None + self._exc_info = None self._callbacks = [] def cancel(self): @@ -60,16 +73,20 @@ class Future(object): return self._done def result(self, timeout=None): - self._check_done() - if self._exception: + if self._result is not None: + return self._result + if self._exc_info is not None: + raise_exc_info(self._exc_info) + elif self._exception is not None: raise self._exception + self._check_done() return self._result def exception(self, timeout=None): - self._check_done() - if self._exception: + if self._exception is not None: return self._exception else: + self._check_done() return None def add_done_callback(self, fn): @@ -86,6 +103,16 @@ class Future(object): self._exception = exception self._set_done() + def exc_info(self): + return self._exc_info + + def set_exc_info(self, exc_info): + """Traceback-aware replacement for + `~concurrent.futures.Future.set_exception`. + """ + self._exc_info = exc_info + self.set_exception(exc_info[1]) + def _check_done(self): if not self._done: raise Exception("DummyFuture does not support blocking for results") @@ -97,6 +124,7 @@ class Future(object): cb(self) self._callbacks = None +TracebackFuture = Future if futures is None: FUTURES = Future @@ -106,33 +134,6 @@ else: def is_future(x): return isinstance(x, FUTURES) -class TracebackFuture(Future): - """Subclass of `Future` which can store a traceback with - exceptions. - - The traceback is automatically available in Python 3, but in the - Python 2 futures backport this information is discarded. - """ - def __init__(self): - super(TracebackFuture, self).__init__() - self.__exc_info = None - - def exc_info(self): - return self.__exc_info - - def set_exc_info(self, exc_info): - """Traceback-aware replacement for - `~concurrent.futures.Future.set_exception`. - """ - self.__exc_info = exc_info - self.set_exception(exc_info[1]) - - def result(self, timeout=None): - if self.__exc_info is not None: - raise_exc_info(self.__exc_info) - else: - return super(TracebackFuture, self).result(timeout=timeout) - class DummyExecutor(object): def submit(self, fn, *args, **kwargs):