Ticket #990: updated-990.diff
| File updated-990.diff, 12.6 KB (added by glyph, 7 years ago) |
|---|
-
twisted/test/test_defer.py
110 110 dl = defer.DeferredList([], fireOnOneCallback=1) 111 111 dl.addCallbacks(cb) 112 112 self.failUnlessEqual(result, []) 113 113 114 114 def testDeferredListFireOnOneError(self): 115 115 defr1 = defer.Deferred() 116 116 defr2 = defer.Deferred() … … 137 137 failure = result[0] 138 138 139 139 # the type of the failure is a FirstError 140 self.failUnless(issubclass(failure.type, defer.FirstError), 140 self.failUnless(issubclass(failure.type, defer.FirstError), 141 141 'issubclass(failure.type, defer.FirstError) failed: ' 142 142 'failure.type is %r' % (failure.type,) 143 143 ) … … 153 153 self.failUnlessEqual(firstError.subFailure.value.args, ("from def2",)) 154 154 self.failUnlessEqual(firstError.index, 1) 155 155 156 157 156 157 158 158 def testDeferredListDontConsumeErrors(self): 159 159 d1 = defer.Deferred() 160 160 dl = defer.DeferredList([d1]) … … 473 473 defer.setDebugging(True) 474 474 d.addBoth(lambda ign: None) 475 475 476 class FooError(Exception): 477 pass 476 478 479 class DeferredCancellerTest(unittest.TestCase): 480 def setUp(self): 481 self.callback_results = None 482 self.errback_results = None 483 self.callback2_results = None 484 self.cancellerCalled = False 485 486 def _callback(self, data): 487 self.callback_results = data 488 return args[0] 489 490 def _callback2(self, data): 491 self.callback2_results = data 492 493 def _errback(self, data): 494 self.errback_results = data 495 496 497 def testNoCanceller(self): 498 # Deferred without a canceller errbacks defer.CancelledError 499 d=defer.Deferred() 500 d.addCallbacks(self._callback, self._errback) 501 d.cancel() 502 self.assertEquals(self.errback_results.type, defer.CancelledError) 503 504 # Test that further callbacks *are* swallowed 505 d.callback(None) 506 507 # But that a second is not 508 self.assertRaises(defer.AlreadyCalledError, d.callback, None) 509 510 def testCanceller(self): 511 def cancel(d): 512 self.cancellerCalled=True 513 514 d=defer.Deferred(canceller=cancel) 515 d.addCallbacks(self._callback, self._errback) 516 d.cancel() 517 self.assertEquals(self.cancellerCalled, True) 518 self.assertEquals(self.errback_results.type, defer.CancelledError) 519 520 # Test that further callbacks are *not* swallowed 521 self.assertRaises(defer.AlreadyCalledError, d.callback, None) 522 523 def testCancellerWithCallback(self): 524 # If we explicitly callback from the canceller, don't callback CancelledError 525 def cancel(d): 526 self.cancellerCalled=True 527 d.errback(FooError()) 528 d=defer.Deferred(canceller=cancel) 529 d.addCallbacks(self._callback, self._errback) 530 d.cancel() 531 self.assertEquals(self.cancellerCalled, True) 532 self.assertEquals(self.errback_results.type, FooError) 533 534 def testCancelAlreadyCalled(self): 535 def cancel(d): 536 self.cancellerCalled=True 537 d=defer.Deferred(canceller=cancel) 538 d.callback(None) 539 self.assertRaises(defer.AlreadyCalledError, d.cancel) 540 self.assertEquals(self.cancellerCalled, False) 541 542 def testCancelNestedDeferred(self): 543 def innerCancel(d): 544 self.assertIdentical(d, innerDeferred) 545 self.cancellerCalled=True 546 def cancel(d): 547 self.assert_(False) 548 549 innerDeferred=defer.Deferred(canceller=innerCancel) 550 d=defer.Deferred(canceller=cancel) 551 d.callback(None) 552 d.addCallback(lambda data: innerDeferred) 553 d.cancel() 554 d.addCallbacks(self._callback, self._errback) 555 self.assertEquals(self.cancellerCalled, True) 556 self.assertEquals(self.errback_results.type, defer.CancelledError) 557 477 558 class LogTestCase(unittest.TestCase): 478 559 479 560 def setUp(self): … … 563 644 self.failUnless(lock.locked) 564 645 self.assertEquals(self.counter, 3) 565 646 647 d = lock.acquire().addBoth(lambda x: setattr(self, 'result', x)) 648 d.cancel() 649 self.assertEquals(self.result.type, defer.CancelledError) 650 566 651 lock.release() 567 652 self.failIf(lock.locked) 568 653 … … 591 676 sem.acquire().addCallback(self._incr) 592 677 self.assertEquals(self.counter, i) 593 678 679 680 success = [] 681 def fail(r): 682 success.append(False) 683 def succeed(r): 684 success.append(True) 685 d = sem.acquire().addCallbacks(fail, succeed) 686 d.cancel() 687 self.assertEquals(success, [True]) 688 594 689 sem.acquire().addCallback(self._incr) 595 690 self.assertEquals(self.counter, N) 596 691 … … 638 733 queue = defer.DeferredQueue(backlog=0) 639 734 self.assertRaises(defer.QueueUnderflow, queue.get) 640 735 736 queue = defer.DeferredQueue(size=0) 737 738 success = [] 739 def fail(r): 740 success.append(False) 741 def succeed(r): 742 success.append(True) 743 d = queue.get().addCallbacks(fail, succeed) 744 d.cancel() 745 self.assertEquals(success, [True]) 746 self.assertRaises(defer.QueueOverflow, queue.put, None) -
twisted/internet/defer.py
22 22 class AlreadyCalledError(Exception): 23 23 pass 24 24 25 class TimeoutError(Exception):25 class CancelledError(Exception): 26 26 pass 27 # Backwards compatibility 28 TimeoutError = CancelledError 27 29 28 30 def logError(err): 29 31 log.err(err) … … 117 119 return deferred 118 120 119 121 def timeout(deferred): 120 deferred. errback(failure.Failure(TimeoutError("Callback timed out")))122 deferred.cancel() 121 123 122 124 def passthru(arg): 123 125 return arg … … 149 151 150 152 For more information about Deferreds, see doc/howto/defer.html or 151 153 U{http://twistedmatrix.com/projects/core/documentation/howto/defer.html} 154 155 When creating a Deferred, you should provide a canceller function, which 156 will be called by d.cancel() to let you do any cleanup necessary if the 157 user decides not to wait for the deferred to complete. 152 158 """ 159 153 160 called = 0 154 161 paused = 0 155 162 timeoutCall = None 156 163 _debugInfo = None 164 _suppressAlreadyCalled = 0 157 165 158 166 # Keep this class attribute for now, for compatibility with code that 159 167 # sets it directly. 160 168 debug = False 161 169 162 def __init__(self ):170 def __init__(self, canceller=None): 163 171 self.callbacks = [] 172 self.canceller = canceller 164 173 if self.debug: 165 174 self._debugInfo = DebugInfo() 166 175 self._debugInfo.creator = traceback.format_stack()[:-1] … … 177 186 cbs = ((callback, callbackArgs, callbackKeywords), 178 187 (errback or (passthru), errbackArgs, errbackKeywords)) 179 188 self.callbacks.append(cbs) 180 189 181 190 if self.called: 182 191 self._runCallbacks() 183 192 return self … … 253 262 254 263 def pause(self): 255 264 """Stop processing on a Deferred until L{unpause}() is called. 265 You probably don't ever have a reason to call this function. 256 266 """ 257 267 self.paused = self.paused + 1 258 268 259 269 260 270 def unpause(self): 261 271 """Process all callbacks made since L{pause}() was called. 272 You probably don't ever have a reason to call this function. 262 273 """ 263 274 self.paused = self.paused - 1 264 275 if self.paused: … … 266 277 if self.called: 267 278 self._runCallbacks() 268 279 280 def cancel(self): 281 """Cancel this deferred. 282 283 If the deferred is waiting on another deferred, forward the 284 cancellation to the other deferred. 285 286 If the deferred has not yet been errback'd/callback'd, call 287 the canceller function provided to the constructor. If that 288 function does not do a callback/errback, or if no canceller 289 function was provided, errback with CancelledError. 290 291 Otherwise, raise AlreadyCalledError. 292 """ 293 canceller = self.canceller 294 if not self.called: 295 if canceller: 296 canceller(self) 297 else: 298 # Eat the callback that will eventually be fired 299 # since there was no real canceller. 300 self._suppressAlreadyCalled = 1 301 302 if not self.called: 303 # The canceller didn't do an errback of its own 304 try: 305 raise CancelledError 306 except: 307 self.errback(failure.Failure()) 308 elif isinstance(self.result, Deferred): 309 # Waiting for another deferred -- cancel it instead 310 self.result.cancel() 311 else: 312 # Called and not waiting for another deferred 313 raise AlreadyCalledError 314 269 315 def _continue(self, result): 270 316 self.result = result 271 317 self.unpause() 272 318 273 319 def _startRunCallbacks(self, result): 320 # Canceller is no longer relevant 321 self.canceller = None 322 274 323 if self.called: 324 if self._suppressAlreadyCalled: 325 self._suppressAlreadyCalled = 0 326 return 275 327 if self.debug: 276 328 if self._debugInfo is None: 277 329 self._debugInfo = DebugInfo() … … 337 389 338 390 @param timeoutFunc: will receive the Deferred and *args, **kw as its 339 391 arguments. The default timeoutFunc will call the errback with a 340 L{TimeoutError}. 392 L{CancelledError}. 393 341 394 """ 342 395 warnings.warn( 343 396 "Deferred.setTimeout is deprecated. Look for timeout " … … 393 446 394 447 class FirstError(Exception): 395 448 """First error to occur in a DeferredList if fireOnOneErrback is set. 396 449 397 450 @ivar subFailure: the L{Failure} that occurred. 398 451 @ivar index: the index of the Deferred in the DeferredList where it 399 452 happened. … … 424 477 if isinstance(other, tuple): 425 478 return tuple(self) == other 426 479 elif isinstance(other, FirstError): 427 return (self.subFailure == other.subFailure and 480 return (self.subFailure == other.subFailure and 428 481 self.index == other.index) 429 482 return False 430 483 … … 705 758 706 759 locked = 0 707 760 761 def _cancelAcquire(self, d): 762 self.waiting.remove(d) 763 708 764 def acquire(self): 709 765 """Attempt to acquire the lock. 710 766 711 767 @return: a Deferred which fires on lock acquisition. 712 768 """ 713 d = Deferred( )769 d = Deferred(canceller=self._cancelAcquire) 714 770 if self.locked: 715 771 self.waiting.append(d) 716 772 else: … … 743 799 self.tokens = tokens 744 800 self.limit = tokens 745 801 802 def _cancelAcquire(self, d): 803 self.waiting.remove(d) 804 746 805 def acquire(self): 747 806 """Attempt to acquire the token. 748 807 749 808 @return: a Deferred which fires on token acquisition. 750 809 """ 751 810 assert self.tokens >= 0, "Internal inconsistency?? tokens should never be negative" 752 d = Deferred( )811 d = Deferred(canceller=self._cancelAcquire) 753 812 if not self.tokens: 754 813 self.waiting.append(d) 755 814 else: … … 803 862 self.size = size 804 863 self.backlog = backlog 805 864 865 def _cancelGet(self, d): 866 self.waiting.remove(d) 867 806 868 def put(self, obj): 807 869 """Add an object to this queue. 808 870 … … 826 888 if self.pending: 827 889 return succeed(self.pending.pop(0)) 828 890 elif self.backlog is None or len(self.waiting) < self.backlog: 829 d = Deferred( )891 d = Deferred(canceller=self._cancelGet) 830 892 self.waiting.append(d) 831 893 return d 832 894 else: … … 834 896 835 897 836 898 __all__ = ["Deferred", "DeferredList", "succeed", "fail", "FAILURE", "SUCCESS", 837 "AlreadyCalledError", "TimeoutError", " gatherResults",899 "AlreadyCalledError", "TimeoutError", "CancelledError", "gatherResults", 838 900 "maybeDeferred", "waitForDeferred", "deferredGenerator", 839 901 "DeferredLock", "DeferredSemaphore", "DeferredQueue", 840 902 ] -
twisted/trial/test/test_deferred.py
219 219 self.failIf(result.wasSuccessful()) 220 220 self.failUnlessEqual(len(result.errors), 1) 221 221 self._wasTimeout(result.errors[0][1]) 222 self.failUnless(result.errors[0][1].check(defer.CancelledError))
