async_stagger API reference

The Main Package

await async_stagger.create_connected_sock(host, port, *, family=<AddressFamily.AF_UNSPEC: 0>, proto=0, flags=0, local_addr=None, local_addrs=None, delay=0.25, interleave=1, async_dns=False, resolution_delay=0.05, detailed_exceptions=False, loop=None)

Connect to (host, port) and return a connected socket.

This function implements RFC 6555 Happy Eyeballs and some features of RFC 8305 Happy Eyeballs v2. When a host name resolves to multiple IP addresses, connection attempts are made in parallel with staggered start times, and the one completing fastest is used. The resolved addresses can be interleaved by address family, so even if network connectivity for one address family is broken (when IPv6 fails, for example), connections still complete quickly. IPv6 and IPv4 addresses of a hostname can also be resolved in parallel.

(Some fancier features specified in RFC 8305, like statefulness and features related to NAT64 and DNS64 are not implemented. Destination address sorting is left for the operating system; it is assumed that the addresses returned by getaddrinfo() is already sorted according to OS’s preferences.)

Most of the arguments should be familiar from the various socket and asyncio methods. delay, interleave, async_dns and resolution_delay control Happy Eyeballs-specific behavior. local_addrs is a new argument providing new features not specific to Happy Eyeballs.

Parameters
  • host (Union[str, bytes, None]) – Host name to connect to. Unlike asyncio.create_connection() there is no default, but it’s still possible to manually specify None here.

  • port (Union[str, bytes, int, None]) – Port number to connect to. Similar to host, None can be specified here as well.

  • family (int) – Address family. Specify socket.AF_INET or socket.AF_INET6 here to limit the type of addresses used. See documentation on the socket module for details.

  • proto (int) – Socket protocol. Since the socket type is always socket.SOCK_STREAM, proto can usually be left unspecified.

  • flags (int) – Flags passed to getaddrinfo(). See documentation on socket.getaddrinfo() for details.

  • local_addr (Optional[Tuple]) – (local_host, local_port) tuple used to bind the socket to locally. The local_host and local_port are looked up using getaddrinfo() if necessary, similar to host and port.

  • local_addrs (Optional[Iterable[Tuple]]) – An iterable of (local_host, local_port) tuples, all of which are candidates for locally binding the socket to. This allows e.g. providing one IPv4 and one IPv6 address. Addresses are looked up using getaddrinfo() if necessary.

  • delay (Optional[float]) – Amount of time to wait before making connections to different addresses. This is the “Connect Attempt Delay” as defined in RFC 8305.

  • interleave (int) – Whether to interleave resolved addresses by address family. 0 means not to interleave and simply use the returned order. An integer >= 1 is interpreted as “First Address Family Count” defined in RFC 8305, i.e. the reordered list will have this many addresses for the first address family, and the rest will be interleaved one to one.

  • async_dns (bool) – Do asynchronous DNS resolution, where IPv6 and IPv4 addresses are resolved in parallel, and connection attempts can be made as soon as either address family is resolved. This behavior is described in RFC 8305#section-3.

  • resolution_delay (float) – Amount of time to wait for IPv6 addresses to resolve if IPv4 addresses are resolved first. This is the “Resolution Delay” as defined in RFC 8305.

  • detailed_exceptions (bool) – Determines what exception to raise when all connection attempts fail. If set to True, an instance of HappyEyeballsConnectError is raised, which contains the individual exceptions raised by each connection and address resolution attempt. When set to false (default), an exception is raised the same way as asyncio.create_connection(): if all the connection attempt exceptions have the same str, one of them is raised, otherwise an instance of OSError is raised whose message contains str representations of all connection attempt exceptions.

  • loop (Optional[AbstractEventLoop]) – Event loop to use.

Return type

socket

Returns

The connected socket.socket object.

New in version v0.1.3: the local_addrs parameter.

New in version v0.2.1: the async_dns and resolution_delay parameters.

await async_stagger.create_connection(protocol_factory, host, port, *, loop=None, **kwargs)

Connect to (host, port) and return (transport, protocol).

This function does the same thing as asyncio.AbstractEventLoop.create_connection(), only more awesome with Happy Eyeballs. Refer to that function’s documentation for explanations of these arguments: protocol_factory, ssl, and server_hostname. Refer to create_connected_sock() for all other arguments.

Return type

Tuple[Transport, Protocol]

Returns

(transport, protocol), the same as asyncio.AbstractEventLoop.create_connection().

await async_stagger.open_connection(host, port, *, loop=None, **kwargs)

Connect to (host, port) and return (reader, writer).

This function does the same thing as asyncio.open_connection(), with added awesomeness of Happy Eyeballs. Refer to the documentation of that function for what limit does, and refer to create_connection() and create_connected_sock() for everything else.

Return type

Tuple[StreamReader, StreamWriter]

Returns

(reader, writer), the same as asyncio.open_connection().

await async_stagger.staggered_race(coro_fns, delay, *, loop=None)

Run coroutines with staggered start times and take the first to finish.

This function takes an async iterable of coroutine functions. The first one is retrieved and started immediately. From then on, whenever the immediately preceding one fails (raises an exception), or when delay seconds has passed, the next coroutine is retrieved and started. This continues until one of the coroutines complete successfully, in which case all others are cancelled, or until all coroutines fail.

The coroutines provided should be well-behaved in the following way:

  • They should only return if completed successfully.

  • They should always raise an exception if they did not complete successfully. In particular, if they handle cancellation, they should probably reraise, like this:

    try:
        # do work
    except asyncio.CancelledError:
        # undo partially completed work
        raise
    
Parameters
  • coro_fns (AsyncIterable[Callable[[], Awaitable]]) – an async iterable of coroutine functions, i.e. callables that return a coroutine object when called. Use functools.partial() or lambdas to pass arguments. If you want to use a regular iterable here, wrap it with aiter_from_iter().

  • delay (Optional[float]) – amount of time, in seconds, between starting coroutines. If None, the coroutines will run sequentially.

  • loop (Optional[AbstractEventLoop]) – the event loop to use.

Return type

Tuple[Any, Optional[int], List[Optional[Exception]], Optional[Exception]]

Returns

tuple (winner_result, winner_index, coro_exc, aiter_exc) where

  • winner_result: the result of the winning coroutine, or None if no coroutines won.

  • winner_index: the index of the winning coroutine in coro_fns, or None if no coroutines won. If the winning coroutine may return None on success, winner_index can be used to definitively determine whether any coroutine won.

  • coro_exc: list of exceptions raised by the coroutines. len(exceptions) is equal to the number of coroutines actually started, and the order is the same as in coro_fns. The winning coroutine’s entry is None.

  • aiter_exc: exception raised by the coro_fns async iterable, or None if coro_fns was iterated to completion without raising any exception.

Changed in version v0.2.0: coro_fns argument now takes an async iterable instead of a regular iterable.

Changed in version v0.3.0: The return value is now a 4-tuple. aiter_exc is added.

aitertools

Tools for working with async iterators.

async_stagger.aitertools.aiter(aiterable)

Return an async iterator from an async iterable.

If an aiter function is available as a builtin or in the operator module, it is imported into async_stagger.aitertools, and this function will not be defined. Only when a stock aiter is not available will this function be defined.

Unlike the built-in iter(), this only support one argument, and does not support the two-argument (callable, sentinel) usage.

Adapted from implementation attached to https://bugs.python.org/issue31861 by Davide Rizzo.

Parameters

aiterable (AsyncIterable[~T]) – The async iterable.

Return type

AsyncIterator[~T]

Returns

The async iterator produced from the given async iterable.

async for ... in async_stagger.aitertools.aiter_from_iter(iterable)

Wrap an async iterator around a regular iterator.

Parameters

iterable (Iterable[~T]) – a regular iterable.

Return type

AsyncIterator[~T]

Returns

An async iterator yielding the same items as the original iterable.

await async_stagger.aitertools.aiterclose(aiterator)

Close the async iterator if possible.

Async generators have an aclose() method that closes the generator and cleans up associated resources. Plain async iterators do not have anything similar, but PEP 533 suggests adding an __aiterclose__() method, and having it called automatically when exiting from an async with loop.

This function tries to close the async iterator using either method, and if neither is available, does nothing.

Parameters

aiterator (AsyncIterator) – the async iterator to close.

async_stagger.aitertools.anext(aiterator)

Return the next item from an async iterator.

If an anext function is available as a builtin or in the operator module, it is imported into async_stagger.aitertools, and this function will not be defined. Only when a stock anext is not available will this function be defined.

Unlike the built-in next(), this does not support providing a default value.

This is a regular function that returns an awaitable, so usually you should await its result: await anext(it)

Adapted from implementation attached to https://bugs.python.org/issue31861 by Davide Rizzo.

Parameters

aiterator (AsyncIterator[~T]) – the async iterator.

Return type

Awaitable[~T]

Returns

An awaitable that will return the next item in the iterator.

async for ... in async_stagger.aitertools.product(*aiterables, repeat=1)

Async version of itertools.product().

Compute the cartesian product of input iterables. The arguments are analogous to its itertools counterpart.

The input async iterables are evaluated lazily. As a result the last input iterable is iterated and exhausted first, then the next-to-last is iterated, and so on.

Parameters
  • aiterables (AsyncIterable) – input async iterables.

  • repeat (int) – used to compute the product of input async iterables with themselves.

Return type

AsyncIterator

exceptions

exception async_stagger.exceptions.HappyEyeballsConnectError

Encapsulate all exceptions encountered during connection.

This exception is raised when create_connected_sock() fails with the detailed_exceptions argument set. The args of this exception consists of a list of exceptions occurred during all connection attempts and address resolution.