def _twisted_test_async(callee, call_args, call_kwargs, timeout):
    """
    Called from the reactor-thread upon invocation of a method 
    decorated with `@twisted_test`.
    
    Performs the actual test sequence.
    
    :param callee: The callable to which the decorator is applied.
    
    :param call_args: Positional arguments passed to the call.
    
    :param call_kwargs: Keyword arguments passed to the call.
    
    :param timeout: Argument of the decorator. See :func:`twisted_test`.
    
    :returns: Return value of `callee`.
    """
    
    def janitor(value):
        """
        Cleans up the reactor and reports any open connections,
        pending calls, ... as failures.
        
        This method is supposed to be used with `Deferred.addBoth()`.
        
        We don't want the janitor to hide a previous
        failure. If it finds the reactor in unclean state it will
        return a corresponding failure, but only if `value` is not
        a failure itself.
        """
        
        # We use the non-public `_Janitor` from trial. The implementation
        # if this class seems to use a non-public API of the reactor.
        # We should try find an official way to do this.
        
        class ErrorCollector(object):
            def __init__(self):
                self.errors = []
            def addError(self, ignored, failure):
                self.errors.append(failure)
           
        collector = ErrorCollector()
        j = _Janitor(None, collector, reactor)
        j.postCaseCleanup()
        j.postClassCleanup()
        
        # If there already was a failure earlier, ignore
        # janitor errors.
        if not isinstance(value, Failure) and collector.errors:
            return collector.errors[0]
        return value
    
    # Chain of callbacks that runs the test procedure.
    # We have to use `deferLater`, or we
    # end up in an infinite recursion due to the janitor-magic.
    # I don't fully understand this, found this workaround
    # by accident.
    chain = task.deferLater(reactor, 0, lambda:None)
    
    # Check if there is a 'twisted_setup()' for us to call.
    if hasattr(callee, '__get__') and len(call_args) >= 1:
        test_case = call_args[0]
        if hasattr(test_case, 'twisted_setup'):
            chain.addCallback(lambda _:test_case.twisted_setup())
    
    # Then call the test method.
    chain.addCallback(lambda _:callee(*call_args, **call_kwargs))
    
    # Check if there is a 'twisted_teardown()' for us to call.
    if hasattr(callee, '__get__') and len(call_args) >= 1:
        test_case = call_args[0]
        if hasattr(test_case, 'twisted_teardown'):
            
            # Callback has to preserve the result of the test, unless
            # the test was successful but the teardown failed.
            def success_teardown(retval):
                d = defer.maybeDeferred(test_case.twisted_teardown)
                d.addCallback(lambda _:retval)
                return d
            def fail_teardown(failure):
                d = defer.maybeDeferred(test_case.twisted_teardown)
                d.addBoth(lambda _:failure)
                return d
            chain.addCallbacks(success_teardown, fail_teardown)

    # Timeout handling (must be before janitor checks, or the delayed call will be found).
    if timeout > 0:
        _timeoutDeferred(chain, timeout)
        
    # Put the reactor-unclean checks to the end of the queue. This makes the checks a bit less thorough.
    # We don't delay by a time, so we just wait til after cleanup stuff which is already planned.
    chain2 = defer.Deferred()
    chain.addBoth(lambda result: task.deferLater(reactor, 0, chain2.callback, result))

    # Reactor-unclean checks.
    chain2.addBoth(janitor)
    
    return chain2
def _twisted_test_async ( callee , call_args , call_kwargs , timeout ) : def janitor ( value ) : class ErrorCollector ( object ) : def __init__ ( self ) : self . errors = [ ] def addError ( self , ignored , failure ) : self . errors . append ( failure ) collector = ErrorCollector ( ) j = _Janitor ( None , collector , reactor ) j . postCaseCleanup ( ) j . postClassCleanup ( ) if not isinstance ( value , Failure ) and collector . errors : return collector . errors [ 0 ] return value chain = task . deferLater ( reactor , 0 , lambda : None ) if hasattr ( callee , '__get__' ) and len ( call_args ) >= 1 : test_case = call_args [ 0 ] if hasattr ( test_case , 'twisted_setup' ) : chain . addCallback ( lambda _ : test_case . twisted_setup ( ) ) chain . addCallback ( lambda _ : callee ( * call_args , ** call_kwargs ) ) if hasattr ( callee , '__get__' ) and len ( call_args ) >= 1 : test_case = call_args [ 0 ] if hasattr ( test_case , 'twisted_teardown' ) : def success_teardown ( retval ) : d = defer . maybeDeferred ( test_case . twisted_teardown ) d . addCallback ( lambda _ : retval ) return d def fail_teardown ( failure ) : d = defer . maybeDeferred ( test_case . twisted_teardown ) d . addBoth ( lambda _ : failure ) return d chain . addCallbacks ( success_teardown , fail_teardown ) if timeout > 0 : _timeoutDeferred ( chain , timeout ) chain2 = defer . Deferred ( ) chain . addBoth ( lambda result : task . deferLater ( reactor , 0 , chain2 . callback , result ) ) chain2 . addBoth ( janitor ) return chain2
Called from the reactor-thread upon invocation of a method 
    decorated with `@twisted_test`.
    
    Performs the actual test sequence.
    
    :param callee: The callable to which the decorator is applied.
    
    :param call_args: Positional arguments passed to the call.
    
    :param call_kwargs: Keyword arguments passed to the call.
    
    :param timeout: Argument of the decorator. See :func:`twisted_test`.
    
    :returns: Return value of `callee`.