# txaio API

The API is identical whether you’re using Twisted or asyncio under the hood. Two `bool` variables are available if you need to know which framework is in use, and two helpers to enforce one or the other framework.

## Explicitly Selecting a Framework

You can simply `import txaio` to get an auto-selected framework (Twisted if available, else asyncio/trollius). If you want to guarantee one or the other, you can do this:

    import txaio               # automatically select framework
    txaio.use_twisted()
    txaio.use_asyncio()

For most cases, a simple `import txaio` will be sufficient.

## Set an Event Loop / Reactor

You can set `txaio.config.loop` to either an EventLoop instance (if using asyncio) or an explicit reactor (if using Twisted). By defualt, `reactor` is imported from `twisted.internet` on the first `call_later` invocation. For asyncio, `asyncio.get_event_loop()` is called at import time.

If you’ve installed your reactor before `import txaio` you shouldn’t need to do anything.

Note that under Twisted, only the IReactorTime interface is required.

## Test Helpers

Test utilities are in `txaio.testutil`. There is a context-manager for testing delayed calls; see `test_call_later.py` for an example.

`txaio.testutil.``replace_loop`(*args, **kwds)

  This is a context-manager that sets the txaio event-loop to the one supplied temporarily. It’s up to you to ensure you pass an event_loop or a reactor instance depending upon asyncio/Twisted.

  Use like so:

      from twisted.internet import task
      with replace_loop(task.Clock()) as fake_reactor:
          f = txaio.call_later(5, foo)
          fake_reactor.advance(10)
          # ...etc

## txaio module

`txaio.``using_twisted`

  `True` only if we’re using Twisted as our underlying event framework

`txaio.``using_asyncio`

  `True` only if we’re using asyncio as our underlying event framework

`txaio.``use_asyncio`()

  Force the use of `asyncio`.

`txaio.``use_twisted`()

  Force the use of Twisted.

`txaio.``create_future`(value=None, error=None)

  Create and return a new framework-specific future object. On asyncio this returns a Future, on Twisted it returns a Deferred.

  Parameters:

  - value – if not `None`, the future is already fulfilled, with the given result.
  - error (class:IFailedFuture or Exception) – if not `None` then the future is already failed, with the given error.

  Raises: | ValueError – if both `value` and `error` are provided.
  Returns: | under Twisted a Deferred, under asyncio a Future

`txaio.``as_future`(func, *args, **kwargs)

  Call `func` with the provided arguments and keyword arguments, and always return a Future/Deferred. If `func` itself returns a future, that is directly returned. If it immediately succeed or failed then an already-resolved Future/Deferred is returned instead.

  This allows you to write code that calls functions (e.g. possibly provided from user-code) and treat them uniformly. For example:

      p = txaio.as_future(some_function, 1, 2, key='word')
      txaio.add_callbacks(p, do_something, it_failed)

  You therefore don’t have to worry if the underlying function was itself asynchronous or not – your code always treats it as async.

`txaio.``reject`(future, error=None)

  Resolve the given future as failed. This will call any errbacks registered against this Future/Deferred. On Twisted, the errback is called with a bare Failure instance; on asyncio we provide an object that implements `IFailedFuture` because there is no equivalent in asyncio (this mimics part of the Failure API).

  Parameters:

  - future – an unresolved Deferred/Future as returned by `create_future()`
  - error (`IFailedFuture` or `Exception`) – The error to fail the Deferred/Future with. If this is `None`, `sys.exc_info()` is used to create an `txaio.IFailedFuture` (or Failure) wrapping the current exception (so in this case it must be called inside an `except:` clause).

`txaio.``resolve`(future, value)

  Resolve the given future with the provided value. This triggers any callbacks registered against this Future/Deferred.

`txaio.``add_callbacks`(future, callback, errback)

  Adds the provided callback and/or errback to the given future. To add multiple callbacks, call this method multiple times. For example, to add just an errback, call `add_callbacks(p, None, my_errback)`

  Note that `txaio` doesn’t do anything special with regards to callback or errback chaining – it is highly recommended that you always return the incoming argument unmodified in your callback/errback so that Twisted and asyncio behave the same. For example:

      def callback_or_errback(value):
          # other code
          return value

  Raises: | ValueError – if both callback and errback are None

`txaio.``call_later`(delay, func, *args, **kwargs)

  This calls the function `func` with the given parameters at the specified time in the future. Although asyncio doesn’t directly support kwargs with `loop.call_later` we wrap it in a `functools.partial`, as asyncio documentation suggests.

  Parameters: | delay – how many seconds in the future to make the call
  Returns: | The underlying library object, which will at least have a `.cancel()` method on it. It’s really IDelayedCall in Twisted and a Handle in asyncio.

`txaio.``gather`(futures, consume_exceptions=True)

  Returns a new Future that waits for the results from all the futures provided.

  The Future/Deferred returned will callback with a list the same length as `futures` containing either the return value from each future, or an `IFailedFuture`/Failure instance if it failed.

  Note that on Twisted, we use DeferredList which usually returns a list of 2-tuples of `(status, value)`. We do inject a callback that unpacks this list to be just the value (or Failure) so that your callback can be identical on Twisted and asyncio.

class `txaio.``IFailedFuture`

  Bases: `object`

  This defines the interface for a common object encapsulating a failure from either an asyncio task/coroutine or a Twisted Deferred.

  An instance implementing this interface is given to any `errback` callables you provde via `txaio.add_callbacks()`

  It is a subset of Twisted’s Failure interface, because on Twisted backends it actually is a Failure.

  `type`

    The type of the exception. Same as the first item returned from `sys.exc_info()`

  `value`

    An actual Exception instance. Same as the second item returned from `sys.exc_info()`

  `tb`

    A traceback object from the exception. Same as the third item returned from `sys.exc_info()`

  `printTraceback`(file=None)

    Prints the exception and its traceback to the given `file`. If that is `None` (the default) then it is printed to `sys.stderr`.

    XXX this is camelCase because Twisted is; can we change somehow?

  `getErrorMessage`()

    Return a string describing the error.

    XXX this is camelCase because Twisted is; can we change somehow?