From 327e31595fd1c79f9bb4c4d209e753cbde1e0c60 Mon Sep 17 00:00:00 2001 From: Erik Rose Date: Fri, 16 Jan 2015 23:53:29 -0500 Subject: Rename a few parts of the input API so they don't require familiarity with terminal jargon or BASIC. * Combine cbreak() and raw() into keystroke_input(). * Rename getch() and kbhit() to _next_char() and _char_is_ready(), and make them private. * Fix a few instances where we were comparing to non-singletons using `is`. * Rename inkey() to keystroke(), and make it raise NoKeyboard if it would otherwise end up hanging forever. --- blessed/keyboard.py | 1 - blessed/terminal.py | 107 +++++++++++++++-------------- blessed/tests/test_keyboard.py | 148 ++++++++++++++++++++--------------------- 3 files changed, 126 insertions(+), 130 deletions(-) diff --git a/blessed/keyboard.py b/blessed/keyboard.py index 28c26b7..d701a16 100644 --- a/blessed/keyboard.py +++ b/blessed/keyboard.py @@ -250,7 +250,6 @@ DEFAULT_SEQUENCE_MIXIN = ( (u"\x1bOx", curses.KEY_KP_8), # 8 (u"\x1bOy", curses.KEY_KP_9), # 9 - # # keypad, numlock off (u"\x1b[1~", curses.KEY_FIND), # find (u"\x1b[2~", curses.KEY_IC), # insert (0) diff --git a/blessed/terminal.py b/blessed/terminal.py index 1e17d73..10ca201 100644 --- a/blessed/terminal.py +++ b/blessed/terminal.py @@ -199,7 +199,7 @@ class Terminal(object): else: warnings.warn( 'A terminal of kind "%s" has been requested; due to an' - ' internal python curses bug, terminal capabilities' + ' internal python curses bug, terminal capabilities' ' for a terminal of kind "%s" will continue to be' ' returned for the remainder of this process.' % ( self._kind, _CUR_TERM,)) @@ -534,12 +534,12 @@ class Terminal(object): return lines - def getch(self): - """T.getch() -> unicode + def _next_char(self): + """T._next_char() -> unicode Read and decode next byte from keyboard stream. May return u'' if decoding is not yet complete, or completed unicode character. - Should always return bytes when self.kbhit() returns True. + Should always return bytes when self._char_is_ready() returns True. Implementors of input streams other than os.read() on the stdin fd should derive and override this method. @@ -548,8 +548,8 @@ class Terminal(object): byte = os.read(self.keyboard_fd, 1) return self._keyboard_decoder.decode(byte, final=False) - def kbhit(self, timeout=None, _intr_continue=True): - """T.kbhit([timeout=None]) -> bool + def _char_is_ready(self, timeout=None, _intr_continue=True): + """T._char_is_ready([timeout=None]) -> bool Returns True if a keypress has been detected on keyboard. @@ -590,15 +590,20 @@ class Terminal(object): return False if self.keyboard_fd is None else check_r == ready_r @contextlib.contextmanager - def cbreak(self): - """Return a context manager that enters 'cbreak' mode: disabling line - buffering of keyboard input, making characters typed by the user - immediately available to the program. Also referred to as 'rare' - mode, this is the opposite of 'cooked' mode, the default for most - shells. + def keystroke_input(self, raw=False): + """Return a context manager that sets up the terminal to do + key-at-a-time input. - In 'cbreak' mode, echo of input is also disabled: the application must - explicitly print any input received, if they so wish. + On entering the context manager, "cbreak" mode is activated, disabling + line buffering of keyboard input and turning off automatic echoing of + input. (You must explicitly print any input if you'd like it shown.) + Also referred to as 'rare' mode, this is the opposite of 'cooked' mode, + the default for most shells. + + If ``raw`` is True, enter "raw" mode instead. Raw mode differs in that + the interrupt, quit, suspend, and flow control characters are all + passed through as their raw character values instead of generating a + signal. More information can be found in the manual page for curses.h, http://www.openbsd.org/cgi-bin/man.cgi?query=cbreak @@ -610,35 +615,14 @@ class Terminal(object): http://www.unixwiz.net/techtips/termios-vmin-vtime.html """ if HAS_TTY and self.keyboard_fd is not None: - # save current terminal mode, + # Save current terminal mode: save_mode = termios.tcgetattr(self.keyboard_fd) - tty.setcbreak(self.keyboard_fd, termios.TCSANOW) + mode_setter = tty.setraw if raw else tty.setcbreak + mode_setter(self.keyboard_fd, termios.TCSANOW) try: yield finally: - # restore prior mode, - termios.tcsetattr(self.keyboard_fd, - termios.TCSAFLUSH, - save_mode) - else: - yield - - @contextlib.contextmanager - def raw(self): - """Return a context manager that enters *raw* mode. Raw mode is - similar to *cbreak* mode, in that characters typed are immediately - available to ``inkey()`` with one exception: the interrupt, quit, - suspend, and flow control characters are all passed through as their - raw character values instead of generating a signal. - """ - if HAS_TTY and self.keyboard_fd is not None: - # save current terminal mode, - save_mode = termios.tcgetattr(self.keyboard_fd) - tty.setraw(self.keyboard_fd, termios.TCSANOW) - try: - yield - finally: - # restore prior mode, + # Restore prior mode: termios.tcsetattr(self.keyboard_fd, termios.TCSAFLUSH, save_mode) @@ -667,8 +651,8 @@ class Terminal(object): finally: self.stream.write(self.rmkx) - def inkey(self, timeout=None, esc_delay=0.35, _intr_continue=True): - """T.inkey(timeout=None, [esc_delay, [_intr_continue]]) -> Keypress() + def keystroke(self, timeout=None, esc_delay=0.35, _intr_continue=True): + """T.keystroke(timeout=None, [esc_delay, [_intr_continue]]) -> Keystroke Receive next keystroke from keyboard (stdin), blocking until a keypress is received or ``timeout`` elapsed, if specified. @@ -683,7 +667,7 @@ class Terminal(object): attributes of this terminal beginning with *KEY*, such as ``KEY_ESCAPE``. - To distinguish between ``KEY_ESCAPE``, and sequences beginning with + To distinguish between ``KEY_ESCAPE`` and sequences beginning with escape, the ``esc_delay`` specifies the amount of time after receiving the escape character (chr(27)) to seek for the completion of other application keys before returning ``KEY_ESCAPE``. @@ -691,8 +675,8 @@ class Terminal(object): Normally, when this function is interrupted by a signal, such as the installment of SIGWINCH, this function will ignore this interruption and continue to poll for input up to the ``timeout`` specified. If - you'd rather this function return ``u''`` early, specify a value - of ``False`` for ``_intr_continue``. + you'd rather this function return ``u''`` early, specify ``False`` for + ``_intr_continue``. """ # TODO(jquast): "meta sends escape", where alt+1 would send '\x1b1', # what do we do with that? Surely, something useful. @@ -700,14 +684,21 @@ class Terminal(object): # TODO(jquast): Ctrl characters, KEY_CTRL_[A-Z], and the rest; # KEY_CTRL_\, KEY_CTRL_{, etc. are not legitimate # attributes. comparator to term.KEY_ctrl('z') ? - def _timeleft(stime, timeout): - """_timeleft(stime, timeout) -> float + + if timeout is None and self.keyboard_fd is None: + raise NoKeyboard( + 'Waiting for a keystroke on a terminal with no keyboard ' + 'attached and no timeout would take a long time. Add a ' + 'timeout and revise your program logic.') + + def time_left(stime, timeout): + """time_left(stime, timeout) -> float Returns time-relative time remaining before ``timeout`` after time elapsed since ``stime``. """ if timeout is not None: - if timeout is 0: + if timeout == 0: return 0 return max(0, timeout - (time.time() - stime)) @@ -723,8 +714,8 @@ class Terminal(object): ucs += self._keyboard_buf.pop() # receive all immediately available bytes - while self.kbhit(0): - ucs += self.getch() + while self._char_is_ready(0): + ucs += self._next_char() # decode keystroke, if any ks = resolve(text=ucs) @@ -732,8 +723,8 @@ class Terminal(object): # so long as the most immediately received or buffered keystroke is # incomplete, (which may be a multibyte encoding), block until until # one is received. - while not ks and self.kbhit(_timeleft(stime, timeout), _intr_continue): - ucs += self.getch() + while not ks and self._char_is_ready(time_left(stime, timeout), _intr_continue): + ucs += self._next_char() ks = resolve(text=ucs) # handle escape key (KEY_ESCAPE) vs. escape sequence (which begins @@ -741,17 +732,23 @@ class Terminal(object): # received. This is not optimal, but causes least delay when # (currently unhandled, and rare) "meta sends escape" is used, # or when an unsupported sequence is sent. - if ks.code is self.KEY_ESCAPE: + if ks.code == self.KEY_ESCAPE: esctime = time.time() - while (ks.code is self.KEY_ESCAPE and - self.kbhit(_timeleft(esctime, esc_delay))): - ucs += self.getch() + while (ks.code == self.KEY_ESCAPE and + self._char_is_ready(time_left(esctime, esc_delay))): + ucs += self._next_char() ks = resolve(text=ucs) # buffer any remaining text received self._keyboard_buf.extendleft(ucs[len(ks):]) return ks + +class NoKeyboard(Exception): + """Exception raised when a Terminal that has no means of input connected is + asked to retrieve a keystroke without an infinite timeout.""" + + # From libcurses/doc/ncurses-intro.html (ESR, Thomas Dickey, et. al): # # "After the call to setupterm(), the global variable cur_term is set to diff --git a/blessed/tests/test_keyboard.py b/blessed/tests/test_keyboard.py index c81154f..b43fc69 100644 --- a/blessed/tests/test_keyboard.py +++ b/blessed/tests/test_keyboard.py @@ -40,8 +40,8 @@ if sys.version_info[0] == 3: unichr = chr -def test_kbhit_interrupted(): - "kbhit() should not be interrupted with a signal handler." +def test_char_is_ready_interrupted(): + "_char_is_ready() should not be interrupted with a signal handler." pid, master_fd = pty.fork() if pid is 0: try: @@ -61,8 +61,8 @@ def test_kbhit_interrupted(): signal.signal(signal.SIGWINCH, on_resize) read_until_semaphore(sys.__stdin__.fileno(), semaphore=SEMAPHORE) os.write(sys.__stdout__.fileno(), SEMAPHORE) - with term.raw(): - assert term.inkey(timeout=1.05) == u'' + with term.keystroke_input(raw=True): + assert term.keystroke(timeout=1.05) == u'' os.write(sys.__stdout__.fileno(), b'complete') assert got_sigwinch is True if cov is not None: @@ -83,8 +83,8 @@ def test_kbhit_interrupted(): assert math.floor(time.time() - stime) == 1.0 -def test_kbhit_interrupted_nonetype(): - "kbhit() should also allow interruption with timeout of None." +def test_char_is_ready_interrupted_nonetype(): + "_char_is_ready() should also allow interruption with timeout of None." pid, master_fd = pty.fork() if pid is 0: try: @@ -104,8 +104,8 @@ def test_kbhit_interrupted_nonetype(): signal.signal(signal.SIGWINCH, on_resize) read_until_semaphore(sys.__stdin__.fileno(), semaphore=SEMAPHORE) os.write(sys.__stdout__.fileno(), SEMAPHORE) - with term.raw(): - term.inkey(timeout=1) + with term.keystroke_input(raw=True): + term.keystroke(timeout=1) os.write(sys.__stdout__.fileno(), b'complete') assert got_sigwinch is True if cov is not None: @@ -127,8 +127,8 @@ def test_kbhit_interrupted_nonetype(): assert math.floor(time.time() - stime) == 1.0 -def test_kbhit_interrupted_no_continue(): - "kbhit() may be interrupted when _intr_continue=False." +def test_char_is_ready_interrupted_no_continue(): + "_char_is_ready() may be interrupted when _intr_continue=False." pid, master_fd = pty.fork() if pid is 0: try: @@ -148,8 +148,8 @@ def test_kbhit_interrupted_no_continue(): signal.signal(signal.SIGWINCH, on_resize) read_until_semaphore(sys.__stdin__.fileno(), semaphore=SEMAPHORE) os.write(sys.__stdout__.fileno(), SEMAPHORE) - with term.raw(): - term.inkey(timeout=1.05, _intr_continue=False) + with term.keystroke_input(raw=True): + term.keystroke(timeout=1.05, _intr_continue=False) os.write(sys.__stdout__.fileno(), b'complete') assert got_sigwinch is True if cov is not None: @@ -171,8 +171,8 @@ def test_kbhit_interrupted_no_continue(): assert math.floor(time.time() - stime) == 0.0 -def test_kbhit_interrupted_nonetype_no_continue(): - "kbhit() may be interrupted when _intr_continue=False with timeout None." +def test_char_is_ready_interrupted_nonetype_no_continue(): + "_char_is_ready() may be interrupted when _intr_continue=False with timeout None." pid, master_fd = pty.fork() if pid is 0: try: @@ -192,8 +192,8 @@ def test_kbhit_interrupted_nonetype_no_continue(): signal.signal(signal.SIGWINCH, on_resize) read_until_semaphore(sys.__stdin__.fileno(), semaphore=SEMAPHORE) os.write(sys.__stdout__.fileno(), SEMAPHORE) - with term.raw(): - term.inkey(timeout=None, _intr_continue=False) + with term.keystroke_input(raw=True): + term.keystroke(timeout=None, _intr_continue=False) os.write(sys.__stdout__.fileno(), b'complete') assert got_sigwinch is True if cov is not None: @@ -216,14 +216,14 @@ def test_kbhit_interrupted_nonetype_no_continue(): assert math.floor(time.time() - stime) == 0.0 -def test_cbreak_no_kb(): - "cbreak() should not call tty.setcbreak() without keyboard." +def test_keystroke_input_no_kb(): + "keystroke_input() should not call tty.setcbreak() without keyboard." @as_subprocess def child(): with tempfile.NamedTemporaryFile() as stream: term = TestTerminal(stream=stream) with mock.patch("tty.setcbreak") as mock_setcbreak: - with term.cbreak(): + with term.keystroke_input(): assert not mock_setcbreak.called assert term.keyboard_fd is None child() @@ -243,85 +243,85 @@ def test_notty_kb_is_None(): child() -def test_raw_no_kb(): - "raw() should not call tty.setraw() without keyboard." +def test_raw_input_no_kb(): + "keystroke_input(raw=True) should not call tty.setraw() without keyboard." @as_subprocess def child(): with tempfile.NamedTemporaryFile() as stream: term = TestTerminal(stream=stream) with mock.patch("tty.setraw") as mock_setraw: - with term.raw(): + with term.keystroke_input(raw=True): assert not mock_setraw.called assert term.keyboard_fd is None child() -def test_kbhit_no_kb(): - "kbhit() always immediately returns False without a keyboard." +def test_char_is_ready_no_kb(): + "_char_is_ready() always immediately returns False without a keyboard." @as_subprocess def child(): term = TestTerminal(stream=StringIO()) stime = time.time() assert term.keyboard_fd is None - assert term.kbhit(timeout=1.1) is False + assert term._char_is_ready(timeout=1.1) is False assert (math.floor(time.time() - stime) == 1.0) child() -def test_inkey_0s_cbreak_noinput(): - "0-second inkey without input; '' should be returned." +def test_keystroke_0s_keystroke_input_noinput(): + "0-second keystroke without input; '' should be returned." @as_subprocess def child(): term = TestTerminal() - with term.cbreak(): + with term.keystroke_input(): stime = time.time() - inp = term.inkey(timeout=0) + inp = term.keystroke(timeout=0) assert (inp == u'') assert (math.floor(time.time() - stime) == 0.0) child() -def test_inkey_0s_cbreak_noinput_nokb(): - "0-second inkey without data in input stream and no keyboard/tty." +def test_keystroke_0s_keystroke_input_noinput_nokb(): + "0-second keystroke without data in input stream and no keyboard/tty." @as_subprocess def child(): term = TestTerminal(stream=StringIO()) - with term.cbreak(): + with term.keystroke_input(): stime = time.time() - inp = term.inkey(timeout=0) + inp = term.keystroke(timeout=0) assert (inp == u'') assert (math.floor(time.time() - stime) == 0.0) child() -def test_inkey_1s_cbreak_noinput(): - "1-second inkey without input; '' should be returned after ~1 second." +def test_keystroke_1s_keystroke_input_noinput(): + "1-second keystroke without input; '' should be returned after ~1 second." @as_subprocess def child(): term = TestTerminal() - with term.cbreak(): + with term.keystroke_input(): stime = time.time() - inp = term.inkey(timeout=1) + inp = term.keystroke(timeout=1) assert (inp == u'') assert (math.floor(time.time() - stime) == 1.0) child() -def test_inkey_1s_cbreak_noinput_nokb(): - "1-second inkey without input or keyboard." +def test_keystroke_1s_keystroke_input_noinput_nokb(): + "1-second keystroke without input or keyboard." @as_subprocess def child(): term = TestTerminal(stream=StringIO()) - with term.cbreak(): + with term.keystroke_input(): stime = time.time() - inp = term.inkey(timeout=1) + inp = term.keystroke(timeout=1) assert (inp == u'') assert (math.floor(time.time() - stime) == 1.0) child() -def test_inkey_0s_cbreak_input(): - "0-second inkey with input; Keypress should be immediately returned." +def test_keystroke_0s_keystroke_input_with_input(): + "0-second keystroke with input; Keypress should be immediately returned." pid, master_fd = pty.fork() if pid is 0: try: @@ -332,8 +332,8 @@ def test_inkey_0s_cbreak_input(): term = TestTerminal() read_until_semaphore(sys.__stdin__.fileno(), semaphore=SEMAPHORE) os.write(sys.__stdout__.fileno(), SEMAPHORE) - with term.cbreak(): - inp = term.inkey(timeout=0) + with term.keystroke_input(): + inp = term.keystroke(timeout=0) os.write(sys.__stdout__.fileno(), inp.encode('utf-8')) if cov is not None: cov.stop() @@ -353,8 +353,8 @@ def test_inkey_0s_cbreak_input(): assert math.floor(time.time() - stime) == 0.0 -def test_inkey_cbreak_input_slowly(): - "0-second inkey with input; Keypress should be immediately returned." +def test_keystroke_keystroke_input_with_input_slowly(): + "0-second keystroke with input; Keypress should be immediately returned." pid, master_fd = pty.fork() if pid is 0: try: @@ -365,9 +365,9 @@ def test_inkey_cbreak_input_slowly(): term = TestTerminal() read_until_semaphore(sys.__stdin__.fileno(), semaphore=SEMAPHORE) os.write(sys.__stdout__.fileno(), SEMAPHORE) - with term.cbreak(): + with term.keystroke_input(): while True: - inp = term.inkey(timeout=0.5) + inp = term.keystroke(timeout=0.5) os.write(sys.__stdout__.fileno(), inp.encode('utf-8')) if inp == 'X': break @@ -395,8 +395,8 @@ def test_inkey_cbreak_input_slowly(): assert math.floor(time.time() - stime) == 0.0 -def test_inkey_0s_cbreak_multibyte_utf8(): - "0-second inkey with multibyte utf-8 input; should decode immediately." +def test_keystroke_0s_keystroke_input_multibyte_utf8(): + "0-second keystroke with multibyte utf-8 input; should decode immediately." # utf-8 bytes represent "latin capital letter upsilon". pid, master_fd = pty.fork() if pid is 0: # child @@ -407,8 +407,8 @@ def test_inkey_0s_cbreak_multibyte_utf8(): term = TestTerminal() read_until_semaphore(sys.__stdin__.fileno(), semaphore=SEMAPHORE) os.write(sys.__stdout__.fileno(), SEMAPHORE) - with term.cbreak(): - inp = term.inkey(timeout=0) + with term.keystroke_input(): + inp = term.keystroke(timeout=0) os.write(sys.__stdout__.fileno(), inp.encode('utf-8')) if cov is not None: cov.stop() @@ -430,8 +430,8 @@ def test_inkey_0s_cbreak_multibyte_utf8(): @pytest.mark.skipif(os.environ.get('TRAVIS', None) is not None or platform.python_implementation() == 'PyPy', reason="travis-ci nor pypy handle ^C very well.") -def test_inkey_0s_raw_ctrl_c(): - "0-second inkey with raw allows receiving ^C." +def test_keystroke_0s_raw_input_ctrl_c(): + "0-second keystroke with raw allows receiving ^C." pid, master_fd = pty.fork() if pid is 0: # child try: @@ -440,9 +440,9 @@ def test_inkey_0s_raw_ctrl_c(): cov = None term = TestTerminal() read_until_semaphore(sys.__stdin__.fileno(), semaphore=SEMAPHORE) - with term.raw(): + with term.keystroke_input(raw=True): os.write(sys.__stdout__.fileno(), RECV_SEMAPHORE) - inp = term.inkey(timeout=0) + inp = term.keystroke(timeout=0) os.write(sys.__stdout__.fileno(), inp.encode('latin1')) if cov is not None: cov.stop() @@ -463,8 +463,8 @@ def test_inkey_0s_raw_ctrl_c(): assert math.floor(time.time() - stime) == 0.0 -def test_inkey_0s_cbreak_sequence(): - "0-second inkey with multibyte sequence; should decode immediately." +def test_keystroke_0s_keystroke_input_sequence(): + "0-second keystroke with multibyte sequence; should decode immediately." pid, master_fd = pty.fork() if pid is 0: # child try: @@ -473,8 +473,8 @@ def test_inkey_0s_cbreak_sequence(): cov = None term = TestTerminal() os.write(sys.__stdout__.fileno(), SEMAPHORE) - with term.cbreak(): - inp = term.inkey(timeout=0) + with term.keystroke_input(): + inp = term.keystroke(timeout=0) os.write(sys.__stdout__.fileno(), inp.name.encode('ascii')) sys.stdout.flush() if cov is not None: @@ -493,8 +493,8 @@ def test_inkey_0s_cbreak_sequence(): assert math.floor(time.time() - stime) == 0.0 -def test_inkey_1s_cbreak_input(): - "1-second inkey w/multibyte sequence; should return after ~1 second." +def test_keystroke_1s_keystroke_input_with_input(): + "1-second keystroke w/multibyte sequence; should return after ~1 second." pid, master_fd = pty.fork() if pid is 0: # child try: @@ -503,8 +503,8 @@ def test_inkey_1s_cbreak_input(): cov = None term = TestTerminal() os.write(sys.__stdout__.fileno(), SEMAPHORE) - with term.cbreak(): - inp = term.inkey(timeout=3) + with term.keystroke_input(): + inp = term.keystroke(timeout=3) os.write(sys.__stdout__.fileno(), inp.name.encode('utf-8')) sys.stdout.flush() if cov is not None: @@ -525,7 +525,7 @@ def test_inkey_1s_cbreak_input(): assert math.floor(time.time() - stime) == 1.0 -def test_esc_delay_cbreak_035(): +def test_esc_delay_keystroke_input_035(): "esc_delay will cause a single ESC (\\x1b) to delay for 0.35." pid, master_fd = pty.fork() if pid is 0: # child @@ -535,9 +535,9 @@ def test_esc_delay_cbreak_035(): cov = None term = TestTerminal() os.write(sys.__stdout__.fileno(), SEMAPHORE) - with term.cbreak(): + with term.keystroke_input(): stime = time.time() - inp = term.inkey(timeout=5) + inp = term.keystroke(timeout=5) measured_time = (time.time() - stime) * 100 os.write(sys.__stdout__.fileno(), ( '%s %i' % (inp.name, measured_time,)).encode('ascii')) @@ -560,7 +560,7 @@ def test_esc_delay_cbreak_035(): assert 34 <= int(duration_ms) <= 45, duration_ms -def test_esc_delay_cbreak_135(): +def test_esc_delay_keystroke_input_135(): "esc_delay=1.35 will cause a single ESC (\\x1b) to delay for 1.35." pid, master_fd = pty.fork() if pid is 0: # child @@ -570,9 +570,9 @@ def test_esc_delay_cbreak_135(): cov = None term = TestTerminal() os.write(sys.__stdout__.fileno(), SEMAPHORE) - with term.cbreak(): + with term.keystroke_input(): stime = time.time() - inp = term.inkey(timeout=5, esc_delay=1.35) + inp = term.keystroke(timeout=5, esc_delay=1.35) measured_time = (time.time() - stime) * 100 os.write(sys.__stdout__.fileno(), ( '%s %i' % (inp.name, measured_time,)).encode('ascii')) @@ -595,7 +595,7 @@ def test_esc_delay_cbreak_135(): assert 134 <= int(duration_ms) <= 145, int(duration_ms) -def test_esc_delay_cbreak_timout_0(): +def test_esc_delay_keystroke_input_timout_0(): """esc_delay still in effect with timeout of 0 ("nonblocking").""" pid, master_fd = pty.fork() if pid is 0: # child @@ -605,9 +605,9 @@ def test_esc_delay_cbreak_timout_0(): cov = None term = TestTerminal() os.write(sys.__stdout__.fileno(), SEMAPHORE) - with term.cbreak(): + with term.keystroke_input(): stime = time.time() - inp = term.inkey(timeout=0) + inp = term.keystroke(timeout=0) measured_time = (time.time() - stime) * 100 os.write(sys.__stdout__.fileno(), ( '%s %i' % (inp.name, measured_time,)).encode('ascii')) -- cgit v1.2.1