[3.14] gh-134466: Don't run when termios is inaccessible (GH-138911) (GH-139029)

Without the ability to set required capabilities, the REPL cannot
function properly (syntax highlighting and multiline editing can't
work).
We refuse to work in this degraded state.

(cherry picked from commit 2fc7004d54)

Co-authored-by: Łukasz Langa <lukasz@langa.pl>
This commit is contained in:
Miss Islington (bot) 2025-10-07 22:15:56 +02:00 committed by GitHub
parent 89a7b05f23
commit 9853bbb1dc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 65 additions and 42 deletions

View file

@ -20,19 +20,25 @@
import termios
class TermState:
def __init__(self, tuples):
(
self.iflag,
self.oflag,
self.cflag,
self.lflag,
self.ispeed,
self.ospeed,
self.cc,
) = tuples
TYPE_CHECKING = False
def as_list(self):
if TYPE_CHECKING:
from typing import cast
else:
cast = lambda typ, val: val
class TermState:
def __init__(self, attrs: list[int | list[bytes]]) -> None:
self.iflag = cast(int, attrs[0])
self.oflag = cast(int, attrs[1])
self.cflag = cast(int, attrs[2])
self.lflag = cast(int, attrs[3])
self.ispeed = cast(int, attrs[4])
self.ospeed = cast(int, attrs[5])
self.cc = cast(list[bytes], attrs[6])
def as_list(self) -> list[int | list[bytes]]:
return [
self.iflag,
self.oflag,
@ -45,32 +51,32 @@ def as_list(self):
self.cc[:],
]
def copy(self):
def copy(self) -> "TermState":
return self.__class__(self.as_list())
def tcgetattr(fd):
def tcgetattr(fd: int) -> TermState:
return TermState(termios.tcgetattr(fd))
def tcsetattr(fd, when, attrs):
def tcsetattr(fd: int, when: int, attrs: TermState) -> None:
termios.tcsetattr(fd, when, attrs.as_list())
class Term(TermState):
TS__init__ = TermState.__init__
def __init__(self, fd=0):
def __init__(self, fd: int = 0) -> None:
self.TS__init__(termios.tcgetattr(fd))
self.fd = fd
self.stack = []
self.stack: list[list[int | list[bytes]]] = []
def save(self):
def save(self) -> None:
self.stack.append(self.as_list())
def set(self, when=termios.TCSANOW):
def set(self, when: int = termios.TCSANOW) -> None:
termios.tcsetattr(self.fd, when, self.as_list())
def restore(self):
def restore(self) -> None:
self.TS__init__(self.stack.pop())
self.set()