aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop
diff options
context:
space:
mode:
authorNikita Slyusarev <nslus@yandex-team.com>2022-02-10 16:46:52 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:46:52 +0300
commitcd77cecfc03a3eaf87816af28a33067c4f0cdb59 (patch)
tree1308e0bae862d52e0020d881fe758080437fe389 /contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop
parentcdae02d225fb5b3afbb28990e79a7ac6c9125327 (diff)
downloadydb-cd77cecfc03a3eaf87816af28a33067c4f0cdb59.tar.gz
Restoring authorship annotation for Nikita Slyusarev <nslus@yandex-team.com>. Commit 1 of 2.
Diffstat (limited to 'contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop')
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_posix.py8
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_win32.py4
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/base.py10
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/inputhook.py30
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix.py84
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix_utils.py82
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/select.py432
-rw-r--r--contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/win32.py44
8 files changed, 347 insertions, 347 deletions
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_posix.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_posix.py
index 426ed96f67..737ca0ec00 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_posix.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_posix.py
@@ -67,10 +67,10 @@ class PosixAsyncioEventLoop(EventLoop):
inputstream.feed(data)
timeout.reset()
- # Quit when the input stream was closed.
- if stdin_reader.closed:
- self.stop()
-
+ # Quit when the input stream was closed.
+ if stdin_reader.closed:
+ self.stop()
+
self.loop.add_reader(stdin.fileno(), stdin_ready)
# Block this coroutine until stop() has been called.
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_win32.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_win32.py
index 45f5f52679..6e4e2ca9e7 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_win32.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/asyncio_win32.py
@@ -66,8 +66,8 @@ class Win32AsyncioEventLoop(EventLoop):
# was not created here.
self.closed = True
- self._console_input_reader.close()
-
+ self._console_input_reader.close()
+
def run_in_executor(self, callback):
self.loop.run_in_executor(None, callback)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/base.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/base.py
index db86face66..520ab9e366 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/base.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/base.py
@@ -74,12 +74,12 @@ class EventLoop(with_metaclass(ABCMeta, object)):
Call this function in the main event loop. Similar to Twisted's
``callFromThread``.
- :param _max_postpone_until: `None` or `time.time` value. For interal
+ :param _max_postpone_until: `None` or `time.time` value. For interal
use. If the eventloop is saturated, consider this task to be low
priority and postpone maximum until this timestamp. (For instance,
repaint is done using low priority.)
-
- Note: In the past, this used to be a datetime.datetime instance,
- but apparently, executing `time.time` is more efficient: it
- does fewer system calls. (It doesn't read /etc/localtime.)
+
+ Note: In the past, this used to be a datetime.datetime instance,
+ but apparently, executing `time.time` is more efficient: it
+ does fewer system calls. (It doesn't read /etc/localtime.)
"""
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/inputhook.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/inputhook.py
index bab1f4c003..44e0a60591 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/inputhook.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/inputhook.py
@@ -25,8 +25,8 @@ controls everything.
from __future__ import unicode_literals
import os
import threading
-from prompt_toolkit.utils import is_windows
-from .select import select_fds
+from prompt_toolkit.utils import is_windows
+from .select import select_fds
__all__ = (
'InputHookContext',
@@ -75,19 +75,19 @@ class InputHookContext(object):
# Flush the read end of the pipe.
try:
- # Before calling 'os.read', call select.select. This is required
- # when the gevent monkey patch has been applied. 'os.read' is never
- # monkey patched and won't be cooperative, so that would block all
- # other select() calls otherwise.
- # See: http://www.gevent.org/gevent.os.html
-
- # Note: On Windows, this is apparently not an issue.
- # However, if we would ever want to add a select call, it
- # should use `windll.kernel32.WaitForMultipleObjects`,
- # because `select.select` can't wait for a pipe on Windows.
- if not is_windows():
- select_fds([self._r], timeout=None)
-
+ # Before calling 'os.read', call select.select. This is required
+ # when the gevent monkey patch has been applied. 'os.read' is never
+ # monkey patched and won't be cooperative, so that would block all
+ # other select() calls otherwise.
+ # See: http://www.gevent.org/gevent.os.html
+
+ # Note: On Windows, this is apparently not an issue.
+ # However, if we would ever want to add a select call, it
+ # should use `windll.kernel32.WaitForMultipleObjects`,
+ # because `select.select` can't wait for a pipe on Windows.
+ if not is_windows():
+ select_fds([self._r], timeout=None)
+
os.read(self._r, 1024)
except OSError:
# This happens when the window resizes and a SIGWINCH was received.
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix.py
index f631dbd891..be70d61f19 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix.py
@@ -3,7 +3,7 @@ import fcntl
import os
import signal
import threading
-import time
+import time
from prompt_toolkit.terminal.vt100_input import InputStream
from prompt_toolkit.utils import DummyContext, in_main_thread
@@ -13,22 +13,22 @@ from .callbacks import EventLoopCallbacks
from .inputhook import InputHookContext
from .posix_utils import PosixStdinReader
from .utils import TimeIt
-from .select import AutoSelector, Selector, fd_to_int
+from .select import AutoSelector, Selector, fd_to_int
__all__ = (
'PosixEventLoop',
)
-_now = time.time
+_now = time.time
class PosixEventLoop(EventLoop):
"""
Event loop for posix systems (Linux, Mac os X).
"""
- def __init__(self, inputhook=None, selector=AutoSelector):
+ def __init__(self, inputhook=None, selector=AutoSelector):
assert inputhook is None or callable(inputhook)
- assert issubclass(selector, Selector)
+ assert issubclass(selector, Selector)
self.running = False
self.closed = False
@@ -37,7 +37,7 @@ class PosixEventLoop(EventLoop):
self._calls_from_executor = []
self._read_fds = {} # Maps fd to handler.
- self.selector = selector()
+ self.selector = selector()
# Create a pipe for inter thread communication.
self._schedule_pipe = os.pipe()
@@ -84,31 +84,31 @@ class PosixEventLoop(EventLoop):
# Set timeout again.
current_timeout[0] = INPUT_TIMEOUT
- # Quit when the input stream was closed.
- if stdin_reader.closed:
- self.stop()
-
+ # Quit when the input stream was closed.
+ if stdin_reader.closed:
+ self.stop()
+
self.add_reader(stdin, read_from_stdin)
self.add_reader(self._schedule_pipe[0], None)
with ctx:
while self._running:
# Call inputhook.
- if self._inputhook_context:
- with TimeIt() as inputhook_timer:
+ if self._inputhook_context:
+ with TimeIt() as inputhook_timer:
def ready(wait):
" True when there is input ready. The inputhook should return control. "
return self._ready_for_reading(current_timeout[0] if wait else 0) != []
self._inputhook_context.call_inputhook(ready)
- inputhook_duration = inputhook_timer.duration
- else:
- inputhook_duration = 0
+ inputhook_duration = inputhook_timer.duration
+ else:
+ inputhook_duration = 0
# Calculate remaining timeout. (The inputhook consumed some of the time.)
if current_timeout[0] is None:
remaining_timeout = None
else:
- remaining_timeout = max(0, current_timeout[0] - inputhook_duration)
+ remaining_timeout = max(0, current_timeout[0] - inputhook_duration)
# Wait until input is ready.
fds = self._ready_for_reading(remaining_timeout)
@@ -126,23 +126,23 @@ class PosixEventLoop(EventLoop):
# case.
tasks = []
low_priority_tasks = []
- now = None # Lazy load time. (Fewer system calls.)
+ now = None # Lazy load time. (Fewer system calls.)
for fd in fds:
# For the 'call_from_executor' fd, put each pending
# item on either the high or low priority queue.
if fd == self._schedule_pipe[0]:
for c, max_postpone_until in self._calls_from_executor:
- if max_postpone_until is None:
- # Execute now.
+ if max_postpone_until is None:
+ # Execute now.
tasks.append(c)
else:
- # Execute soon, if `max_postpone_until` is in the future.
- now = now or _now()
- if max_postpone_until < now:
- tasks.append(c)
- else:
- low_priority_tasks.append((c, max_postpone_until))
+ # Execute soon, if `max_postpone_until` is in the future.
+ now = now or _now()
+ if max_postpone_until < now:
+ tasks.append(c)
+ else:
+ low_priority_tasks.append((c, max_postpone_until))
self._calls_from_executor = []
# Flush all the pipe content.
@@ -185,8 +185,8 @@ class PosixEventLoop(EventLoop):
"""
Return the file descriptors that are ready for reading.
"""
- fds = self.selector.select(timeout)
- return fds
+ fds = self.selector.select(timeout)
+ return fds
def received_winch(self):
"""
@@ -230,23 +230,23 @@ class PosixEventLoop(EventLoop):
Call this function in the main event loop.
Similar to Twisted's ``callFromThread``.
- :param _max_postpone_until: `None` or `time.time` value. For interal
+ :param _max_postpone_until: `None` or `time.time` value. For interal
use. If the eventloop is saturated, consider this task to be low
priority and postpone maximum until this timestamp. (For instance,
repaint is done using low priority.)
"""
- assert _max_postpone_until is None or isinstance(_max_postpone_until, float)
+ assert _max_postpone_until is None or isinstance(_max_postpone_until, float)
self._calls_from_executor.append((callback, _max_postpone_until))
if self._schedule_pipe:
- try:
- os.write(self._schedule_pipe[1], b'x')
- except (AttributeError, IndexError, OSError):
- # Handle race condition. We're in a different thread.
- # - `_schedule_pipe` could have become None in the meantime.
- # - We catch `OSError` (actually BrokenPipeError), because the
- # main thread could have closed the pipe already.
- pass
+ try:
+ os.write(self._schedule_pipe[1], b'x')
+ except (AttributeError, IndexError, OSError):
+ # Handle race condition. We're in a different thread.
+ # - `_schedule_pipe` could have become None in the meantime.
+ # - We catch `OSError` (actually BrokenPipeError), because the
+ # main thread could have closed the pipe already.
+ pass
def stop(self):
"""
@@ -270,18 +270,18 @@ class PosixEventLoop(EventLoop):
def add_reader(self, fd, callback):
" Add read file descriptor to the event loop. "
- fd = fd_to_int(fd)
+ fd = fd_to_int(fd)
self._read_fds[fd] = callback
- self.selector.register(fd)
+ self.selector.register(fd)
def remove_reader(self, fd):
" Remove read file descriptor from the event loop. "
- fd = fd_to_int(fd)
-
+ fd = fd_to_int(fd)
+
if fd in self._read_fds:
del self._read_fds[fd]
- self.selector.unregister(fd)
+ self.selector.unregister(fd)
class call_on_sigwinch(object):
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix_utils.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix_utils.py
index 320df438ca..bb675ba9aa 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix_utils.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/posix_utils.py
@@ -2,7 +2,7 @@ from __future__ import unicode_literals
from codecs import getincrementaldecoder
import os
-import six
+import six
__all__ = (
'PosixStdinReader',
@@ -13,42 +13,42 @@ class PosixStdinReader(object):
"""
Wrapper around stdin which reads (nonblocking) the next available 1024
bytes and decodes it.
-
- Note that you can't be sure that the input file is closed if the ``read``
- function returns an empty string. When ``errors=ignore`` is passed,
- ``read`` can return an empty string if all malformed input was replaced by
- an empty string. (We can't block here and wait for more input.) So, because
- of that, check the ``closed`` attribute, to be sure that the file has been
- closed.
-
- :param stdin_fd: File descriptor from which we read.
- :param errors: Can be 'ignore', 'strict' or 'replace'.
- On Python3, this can be 'surrogateescape', which is the default.
-
- 'surrogateescape' is preferred, because this allows us to transfer
- unrecognised bytes to the key bindings. Some terminals, like lxterminal
- and Guake, use the 'Mxx' notation to send mouse events, where each 'x'
- can be any possible byte.
+
+ Note that you can't be sure that the input file is closed if the ``read``
+ function returns an empty string. When ``errors=ignore`` is passed,
+ ``read`` can return an empty string if all malformed input was replaced by
+ an empty string. (We can't block here and wait for more input.) So, because
+ of that, check the ``closed`` attribute, to be sure that the file has been
+ closed.
+
+ :param stdin_fd: File descriptor from which we read.
+ :param errors: Can be 'ignore', 'strict' or 'replace'.
+ On Python3, this can be 'surrogateescape', which is the default.
+
+ 'surrogateescape' is preferred, because this allows us to transfer
+ unrecognised bytes to the key bindings. Some terminals, like lxterminal
+ and Guake, use the 'Mxx' notation to send mouse events, where each 'x'
+ can be any possible byte.
"""
- # By default, we want to 'ignore' errors here. The input stream can be full
- # of junk. One occurrence of this that I had was when using iTerm2 on OS X,
- # with "Option as Meta" checked (You should choose "Option as +Esc".)
-
- def __init__(self, stdin_fd,
- errors=('ignore' if six.PY2 else 'surrogateescape')):
+ # By default, we want to 'ignore' errors here. The input stream can be full
+ # of junk. One occurrence of this that I had was when using iTerm2 on OS X,
+ # with "Option as Meta" checked (You should choose "Option as +Esc".)
+
+ def __init__(self, stdin_fd,
+ errors=('ignore' if six.PY2 else 'surrogateescape')):
assert isinstance(stdin_fd, int)
self.stdin_fd = stdin_fd
- self.errors = errors
+ self.errors = errors
# Create incremental decoder for decoding stdin.
# We can not just do `os.read(stdin.fileno(), 1024).decode('utf-8')`, because
# it could be that we are in the middle of a utf-8 byte sequence.
self._stdin_decoder_cls = getincrementaldecoder('utf-8')
- self._stdin_decoder = self._stdin_decoder_cls(errors=errors)
-
- #: True when there is nothing anymore to read.
- self.closed = False
+ self._stdin_decoder = self._stdin_decoder_cls(errors=errors)
+ #: True when there is nothing anymore to read.
+ self.closed = False
+
def read(self, count=1024):
# By default we choose a rather small chunk size, because reading
# big amounts of input at once, causes the event loop to process
@@ -56,27 +56,27 @@ class PosixStdinReader(object):
# loop. This will make the application feel unresponsive.
"""
Read the input and return it as a string.
-
- Return the text. Note that this can return an empty string, even when
- the input stream was not yet closed. This means that something went
- wrong during the decoding.
+
+ Return the text. Note that this can return an empty string, even when
+ the input stream was not yet closed. This means that something went
+ wrong during the decoding.
"""
- if self.closed:
- return b''
-
+ if self.closed:
+ return b''
+
# Note: the following works better than wrapping `self.stdin` like
# `codecs.getreader('utf-8')(stdin)` and doing `read(1)`.
# Somehow that causes some latency when the escape
# character is pressed. (Especially on combination with the `select`.)
try:
data = os.read(self.stdin_fd, count)
-
- # Nothing more to read, stream is closed.
- if data == b'':
- self.closed = True
- return ''
+
+ # Nothing more to read, stream is closed.
+ if data == b'':
+ self.closed = True
+ return ''
except OSError:
# In case of SIGWINCH
data = b''
- return self._stdin_decoder.decode(data)
+ return self._stdin_decoder.decode(data)
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/select.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/select.py
index f678f84c55..66e8e346b8 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/select.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/select.py
@@ -1,216 +1,216 @@
-"""
-Selectors for the Posix event loop.
-"""
-from __future__ import unicode_literals, absolute_import
-import sys
-import abc
-import errno
-import select
-import six
-
-__all__ = (
- 'AutoSelector',
- 'PollSelector',
- 'SelectSelector',
- 'Selector',
- 'fd_to_int',
-)
-
-def fd_to_int(fd):
- assert isinstance(fd, int) or hasattr(fd, 'fileno')
-
- if isinstance(fd, int):
- return fd
- else:
- return fd.fileno()
-
-
-class Selector(six.with_metaclass(abc.ABCMeta, object)):
- @abc.abstractmethod
- def register(self, fd):
- assert isinstance(fd, int)
-
- @abc.abstractmethod
- def unregister(self, fd):
- assert isinstance(fd, int)
-
- @abc.abstractmethod
- def select(self, timeout):
- pass
-
- @abc.abstractmethod
- def close(self):
- pass
-
-
-class AutoSelector(Selector):
- def __init__(self):
- self._fds = []
-
- self._select_selector = SelectSelector()
- self._selectors = [self._select_selector]
-
- # When 'select.poll' exists, create a PollSelector.
- if hasattr(select, 'poll'):
- self._poll_selector = PollSelector()
- self._selectors.append(self._poll_selector)
- else:
- self._poll_selector = None
-
- # Use of the 'select' module, that was introduced in Python3.4. We don't
- # use it before 3.5 however, because this is the point where this module
- # retries interrupted system calls.
- if sys.version_info >= (3, 5):
- self._py3_selector = Python3Selector()
- self._selectors.append(self._py3_selector)
- else:
- self._py3_selector = None
-
- def register(self, fd):
- assert isinstance(fd, int)
-
- self._fds.append(fd)
-
- for sel in self._selectors:
- sel.register(fd)
-
- def unregister(self, fd):
- assert isinstance(fd, int)
-
- self._fds.remove(fd)
-
- for sel in self._selectors:
- sel.unregister(fd)
-
- def select(self, timeout):
- # Try Python 3 selector first.
- if self._py3_selector:
- try:
- return self._py3_selector.select(timeout)
- except PermissionError:
- # We had a situation (in pypager) where epoll raised a
- # PermissionError when a local file descriptor was registered,
- # however poll and select worked fine. So, in that case, just
- # try using select below.
- pass
-
- try:
- # Prefer 'select.select', if we don't have much file descriptors.
- # This is more universal.
- return self._select_selector.select(timeout)
- except ValueError:
- # When we have more than 1024 open file descriptors, we'll always
- # get a "ValueError: filedescriptor out of range in select()" for
- # 'select'. In this case, try, using 'poll' instead.
- if self._poll_selector is not None:
- return self._poll_selector.select(timeout)
- else:
- raise
-
- def close(self):
- for sel in self._selectors:
- sel.close()
-
-
-class Python3Selector(Selector):
- """
- Use of the Python3 'selectors' module.
-
- NOTE: Only use on Python 3.5 or newer!
- """
- def __init__(self):
- assert sys.version_info >= (3, 5)
-
- import selectors # Inline import: Python3 only!
- self._sel = selectors.DefaultSelector()
-
- def register(self, fd):
- assert isinstance(fd, int)
- import selectors # Inline import: Python3 only!
- self._sel.register(fd, selectors.EVENT_READ, None)
-
- def unregister(self, fd):
- assert isinstance(fd, int)
- self._sel.unregister(fd)
-
- def select(self, timeout):
- events = self._sel.select(timeout=timeout)
- return [key.fileobj for key, mask in events]
-
- def close(self):
- self._sel.close()
-
-
-class PollSelector(Selector):
- def __init__(self):
- self._poll = select.poll()
-
- def register(self, fd):
- assert isinstance(fd, int)
- self._poll.register(fd, select.POLLIN)
-
- def unregister(self, fd):
- assert isinstance(fd, int)
-
- def select(self, timeout):
- tuples = self._poll.poll(timeout) # Returns (fd, event) tuples.
- return [t[0] for t in tuples]
-
- def close(self):
- pass # XXX
-
-
-class SelectSelector(Selector):
- """
- Wrapper around select.select.
-
- When the SIGWINCH signal is handled, other system calls, like select
- are aborted in Python. This wrapper will retry the system call.
- """
- def __init__(self):
- self._fds = []
-
- def register(self, fd):
- self._fds.append(fd)
-
- def unregister(self, fd):
- self._fds.remove(fd)
-
- def select(self, timeout):
- while True:
- try:
- return select.select(self._fds, [], [], timeout)[0]
- except select.error as e:
- # Retry select call when EINTR
- if e.args and e.args[0] == errno.EINTR:
- continue
- else:
- raise
-
- def close(self):
- pass
-
-
-def select_fds(read_fds, timeout, selector=AutoSelector):
- """
- Wait for a list of file descriptors (`read_fds`) to become ready for
- reading. This chooses the most appropriate select-tool for use in
- prompt-toolkit.
- """
- # Map to ensure that we return the objects that were passed in originally.
- # Whether they are a fd integer or an object that has a fileno().
- # (The 'poll' implementation for instance, returns always integers.)
- fd_map = dict((fd_to_int(fd), fd) for fd in read_fds)
-
- # Wait, using selector.
- sel = selector()
- try:
- for fd in read_fds:
- sel.register(fd)
-
- result = sel.select(timeout)
-
- if result is not None:
- return [fd_map[fd_to_int(fd)] for fd in result]
- finally:
- sel.close()
+"""
+Selectors for the Posix event loop.
+"""
+from __future__ import unicode_literals, absolute_import
+import sys
+import abc
+import errno
+import select
+import six
+
+__all__ = (
+ 'AutoSelector',
+ 'PollSelector',
+ 'SelectSelector',
+ 'Selector',
+ 'fd_to_int',
+)
+
+def fd_to_int(fd):
+ assert isinstance(fd, int) or hasattr(fd, 'fileno')
+
+ if isinstance(fd, int):
+ return fd
+ else:
+ return fd.fileno()
+
+
+class Selector(six.with_metaclass(abc.ABCMeta, object)):
+ @abc.abstractmethod
+ def register(self, fd):
+ assert isinstance(fd, int)
+
+ @abc.abstractmethod
+ def unregister(self, fd):
+ assert isinstance(fd, int)
+
+ @abc.abstractmethod
+ def select(self, timeout):
+ pass
+
+ @abc.abstractmethod
+ def close(self):
+ pass
+
+
+class AutoSelector(Selector):
+ def __init__(self):
+ self._fds = []
+
+ self._select_selector = SelectSelector()
+ self._selectors = [self._select_selector]
+
+ # When 'select.poll' exists, create a PollSelector.
+ if hasattr(select, 'poll'):
+ self._poll_selector = PollSelector()
+ self._selectors.append(self._poll_selector)
+ else:
+ self._poll_selector = None
+
+ # Use of the 'select' module, that was introduced in Python3.4. We don't
+ # use it before 3.5 however, because this is the point where this module
+ # retries interrupted system calls.
+ if sys.version_info >= (3, 5):
+ self._py3_selector = Python3Selector()
+ self._selectors.append(self._py3_selector)
+ else:
+ self._py3_selector = None
+
+ def register(self, fd):
+ assert isinstance(fd, int)
+
+ self._fds.append(fd)
+
+ for sel in self._selectors:
+ sel.register(fd)
+
+ def unregister(self, fd):
+ assert isinstance(fd, int)
+
+ self._fds.remove(fd)
+
+ for sel in self._selectors:
+ sel.unregister(fd)
+
+ def select(self, timeout):
+ # Try Python 3 selector first.
+ if self._py3_selector:
+ try:
+ return self._py3_selector.select(timeout)
+ except PermissionError:
+ # We had a situation (in pypager) where epoll raised a
+ # PermissionError when a local file descriptor was registered,
+ # however poll and select worked fine. So, in that case, just
+ # try using select below.
+ pass
+
+ try:
+ # Prefer 'select.select', if we don't have much file descriptors.
+ # This is more universal.
+ return self._select_selector.select(timeout)
+ except ValueError:
+ # When we have more than 1024 open file descriptors, we'll always
+ # get a "ValueError: filedescriptor out of range in select()" for
+ # 'select'. In this case, try, using 'poll' instead.
+ if self._poll_selector is not None:
+ return self._poll_selector.select(timeout)
+ else:
+ raise
+
+ def close(self):
+ for sel in self._selectors:
+ sel.close()
+
+
+class Python3Selector(Selector):
+ """
+ Use of the Python3 'selectors' module.
+
+ NOTE: Only use on Python 3.5 or newer!
+ """
+ def __init__(self):
+ assert sys.version_info >= (3, 5)
+
+ import selectors # Inline import: Python3 only!
+ self._sel = selectors.DefaultSelector()
+
+ def register(self, fd):
+ assert isinstance(fd, int)
+ import selectors # Inline import: Python3 only!
+ self._sel.register(fd, selectors.EVENT_READ, None)
+
+ def unregister(self, fd):
+ assert isinstance(fd, int)
+ self._sel.unregister(fd)
+
+ def select(self, timeout):
+ events = self._sel.select(timeout=timeout)
+ return [key.fileobj for key, mask in events]
+
+ def close(self):
+ self._sel.close()
+
+
+class PollSelector(Selector):
+ def __init__(self):
+ self._poll = select.poll()
+
+ def register(self, fd):
+ assert isinstance(fd, int)
+ self._poll.register(fd, select.POLLIN)
+
+ def unregister(self, fd):
+ assert isinstance(fd, int)
+
+ def select(self, timeout):
+ tuples = self._poll.poll(timeout) # Returns (fd, event) tuples.
+ return [t[0] for t in tuples]
+
+ def close(self):
+ pass # XXX
+
+
+class SelectSelector(Selector):
+ """
+ Wrapper around select.select.
+
+ When the SIGWINCH signal is handled, other system calls, like select
+ are aborted in Python. This wrapper will retry the system call.
+ """
+ def __init__(self):
+ self._fds = []
+
+ def register(self, fd):
+ self._fds.append(fd)
+
+ def unregister(self, fd):
+ self._fds.remove(fd)
+
+ def select(self, timeout):
+ while True:
+ try:
+ return select.select(self._fds, [], [], timeout)[0]
+ except select.error as e:
+ # Retry select call when EINTR
+ if e.args and e.args[0] == errno.EINTR:
+ continue
+ else:
+ raise
+
+ def close(self):
+ pass
+
+
+def select_fds(read_fds, timeout, selector=AutoSelector):
+ """
+ Wait for a list of file descriptors (`read_fds`) to become ready for
+ reading. This chooses the most appropriate select-tool for use in
+ prompt-toolkit.
+ """
+ # Map to ensure that we return the objects that were passed in originally.
+ # Whether they are a fd integer or an object that has a fileno().
+ # (The 'poll' implementation for instance, returns always integers.)
+ fd_map = dict((fd_to_int(fd), fd) for fd in read_fds)
+
+ # Wait, using selector.
+ sel = selector()
+ try:
+ for fd in read_fds:
+ sel.register(fd)
+
+ result = sel.select(timeout)
+
+ if result is not None:
+ return [fd_map[fd_to_int(fd)] for fd in result]
+ finally:
+ sel.close()
diff --git a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/win32.py b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/win32.py
index 18e356f088..0a3f63620c 100644
--- a/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/win32.py
+++ b/contrib/python/prompt-toolkit/py2/prompt_toolkit/eventloop/win32.py
@@ -15,7 +15,7 @@ from .utils import TimeIt
from ctypes import windll, pointer
from ctypes.wintypes import DWORD, BOOL, HANDLE
-import msvcrt
+import msvcrt
import threading
__all__ = (
@@ -29,23 +29,23 @@ INPUT_TIMEOUT_MS = int(1000 * INPUT_TIMEOUT)
class Win32EventLoop(EventLoop):
"""
Event loop for Windows systems.
-
- :param recognize_paste: When True, try to discover paste actions and turn
- the event into a BracketedPaste.
+
+ :param recognize_paste: When True, try to discover paste actions and turn
+ the event into a BracketedPaste.
"""
- def __init__(self, inputhook=None, recognize_paste=True):
+ def __init__(self, inputhook=None, recognize_paste=True):
assert inputhook is None or callable(inputhook)
self._event = HANDLE(_create_event())
- self._console_input_reader = ConsoleInputReader(recognize_paste=recognize_paste)
+ self._console_input_reader = ConsoleInputReader(recognize_paste=recognize_paste)
self._calls_from_executor = []
self.closed = False
self._running = False
- # Additional readers.
- self._read_fds = {} # Maps fd to handler.
-
+ # Additional readers.
+ self._read_fds = {} # Maps fd to handler.
+
# Create inputhook context.
self._inputhook_context = InputHookContext(inputhook) if inputhook else None
@@ -86,9 +86,9 @@ class Win32EventLoop(EventLoop):
windll.kernel32.ResetEvent(self._event)
self._process_queued_calls_from_executor()
- elif handle in self._read_fds:
- callback = self._read_fds[handle]
- callback()
+ elif handle in self._read_fds:
+ callback = self._read_fds[handle]
+ callback()
else:
# Fire input timeout event.
callbacks.input_timeout()
@@ -98,9 +98,9 @@ class Win32EventLoop(EventLoop):
"""
Return the handle that is ready for reading or `None` on timeout.
"""
- handles = [self._event, self._console_input_reader.handle]
- handles.extend(self._read_fds.keys())
- return _wait_for_handles(handles, timeout)
+ handles = [self._event, self._console_input_reader.handle]
+ handles.extend(self._read_fds.keys())
+ return _wait_for_handles(handles, timeout)
def stop(self):
self._running = False
@@ -114,8 +114,8 @@ class Win32EventLoop(EventLoop):
if self._inputhook_context:
self._inputhook_context.close()
- self._console_input_reader.close()
-
+ self._console_input_reader.close()
+
def run_in_executor(self, callback):
"""
Run a long running function in a background thread.
@@ -148,14 +148,14 @@ class Win32EventLoop(EventLoop):
def add_reader(self, fd, callback):
" Start watching the file descriptor for read availability. "
- h = msvcrt.get_osfhandle(fd)
- self._read_fds[h] = callback
+ h = msvcrt.get_osfhandle(fd)
+ self._read_fds[h] = callback
def remove_reader(self, fd):
" Stop watching the file descriptor for read availability. "
- h = msvcrt.get_osfhandle(fd)
- if h in self._read_fds:
- del self._read_fds[h]
+ h = msvcrt.get_osfhandle(fd)
+ if h in self._read_fds:
+ del self._read_fds[h]
def _wait_for_handles(handles, timeout=-1):