This release is a pre-release and may not be stable for production use.
EAsync – easy async decorator and promises
@async
Decorator around the functions for them to be asynchronous.
Used as a simple decorator or along with named arguments. Preserves function’s or method’s docs, names and other stuff using functools.wraps.
When the wrapped function is called, it produces the Promise of itself.
Usage:
>>> from easync import async >>> @async >>> def f1(): >>> # some heavy-weight code
>>> @async(daemon=True, print_exception=False) >>> def f2(): >>> # some faulty daemon we don't really care about
>>> @async(print_exception=logging.WARNING) >>> def f3(): >>> # setting another logging level
>>> f1().wait() <result> >>> f2() # started daemon easync.Promise(...) >>> f3().then(callback, error) # notice, here the print_exception is suppressed (see Promise doc for more) easync.Promise(...)
- param function:
The function to be decorated.
- param Boolean daemon:
Optional. Create the daemon thread, that will die when no other threads left.
- param print_exception:
Log level to log the exception, if any, or None to mute it. See logging.
- param no_promise:
Will not return a thing, instead of returning Promise, good for decorating, for example, Tornado handlers.
- return:
Wrapped function, Promise generator.
Promise
This is a threading wrapper that performs asynchronous call of the provided function. The behaviour is inspired by JavaScript Promises, but differs in several points.
First, the resolution is based upon the return of the function beneath. On successful return, the result is stored in Promise.result On exception, exception is stored in Promise.exception More about how Promise resolves in Resolving Promises.
You can add callbacks by using methods Promise.then or Promise.catch They will create a new Promise resolving in either the resolution of the previous one or the underlying callback.
If at the final stage no exception is processed or were generated new ones, they will be printed.
Basic usage:
>>> from easync import Promise >>> promise = Promise(func)(...args) >>> promise.wait() <result> # if any >>> promise.result <result> # if any >>> promise.exception Exception # if something went wrong >>> promise.exc_info Tuple (Exception.__class__, Exception, traceback) # if any
Callbacks usage:
>>> def callback(result): >>> do_stuff(result) >>> def error(exception, exc_info): >>> my_log(exception, exc_info=exc_info) >>> def some_final(_): >>> cleanup() >>> Promise(func)(...args).then(callback, error).then(some_final) Promise(...)
- Promise.Callable
The to-be-runned function.
- Promise.result
This parameter holds the result the underlying function returned.
- Promise.exception
This parameter holds the exception if the underlying function fails.
- Promise.exc_info
This parameter holds the exception information tuple if the underlying function fails and the tuple was recovered. In case of Promise.reject, it will be None.
- Promise.resolved
True if the function resolves. More about it in Resolving Promises.
- Promise.started
threading.Event, sets when thread is started.
- Promise.finished
threading.Event, sets when thread is finished, no matter where had it been resolved or not.
- Promise.print_exception
Enables exception printout if caught. Uses logging to do so and has to be one of logging levels. False or None disable. Also automatically sets to False when a dependent Promise created through Promise.then or Promise.catch.
Resolving Promises
Functions
If the Promise is constructed with a function, it will resolve in it’s return or reject with the caught exception.
Other Promises
Just resolves in the same way the other one is resolved. Printouts will be suppressed in the first one.
Events and Conditions
If Promise is based on threading.Event or threading.Condition, it is resolved when the underlying Event or Condition occurs. The type testing is duck-type for having the wait method, so anything using the interface of waiting can be resolved, for example other Promises, or threads.
The resolving is based on testing is_failed on the object, and if that one returns, the Promise rejects. Otherwise, the get_result is called to obtain the result. Both are duck-type thingeys.
Anything else
Resolves successfully with the result equals to the passed-in argument.
Promise.__init__
__init__(function[, daemon=False, print_exception=logging.ERROR])
The constructor creates a threading.Thread wrapping the function. To start it, call the resulting object as a function with it’s arguments. (Explained in Promise.__call__)
>>> promise = Promise(func, print_exception=None) >>> promise()
- param function:
Function, Event, Condition, or anything else to resolve.
- param daemon:
Sets up daemon flag in the thread. May be set later. Optional.
- param print_exception:
Sets up the final exception printing level. Pass False to suppress.
Promise.__call__
__call__(*args, **kwargs)
Starts the thread and passes the arguments of the function into it. Returns self, for simple adding Promise.then, Promise.wait or Promise.catch.
Promise.wait
wait([timeout=None])
Pauses the current thread to wait until the underlying promise resolves.
If timeout is set, raises easync.TimeoutError if it’s reached.
Returns result of the underlying function if there’s any.
Promise.then
then([resolved=None, rejected=None, print_exception=Promise.print_exception])
This method sets callbacks for a Promise.
NOTE this method suppresses the Promise default error handling by setting Promise.print_exception to False. You can then re-enable printouts manually, overriding the Promise.print_exception yourself.
NOTE calling this method twice on the same Promise object will result in duplicated exception printouts unless changed.
The result is a new Promise which resolves in:
- callback exception:
If the called callback (either resolved or rejected) failed or raised anything.
- reject:
If the underlying Promise rejected and no rejected callback was passed.
- callback return:
The result of the called callback.
- resolve:
The result of the underlying Promise if it resolves and no resolved callback was passed.
This is done to have this kind of behaviour:
>>> Promise(action)(...args).then(parse_result).then(parse_one_more_result).catch(any_exception).then(cleanup)
- function resolved(result):
The positive callback for the Promise. Has to accept one positional argument - the result.
- function rejected(exception, exc_info):
The negative callback for the Promise. Has to accept two positional arguments - the caught exception and it’s exc_info.
- print_exception:
Passed into the corresponding argument of the newly created Promise.
- return:
New Promise.
Promise.catch
catch([callback=None, print_exception=Promise.print_exception])
The same as Promise.then (resolved=None, callback, print_exception).
Promise static methods
Promise.resolve
Promise.resolve(thing)
Resolves thing, regardless of what it is, to result.
- param thing:
any
- return:
resolved Promise with the Promise.result equals to thing.
Promise.reject
Promise.reject(thing)
Rejects thing, regardless of what it is.
NOTE, if this will be called, the Promise.exc_info will be set None.
- param thing:
any
- return:
rejected Promise with the Promise.exception equals to thing.
Promise.all
Promise.all(things)
Resolves when all the items in the enumerate(things) are resolved. Or rejects when any of the items is rejected.
- param things:
list of things or anything to be enumerate’d.
- result:
list of results of all the Promises for each of the items.
- exception:
first caught exception.
Promise.race
Promise.race(things)
Resolves when any of the items in the enumerate(things) is resolved. Or rejects when any of the items is rejected.
- param things:
list of things or anything to be enumerate’d.
- result:
the result of the first resolved item.
- exception:
first caught exception.
Other functions
get_result
get_result(obj)
Returns the first found attribute of result or success of the object obj, if any. Otherwise returns None.
is_failed
is_failed(obj)
Returns:
- found property:
if one of error, exception, failure is found.
- True:
if one of failed or is_failed is true.
- True:
if success is present and is False.
- None:
Otherwise
Metadata
Release files for easync 1.2.0b2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| easync-1.2.0b2.tar.gz | 12.5 kB | Without provenance | Details for easync-1.2.0b2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| easync-1.2.0b2-py2.py3-none-any.whl | Python 2, Python 3 | none | any | Details for easync-1.2.0b2-py2.py3-none-any.whl |
Total release size: 27.7 kB
Release files / easync-1.2.0b2.tar.gz
| Download URL | easync-1.2.0b2.tar.gz |
|---|---|
| Size | 12.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
079f25d0d1c325e322473159fb9b1a77a24a1f84ebf143065eed3d418f0b0471
|
|
BLAKE2b-256 checksum How to use checksums |
7bd1fc728d97a9f0c8e2e12f93097b1d1d1f9e1304f71a210bad99b1005bc3c3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
Release files / easync-1.2.0b2-py2.py3-none-any.whl
| Download URL | easync-1.2.0b2-py2.py3-none-any.whl |
|---|---|
| Size | 15.2 kB |
| Tags | Python 2 Python 3 |
|
SHA-256 checksum How to use checksums |
9f5b49cc8e0d612e1a383a697fcd90c8b61c4377f2605603d04b71b03bbecb2e
|
|
BLAKE2b-256 checksum How to use checksums |
5e9728016350031c2de32cb950522b22f24e4cb34ef4189cb914929fe2c424ed
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
Security for easync 1.2.0b2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.