Python decorator for async properties.
.. image:: https://img.shields.io/pypi/v/async_property.svg :target: https://pypi.org/project/async-property/
.. image:: https://app.travis-ci.com/ryananguiano/async_property.svg?branch=master :target: https://app.travis-ci.com/github/ryananguiano/async_property
.. image:: https://readthedocs.org/projects/async-property/badge/?version=latest :target: https://async-property.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status
.. image:: https://pyup.io/repos/github/ryananguiano/async_property/shield.svg :target: https://pyup.io/repos/github/ryananguiano/async_property/ :alt: Updates
Python decorator for async properties.
To install async_property, run this command in your terminal:
.. code-block:: console
$ pip install async-property
Or if you have pipenv:
.. code-block:: console
$ pipenv install async-property
You can use @async_property
just as you would with @property
, but on an async function.
.. code-block:: python
class Foo:
@async_property
async def remote_value(self):
return await get_remote_value()
The property remote_value
now returns an awaitable coroutine.
.. code-block:: python
instance = Foo()
await instance.remote_value
Cached Properties
``@async_cached_property`` will call the function only once. Subsequent awaits to the property will return a cached value.
.. code-block:: python
class Foo:
@async_cached_property
async def value(self):
print('loading value')
return 123
>>> instance = Foo()
>>> instance.value
<AwaitableOnly "Foo.value">
>>> await instance.value
loading value
123
>>> await instance.value
123
>>> instance.value
123
>>> instance.value = 'abc'
>>> instance.value
'abc'
>>> await instance.value
'abc'
>>> del instance.value
>>> await instance.value
loading value
123
AwaitLoader
~~~~~~~~~~~
If you have an object with multiple cached properties, you can subclass ``AwaitLoader``. This will make your class instances awaitable and will load all ``@async_cached_property`` fields concurrently. ``AwaitLoader`` will call ``await instance.load()``, if it exists, before loading properties.
.. code-block:: python
class Foo(AwaitLoader):
async def load(self):
print('load called')
@async_cached_property
async def db_lookup(self):
return 'success'
@async_cached_property
async def api_call(self):
print('calling api')
return 'works every time'
>>> instance = await Foo()
load called
calling api
>>> instance.db_lookup
'success'
>>> instance.api_call
'works every time'
Features
--------
* Both regular and cached property.
* Cached properties can be accessed multiple times without repeating function call.
* Uses asyncio.Lock to ensure cached functions are called only once.
* Full test coverage with py.test
Credits
-------
This package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypackage`_ project template.
.. _Cookiecutter: https://github.com/audreyr/cookiecutter
.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage
The ObjectProxy_ class was taken from wrapt_ library by Graham Dumpleton.
.. _ObjectProxy: https://github.com/GrahamDumpleton/wrapt/blob/master/src/wrapt/wrappers.py
.. _wrapt: https://github.com/GrahamDumpleton/wrapt
=======
History
=======
0.2.2 (2023-07-03)
------------------
* Add Python 3.11 support and drop Python 3.6.
0.2.1 (2019-04-13)
------------------
* Update docs and readme
0.2.0 (2019-04-12)
------------------
* Use instance state to hold cache and locks
0.1.4 (2019-04-12)
------------------
* Fix inheritance issues on AwaitLoader
0.1.3 (2019-04-12)
------------------
* Cleanup code
0.1.2 (2019-04-12)
------------------
* Fix asyncio.Lock issues
0.1.1 (2019-04-11)
------------------
* Complete test coverage and update readme
0.1.0 (2019-04-11)
------------------
* First release on PyPI.