Extract extract_result
This commit is contained in:
30
testtools/_deferred.py
Normal file
30
testtools/_deferred.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# Copyright (c) testtools developers. See LICENSE for details.
|
||||
|
||||
"""Utilities for Deferreds."""
|
||||
|
||||
|
||||
class DeferredNotFired(Exception):
|
||||
"""Raised when we extract a result from a Deferred that's not fired yet."""
|
||||
|
||||
|
||||
def extract_result(deferred):
|
||||
"""Extract the result from a fired deferred.
|
||||
|
||||
It can happen that you have an API that returns Deferreds for
|
||||
compatibility with Twisted code, but is in fact synchronous, i.e. the
|
||||
Deferreds it returns have always fired by the time it returns. In this
|
||||
case, you can use this function to convert the result back into the usual
|
||||
form for a synchronous API, i.e. the result itself or a raised exception.
|
||||
|
||||
It would be very bad form to use this as some way of checking if a
|
||||
Deferred has fired.
|
||||
"""
|
||||
failures = []
|
||||
successes = []
|
||||
deferred.addCallbacks(successes.append, failures.append)
|
||||
if len(failures) == 1:
|
||||
failures[0].raiseException()
|
||||
elif len(successes) == 1:
|
||||
return successes[0]
|
||||
else:
|
||||
raise DeferredNotFired("%r has not fired yet." % (deferred,))
|
||||
@@ -7,8 +7,6 @@ you couldn't write this yourself, you should not be using it.
|
||||
"""
|
||||
|
||||
__all__ = [
|
||||
'DeferredNotFired',
|
||||
'extract_result',
|
||||
'NoResultError',
|
||||
'not_reentrant',
|
||||
'ReentryError',
|
||||
@@ -54,33 +52,6 @@ def not_reentrant(function, _calls={}):
|
||||
return mergeFunctionMetadata(function, decorated)
|
||||
|
||||
|
||||
class DeferredNotFired(Exception):
|
||||
"""Raised when we extract a result from a Deferred that's not fired yet."""
|
||||
|
||||
|
||||
def extract_result(deferred):
|
||||
"""Extract the result from a fired deferred.
|
||||
|
||||
It can happen that you have an API that returns Deferreds for
|
||||
compatibility with Twisted code, but is in fact synchronous, i.e. the
|
||||
Deferreds it returns have always fired by the time it returns. In this
|
||||
case, you can use this function to convert the result back into the usual
|
||||
form for a synchronous API, i.e. the result itself or a raised exception.
|
||||
|
||||
It would be very bad form to use this as some way of checking if a
|
||||
Deferred has fired.
|
||||
"""
|
||||
failures = []
|
||||
successes = []
|
||||
deferred.addCallbacks(successes.append, failures.append)
|
||||
if len(failures) == 1:
|
||||
failures[0].raiseException()
|
||||
elif len(successes) == 1:
|
||||
return successes[0]
|
||||
else:
|
||||
raise DeferredNotFired("%r has not fired yet." % (deferred,))
|
||||
|
||||
|
||||
def trap_unhandled_errors(function, *args, **kwargs):
|
||||
"""Run a function, trapping any unhandled errors in Deferreds.
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@ import sys
|
||||
from testtools.compat import StringIO
|
||||
from testtools.content import text_content
|
||||
from testtools.runtest import RunTest
|
||||
from testtools._deferred import extract_result
|
||||
from testtools._spinner import (
|
||||
extract_result,
|
||||
NoResultError,
|
||||
Spinner,
|
||||
TimeoutError,
|
||||
|
||||
@@ -14,6 +14,7 @@ def test_suite():
|
||||
test_compat,
|
||||
test_content,
|
||||
test_content_type,
|
||||
test_deferred,
|
||||
test_deferredmatchers,
|
||||
test_deferredruntest,
|
||||
test_distutilscmd,
|
||||
@@ -35,6 +36,7 @@ def test_suite():
|
||||
test_compat,
|
||||
test_content,
|
||||
test_content_type,
|
||||
test_deferred,
|
||||
test_deferredmatchers,
|
||||
test_deferredruntest,
|
||||
test_distutilscmd,
|
||||
|
||||
51
testtools/tests/test_deferred.py
Normal file
51
testtools/tests/test_deferred.py
Normal file
@@ -0,0 +1,51 @@
|
||||
# Copyright (c) testtools developers. See LICENSE for details.
|
||||
|
||||
"""Tests for testtools._deferred."""
|
||||
|
||||
from extras import try_import
|
||||
|
||||
from testtools.matchers import (
|
||||
Equals,
|
||||
MatchesException,
|
||||
Raises,
|
||||
)
|
||||
from testtools.tests.test_spinner import NeedsTwistedTestCase
|
||||
|
||||
from testtools._deferred import DeferredNotFired, extract_result
|
||||
|
||||
defer = try_import('twisted.internet.defer')
|
||||
Failure = try_import('twisted.python.failure.Failure')
|
||||
|
||||
|
||||
class TestExtractResult(NeedsTwistedTestCase):
|
||||
|
||||
def test_not_fired(self):
|
||||
# _spinner.extract_result raises _spinner.DeferredNotFired if it's
|
||||
# given a Deferred that has not fired.
|
||||
self.assertThat(
|
||||
lambda: extract_result(defer.Deferred()),
|
||||
Raises(MatchesException(DeferredNotFired)))
|
||||
|
||||
def test_success(self):
|
||||
# _spinner.extract_result returns the value of the Deferred if it has
|
||||
# fired successfully.
|
||||
marker = object()
|
||||
d = defer.succeed(marker)
|
||||
self.assertThat(extract_result(d), Equals(marker))
|
||||
|
||||
def test_failure(self):
|
||||
# _spinner.extract_result raises the failure's exception if it's given
|
||||
# a Deferred that is failing.
|
||||
try:
|
||||
1/0
|
||||
except ZeroDivisionError:
|
||||
f = Failure()
|
||||
d = defer.fail(f)
|
||||
self.assertThat(
|
||||
lambda: extract_result(d),
|
||||
Raises(MatchesException(ZeroDivisionError)))
|
||||
|
||||
|
||||
def test_suite():
|
||||
from unittest2 import TestLoader, TestSuite
|
||||
return TestLoader().loadTestsFromName(__name__)
|
||||
@@ -63,33 +63,6 @@ class TestNotReentrant(NeedsTwistedTestCase):
|
||||
self.assertEqual(2, len(calls))
|
||||
|
||||
|
||||
class TestExtractResult(NeedsTwistedTestCase):
|
||||
|
||||
def test_not_fired(self):
|
||||
# _spinner.extract_result raises _spinner.DeferredNotFired if it's
|
||||
# given a Deferred that has not fired.
|
||||
self.assertThat(lambda:_spinner.extract_result(defer.Deferred()),
|
||||
Raises(MatchesException(_spinner.DeferredNotFired)))
|
||||
|
||||
def test_success(self):
|
||||
# _spinner.extract_result returns the value of the Deferred if it has
|
||||
# fired successfully.
|
||||
marker = object()
|
||||
d = defer.succeed(marker)
|
||||
self.assertThat(_spinner.extract_result(d), Equals(marker))
|
||||
|
||||
def test_failure(self):
|
||||
# _spinner.extract_result raises the failure's exception if it's given
|
||||
# a Deferred that is failing.
|
||||
try:
|
||||
1/0
|
||||
except ZeroDivisionError:
|
||||
f = Failure()
|
||||
d = defer.fail(f)
|
||||
self.assertThat(lambda:_spinner.extract_result(d),
|
||||
Raises(MatchesException(ZeroDivisionError)))
|
||||
|
||||
|
||||
class TestTrapUnhandledErrors(NeedsTwistedTestCase):
|
||||
|
||||
def test_no_deferreds(self):
|
||||
|
||||
Reference in New Issue
Block a user