84 lines
2.4 KiB
Python
84 lines
2.4 KiB
Python
"""
|
|
Win32 asyncio event loop.
|
|
|
|
Windows notes:
|
|
- Somehow it doesn't seem to work with the 'ProactorEventLoop'.
|
|
"""
|
|
from __future__ import unicode_literals
|
|
|
|
from .base import EventLoop, INPUT_TIMEOUT
|
|
from ..terminal.win32_input import ConsoleInputReader
|
|
from .callbacks import EventLoopCallbacks
|
|
from .asyncio_base import AsyncioTimeout
|
|
|
|
import asyncio
|
|
|
|
__all__ = (
|
|
'Win32AsyncioEventLoop',
|
|
)
|
|
|
|
|
|
class Win32AsyncioEventLoop(EventLoop):
|
|
def __init__(self, loop=None):
|
|
self._console_input_reader = ConsoleInputReader()
|
|
self.running = False
|
|
self.closed = False
|
|
self.loop = loop or asyncio.get_event_loop()
|
|
|
|
@asyncio.coroutine
|
|
def run_as_coroutine(self, stdin, callbacks):
|
|
"""
|
|
The input 'event loop'.
|
|
"""
|
|
# Note: We cannot use "yield from", because this package also
|
|
# installs on Python 2.
|
|
assert isinstance(callbacks, EventLoopCallbacks)
|
|
|
|
if self.closed:
|
|
raise Exception('Event loop already closed.')
|
|
|
|
timeout = AsyncioTimeout(INPUT_TIMEOUT, callbacks.input_timeout, self.loop)
|
|
self.running = True
|
|
|
|
try:
|
|
while self.running:
|
|
timeout.reset()
|
|
|
|
# Get keys
|
|
try:
|
|
g = iter(self.loop.run_in_executor(None, self._console_input_reader.read))
|
|
while True:
|
|
yield next(g)
|
|
except StopIteration as e:
|
|
keys = e.args[0]
|
|
|
|
# Feed keys to input processor.
|
|
for k in keys:
|
|
callbacks.feed_key(k)
|
|
finally:
|
|
timeout.stop()
|
|
|
|
def stop(self):
|
|
self.running = False
|
|
|
|
def close(self):
|
|
# Note: we should not close the asyncio loop itself, because that one
|
|
# was not created here.
|
|
self.closed = True
|
|
|
|
self._console_input_reader.close()
|
|
|
|
def run_in_executor(self, callback):
|
|
self.loop.run_in_executor(None, callback)
|
|
|
|
def call_from_executor(self, callback, _max_postpone_until=None):
|
|
self.loop.call_soon_threadsafe(callback)
|
|
|
|
def add_reader(self, fd, callback):
|
|
" Start watching the file descriptor for read availability. "
|
|
self.loop.add_reader(fd, callback)
|
|
|
|
def remove_reader(self, fd):
|
|
" Stop watching the file descriptor for read availability. "
|
|
self.loop.remove_reader(fd)
|