ryananguiano / async_property

Python decorator for async properties.
MIT License
82 stars 8 forks source link

async value setter #2

Closed kai3341 closed 4 years ago

kai3341 commented 5 years ago

Description

I'm trying to set value asynchronously. Is it possible? Setter must send value remotely. It's nothing difficult to mutate it locally

What I Did

    @async_property
    async def value(self, *args):
        connection = self.connection()
        key = self.__key(args)
        return await connection.get(key)

    @value.setter
    async def value(self, *args, newval):
        connection = self.connection()
        key = self.__key(args)
        return await connection.set(key, newval)

AttributeError: 'AsyncPropertyDescriptor' object has no attribute 'setter' Maybe it's my stupid mistake?

ryananguiano commented 5 years ago

It is not possible to use an async __set__ method; the call to __set__ must always be synchronous. This is because the purpose of the set operation is to assign a python object to a variable.

If you want to be able to set the value of an async_property, you must use async_cached_property. You can use a custom async method to do some asynchronous saving, and then overwrite the local cached value.

class Foo:
    @async_cached_property
    async def value(self):
        print('loading value')
        return 123

    async def set_value(self, value):
        print(f'async save: {value}')
        self.value = value
kai3341 commented 5 years ago

Nice. Thank a lot!

kai3341 commented 4 years ago

Now I know, how to make setter asyncronous: https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task So, we can create setter coroutine and add it to event loop without waiting result As (ugly) option, we can use loop.run_until_complete instead of await in syncronous code