Skip to content

Commit

Permalink
Feature: switch from select.select to selectors
Browse files Browse the repository at this point in the history
Use `DefaultSelector` as automatically selected most efficient.
Use context manager for not holding resources.
  • Loading branch information
penguinolog committed Dec 8, 2023
1 parent fc61c67 commit 9246088
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 33 deletions.
37 changes: 19 additions & 18 deletions urwid/event_loop/select_loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

import contextlib
import heapq
import select
import selectors
import time
import typing
from contextlib import suppress
Expand All @@ -43,7 +43,7 @@

class SelectEventLoop(EventLoop):
"""
Event loop based on :func:`select.select`
Event loop based on :func:`selectors.DefaultSelector.select`
"""

def __init__(self) -> None:
Expand Down Expand Up @@ -159,28 +159,29 @@ def _loop(self) -> None:
fds = list(self._watch_files)
tm: float | Literal["idle"] | None = None

if self._alarms or self._did_something:
timeout = 0.0
with selectors.DefaultSelector() as selector:
for fd in fds:
selector.register(fd, selectors.EVENT_READ)

if self._alarms:
timeout_ = self._alarms[0][0]
tm = timeout_
timeout = max(timeout, timeout_ - time.time())

if self._did_something and (not self._alarms or (self._alarms and timeout > 0)):
if self._alarms or self._did_something:
timeout = 0.0
tm = "idle"

if fds:
ready, _w, _err = select.select(fds, [], fds, timeout)
if self._alarms:
timeout_ = self._alarms[0][0]
tm = timeout_
timeout = max(timeout, timeout_ - time.time())

if self._did_something and (not self._alarms or (self._alarms and timeout > 0)):
timeout = 0.0
tm = "idle"

ready = [event.fd for event, _ in selector.select(timeout)]

elif fds:
ready = [event.fd for event, _ in selector.select()]
else:
ready = []

elif fds:
ready, _w, _err = select.select(fds, [], fds)
else:
ready = []

if not ready:
if tm == "idle":
self._entering_idle()
Expand Down
17 changes: 9 additions & 8 deletions urwid/vterm.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import fcntl
import os
import pty
import select
import selectors
import signal
import struct
import sys
Expand Down Expand Up @@ -1689,13 +1689,14 @@ def remove_watch(self) -> None:
self.main_loop.remove_watch_file(self.master)

def wait_and_feed(self, timeout: float = 1.0) -> None:
while True:
try:
select.select([self.master], [], [], timeout)
break
except OSError as e:
if e.args[0] != 4:
raise
with selectors.DefaultSelector() as selector:
selector.register(self.master, selectors.EVENT_READ)
while True:
try:
selector.select(timeout)
break
except InterruptedError:
pass # Allow interrupt
self.feed()

def feed(self) -> None:
Expand Down
14 changes: 7 additions & 7 deletions urwid/web_display.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import glob
import os
import random
import select
import selectors
import signal
import socket
import string
Expand Down Expand Up @@ -904,16 +904,16 @@ def get_input(self, raw_keys: bool = False) -> list[str] | tuple[list[str], list
"""Return pending input as a list."""
pending_input = []
resized = False
with selectors.DefaultSelector() as selector:
selector.register(self.input_fd, selectors.EVENT_READ)

try:
iready, _oready, _eready = select.select([self.input_fd], [], [], 0.5)
except OSError as e:
# return on interruptions
if e.args[0] == 4:
try:
iready = [event.fd for event, _ in selector.select(0.5)]
except InterruptedError:
# return on interruptions
if raw_keys:
return [], []
return []
raise

if not iready:
if raw_keys:
Expand Down

0 comments on commit 9246088

Please sign in to comment.