|
9 | 9 |
|
10 | 10 | from .utils import print_warning |
11 | 11 |
|
| 12 | +# Import termios to save and restore terminal echo. This is only available on |
| 13 | +# Unix, and it's fine if the module can't be found. |
| 14 | +try: |
| 15 | + import termios # noqa: F401 |
| 16 | +except ModuleNotFoundError: |
| 17 | + pass |
| 18 | + |
12 | 19 |
|
13 | 20 | class SkipTestEnvironment(Exception): |
14 | 21 | pass |
@@ -65,6 +72,7 @@ def __init__(self, test_name, verbose, quiet, *, pgo): |
65 | 72 | 'shutil_archive_formats', 'shutil_unpack_formats', |
66 | 73 | 'asyncio.events._event_loop_policy', |
67 | 74 | 'urllib.requests._url_tempfiles', 'urllib.requests._opener', |
| 75 | + 'stty_echo', |
68 | 76 | ) |
69 | 77 |
|
70 | 78 | def get_module(self, name): |
@@ -292,6 +300,24 @@ def restore_warnings_showwarning(self, fxn): |
292 | 300 | warnings = self.get_module('warnings') |
293 | 301 | warnings.showwarning = fxn |
294 | 302 |
|
| 303 | + def get_stty_echo(self): |
| 304 | + termios = self.try_get_module('termios') |
| 305 | + if not os.isatty(fd := sys.__stdin__.fileno()): |
| 306 | + return None |
| 307 | + attrs = termios.tcgetattr(fd) |
| 308 | + lflags = attrs[3] |
| 309 | + return bool(lflags & termios.ECHO) |
| 310 | + def restore_stty_echo(self, echo): |
| 311 | + termios = self.get_module('termios') |
| 312 | + attrs = termios.tcgetattr(fd := sys.__stdin__.fileno()) |
| 313 | + if echo: |
| 314 | + # Turn echo on. |
| 315 | + attrs[3] |= termios.ECHO |
| 316 | + else: |
| 317 | + # Turn echo off. |
| 318 | + attrs[3] &= ~termios.ECHO |
| 319 | + termios.tcsetattr(fd, termios.TCSADRAIN, attrs) |
| 320 | + |
295 | 321 | def resource_info(self): |
296 | 322 | for name in self.resources: |
297 | 323 | method_suffix = name.replace('.', '_') |
|
0 commit comments