dabeaz / curio

Good Curio!
Other
4.04k stars 243 forks source link

Support other awaitables #173

Closed dimaqq closed 7 years ago

dimaqq commented 7 years ago

I was trying to write a proxy, and following works:

async def test(): pass

class Proxy:
    def __init__(self, c): self.c = c
    def __await__(self): return self.c.__await__()
    def send(self, x): return self.c.send(x)
    def throw(self, type, value=None, traceback=None): return self.x.throw(type, value, traceback)
    def close(self): return self.c.close()

curio.run(Proxy(test()))

While I was getting there I made mistake (forgot to call actual coroutine) and call crashed, which led to another error (which is what this bug is about).

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
/Users/dima/.pyenv/versions/3.6.0/envs/daw-popular/lib/python3.6/site-packages/curio/kernel.py in _run(self, coro, shutdown)
    835                         if current.next_exc is None:
--> 836                             trap = current._send(current.next_value)
    837                             current.next_value = None

<ipython-input-29-61870aa9001a> in send(self, x)
      3     def __await__(self): return self.c.__await__()
----> 4     def send(self, x): return self.c.send(x)
      5     def throw(self, type, value=None, traceback=None): return self.x.throw(type, value, traceback)

AttributeError: 'function' object has no attribute 'send'

During handling of the above exception, another exception occurred:

AttributeError                            Traceback (most recent call last)
<ipython-input-45-76500f36655d> in <module>()
----> 1 curio.run(Proxy(test))

/Users/dima/.pyenv/versions/3.6.0/envs/daw-popular/lib/python3.6/site-packages/curio/kernel.py in run(coro, log_errors, with_monitor, selector, warn_if_task_blocks_for, **extra)
    962
    963     with kernel:
--> 964         return kernel.run(coro)
    965
    966 __all__ = ['Kernel', 'run', 'BlockingTaskWarning']

/Users/dima/.pyenv/versions/3.6.0/envs/daw-popular/lib/python3.6/site-packages/curio/kernel.py in run(self, coro, shutdown)
    265         self._local.running = True
    266         try:
--> 267             self._run(coro, shutdown=shutdown)
    268         finally:
    269             self._local.running = False

/Users/dima/.pyenv/versions/3.6.0/envs/daw-popular/lib/python3.6/site-packages/curio/kernel.py in _run(self, coro, shutdown)
    887                     _cleanup_task(current, exc=exc)
    888                     if self._log_errors:
--> 889                         log.error('Curio: Task Crash: %s' % current, exc_info=True)
    890
    891                 except:  # (SystemExit, KeyboardInterrupt):

/Users/dima/.pyenv/versions/3.6.0/envs/daw-popular/lib/python3.6/site-packages/curio/task.py in __str__(self)
     60
     61     def __str__(self):
---> 62         return self.coro.__qualname__
     63
     64     def __del__(self):

AttributeError: 'Proxy' object has no attribute '__qualname__'

Now, there is Proxy.__qualname__ per PEP-3155, but there is no such thing as Proxy(...).__qualname__. This magic is not inherited by objects of the class.

dabeaz commented 7 years ago

Aside from the qualname issue, does this actually work? I guess I can't see any reason why it wouldn't. Hmmm. Interesting.

dimaqq commented 7 years ago

@dabeaz correct invocation works, wrong invocation dies with 'function' object has no attribute 'send', which is consistent...

dabeaz commented 7 years ago

Made a fix for this.