File: api.rst

package info (click to toggle)
python-txaio 1.0.0-3~bpo8%2B1
  • links: PTS, VCS
  • area: main
  • in suites: jessie-backports
  • size: 216 kB
  • sloc: python: 738; makefile: 215
file content (203 lines) | stat: -rw-r--r-- 7,012 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
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:

.. sourcecode:: python

    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.

.. automodule:: txaio.testutil


txaio module
------------

.. py:module:: txaio

.. py:data:: using_twisted

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


.. py:data:: using_asyncio

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


.. py:function:: use_asyncio()

    Force the use of ``asyncio``.


.. py:function:: use_twisted()

    Force the use of Twisted.


.. py:function:: 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`_.

    :param value: if not ``None``, the future is already fulfilled,
        with the given result.

    :param error: if not ``None`` then the future is already failed,
        with the given error.
    :type error: class:`IFailedFuture` or Exception

    :raises ValueError: if both ``value`` and ``error`` are provided.

    :return: under Twisted a `Deferred`_, under asyncio a `Future`_


.. py:function:: 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:

    .. sourcecode:: python

        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.


.. py:function:: 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).

    :param future: an unresolved `Deferred`_/`Future`_ as returned by
                    :meth:`create_future`

    :param error: The error to fail the `Deferred`_/`Future`_ with. If this
                  is ``None``, ``sys.exc_info()`` is used to create an
                  :class:`txaio.IFailedFuture` (or `Failure`_)
                  wrapping the current exception (so in this case it
                  must be called inside an ``except:`` clause).

    :type error: :class:`IFailedFuture` or :class:`Exception`


.. py:function:: resolve(future, value)

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


.. py:function:: 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:

    .. sourcecode:: python

        def callback_or_errback(value):
            # other code
            return value

    :raises ValueError: if both callback and errback are None


.. py:function:: 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.

    :param 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.


.. py:function:: 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 :class:`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.


.. autoclass:: txaio.IFailedFuture


.. _Autobahn|Python: http://autobahn.ws/python/
.. _Deferred: https://twistedmatrix.com/documents/current/api/twisted.internet.defer.Deferred.html
.. _DeferredList: https://twistedmatrix.com/documents/current/api/twisted.internet.defer.DeferredList.html
.. _Failure: https://twistedmatrix.com/documents/current/api/twisted.python.failure.Failure.html
.. _IDelayedCall: https://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IDelayedCall.html
.. _IReactorTime: https://twistedmatrix.com/documents/current/api/twisted.internet.interfaces.IReactorTime.html

.. _Handle: https://docs.python.org/3.4/library/asyncio-eventloop.html#asyncio.Handle
.. _Future: https://docs.python.org/3.4/library/asyncio-task.html#asyncio.Future