Setting a descriptor in python3.5 asynchronously
<p>I can write a descriptor returning a future which could be awaited on.</p>

<pre><code>class AsyncDescriptor:
    def __get__(self, obj, cls=None):
         # generate some async future here
         return future

    def __set__(self, obj, value):
         # generate some async future here
         return future

class Device:
    attr=AsyncDescriptor()

device=Device()
</code></pre>

<p>Now I can get the value in a coroutine with <code>value=await device.attr</code>.</p>

<p>How would I set this attribute?</p>

<ul>
<li><code>await device.attr=5</code> -> SyntaxError: can't assign to await expression</li>
<li><code>await setattr(device, 'attr', 5)</code> -> TypeError: object NoneType can't be used in 'await' expression</li>
<li><code>device.attr=5</code> -> RuntimeWarning: coroutine '__set__' was never awaited</li>
</ul>

<p>What you are trying to do is not possible (with Python 3.5).</p>

<p>While it may be sensible for <code>__get__</code> to return a Future, making <code>__set__</code> async is simply not supported by Python 3.5. The return value of <code>__set__</code> is ignored by Python since there is no "return value" of assignments. And the call to <code>__set__</code> is always synchronous. Something like <code>a = (b.c = 5)</code> actually raises a <code>SyntaxError</code> as you already noticed.</p>

<p>If async assignments like <code>await device.attr = 5</code> were allowed, there would probably be a separate protocol for async descriptors, i.e. with coroutines <code>__aget__</code> and <code>__aset__</code> as special methods in analogy to async context manager (<code>async with</code> / <code>__aenter__</code> ) and async iteration (<code>async for</code> / <code>__aiter__</code>). See <a href="https://www.python.org/dev/peps/pep-0492/" rel="nofollow">PEP 492</a> for the design decisions behind the <code>async</code> / <code>await</code> support.</p>

<p>Also note that <code>__get__</code> returning a future does not make <code>__get__</code> a coroutine.</p>

<p>Without further context, it looks like you want to hide something behind the attribute access abstraction provided by the descriptor protocol which should better be done explicitly, but that's up to you of course. </p>

python python-3.5 python-asyncio descriptor