forked from python/cpython
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pythongh-110944: Move pty helper to test.support and add basic pdb co…
…mpletion test (pythonGH-111826)
- Loading branch information
1 parent
c61de45
commit 1c7ed7e
Showing
3 changed files
with
91 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
""" | ||
Helper to run a script in a pseudo-terminal. | ||
""" | ||
import os | ||
import selectors | ||
import subprocess | ||
import sys | ||
from contextlib import ExitStack | ||
from errno import EIO | ||
|
||
from test.support.import_helper import import_module | ||
|
||
def run_pty(script, input=b"dummy input\r", env=None): | ||
pty = import_module('pty') | ||
output = bytearray() | ||
[master, slave] = pty.openpty() | ||
args = (sys.executable, '-c', script) | ||
proc = subprocess.Popen(args, stdin=slave, stdout=slave, stderr=slave, env=env) | ||
os.close(slave) | ||
with ExitStack() as cleanup: | ||
cleanup.enter_context(proc) | ||
def terminate(proc): | ||
try: | ||
proc.terminate() | ||
except ProcessLookupError: | ||
# Workaround for Open/Net BSD bug (Issue 16762) | ||
pass | ||
cleanup.callback(terminate, proc) | ||
cleanup.callback(os.close, master) | ||
# Avoid using DefaultSelector and PollSelector. Kqueue() does not | ||
# work with pseudo-terminals on OS X < 10.9 (Issue 20365) and Open | ||
# BSD (Issue 20667). Poll() does not work with OS X 10.6 or 10.4 | ||
# either (Issue 20472). Hopefully the file descriptor is low enough | ||
# to use with select(). | ||
sel = cleanup.enter_context(selectors.SelectSelector()) | ||
sel.register(master, selectors.EVENT_READ | selectors.EVENT_WRITE) | ||
os.set_blocking(master, False) | ||
while True: | ||
for [_, events] in sel.select(): | ||
if events & selectors.EVENT_READ: | ||
try: | ||
chunk = os.read(master, 0x10000) | ||
except OSError as err: | ||
# Linux raises EIO when slave is closed (Issue 5380) | ||
if err.errno != EIO: | ||
raise | ||
chunk = b"" | ||
if not chunk: | ||
return output | ||
output.extend(chunk) | ||
if events & selectors.EVENT_WRITE: | ||
try: | ||
input = input[os.write(master, input):] | ||
except OSError as err: | ||
# Apparently EIO means the slave was closed | ||
if err.errno != EIO: | ||
raise | ||
input = b"" # Stop writing | ||
if not input: | ||
sel.modify(master, selectors.EVENT_READ) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters