API

This part of the documentation shows the full API reference of all public classes and functions.

Creating Promises

classmethod Promise.value(val)

Construct a Promise that is already resolved successfully to a value.

Parameters:

val : anything

Value to resolve new Promise to.

Returns:

result : Future

Future containing val as its value.

classmethod Promise.exception(exc)

Construct a Promise that has already failed with a given exception.

Parameters:

exc : Exception

Exception to fail new Promise with

Returns:

result : Future

New Promise that has already failed with the given exception.

classmethod Promise.call(fn, *args, **kwargs)

Call a function asynchronously and return a Promise with its result. If an exception is thrown inside fn, a new exception type will be constructed inheriting both from MiraiError and the exception’s original type. The new exception is the same the original, except that it also contains a context attribute detailing the stack at the time the exception was thrown.

Parameters:

fn : function

Function to be called

*args : arguments

**kwargs : keyword arguments

Returns:

result : Future

Future containing the result of fn(*args, **kwargs) as its value or the exception thrown as its exception.

classmethod Promise.wait(duration)

Construct a Promise that succeeds in duration seconds with value None.

Parameters:

duration : number

Number of seconds to wait before resolving a TimeoutError

Returns:

result : Future

Promise that will resolve in duration seconds with value None.

classmethod Promise.eval(fn, *args, **kwargs)

Call a function (synchronously) and return a Promise with its result. If an exception is thrown inside fn, a new exception type will be constructed inheriting both from MiraiError and the exception’s original type. The new exception is the same the original, except that it also contains a context string detailing the stack at the time the exception was thrown.

Parameters:

fn : function

Function to be called

*args : arguments

**kwargs : keyword arguments

Returns:

result : Future

Future containing the result of fn(*args, **kwargs) as its value or the exception thrown as its exception.

Using Promises

class mirai.Promise(future=None)

A Promise encapsulates the result of an asynchronous computation. Think of it as a single-use mailbox – you receive a promise which will later contain a message.:

import requests
from mirai import Promise

def async_request(method, url, *args, **kwargs):
  "fetch a url asynchronously using `requests`"

  # construct a promise to fill later
  promise = Promise()

  def sync_request():
    "fetches synchronously & propagates exceptions"
    try:
      response = requests.request(method, url, *args, **kwargs)
      promise.setvalue(response)
    except Exception as e:
      promise.setexception(e)

  # start asynchronous computation
  Promise.call(sync_request)

  # return read-only version of promise
  return promise.future()
Parameters:

future : concurrent.futures.Future

Future this promise wraps.

Methods

andthen(fn)

Apply a function with a single argument: the value this Promise resolves to. The function must return another future. If this Promise fails, fn will not be called. Same as as Promise.flatmap.

Parameters:

fn : (value,) -> Promise

Function to apply. Takes 1 positional argument. Must return a Promise.

Returns:

result : Future

Promise fn will return.

ensure(fn)

Ensure that no-argument function fn is called when this Promise resolves, regardless of whether or not it completes successfuly.

Parameters:

fn : (,) -> None

function to apply upon Promise completion. takes no arguments. Return value ignored.

Returns:

self : Future

filter(fn)

Construct a new Promise that fails if fn doesn’t evaluate truthily when given self.get() as its only argument. If fn evaluates falsily, then the resulting Promise fails with a MiraiError.

Parameters:

fn : (value,) -> bool

function used to check self.get(). Must return a boolean-like value.

Returns:

result : Future

Future whose contents are the contents of this Promise if fn evaluates truth on this Promise’s contents.

flatmap(fn)

Apply a function with a single argument: the value this Promise resolves to. The function must return another future. If this Promise fails, fn will not be called.

Parameters:

fn : (value,) -> Promise

Function to apply. Takes 1 positional argument. Must return a Promise.

Returns:

result : Future

Future containing return result of fn.

foreach(fn)

Apply a function if this Promise resolves successfully. The function receives the contents of this Promise as its only argument.

Parameters:

fn : (value,) -> None

Function to apply to this Promise’s contents. Return value ignored.

Returns:

self : Promise

future()

Retrieve a Future encapsulating this promise. A Future is a read-only version of the exact same thing.

Returns:

future : Future

Future encapsulating this Promise.

get(timeout=None)

Retrieve value of Promise; block until it’s ready or timeout seconds have passed. If timeout seconds pass, then a TimeoutError will be raised. If this Promise failed, the set exception will be raised.

Parameters:

timeout : number or None

Number of seconds to wait until raising a TimeoutError. If None, then wait indefinitely.

Returns:

result : anything

Contents of this future if it resolved successfully.

Raises:

Exception :

Set exception if this future failed.

getorelse(default, timeout=None)

Like Promise.get, but instead of raising an exception when this Promise fails, returns a default value.

Parameters:

default : anything

default value to return in case of timeout or exception.

timeout : None or float

time to wait before returning default value if this promise is unresolved.

Returns:

result : anything

value this Promise resolves to, if it resolves successfully, else default.

handle(fn)

If this Promise fails, call fn on the ensuing exception to obtain a successful value.

Parameters:

fn : (exception,) -> anything

Function applied to recover from a failed exception. Its return value will be the value of the resulting Promise.

Returns:

result : Future

Resulting Future returned by applying fn to the exception, then setting the return value to result‘s value. If this Promise is already successful, its value is propagated onto result.

isdefined()

Return True if this Promise has already been resolved, successfully or unsuccessfully.

Returns:result : bool
isfailure()

Return True if this Promise failed, False if it succeeded, and None if it’s not yet resolved.

Returns:result : bool
issuccess()

Return True if this Promise succeeded, False if it failed, and None if it’s not yet resolved.

Returns:result : bool
join_(*others)

Combine values of this Promise and 1 or more other Promises into a list. Results are in the same order [self] + others is in.

Parameters:

others : 1 or more Promises

Promises to combine with this Promise.

Returns:

result : Future

Future resolving to a list of containing the values of this Promise and all other Promises. If any Promise fails, result holds the exception in the one which fails soonest.

map(fn)

Transform this Promise by applying a function to its value. If this Promise contains an exception, fn is not applied.

Parameters:

fn : (value,) -> anything

Function to apply to this Promise’s value on completion.

Returns:

result : Future

Future containing fn applied to this Promise’s value. If this Promise fails, the exception is propagated.

onfailure(fn)

Apply a callback if this Promise fails. Callbacks can be added after this Promise has resolved. If fn throws an exception, a warning is printed via logging.

Parameters:

fn : (exception,) -> None

Function to call upon failure. Its only argument is the exception set to this Promise. If this future succeeds, fn will not be called.

Returns:

self : Promise

onsuccess(fn)

Apply a callback if this Promise succeeds. Callbacks can be added after this Promise has resolved. If fn throws an exception, a warning is printed via logging.

Parameters:

fn : (value,) -> None

Function to call upon success. Its only argument is the value set to this Promise. If this future fails, fn will not be called.

Returns:

self : Promise

or_(*others)

Return the first Promise that finishes among this Promise and one or more other Promises.

Parameters:

others : one or more Promises

Other futures to consider.

Returns:

result : Future

First future that is resolved, successfully or otherwise.

proxyto(other)

Copy the state of this Promise to another.

Parameters:

other : Promise

Another Promise to copy the state of this Promise to, upon completion.

Returns:

self : Promise

Raises:

MiraiError :

if other isn’t a Promise instance

rescue(fn)

If this Promise fails, call fn on the ensuing exception to recover another (potentially successful) Promise. Similar to Promise.handle, but must return a Promise (rather than a value).

Parameters:

fn : (exception,) -> Promise

Function applied to recover from a failed exception. Must return a Promise.

Returns:

result : Future

Resulting Future returned by apply fn to the exception this Promise contains. If this Promise is successful, its value is propagated onto result.

respond(fn)

Apply a function to this Promise when it’s resolved. If fn raises an exception a warning will be printed via logging, but no action will be taken.

Parameters:

fn : (future,) -> None

Function to apply to this Promise upon completion. Return value is ignored

Returns:

self : Promise

select_(*others)

Return the first Promise that finishes among this Promise and one or more other Promises.

Parameters:

others : one or more Promises

Other futures to consider.

Returns:

result : Future

First future that is resolved, successfully or otherwise.

setexception(e)

Set the state of this Promise as failed with a given Exception. State can only be set once; once a Promise is defined, it cannot be redefined. This operation is thread (but not process) safe.

Parameters:

e : Exception

Returns:

self : Promise

Raises:

AlreadyResolvedError :

if this Promise’s value is already set

setvalue(val)

Set the state of this Promise as successful with a given value. State can only be set once; once a Promise is defined, it cannot be redefined. This operation is thread (but not process) safe.

Parameters:

val : value

Returns:

self : Promise

Raises:

AlreadyResolvedError :

if this Promise’s value is already set

transform(fn)

Apply a function with a single argument (this Promise) after resolving. The function must return another future.

Parameters:

fn : (future,) -> Promise

Function to apply. Takes 1 positional argument. Must return a Promise.

Returns:

result : Future

Future containing return result of fn.

unit()

Convert this Promise to another that disregards its result.

Returns:

result : Future

Promise with a value of None if this Promise succeeds. If this Promise fails, the exception is propagated.

update(other)

Populate this Promise with the contents of another.

Parameters:

other : Promise

Promise to copy

Returns:

self : Promise

Raises:

MiraiError :

if other isn’t a Promise

updateifempty(other)

Like Promise.update, but update only if this Promise isn’t already defined.

Parameters:

other : Promise

Promise to copy, if necessary.

Returns:

self : Promise

Raises:

MiraiError :

if other isn’t a Promise

within(duration)

Return a Promise whose state is guaranteed to be resolved within duration seconds. If this Promise completes before duration seconds expire, it will contain this Promise’s contents. If this Promise is not resolved by then, the resulting Promise will fail with a TimeoutError.

Parameters:

duration : number

Number of seconds to wait before resolving a TimeoutError

Returns:

result : Promise

Promise guaranteed to resolve in duration seconds.

Combining Promises

classmethod Promise.collect(fs)

Convert a sequence of Promises into a Promise containing a sequence of values, one per Promise in fs. The resulting Promise resolves once all Promises in fs resolve successsfully or upon the first failure. In the latter case, the failing Promise’s exception is propagated.

Parameters:

fs : [Promise]

List of Promises to merge.

Returns:

result : Future

Future containing values of all Futures in fs. If any Future in fs fails, result fails with the same exception.

classmethod Promise.join(fs)

Construct a Promise that resolves when all Promises in fs have resolved. If any Promise in fs fails, the error is propagated into the resulting Promise.

Parameters:

fs : [Promise]

List of Promises to merge.

Returns:

result : Future

Future containing None if all Futures in fs succeed, or the exception of the first failing Future in fs.

classmethod Promise.select(fs)

Return a Promise containing a tuple of 2 elements. The first is the first Promise in fs to resolve; the second is all remaining Promises that may or may not be resolved yet. The resolved Promise is not guaranteed to have completed successfully.

Parameters:

fs : [Promise]

List of Promises to merge.

Returns:

result : Future

Future containing the first Future in fs to finish and all remaining (potentially) unresolved Futures as a tuple of 2 elements for its value.

Thread Management

classmethod Promise.executor(executor=None, wait=True)

Set/Get the EXECUTOR Promise uses. If setting, the current executor is first shut down.

Parameters:

executor : concurrent.futures.Executor or None

If None, retrieve the current executor, otherwise, shutdown the current Executor object and replace it with this argument.

wait : bool, optional

Whether or not to block this thread until all workers are shut down cleanly.

Returns:

executor : Executor

Current executor

class mirai.UnboundedThreadPoolExecutor(max_workers=None)

A thread pool with an infinite number of threads.

This interface conforms to the typical concurrent.futures.Executor interface, but doesn’t limit the user to a finite number of threads. In normal situations, this is undesirable – too many threads, and your program will spend more time switching contexts than actually working!

On the other hand, if you patch the thread module with gevent, spawning tens of thousands of threads is totally OK. This is where this executor comes in.

Parameters:

max_workers: None or int, optional :

Number of worker threads. If None, a new thread is created every time a new task is submitted. If an integer, this executor acts exactly like a normal concurrent.futures.ThreadPoolExecutor.

Methods

shutdown(wait=True)

Shutdown this thread pool, preventing future tasks from being enqueued.

Parameters:

wait : bool

Wait for all running threads to finish. Only used if this pool was initialized with a fixed number of workers.

submit(fn, *args, **kwargs)

Submit a new task to be executed asynchronously.

If self.max_workers is an integer, then the behavior of this function will be identical to that of concurrent.futures.ThreadPoolExecutor. However, if it is None, then a new daemonized thread will be constructed and started.

Parameters:

fn : function-like

function (or callable object) to execute asynchronously.

args : list

positional arguments to pass to fn.

kwargs: dict :

keyword arguments to pass to fn.

Returns:

future : concurrent.futures.Future

Container for future result or exception

Exceptions

exception mirai.MiraiError

Base class for all exceptions raise by Promises

exception mirai.AlreadyResolvedError

Exception thrown when attempting to set the value or exception of a Promise that has already had its value or exception set.

exception mirai.TimeoutError

The operation exceeded the given deadline.