Skip to content

Commit e351ca3

Browse files
8vasugpsheadencukou
authored
gh-85984: Add POSIX pseudo-terminal functions. (GH-102413)
Signed-off-by: Soumendra Ganguly <soumendraganguly@gmail.com> Co-authored-by: Gregory P. Smith <greg@krypto.org> Co-authored-by: Petr Viktorin <encukou@gmail.com>
1 parent 0f54ee4 commit e351ca3

File tree

9 files changed

+468
-11
lines changed

9 files changed

+468
-11
lines changed

Doc/conf.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,19 +97,24 @@
9797
('c:func', 'free'),
9898
('c:func', 'gettimeofday'),
9999
('c:func', 'gmtime'),
100+
('c:func', 'grantpt'),
100101
('c:func', 'localeconv'),
101102
('c:func', 'localtime'),
102103
('c:func', 'main'),
103104
('c:func', 'malloc'),
104105
('c:func', 'mktime'),
106+
('c:func', 'posix_openpt'),
105107
('c:func', 'printf'),
108+
('c:func', 'ptsname'),
109+
('c:func', 'ptsname_r'),
106110
('c:func', 'realloc'),
107111
('c:func', 'snprintf'),
108112
('c:func', 'sprintf'),
109113
('c:func', 'stat'),
110114
('c:func', 'strftime'),
111115
('c:func', 'system'),
112116
('c:func', 'time'),
117+
('c:func', 'unlockpt'),
113118
('c:func', 'vsnprintf'),
114119
# Standard C types
115120
('c:type', 'FILE'),

Doc/library/os.rst

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,6 +1122,20 @@ as internal buffering of data.
11221122
.. versionchanged:: 3.12
11231123
Added support for pipes on Windows.
11241124

1125+
1126+
.. function:: grantpt(fd, /)
1127+
1128+
Grant access to the slave pseudo-terminal device associated with the
1129+
master pseudo-terminal device to which the file descriptor *fd* refers.
1130+
The file descriptor *fd* is not closed upon failure.
1131+
1132+
Calls the C standard library function :c:func:`grantpt`.
1133+
1134+
.. availability:: Unix, not Emscripten, not WASI.
1135+
1136+
.. versionadded:: 3.13
1137+
1138+
11251139
.. function:: isatty(fd, /)
11261140

11271141
Return ``True`` if the file descriptor *fd* is open and connected to a
@@ -1429,6 +1443,23 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo
14291443
.. versionadded:: 3.3
14301444

14311445

1446+
.. function:: posix_openpt(oflag, /)
1447+
1448+
Open and return a file descriptor for a master pseudo-terminal device.
1449+
1450+
Calls the C standard library function :c:func:`posix_openpt`. The *oflag*
1451+
argument is used to set file status flags and file access modes as
1452+
specified in the manual page of :c:func:`posix_openpt` of your system.
1453+
1454+
The returned file descriptor is :ref:`non-inheritable <fd_inheritance>`.
1455+
If the value :data:`O_CLOEXEC` is available on the system, it is added to
1456+
*oflag*.
1457+
1458+
.. availability:: Unix, not Emscripten, not WASI.
1459+
1460+
.. versionadded:: 3.13
1461+
1462+
14321463
.. function:: preadv(fd, buffers, offset, flags=0, /)
14331464

14341465
Read from a file descriptor *fd* at a position of *offset* into mutable
@@ -1486,6 +1517,21 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo
14861517
.. versionadded:: 3.7
14871518

14881519

1520+
.. function:: ptsname(fd, /)
1521+
1522+
Return the name of the slave pseudo-terminal device associated with the
1523+
master pseudo-terminal device to which the file descriptor *fd* refers.
1524+
The file descriptor *fd* is not closed upon failure.
1525+
1526+
Calls the reentrant C standard library function :c:func:`ptsname_r` if
1527+
it is available; otherwise, the C standard library function
1528+
:c:func:`ptsname`, which is not guaranteed to be thread-safe, is called.
1529+
1530+
.. availability:: Unix, not Emscripten, not WASI.
1531+
1532+
.. versionadded:: 3.13
1533+
1534+
14891535
.. function:: pwrite(fd, str, offset, /)
14901536

14911537
Write the bytestring in *str* to file descriptor *fd* at position of
@@ -1738,6 +1784,19 @@ or `the MSDN <https://msdn.microsoft.com/en-us/library/z0kc8e3z.aspx>`_ on Windo
17381784
.. availability:: Unix.
17391785

17401786

1787+
.. function:: unlockpt(fd, /)
1788+
1789+
Unlock the slave pseudo-terminal device associated with the master
1790+
pseudo-terminal device to which the file descriptor *fd* refers.
1791+
The file descriptor *fd* is not closed upon failure.
1792+
1793+
Calls the C standard library function :c:func:`unlockpt`.
1794+
1795+
.. availability:: Unix, not Emscripten, not WASI.
1796+
1797+
.. versionadded:: 3.13
1798+
1799+
17411800
.. function:: write(fd, str, /)
17421801

17431802
Write the bytestring in *str* to file descriptor *fd*.

Lib/test/test_os.py

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4536,13 +4536,46 @@ def test_dup2(self):
45364536
self.assertEqual(os.dup2(fd, fd3, inheritable=False), fd3)
45374537
self.assertFalse(os.get_inheritable(fd3))
45384538

4539-
@unittest.skipUnless(hasattr(os, 'openpty'), "need os.openpty()")
4539+
@unittest.skipUnless(hasattr(os, 'openpty'), "need os.openpty()")
4540+
class PseudoterminalTests(unittest.TestCase):
4541+
def open_pty(self):
4542+
"""Open a pty fd-pair, and schedule cleanup for it"""
4543+
main_fd, second_fd = os.openpty()
4544+
self.addCleanup(os.close, main_fd)
4545+
self.addCleanup(os.close, second_fd)
4546+
return main_fd, second_fd
4547+
45404548
def test_openpty(self):
4541-
master_fd, slave_fd = os.openpty()
4542-
self.addCleanup(os.close, master_fd)
4543-
self.addCleanup(os.close, slave_fd)
4544-
self.assertEqual(os.get_inheritable(master_fd), False)
4545-
self.assertEqual(os.get_inheritable(slave_fd), False)
4549+
main_fd, second_fd = self.open_pty()
4550+
self.assertEqual(os.get_inheritable(main_fd), False)
4551+
self.assertEqual(os.get_inheritable(second_fd), False)
4552+
4553+
@unittest.skipUnless(hasattr(os, 'ptsname'), "need os.ptsname()")
4554+
@unittest.skipUnless(hasattr(os, 'O_RDWR'), "need os.O_RDWR")
4555+
@unittest.skipUnless(hasattr(os, 'O_NOCTTY'), "need os.O_NOCTTY")
4556+
def test_open_via_ptsname(self):
4557+
main_fd, second_fd = self.open_pty()
4558+
second_path = os.ptsname(main_fd)
4559+
reopened_second_fd = os.open(second_path, os.O_RDWR|os.O_NOCTTY)
4560+
self.addCleanup(os.close, reopened_second_fd)
4561+
os.write(reopened_second_fd, b'foo')
4562+
self.assertEqual(os.read(main_fd, 3), b'foo')
4563+
4564+
@unittest.skipUnless(hasattr(os, 'posix_openpt'), "need os.posix_openpt()")
4565+
@unittest.skipUnless(hasattr(os, 'grantpt'), "need os.grantpt()")
4566+
@unittest.skipUnless(hasattr(os, 'unlockpt'), "need os.unlockpt()")
4567+
@unittest.skipUnless(hasattr(os, 'ptsname'), "need os.ptsname()")
4568+
@unittest.skipUnless(hasattr(os, 'O_RDWR'), "need os.O_RDWR")
4569+
@unittest.skipUnless(hasattr(os, 'O_NOCTTY'), "need os.O_NOCTTY")
4570+
def test_posix_pty_functions(self):
4571+
mother_fd = os.posix_openpt(os.O_RDWR|os.O_NOCTTY)
4572+
self.addCleanup(os.close, mother_fd)
4573+
os.grantpt(mother_fd)
4574+
os.unlockpt(mother_fd)
4575+
son_path = os.ptsname(mother_fd)
4576+
son_fd = os.open(son_path, os.O_RDWR|os.O_NOCTTY)
4577+
self.addCleanup(os.close, son_fd)
4578+
self.assertEqual(os.ptsname(mother_fd), os.ttyname(son_fd))
45464579

45474580
@unittest.skipUnless(hasattr(os, 'spawnl'), "need os.openpty()")
45484581
def test_pipe_spawnl(self):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add POSIX pseudo-terminal functions :func:`os.posix_openpt`,
2+
:func:`os.grantpt`, :func:`os.unlockpt`, and :func:`os.ptsname`.

Modules/clinic/posixmodule.c.h

Lines changed: 167 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy