Skip to content

KeyboardInterrupt about test for REPL was directly captured by the test program #128676

Open
@Natural-selection1

Description

Bug report

Bug description:

When I was writing test for PR #128467

# under class TestPyReplCompleter(line ≈ 806) Lib/test/test_pyrepl/test_pyrepl.py
    def test_completion_menu_cleared_after_KeyboardInterrupt(self):
        events = itertools.chain(
            code_to_events("int."),
            [
                Event(evt="key", data="\t", raw=bytearray(b"\t")),
                Event(evt="key", data="\t", raw=bytearray(b"\t")),
                Event(evt="key", data="\x03", raw=bytearray(b"\x03")),  # Ctrl+C
            ],
        )

        namespace = {}
        reader = self.prepare_reader(events, namespace)
        output = multiline_input(reader, namespace)

        self.assertEqual(clean_screen(reader.screen), "int.") # asser condition isn't good now

I found the KeyboardInterrupt caused by Event(evt="key", data="\x03", raw=bytearray(b"\x03")) will be directly captured by the test program itself

# result of ".\python.bat -m test test_pyrepl.test_pyrepl -v"
== Tests result: INTERRUPTED ==

1 test omitted:
    test_pyrepl.test_pyrepl

Test suite interrupted by signal SIGINT.

Total duration: 1.3 sec
Total tests: run=0
Total test files: run=0/1
Result: INTERRUPTED

So I added a traceback in the test function

    def test_completion_menu_cleared_after_KeyboardInterrupt(self):
        events = itertools.chain(
            code_to_events("int."),
            [
                Event(evt="key", data="\t", raw=bytearray(b"\t")),
                Event(evt="key", data="\t", raw=bytearray(b"\t")),
                Event(evt="key", data="\x03", raw=bytearray(b"\x03")),  # Ctrl+C
            ],
        )

        namespace = {}
        reader = self.prepare_reader(events, namespace)

        try:
            output = multiline_input(reader, namespace)
        except KeyboardInterrupt:
            traceback.print_exc()

        self.assertEqual(clean_screen(reader.screen), "int.")

I also added traceback.print_exc() in Lib/_pyrepl/simple_interact.py(line ≈ 164)(the user-facing REPL)

        except KeyboardInterrupt:
            traceback.print_exc() # here
            r = _get_reader()
            if r.input_trans is r.isearch_trans:
                r.do_cmd(("isearch-end", [""]))
            if r.cmpltn_menu_choices:
                r.cmpltn_reset()
            r.pos = len(r.get_unicode())
            r.dirty = True
            r.refresh()
            r.in_bracketed_paste = False
            console.write("\nKeyboardInterrupt\n")
            console.resetbuffer()

recompile and run

Python 3.14.0a3+ (heads/clean_suggestion-dirty:9801a103467, Jan  9 2025, 14:45:54) [MSC v.1942 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> Traceback (most recent call last):
  File "E:\0000__Python_Project\00__cpython\Lib\_pyrepl\simple_interact.py", line 151, in run_multiline_interactive_console
    statement = multiline_input(more_lines, ps1, ps2)
  File "E:\0000__Python_Project\00__cpython\Lib\_pyrepl\readline.py", line 389, in multiline_input
    return reader.readline()
           ~~~~~~~~~~~~~~~^^
  File "E:\0000__Python_Project\00__cpython\Lib\_pyrepl\reader.py", line 801, in readline
    self.handle1()
    ~~~~~~~~~~~~^^
  File "E:\0000__Python_Project\00__cpython\Lib\_pyrepl\reader.py", line 756, in handle1
    self.console.wait(100)
    ~~~~~~~~~~~~~~~~~^^^^^
  File "E:\0000__Python_Project\00__cpython\Lib\_pyrepl\windows_console.py", line 486, in wait
    time.sleep(0.01)
    ~~~~~~~~~~^^^^^^
KeyboardInterrupt

KeyboardInterrupt
>>>

At the same time, the related error in the test is

File "E:\0000__Python_Project\00__cpython\Lib\test\test_pyrepl\test_pyrepl.py", line 864, in test_completion_menu_cleared_after_KeyboardInterrupt
    output = multiline_input(reader, namespace)
  File "E:\0000__Python_Project\00__cpython\Lib\test\test_pyrepl\support.py", line 18, in multiline_input
    return reader.readline()
           ~~~~~~~~~~~~~~~^^
  File "E:\0000__Python_Project\00__cpython\Lib\_pyrepl\reader.py", line 801, in readline
    self.handle1()
    ~~~~~~~~~~~~^^
  File "E:\0000__Python_Project\00__cpython\Lib\_pyrepl\reader.py", line 784, in handle1
    self.do_cmd(cmd)
    ~~~~~~~~~~~^^^^^
  File "E:\0000__Python_Project\00__cpython\Lib\_pyrepl\reader.py", line 709, in do_cmd
    command.do()
    ~~~~~~~~~~^^
  File "E:\0000__Python_Project\00__cpython\Lib\_pyrepl\commands.py", line 227, in do
    raise KeyboardInterrupt
KeyboardInterrupt
FAIL

# something...

======================================================================
FAIL: test_completion_menu_cleared_after_KeyboardInterrupt (test.test_pyrepl.test_pyrepl.TestPyReplCompleter.test_completion_menu_cleared_after_KeyboardInterrupt)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "E:\0000__Python_Project\00__cpython\Lib\test\test_pyrepl\test_pyrepl.py", line 868, in test_completion_menu_cleared_after_KeyboardInterrupt
    self.assertEqual(clean_screen(reader.screen), "int.")
    ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: 'int.as_integer_ratio(  int.denominator       [259 chars]int.' != 'int.'
+ int.
- int.as_integer_ratio(  int.denominator        int.mro()
- int.bit_count(         int.from_bytes(        int.numerator
- int.bit_length(        int.imag               int.real
- int.conjugate(         int.is_integer(        int.to_bytes(
- >>>int.


----------------------------------------------------------------------

So the KeyboardInterrupt in test did not behave correctly as if the user pressed Ctrl+C, but was directly captured by the test program

CPython versions tested on:

CPython main branch

Operating systems tested on:

Windows

Metadata

Assignees

No one assigned

    Labels

    topic-replRelated to the interactive shelltype-bugAn unexpected behavior, bug, or error

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions