Skip to main content

AsyncED


PyPI version shields.io PyPI pyversions PyPI license


Async python for Event-Driven applications

Installation

pip install asynced

Usage

At the core of asynced lies StateVar. It can (but does not have to) contain a value, can be watched for changed, and can easily be mapped to other StateVar instances.

For the sake of brevity, next examples are assumed to be run from within an async function, as StateVar requires a running event loop..

Creating an empty state var is as easy as:

>>> from asynced import StateVar
>>> spam = StateVar()

We can check whether it is set:

>>> spam.is_set
False

Let's create an asyncio.Task that prints the spam value once it's set.

>>> async def print_spam():
...     print(await spam)
... 
... task = asyncio.create_task(print_spam)

Nothing is printed yet until we set the statevar:

>>> spam.set('Spam!')
Spam!

After we set the statevar, we see that print_spam printed the value.

Up to here, we've done nothing that asyncio.Future cannot do. But an asyncio.Future can only be set once, whereas a StateVar can be set to a different value as much as needed.

We can watch for any changes of a statevar by async iteration:

>>> async def print_spam_changes():
...     async for value in spam:
...         print(value)
... 
... task = asyncio.create_task(print_spam_changes)

Now any time we set spam to a different value, it'll be printed:

>>> spam.set('Spam and ham!')
Spam and ham!
>>> spam.set('Spam and eggs!')
Spam and eggs!

Neat eh?

A StateVar can also be constructed by passing async iterable, making it behave more like an asyncio.Task:

>>> async def slowrange(*args):
...     for i in range(*args):
...         await asyncio.sleep(1)
...         yield i
...
>>> count4 = StateVar(slowrange(4))
>>> await asyncio.sleep(3.14)
>>> await count4
2

As we see here, the statevar will set itself to the values from the async iterable in the background automatically.

Mapping

StateVar's can also be constructed by applying a function to another StateVar:

>>> count4_inv = StateVar(slowrange(4)).map(lambda i: -i)
>>> async for i in count4_inv:
...     print(i)

Now with one-second intervals, 0, -1, -2 and -3 will be printed.

StateVar.map only works for functions with a single argument, i.e. for one statevar at a time. But fear not, mapping multiple statevars together is possible by using asynced.statefunction. It transforms any function (a: A, b: B, ...) -> R into one that accepts State's (State is the superclass of StateVar) and returns a new StateVar (or some other that subclasses State), (a: State[A], b: State[B], ...) -> StateVar[R].

>>> from asynced import statefunction
>>> @statefunction
... def sadd(_a: float, _b: float) -> float:
...    return _a + _b
... 
>>> a, b = StateVar(), StateVar()
>>> c = sadd(a, b)

Here, c will be set iff both a and b are set:

>>>import calendar c.is_set
False
>>> a.set(12)
c.is_set
False
>>> b.set(30)
>>> await c
42

Now, every time that a or b change, c will change as well.

StateTuple

In the same way as StateVar, a StateTuple can be awaited to get the current value once it's available, and async-iterated to get the values once they are set. Additionally, it can also be used as a tuple of individual StateVar instances.

>>> st = StateTuple(2)  # equivalent StateTuple(StateVar(), StateVar())
>>> st[0].set('spam')
>>> st[1].set('ham')
>>> await st
('spam', 'ham')
>>> await st[-1]
'ham'
>>> st[1] = 'eggs'  # equivalent to st[1].set('eggs')
>>> await st
('spam', 'eggs')
>>> s0, s1 = st
>>> await s1
'eggs'
>>> st2 = 2 * st  # equivalent to StateTuple((st[0], st[1], st[0], st[1]))
>>> st2[2] = 'bacon'
>>> await st2
('bacon', 'eggs', 'bacon', 'eggs')
>>> await st
('bacon', 'eggs')

StateDict

Like StateTuple, a StateDict is a collection of individual StateVar's. It is more similar to a collections.defaultdict than a regular dict, because accessing keys without values will return an empty StateVar.

>>> sd = StateDict()
>>> await sd
{}
>>> sd['spam'] = 'Spam!'
>>> await sd
{'spam': 'Spam!'}
>>> ham = sd['ham']
>>> ham.is_set
False
>>> list(sd.keys())
['spam']
>>> sd['ham'] = 'Ham and eggs!'
>>> await ham
'Ham and eggs!'

.get()

StateVar, StateTuple and StateDict all implement a .get() method, that can be used to get the current value, without having to use await. If no value has been set, it will raise a LookupError. Alternatively, you can pass a default value, that is to be returned in case no value is set.

Error handling

If the async iterable used to create e.g. a StateVar raises an error, the .is_error property will become True, and the error will be raised when its awaited, or when.get or .map are called. The exception will propagate to its mapped "child" State's.

If the async iterable is exhausted (or raises StopAsyncIteration directly), .is_stopped will be set to True instead, and StopAsyncIteration will be only reraised for the waiters of __aiter__ and __anext__.

API reference

*~ coming soon ~*

Release files for asynced 1.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for asynced 1.3.1
File Size Uploaded
asynced-1.3.1.tar.gz 18.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for asynced 1.3.1
File Interpreter ABI Platform
asynced-1.3.1-py3-none-any.whl Python 3 none any Details

Total release size: 37.3 kB

Release files / asynced-1.3.1.tar.gz

Download URL asynced-1.3.1.tar.gz
Size 18.8 kB
Tags Source
SHA-256 checksum
How to use checksums
b3d4d535182e607d2ddaaeeaf0f8aa23fc80f5c60b37ef9a54ba9e9f9fd7dff3
BLAKE2b-256 checksum
How to use checksums
be7882b203fa21f046044d7cdf504d7458d6e4812d4c3d5071f996e10f5c34ec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.1.13 CPython/3.10.4 Linux/5.13.0-44-generic

Release files / asynced-1.3.1-py3-none-any.whl

Download URL asynced-1.3.1-py3-none-any.whl
Size 18.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5e27967ab4a37ccd1c5db51200063fedf6007770ca260e26796f61185909db34
BLAKE2b-256 checksum
How to use checksums
116a6a4a561c3287eae2ea7b9576d12c3d49a799121f16b0b644b959e5cb1dfd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/1.1.13 CPython/3.10.4 Linux/5.13.0-44-generic

Release history Release notifications | RSS feed

This release

1.3.1 This release

2 release files

1.3.0

2 release files

1.2.1

2 release files

1.2.0

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page