asyncio_win32.py 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. """
  2. Win32 asyncio event loop.
  3. Windows notes:
  4. - Somehow it doesn't seem to work with the 'ProactorEventLoop'.
  5. """
  6. from __future__ import unicode_literals
  7. from .base import EventLoop, INPUT_TIMEOUT
  8. from ..terminal.win32_input import ConsoleInputReader
  9. from .callbacks import EventLoopCallbacks
  10. from .asyncio_base import AsyncioTimeout
  11. import asyncio
  12. __all__ = (
  13. 'Win32AsyncioEventLoop',
  14. )
  15. class Win32AsyncioEventLoop(EventLoop):
  16. def __init__(self, loop=None):
  17. self._console_input_reader = ConsoleInputReader()
  18. self.running = False
  19. self.closed = False
  20. self.loop = loop or asyncio.get_event_loop()
  21. @asyncio.coroutine
  22. def run_as_coroutine(self, stdin, callbacks):
  23. """
  24. The input 'event loop'.
  25. """
  26. # Note: We cannot use "yield from", because this package also
  27. # installs on Python 2.
  28. assert isinstance(callbacks, EventLoopCallbacks)
  29. if self.closed:
  30. raise Exception('Event loop already closed.')
  31. timeout = AsyncioTimeout(INPUT_TIMEOUT, callbacks.input_timeout, self.loop)
  32. self.running = True
  33. try:
  34. while self.running:
  35. timeout.reset()
  36. # Get keys
  37. try:
  38. g = iter(self.loop.run_in_executor(None, self._console_input_reader.read))
  39. while True:
  40. yield next(g)
  41. except StopIteration as e:
  42. keys = e.args[0]
  43. # Feed keys to input processor.
  44. for k in keys:
  45. callbacks.feed_key(k)
  46. finally:
  47. timeout.stop()
  48. def stop(self):
  49. self.running = False
  50. def close(self):
  51. # Note: we should not close the asyncio loop itself, because that one
  52. # was not created here.
  53. self.closed = True
  54. self._console_input_reader.close()
  55. def run_in_executor(self, callback):
  56. self.loop.run_in_executor(None, callback)
  57. def call_from_executor(self, callback, _max_postpone_until=None):
  58. self.loop.call_soon_threadsafe(callback)
  59. def add_reader(self, fd, callback):
  60. " Start watching the file descriptor for read availability. "
  61. self.loop.add_reader(fd, callback)
  62. def remove_reader(self, fd):
  63. " Stop watching the file descriptor for read availability. "
  64. self.loop.remove_reader(fd)