Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 1c7ed7e

Browse filesBrowse files
pythongh-110944: Move pty helper to test.support and add basic pdb completion test (pythonGH-111826)
1 parent c61de45 commit 1c7ed7e
Copy full SHA for 1c7ed7e

File tree

3 files changed

+91
-54
lines changed
Filter options

3 files changed

+91
-54
lines changed

‎Lib/test/support/pty_helper.py

Copy file name to clipboard
+60Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
"""
2+
Helper to run a script in a pseudo-terminal.
3+
"""
4+
import os
5+
import selectors
6+
import subprocess
7+
import sys
8+
from contextlib import ExitStack
9+
from errno import EIO
10+
11+
from test.support.import_helper import import_module
12+
13+
def run_pty(script, input=b"dummy input\r", env=None):
14+
pty = import_module('pty')
15+
output = bytearray()
16+
[master, slave] = pty.openpty()
17+
args = (sys.executable, '-c', script)
18+
proc = subprocess.Popen(args, stdin=slave, stdout=slave, stderr=slave, env=env)
19+
os.close(slave)
20+
with ExitStack() as cleanup:
21+
cleanup.enter_context(proc)
22+
def terminate(proc):
23+
try:
24+
proc.terminate()
25+
except ProcessLookupError:
26+
# Workaround for Open/Net BSD bug (Issue 16762)
27+
pass
28+
cleanup.callback(terminate, proc)
29+
cleanup.callback(os.close, master)
30+
# Avoid using DefaultSelector and PollSelector. Kqueue() does not
31+
# work with pseudo-terminals on OS X < 10.9 (Issue 20365) and Open
32+
# BSD (Issue 20667). Poll() does not work with OS X 10.6 or 10.4
33+
# either (Issue 20472). Hopefully the file descriptor is low enough
34+
# to use with select().
35+
sel = cleanup.enter_context(selectors.SelectSelector())
36+
sel.register(master, selectors.EVENT_READ | selectors.EVENT_WRITE)
37+
os.set_blocking(master, False)
38+
while True:
39+
for [_, events] in sel.select():
40+
if events & selectors.EVENT_READ:
41+
try:
42+
chunk = os.read(master, 0x10000)
43+
except OSError as err:
44+
# Linux raises EIO when slave is closed (Issue 5380)
45+
if err.errno != EIO:
46+
raise
47+
chunk = b""
48+
if not chunk:
49+
return output
50+
output.extend(chunk)
51+
if events & selectors.EVENT_WRITE:
52+
try:
53+
input = input[os.write(master, input):]
54+
except OSError as err:
55+
# Apparently EIO means the slave was closed
56+
if err.errno != EIO:
57+
raise
58+
input = b"" # Stop writing
59+
if not input:
60+
sel.modify(master, selectors.EVENT_READ)

‎Lib/test/test_pdb.py

Copy file name to clipboardExpand all lines: Lib/test/test_pdb.py
+30Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
from io import StringIO
1616
from test import support
1717
from test.support import os_helper
18+
from test.support.import_helper import import_module
19+
from test.support.pty_helper import run_pty
1820
# This little helper class is essential for testing pdb under doctest.
1921
from test.test_doctest import _FakeInput
2022
from unittest.mock import patch
@@ -3260,6 +3262,34 @@ def test_checkline_is_not_executable(self):
32603262
self.assertFalse(db.checkline(os_helper.TESTFN, lineno))
32613263

32623264

3265+
@support.requires_subprocess()
3266+
class PdbTestReadline(unittest.TestCase):
3267+
def setUpClass():
3268+
# Ensure that the readline module is loaded
3269+
# If this fails, the test is skipped because SkipTest will be raised
3270+
readline = import_module('readline')
3271+
if readline.__doc__ and "libedit" in readline.__doc__:
3272+
raise unittest.SkipTest("libedit readline is not supported for pdb")
3273+
3274+
def test_basic_completion(self):
3275+
script = textwrap.dedent("""
3276+
import pdb; pdb.Pdb().set_trace()
3277+
# Concatenate strings so that the output doesn't appear in the source
3278+
print('hello' + '!')
3279+
""")
3280+
3281+
# List everything starting with 'co', there should be multiple matches
3282+
# then add ntin and complete 'contin' to 'continue'
3283+
input = b"co\t\tntin\t\n"
3284+
3285+
output = run_pty(script, input)
3286+
3287+
self.assertIn(b'commands', output)
3288+
self.assertIn(b'condition', output)
3289+
self.assertIn(b'continue', output)
3290+
self.assertIn(b'hello!', output)
3291+
3292+
32633293
def load_tests(loader, tests, pattern):
32643294
from test import test_pdb
32653295
tests.addTest(doctest.DocTestSuite(test_pdb))

‎Lib/test/test_readline.py

Copy file name to clipboardExpand all lines: Lib/test/test_readline.py
+1-54Lines changed: 1 addition & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,15 @@
11
"""
22
Very minimal unittests for parts of the readline module.
33
"""
4-
from contextlib import ExitStack
5-
from errno import EIO
64
import locale
75
import os
8-
import selectors
9-
import subprocess
106
import sys
117
import tempfile
128
import unittest
139
from test.support import verbose
1410
from test.support.import_helper import import_module
1511
from test.support.os_helper import unlink, temp_dir, TESTFN
12+
from test.support.pty_helper import run_pty
1613
from test.support.script_helper import assert_python_ok
1714

1815
# Skip tests if there is no readline module
@@ -304,55 +301,5 @@ def test_history_size(self):
304301
self.assertEqual(lines[-1].strip(), b"last input")
305302

306303

307-
def run_pty(script, input=b"dummy input\r", env=None):
308-
pty = import_module('pty')
309-
output = bytearray()
310-
[master, slave] = pty.openpty()
311-
args = (sys.executable, '-c', script)
312-
proc = subprocess.Popen(args, stdin=slave, stdout=slave, stderr=slave, env=env)
313-
os.close(slave)
314-
with ExitStack() as cleanup:
315-
cleanup.enter_context(proc)
316-
def terminate(proc):
317-
try:
318-
proc.terminate()
319-
except ProcessLookupError:
320-
# Workaround for Open/Net BSD bug (Issue 16762)
321-
pass
322-
cleanup.callback(terminate, proc)
323-
cleanup.callback(os.close, master)
324-
# Avoid using DefaultSelector and PollSelector. Kqueue() does not
325-
# work with pseudo-terminals on OS X < 10.9 (Issue 20365) and Open
326-
# BSD (Issue 20667). Poll() does not work with OS X 10.6 or 10.4
327-
# either (Issue 20472). Hopefully the file descriptor is low enough
328-
# to use with select().
329-
sel = cleanup.enter_context(selectors.SelectSelector())
330-
sel.register(master, selectors.EVENT_READ | selectors.EVENT_WRITE)
331-
os.set_blocking(master, False)
332-
while True:
333-
for [_, events] in sel.select():
334-
if events & selectors.EVENT_READ:
335-
try:
336-
chunk = os.read(master, 0x10000)
337-
except OSError as err:
338-
# Linux raises EIO when slave is closed (Issue 5380)
339-
if err.errno != EIO:
340-
raise
341-
chunk = b""
342-
if not chunk:
343-
return output
344-
output.extend(chunk)
345-
if events & selectors.EVENT_WRITE:
346-
try:
347-
input = input[os.write(master, input):]
348-
except OSError as err:
349-
# Apparently EIO means the slave was closed
350-
if err.errno != EIO:
351-
raise
352-
input = b"" # Stop writing
353-
if not input:
354-
sel.modify(master, selectors.EVENT_READ)
355-
356-
357304
if __name__ == "__main__":
358305
unittest.main()

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.