Skip to content

Commit 7411422

Browse files
committed
Extract patched_spawn to test/helpers.py for reuse
Move pexpect wrapper with improved error messages from test_autocomplete to shared helpers module, and use it in test_help PTY test.
1 parent df6a3ae commit 7411422

File tree

3 files changed

+44
-43
lines changed

3 files changed

+44
-43
lines changed

test/helpers.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
#
99
######################################################################
1010
import platform
11+
import sys
1112

13+
import pexpect
1214
import pytest
1315

1416
_MISSING = object()
@@ -21,6 +23,40 @@ def skip_on_windows(*args, reason='Not supported on Windows', **kwargs):
2123
)(*args, **kwargs)
2224

2325

26+
def patched_spawn(*args, **kwargs):
27+
"""
28+
Wrapper around pexpect.spawn with improved error messages.
29+
30+
pexpect's errors are confusing to interpret when things go wrong,
31+
because it doesn't output the actual stdout by default. This wrapper
32+
addresses that inconvenience.
33+
"""
34+
instance = pexpect.spawn(*args, **kwargs)
35+
36+
def _patch_expect(func):
37+
def _wrapper(pattern_list, **kwargs):
38+
try:
39+
return func(pattern_list, **kwargs)
40+
except pexpect.exceptions.TIMEOUT as exc:
41+
raise pexpect.exceptions.TIMEOUT(
42+
f'Timeout reached waiting for `{pattern_list}`'
43+
) from exc
44+
except pexpect.exceptions.EOF as exc:
45+
raise pexpect.exceptions.EOF(f'Received EOF waiting for `{pattern_list}`') from exc
46+
except Exception as exc:
47+
raise RuntimeError(f'Unexpected error waiting for `{pattern_list}`') from exc
48+
49+
return _wrapper
50+
51+
instance.expect = _patch_expect(instance.expect)
52+
instance.expect_exact = _patch_expect(instance.expect_exact)
53+
54+
# capture child shell's output for debugging
55+
instance.logfile = sys.stdout.buffer
56+
57+
return instance
58+
59+
2460
def b2_uri_args_v3(bucket_name, path=_MISSING):
2561
if path is _MISSING:
2662
return [bucket_name]

test/integration/test_autocomplete.py

Lines changed: 1 addition & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import pexpect
1414
import pytest
1515

16-
from test.helpers import skip_on_windows
16+
from test.helpers import patched_spawn, skip_on_windows
1717

1818
TIMEOUT = 120 # CI can be slow at times when parallelization is extreme
1919

@@ -27,41 +27,6 @@
2727
"""
2828

2929

30-
def patched_spawn(*args, **kwargs):
31-
"""
32-
Patch pexpect.spawn to improve error messages
33-
"""
34-
35-
instance = pexpect.spawn(*args, **kwargs)
36-
37-
def _patch_expect(func):
38-
def _wrapper(pattern_list, **kwargs):
39-
try:
40-
return func(pattern_list, **kwargs)
41-
except pexpect.exceptions.TIMEOUT as exc:
42-
raise pexpect.exceptions.TIMEOUT(
43-
f'Timeout reached waiting for `{pattern_list}` to be autocompleted'
44-
) from exc
45-
except pexpect.exceptions.EOF as exc:
46-
raise pexpect.exceptions.EOF(
47-
f'Received EOF waiting for `{pattern_list}` to be autocompleted'
48-
) from exc
49-
except Exception as exc:
50-
raise RuntimeError(
51-
f'Unexpected error waiting for `{pattern_list}` to be autocompleted'
52-
) from exc
53-
54-
return _wrapper
55-
56-
instance.expect = _patch_expect(instance.expect)
57-
instance.expect_exact = _patch_expect(instance.expect_exact)
58-
59-
# capture child shell's output for debugging
60-
instance.logfile = sys.stdout.buffer
61-
62-
return instance
63-
64-
6530
@pytest.fixture(scope='session')
6631
def bashrc(homedir):
6732
bashrc_path = homedir / '.bashrc'

test/integration/test_help.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,11 @@
1212
import re
1313
import subprocess
1414

15+
import pexpect
1516
import pytest
1617

18+
from test.helpers import patched_spawn
19+
1720

1821
def test_help(cli_version):
1922
p = subprocess.run(
@@ -44,16 +47,14 @@ def test_help_with_tty(cli_version):
4447
4548
NOTE: Works in CI with pytest-xdist, but may not trigger the bug locally.
4649
"""
47-
pexpect = pytest.importorskip('pexpect')
48-
4950
# Set up environment - remove LINES/COLUMNS to ensure ioctl is called
5051
env = os.environ.copy()
5152
env.pop('LINES', None)
5253
env.pop('COLUMNS', None)
5354

5455
# Spawn b2 --help with pexpect to create a real PTY
5556
# This is where the bug would trigger on Python 3.14 without our fix
56-
child = pexpect.spawn(
57+
child = patched_spawn(
5758
cli_version,
5859
['--help'],
5960
env=env,
@@ -79,7 +80,6 @@ def test_help_with_tty(cli_version):
7980
)
8081

8182
# Verify help output contains expected content
82-
assert 'b2 <command>' in output or cli_version in output, (
83-
f'Help output does not contain expected content.\n'
84-
f'Output: {output}'
85-
)
83+
assert (
84+
'b2 <command>' in output or cli_version in output
85+
), f'Help output does not contain expected content.\nOutput: {output}'

0 commit comments

Comments
 (0)