Package: asynced
AsyncEDAsyncpython forEvent-Driven applicationsInstallationpipinstallasyncedUsageAt the core ofasyncedliesStateVar. It can (but does not have to) contain
a value, can be watched for changed, and can easily be mapped to otherStateVarinstances.For the sake of brevity, next examples are assumed to be run from within an async function, asStateVarrequires a running event loop..Creating an empty state var is as easy as:>>>fromasyncedimportStateVar>>>spam=StateVar()We can check whether it is set:>>>spam.is_setFalseLet's create anasyncio.Taskthat prints the spam value once it's set.>>>asyncdefprint_spam():...print(awaitspam)......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 thatprint_spamprinted the value.Up to here, we've done nothing thatasyncio.Futurecannot do. But anasyncio.Futurecan only be set once, whereas aStateVarcan be set to a
different value as much as needed.We can watch for any changes of a statevar by async iteration:>>>asyncdefprint_spam_changes():...asyncforvalueinspam:...print(value)......task=asyncio.create_task(print_spam_changes)Now any time we setspamto 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?AStateVarcan also be constructed by passing async iterable, making it
behave more like anasyncio.Task:>>>asyncdefslowrange(*args):...foriinrange(*args):...awaitasyncio.sleep(1)...yieldi...>>>count4=StateVar(slowrange(4))>>>awaitasyncio.sleep(3.14)>>>awaitcount42As we see here, the statevar will set itself to the values from the async
iterable in the background automatically.MappingStateVar's can also be constructed by applying a function to anotherStateVar:>>>count4_inv=StateVar(slowrange(4)).map(lambdai:-i)>>>asyncforiincount4_inv:...print(i)Now with one-second intervals,0,-1,-2and-3will be printed.StateVar.maponly 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 usingasynced.statefunction. It transforms any function(a: A, b: B, ...) -> Rinto one that acceptsState's (Stateis the superclass ofStateVar) and returns a
newStateVar(or some other that subclassesState),(a: State[A], b: State[B], ...) -> StateVar[R].>>>fromasyncedimportstatefunction>>>@statefunction...defsadd(_a:float,_b:float)->float:...return_a+_b...>>>a,b=StateVar(),StateVar()>>>c=sadd(a,b)Here,cwill be set iff bothaandbare set:>>>import calendar c.is_setFalse>>>a.set(12)c.is_setFalse>>>b.set(30)>>>awaitc42Now, every time thataorbchange,cwill change as well.StateTupleIn the same way asStateVar, aStateTuplecan 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 individualStateVarinstances.>>>st=StateTuple(2)# equivalent StateTuple(StateVar(), StateVar())>>>st[0].set('spam')>>>st[1].set('ham')>>>awaitst('spam', 'ham')>>>awaitst[-1]'ham'>>>st[1]='eggs'# equivalent to st[1].set('eggs')>>>awaitst('spam', 'eggs')>>>s0,s1=st>>>awaits1'eggs'>>>st2=2*st# equivalent to StateTuple((st[0], st[1], st[0], st[1]))>>>st2[2]='bacon'>>>awaitst2('bacon', 'eggs', 'bacon', 'eggs')>>>awaitst('bacon', 'eggs')StateDictLikeStateTuple, aStateDictis a collection of individualStateVar's.
It is more similar to acollections.defaultdictthan a regular dict, because
accessing keys without values will return an emptyStateVar.>>>sd=StateDict()>>>awaitsd{}>>>sd['spam']='Spam!'>>>awaitsd{'spam': 'Spam!'}>>>ham=sd['ham']>>>ham.is_setFalse>>>list(sd.keys())['spam']>>>sd['ham']='Ham and eggs!'>>>awaitham'Ham and eggs!'.get()StateVar,StateTupleandStateDictall implement a.get()method,
that can be used to get the current value, without having to useawait.
If no value has been set, it will raise aLookupError. Alternatively,
you can pass adefaultvalue, that is to be returned in case no value is set.Error handlingIf the async iterable used to create e.g. aStateVarraises an error,
the.is_errorproperty will becomeTrue, and the error will be raised when
its awaited, or when.getor.mapare called. The exception will propagate
to its mapped "child"State's.If the async iterable is exhausted (or raisesStopAsyncIterationdirectly),.is_stoppedwill be set toTrueinstead, andStopAsyncIterationwill beonlyreraised for the waiters of__aiter__and__anext__.API reference*~ coming soon ~*