Repository navigation
Lib/pty.py major revision #85984
Description
Activity
The current pty library has the following issues:
-
Does not set slave termios. Documented in the source.
-
Does not set initial slave window size. Documented in the source. Does not handle SIGWINCH. See bpo-41494, bpo-41541. This is essential in the following practical scenarios: i. creating split windows/panes while using a terminal multiplexer; ii. when resizing GUI terminal emulator window, especially relevant when using tiling window managers; iii. resizing an ansi-term window created inside a GNU Emacs frame.
-
Does not perform signal handling. Signals must be blocked during sensitive portions of code.
-
Hangs on FreeBSD. See bpo-26228.
-
Includes deprecated functions pty.master_open(), pty.slave_open().
-
In pty.fork(), the fallback code should try using TIOCSCTTY first. It is still using the old method of opening a tty to make it the controlling tty. Currently even SysV based systems provide TIOCSCTTY. See https://stackoverflow.com/questions/51593530/code-explanation-for-glibc-login-tty-function-openttyname-immediately-f
The current version of pty.spawn() uses pty.fork() internally. However, pty.fork() closes slave and only returns (pid, master_fd). To update winsize, access to slave is necessary. Further, slave termios must be properly set. The proposed modifications do this by implementing a login_tty(3) based function ( tty.login() ), and using that in pty.spawn() instead of pty.fork(). tty.login() tries TIOCSCTTY before falling back to the old SysV method because Python currently does not provide an interface to the native login_tty(3).
-
tty.setraw() is called right after tty.tcgetattr(). This increases redundancy of code because tty.setraw() itself makes an identical tty.tcgetattr() call.
-
Requires testing/porting to more platforms. Solaris, Illumos, macOS, Cygwin, etc. Windows ConPTY?
-
There should be an option in pty.spawn() to turn off slave's ECHO flag. For example, when it is being used in a pipe. See util-linux/util-linux@1eee1ac and util-linux/util-linux@75ccd75#diff-3834a3d25eeaf20d9d0dcb05a46995f6
-
Tests are incomplete. Tests consider OSes such as Tru64 but not {Free/Net/Open/...}BSD.
Find ongoing work here: https://github.com/8vasu/pypty2
-
- added3.8 (EOL)end of lifeend of life3.9 (EOL)end of lifeend of life3.10 (EOL)end of lifeend of lifestdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytestsTests in the Lib/test dirTests in the Lib/test dir
on Sep 19, 2020 In addition to the above, if a major revision is made to pty, I'd suggest also addressing the issue of "master/slave" terminology, and replace it with something comparable like "parent/child". There's an open devguide issue (python/devguide#605) to more explicitly state terms to avoid, and support for avoiding usage of "slave/master" seems uncontroversial (especially in any new code).
Makes sense. I will happily make a change of terminology in the pypty2 repository after the most desirable alternative is determined based on the choice of the majority. I think 'mother/son' sounds cute while still retaining the same initials as before; people used to the older
terminology will find this easy to remember. Terminology such as parent/child and server/client might make it a little confusing.This change broke x86 Gentoo buildbots: bpo-42463.
#23514 has the fix, waiting for all buildbots finish before pressing "Merge" button.
Gentoo bots are green.24 remaining items
- added a commit that references this issue
on May 20, 2023 - added a commit that references this issue
on Sep 28, 2023 - added a commit that references this issue
on Oct 4, 2023 Why not make cfmakeraw() and cfmakecbreak() returning a new list instead of modifying the input in-place? In any case you need to make a copy, but it is errorprone, because the list contains a nested list. See #110392.
Regarding "master/slave" terminology:
I plan to use a strategy I learned at @evildmp's workshop. First, merge #102413, which extendsoswith a bunch of functions that handle PTY-pairs. There's no simple way to avoid using the inappropriate terms in these functions' docs.
The merge will make theosdocs worse in this respect -- but it'll also make the issue more obvious, and hopefully easier to solve.
After that I'll propose a PR. Still don't know how that will look, but there's lively brainstorming and style guide recommendations over at the Docs community discord.Anyway: @8vasu, feel free to focus on the techincal side, and leave terminology to me.
Reacted by Soumendra GangulyRegarding "master/slave" terminology
See also: python/devguide#605 (which was already mentioned previously).
I have also commented a variation of this on: #102413
@vstinner While I am not a CPython maintainer and hence do not have much say in deciding which directions such a prestigious project should take, I am an end user who does
ptyprogramming frequently (Python or otherwise) and I will have to deal with the consequences (good or bad) of any decisions taken here.I have severe clinical OCD/OCPD and would like to issue a warning here: using generic names like
main_fd, second_fd, orparent_fd, child_fd, orserver_fd, client_fdwill lead to havoc very easily. Just take a look at the source of your very own https://github.com/python/cpython/blob/3.12/Lib/pty.py and try a search/replace involving terms parent/child (already used by processes) or a program likessh(1)which uses the terms server/client in networking context and also sets up a pty pair.On the other hand one can easily have
first_fd, second_fd, third_fdor evenmain_fdin their existing programs. The pairmain, subordinatecomes to mind, but again,main_fdmight be taken andmain, subordinatecarry the same overtones asmaster, slave, which is what you are trying to avoid in the first place.For a change that is easy to maintain for current and future Python maintainers and eliminates all possibility of confusion for end users when they are referring to documentation, we must use something that is:
- not already taken to almost absolutely eliminate any chances of variable name collision while
- maintaining that the initials
mandsstay the same.
Edit:
Some data: about naming pty-pairs; apart from the file/project/module/documentation-local confusion that inevitably will arise due to using process-specific terminology parent/child; networking-specific terminology server/client, and generic terms main, primary/seconday, here is some global data directly generated using script at the bottom of this post:
Current timezone and date: Sun Jan 21 06:17:13 AM CET 2024
Current directory: /tmp/tmp.21-Jan-2024+05:14:25.JZlA6tqeCz
Temporarily moving into directory: /tmp/tmp.uZECXBwUzECloning CPython repository...
Cloning into 'cpython'...
remote: Enumerating objects: 1004157, done.
remote: Counting objects: 100% (690/690), done.
remote: Compressing objects: 100% (425/425), done.
remote: Total 1004157 (delta 428), reused 448 (delta 265), pack-reused 1003467
Receiving objects: 100% (1004157/1004157), 549.31 MiB | 5.16 MiB/s, done.
Resolving deltas: 100% (804152/804152), done.Moving into CPython repository...
/tmp/tmp.uZECXBwUzE/cpythonRunning grep to count number of occurences of concerned terms:
master:757occurences ignoring cases and727occurences not ignoring cases
master_fd:80occurences ignoring cases and80occurences not ignoring cases
slave:155occurences ignoring cases and154occurences not ignoring cases
slave_fd:43occurences ignoring cases and43occurences not ignoring cases
parent:3760occurences ignoring cases and3255occurences not ignoring cases
parent_fd:0occurences ignoring cases and0occurences not ignoring cases
child:5703occurences ignoring cases and5067occurences not ignoring cases
child_fd:3occurences ignoring cases and3occurences not ignoring cases
server:6237occurences ignoring cases and5045occurences not ignoring cases
server_fd:0occurences ignoring cases and0occurences not ignoring cases
client:3036occurences ignoring cases and2682occurences not ignoring cases
client_fd:0occurences ignoring cases and0occurences not ignoring cases
primary:378occurences ignoring cases and346occurences not ignoring cases
primary_fd:0occurences ignoring cases and0occurences not ignoring cases
secondary:38occurences ignoring cases and35occurences not ignoring cases
secondary_fd:0occurences ignoring cases and0occurences not ignoring cases
main:25612occurences ignoring cases and24847occurences not ignoring cases
main_fd:0occurences ignoring cases and0occurences not ignoring cases
second:4361occurences ignoring cases and3987occurences not ignoring cases
second_fd:0occurences ignoring cases and0occurences not ignoring cases
mother:1occurences ignoring cases and1occurences not ignoring cases
mother_fd:0occurences ignoring cases and0occurences not ignoring cases
(^|[^j])son:0occurences ignoring cases and0occurences not ignoring cases
(^|[^j])son_fd:0occurences ignoring cases and0occurences not ignoring casesRemoving CPython repository to free up space in /tmp...
#!/bin/sh -e l="master master_fd slave slave_fd parent parent_fd \ child child_fd server server_fd client client_fd primary \ primary_fd secondary secondary_fd main main_fd second \ second_fd mother mother_fd (^|[^j])son (^|[^j])son_fd" TMP_DIR_PARENT="${1:-/tmp}" echo "*Current timezone and date:* $(date)" echo "*Current directory:* $(pwd)" # mktemp(1) is not POSIX TMP_DIR="$(mktemp -d --tmpdir="$TMP_DIR_PARENT")" echo "*Temporarily moving into directory:* $TMP_DIR" cd "$TMP_DIR" echo echo "*Cloning CPython repository...*" echo git clone https://github.com/python/cpython.git echo echo "*Moving into CPython repository...*" cd cpython echo echo "*Running grep to count number of occurences of concerned terms:*" echo for i in $l do # "grep -r" is not POSIX n="$(grep -r -e $i 2>/dev/null | wc -l)" m="$(grep -ri -e $i 2>/dev/null | wc -l)" echo "\`$i\`: \`$m\` occurences ignoring cases and \`$n\` occurences not ignoring cases" done echo echo "*Removing CPython repository to free up space in ${TMP_DIR_PARENT}...*" cd .. rm -rf ./cpython
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
Linked PRs