Promise
=======

This is a implementation of Promises in Python. It is a super set of
Promises/A+ designed to have readable, performant code and to provide
just the extensions that are absolutely necessary for using async_promises in
Python.

This was forked to make it fully compatible with the `Promise/A+
spec <http://promise-aplus.github.io/promise-spec/>`__

On completion of `promise PR #20 <https://github.com/syrusakbary/promise/pull/20>`__,
maintenence for this fork will be dropped.

|travis| |pypi| |coveralls|

Installation
------------

::

    $ pip install async_promises

Usage
-----

The example below shows how you can load the async_promises library. It then
demonstrates creating a async_promises from scratch. You simply call
``Promise(fn)``. There is a complete specification for what is returned
by this method in
`Promise/A+ <http://promise-aplus.github.com/promise-spec/>`__.

.. code:: python

    from async_promises import Promise

    async_promises = Promise(
        lambda resolve, reject: resolve('RESOLVED!')
    )

API
---

Before all examples, you will need:

.. code:: python

    from async_promises import Promise

Promise(resolver)
~~~~~~~~~~~~~~~~~

This creates and returns a new Promise. ``resolver`` must be a function.
The ``resolver`` function is passed two arguments:

1. ``resolve`` should be called with a single argument. If it is called
   with a non-promise value then the promise is fulfilled with that
   value. If it is called with a promise (A) then the returned promise
   takes on the state of that new promise (A).
2. ``reject`` should be called with a single argument. The returned
   promise will be rejected with that argument.

Class Methods
~~~~~~~~~~~~~

These methods are invoked by calling ``Promise.methodName``.

Promise.resolve(value)
^^^^^^^^^^^^^^^^^^^^^^

Converts values and foreign Promises into Promise/A+ Promises. If you
pass it a value then it returns a Promise for that value. If you pass it
something that is close to a promise (such as a jQuery attempt at a
promise) it returns a Promise that takes on the state of ``value``
(rejected or fulfilled).

Promise.rejected(value)
^^^^^^^^^^^^^^^^^^^^^^^

Returns a rejected promise with the given value.

Promise.all(list)
^^^^^^^^^^^^^^^^^

Returns a Promise for a list. If it is called with a single argument
then this returns a Promise for a copy of that list with any Promises
replaced by their fulfilled values. e.g.

.. code:: python

    p = Promise.all([Promise.resolve('a'), 'b', Promise.resolve('c')]) \
           .then(lambda res: res == ['a', 'b', 'c'])

    assert p.get() is True

Promise.promisify(obj)
^^^^^^^^^^^^^^^^^^^^^^

This function wraps the ``obj`` act as a ``Promise`` if possible. Python
``Future``\ s are supported, with a callback to ``async_promises.done`` when
resolved.

Promise.for\_dict(d)
^^^^^^^^^^^^^^^^^^^^

A special function that takes a dictionary of Promises and turns them
into a Promises for a dictionary of values. In other words, this turns an
dictionary of Promises for values into a Promises for a dictionary of
values.

Instance Methods
~~~~~~~~~~~~~~~~

These methods are invoked on a Promise instance by calling
``myPromise.methodName``

async_promises.then(on\_fulfilled, on\_rejected)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This method follows the `Promise/A+
spec <http://promise-aplus.github.io/promise-spec/>`__. It explains
things very clearly so I recommend you read it.

Either ``on_fulfilled`` or ``on_rejected`` will be called and they will
not be called more than once. They will be passed a single argument and
will always be called asynchronously (in the next turn of the event
loop).

If the Promise is fulfilled then ``on_fulfilled`` is called. If the
Promise is rejected then ``on_rejected`` is called.

The call to ``.then`` also returns a Promise. If the handler that is
called returns a Promise, the Promise returned by ``.then`` takes on the
state of that returned Promise. If the handler that is called returns a
value that is not a Promise, the Promise returned by ``.then`` will be
fulfilled with that value. If the handler that is called throws an
exception then the Promise returned by ``.then`` is rejected with that
exception.

async_promises.catch(on\_rejected)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Sugar for ``async_promises.then(None, on_rejected)``, to mirror ``catch`` in
synchronous code.

async_promises.done(on\_fulfilled, on\_rejected)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

The same semantics as ``.then`` except that it does not return a Promise
and any exceptions are re-thrown so that they can be logged (crashing
the application in non-browser environments)

Other package functions
-----------------------

is\_thenable(obj)
~~~~~~~~~~~~~~~~~

This function checks if the ``obj`` is a ``Promise``, or could be
``promisify``\ ed.

Notes
=====

This package is heavily insipired in
`aplus <https://github.com/xogeny/aplus>`__.

License
-------

`MIT
License <https://github.com/syrusakbary/promise/blob/master/LICENSE>`__

.. |travis| image:: https://img.shields.io/travis/p2p-project/promise.svg?style=flat
   :target: https://travis-ci.org/p2p-project/promise
.. |pypi| image:: https://img.shields.io/pypi/v/async_promise.svg?style=flat
   :target: https://pypi.python.org/pypi/async_promise
.. |coveralls| image:: https://coveralls.io/repos/p2p-project/promise/badge.svg?branch=master&service=github
   :target: https://coveralls.io/github/p2p-project/promise?branch=master
