Skip to content

Commit f0f0d9a

Browse files
committed
session: allow polling on a provided fd
1 parent d8830e8 commit f0f0d9a

File tree

7 files changed

+56
-0
lines changed

7 files changed

+56
-0
lines changed

neovim/api/common.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,10 @@ def threadsafe_call(self, fn, *args, **kwargs):
211211
"""Wrapper for Session.threadsafe_call."""
212212
self._session.threadsafe_call(fn, *args, **kwargs)
213213

214+
def poll_fd(self, fd, on_readable=None, on_writable=None):
215+
"""Wrapper around `Session.poll_fd`."""
216+
return self._session.poll_fd(fd, on_readable, on_writable)
217+
214218
def next_message(self):
215219
"""Wrapper for Session.next_message."""
216220
msg = self._session.next_message()

neovim/msgpack_rpc/async_session.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ def threadsafe_call(self, fn):
3232
"""Wrapper around `MsgpackStream.threadsafe_call`."""
3333
self._msgpack_stream.threadsafe_call(fn)
3434

35+
def poll_fd(self, fd, on_readable, on_writable):
36+
"""Wrapper around `BaseEventLoop.poll_fd`."""
37+
return self._msgpack_stream.poll_fd(fd, on_readable, on_writable)
38+
3539
def request(self, method, args, response_cb):
3640
"""Send a msgpack-rpc request to Nvim.
3741

neovim/msgpack_rpc/event_loop/asyncio.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,18 @@ def _stop(self):
110110
def _threadsafe_call(self, fn):
111111
self._loop.call_soon_threadsafe(fn)
112112

113+
def _poll_fd(self, fd, on_readable, on_writable):
114+
if on_readable is not None:
115+
self._loop.add_reader(fd, on_readable)
116+
if on_writable is not None:
117+
self._loop.add_writer(fd, on_writable)
118+
def cancel():
119+
if on_readable is not None:
120+
self._loop.remove_reader(fd)
121+
if on_writable is not None:
122+
self._loop.remove_writer(fd)
123+
return cancel
124+
113125
def _setup_signals(self, signals):
114126
self._signals = list(signals)
115127
for signum in self._signals:

neovim/msgpack_rpc/event_loop/base.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,18 @@ def threadsafe_call(self, fn):
121121
"""
122122
self._threadsafe_call(fn)
123123

124+
def poll_fd(self, fd, on_readable=None, on_writable=None):
125+
"""
126+
Invoke callbacks when the fd is ready for reading and/or writing. if `on_readable` is not None, it should be callback, which will be invokedi (with no arguments) when the fd is ready for writing. Similarily if `on_writable` is not None it will be invoked when the fd is ready for writing.
127+
128+
Only one callback (of each kind) can be registered on the same fd at a time. If both readability and writability should be monitored, both callbacks must be registered by the same `poll_fd` call.
129+
130+
Returns a function that deactivates the callback(s).
131+
"""
132+
if on_readable is None and on_writable is None:
133+
raise ValueError("poll_fd: At least one of `on_readable` and `on_writable` must be present")
134+
return self._poll_fd(fd, on_readable, on_writable)
135+
124136
def run(self, data_cb):
125137
"""Run the event loop."""
126138
if self._error:

neovim/msgpack_rpc/event_loop/uv.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,22 @@ def _on_async(self, handle):
106106
while self._callbacks:
107107
self._callbacks.popleft()()
108108

109+
def _poll_fd(self, fd, on_readable, on_writable):
110+
poll = pyuv.Poll(self._loop, fd)
111+
events = 0
112+
if on_readable is not None:
113+
events |= pyuv.UV_READABLE
114+
if on_writable is not None:
115+
events |= pyuv.UV_WRITABLE
116+
def callback(poll_handle, evts, errorno):
117+
if evts & pyuv.UV_READABLE:
118+
on_readable()
119+
if evts & pyuv.UV_WRITABLE:
120+
on_writable()
121+
122+
poll.start(events, callback)
123+
return poll.stop
124+
109125
def _setup_signals(self, signals):
110126
self._signal_handles = []
111127

neovim/msgpack_rpc/msgpack_stream.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ def threadsafe_call(self, fn):
3131
"""Wrapper around `BaseEventLoop.threadsafe_call`."""
3232
self._event_loop.threadsafe_call(fn)
3333

34+
def poll_fd(self, fd, on_readable, on_writable):
35+
"""Wrapper around `BaseEventLoop.poll_fd`."""
36+
return self._event_loop.poll_fd(fd, on_readable, on_writable)
37+
3438
def send(self, msg):
3539
"""Queue `msg` for sending to Nvim."""
3640
debug('sent %s', msg)

neovim/msgpack_rpc/session.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ def greenlet_wrapper():
3939

4040
self._async_session.threadsafe_call(greenlet_wrapper)
4141

42+
def poll_fd(self, fd, on_readable, on_writable):
43+
"""Wrapper around `AsyncSession.threadsafe_call`."""
44+
self._async_session.poll_fd(fd, on_readable, on_writable)
45+
4246
def next_message(self):
4347
"""Block until a message(request or notification) is available.
4448

0 commit comments

Comments
 (0)