def test_suppressWarnings(self): """ L{utils.suppressWarnings} decorates a function so that the given warnings are suppressed. """ result = [] def showwarning(self, *a, **kw): result.append((a, kw)) self.patch(warnings, "showwarning", showwarning) def f(msg): warnings.warn(msg) g = utils.suppressWarnings( f, (('ignore', ), dict(message="This is message"))) # Start off with a sanity check - calling the original function # should emit the warning. f("Sanity check message") self.assertEqual(len(result), 1) # Now that that's out of the way, call the wrapped function, and # make sure no new warnings show up. g("This is message") self.assertEqual(len(result), 1) # Finally, emit another warning which should not be ignored, and # make sure it is not. g("Unignored message") self.assertEqual(len(result), 2)
def test_suppressWarnings(self): """ L{utils.suppressWarnings} decorates a function so that the given warnings are suppressed. """ result = [] def showwarning(self, *a, **kw): result.append((a, kw)) self.patch(warnings, "showwarning", showwarning) def f(msg): warnings.warn(msg) g = utils.suppressWarnings(f, (('ignore',), dict(message="This is message"))) # Start off with a sanity check - calling the original function # should emit the warning. f("Sanity check message") self.assertEqual(len(result), 1) # Now that that's out of the way, call the wrapped function, and # make sure no new warnings show up. g("This is message") self.assertEqual(len(result), 1) # Finally, emit another warning which should not be ignored, and # make sure it is not. g("Unignored message") self.assertEqual(len(result), 2)
def _run(self, methodName, result): from twisted.internet import reactor timeout = self.getTimeout() def onTimeout(d): e = defer.TimeoutError("%r (%s) still running at %s secs" % (self, methodName, timeout)) f = failure.Failure(e) # try to errback the deferred that the test returns (for no gorram # reason) (see issue1005 and test_errorPropagation in # test_deferred) try: d.errback(f) except defer.AlreadyCalledError: # if the deferred has been called already but the *back chain # is still unfinished, crash the reactor and report timeout # error ourself. reactor.crash() self._timedOut = True # see self._wait todo = self.getTodo() if todo is not None and todo.expected(f): result.addExpectedFailure(self, f, todo) else: result.addError(self, f) onTimeout = utils.suppressWarnings( onTimeout, util.suppress(category=DeprecationWarning)) method = getattr(self, methodName) d = defer.maybeDeferred(utils.runWithWarningsSuppressed, self._getSuppress(), method) call = reactor.callLater(timeout, onTimeout, d) d.addBoth(lambda x: call.active() and call.cancel() or x) return d
def _run(self, methodName, result): from twisted.internet import reactor timeout = self.getTimeout() def onTimeout(d): e = defer.TimeoutError("%r (%s) still running at %s secs" % (self, methodName, timeout)) f = failure.Failure(e) # try to errback the deferred that the test returns (for no gorram # reason) (see issue1005 and test_errorPropagation in # test_deferred) try: d.errback(f) except defer.AlreadyCalledError: # if the deferred has been called already but the *back chain # is still unfinished, crash the reactor and report timeout # error ourself. reactor.crash() self._timedOut = True # see self._wait todo = self.getTodo() if todo is not None and todo.expected(f): result.addExpectedFailure(self, f, todo) else: result.addError(self, f) onTimeout = utils.suppressWarnings( onTimeout, util.suppress(category=DeprecationWarning)) method = getattr(self, methodName) d = defer.maybeDeferred( utils.runWithWarningsSuppressed, self._getSuppress(), method) call = reactor.callLater(timeout, onTimeout, d) d.addBoth(lambda x : call.active() and call.cancel() or x) return d
class _Janitor(object): """ The guy that cleans up after you. @ivar test: The L{TestCase} to report errors about. @ivar result: The L{IReporter} to report errors to. @ivar reactor: The reactor to use. If None, the global reactor will be used. """ def __init__(self, test, result, reactor=None): """ @param test: See L{_Janitor.test}. @param result: See L{_Janitor.result}. @param reactor: See L{_Janitor.reactor}. """ self.test = test self.result = result self.reactor = reactor def postCaseCleanup(self): """ Called by L{unittest.TestCase} after a test to catch any logged errors or pending L{DelayedCall<twisted.internet.base.DelayedCall>}s. """ calls = self._cleanPending() if calls: aggregate = DirtyReactorAggregateError(calls) self.result.addError(self.test, Failure(aggregate)) return False return True def postClassCleanup(self): """ Called by L{unittest.TestCase} after the last test in a C{TestCase} subclass. Ensures the reactor is clean by murdering the threadpool, catching any pending L{DelayedCall<twisted.internet.base.DelayedCall>}s, open sockets etc. """ selectables = self._cleanReactor() calls = self._cleanPending() if selectables or calls: aggregate = DirtyReactorAggregateError(calls, selectables) self.result.addError(self.test, Failure(aggregate)) self._cleanThreads() def _getReactor(self): """ Get either the passed-in reactor or the global reactor. """ if self.reactor is not None: reactor = self.reactor else: from twisted.internet import reactor return reactor def _cleanPending(self): """ Cancel all pending calls and return their string representations. """ reactor = self._getReactor() # flush short-range timers reactor.iterate(0) reactor.iterate(0) delayedCallStrings = [] for p in reactor.getDelayedCalls(): if p.active(): delayedString = str(p) p.cancel() else: print("WEIRDNESS! pending timed call not active!") delayedCallStrings.append(delayedString) return delayedCallStrings _cleanPending = utils.suppressWarnings( _cleanPending, (('ignore',), {'category': DeprecationWarning, 'message': r'reactor\.iterate cannot be used.*'})) def _cleanThreads(self): reactor = self._getReactor() if interfaces.IReactorThreads.providedBy(reactor): if reactor.threadpool is not None: # Stop the threadpool now so that a new one is created. # This improves test isolation somewhat (although this is a # post class cleanup hook, so it's only isolating classes # from each other, not methods from each other). reactor._stopThreadPool() def _cleanReactor(self): """ Remove all selectables from the reactor, kill any of them that were processes, and return their string representation. """ reactor = self._getReactor() selectableStrings = [] for sel in reactor.removeAll(): if interfaces.IProcessTransport.providedBy(sel): sel.signalProcess('KILL') selectableStrings.append(repr(sel)) return selectableStrings
def _wait(self, d, running=_wait_is_running): """Take a Deferred that only ever callbacks. Block until it happens. """ if running: raise RuntimeError("_wait is not reentrant") from twisted.internet import reactor results = [] def append(any): if results is not None: results.append(any) def crash(ign): if results is not None: reactor.crash() crash = utils.suppressWarnings( crash, util.suppress(message=r'reactor\.crash cannot be used.*', category=DeprecationWarning)) def stop(): reactor.crash() stop = utils.suppressWarnings( stop, util.suppress(message=r'reactor\.crash cannot be used.*', category=DeprecationWarning)) running.append(None) try: d.addBoth(append) if results: # d might have already been fired, in which case append is # called synchronously. Avoid any reactor stuff. return d.addBoth(crash) reactor.stop = stop try: reactor.run() finally: del reactor.stop # If the reactor was crashed elsewhere due to a timeout, hopefully # that crasher also reported an error. Just return. # _timedOut is most likely to be set when d has fired but hasn't # completed its callback chain (see self._run) if results or self._timedOut: #defined in run() and _run() return # If the timeout didn't happen, and we didn't get a result or # a failure, then the user probably aborted the test, so let's # just raise KeyboardInterrupt. # FIXME: imagine this: # web/test/test_webclient.py: # exc = self.assertRaises(error.Error, wait, method(url)) # # wait() will raise KeyboardInterrupt, and assertRaises will # swallow it. Therefore, wait() raising KeyboardInterrupt is # insufficient to stop trial. A suggested solution is to have # this code set a "stop trial" flag, or otherwise notify trial # that it should really try to stop as soon as possible. raise KeyboardInterrupt() finally: results = None running.pop()