Skip to content

gh-133400: Fixed Ctrl+D (^D) behavior in :mod:_pyrepl module #133883

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

deepwzh
Copy link

@deepwzh deepwzh commented May 11, 2025

Fixed Ctrl+D (^D) behavior in :mod:_pyrepl module:

  • Now properly exits multiline mode when pressed in multiline section
  • Added test cases to verify the behavior in both multiline and single line modes

@StanFromIreland
Copy link
Member

StanFromIreland commented May 11, 2025

This is not ideal:

>>> if True:
...     
  File "<python-input-2>", line 1
    if True:
            ^
IndentationError: expected an indented block after 'if' statement on line 1
>>>

@deepwzh
Copy link
Author

deepwzh commented May 11, 2025

This is not ideal:

>>> if True:
...     
  File "<python-input-2>", line 1
    if True:
            ^
IndentationError: expected an indented block after 'if' statement on line 1
>>>

This fix is ​​to correctly handle the issue of Ctrl+D to exit multi-line mode. What do you think the expected behavior should be?
@StanFromIreland

@ZeroIntensity ZeroIntensity added topic-repl Related to the interactive shell needs backport to 3.13 bugs and security fixes needs backport to 3.14 bugs and security fixes labels May 11, 2025
@feoh
Copy link
Contributor

feoh commented May 19, 2025

@ambv FWIW I tested this PR on my Mac (main branch, latest, MacOS latest) and it works great. I tried throwing a bunch of other unclosed constructs (e.g. {, [, etc.) and none exhibited this error either.

@feoh
Copy link
Contributor

feoh commented May 19, 2025

@StanFromIreland Are you suggesting that the error message in the if True: case could be more clear?

The fact that the user isn't supplying a valid indented block after the if True: is indeed a problem the language needs to flag, so I'm curious what specific wording you think might be more clear. Also it seems to me like this could be a separate Github issue. Do you agree?

@adqm
Copy link
Contributor

adqm commented Jul 20, 2025

Looking at those lines again, I would probably refactor to bring the check for self.event[-1] == "\004" out in front, replacing the current if/elif structure with something like the following:

        if self.event[-1] == "\004":
            if b and b[-1].endswith("\n"):
                self.finish = True
            elif (
                r.pos == 0
                and len(b) == 0  # this is something of a hack
            ):
                r.update_screen()
                r.console.finish()
                raise EOFError

I tried looking at the test cases a little bit, but I haven't been able to figure out how best to add the tests yet. What I wanted to test was that the following happens:

  • ^D in the middle of a line deletes the current character
  • ^D at the end of a nonempty line does nothing
  • ^D on a blank line with no preceding lines raises EOFError
  • ^D on a blank line with preceding lines runs the code up to that point

I tested that at my own terminal (using the version of the code I pasted above), but I'm not sure the best way to encode that as test cases since multiline_input is unhappy with what I tried to feed it to simulate those cases.


@StanFromIreland, this behavior would be consistent with the pre-3.13 REPL, which is what I think we should be aiming for here.

@deepwzh deepwzh force-pushed the fix-issue-133400 branch from 92bb608 to d0dc732 Compare July 20, 2025 09:03
@deepwzh
Copy link
Author

deepwzh commented Jul 20, 2025

Looking at those lines again, I would probably refactor to bring the check for self.event[-1] == "\004" out in front, replacing the current if/elif structure with something like the following:

        if self.event[-1] == "\004":
            if b and b[-1].endswith("\n"):
                self.finish = True
            elif (
                r.pos == 0
                and len(b) == 0  # this is something of a hack
            ):
                r.update_screen()
                r.console.finish()
                raise EOFError

I tried looking at the test cases a little bit, but I haven't been able to figure out how best to add the tests yet. What I wanted to test was that the following happens:

  • ^D in the middle of a line deletes the current character
  • ^D at the end of a nonempty line does nothing
  • ^D on a blank line with no preceding lines raises EOFError
  • ^D on a blank line with preceding lines runs the code up to that point

I tested that at my own terminal (using the version of the code I pasted above), but I'm not sure the best way to encode that as test cases since multiline_input is unhappy with what I tried to feed it to simulate those cases.

@StanFromIreland, this behavior would be consistent with the pre-3.13 REPL, which is what I think we should be aiming for here.

I tried to make some modifications and add more tests based on what you just said

@adqm
Copy link
Contributor

adqm commented Jul 21, 2025

I tried to make some modifications and add more tests based on what you just said

Thanks! I just tested this out and it feels right to me (at least if the goal is indeed to mimic the behavior of the old pre-3.13 REPL, which I think is the right thing to do here).

Unfortunately I don't have any authority here, but hopefully you'll get some additional code review 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting review needs backport to 3.13 bugs and security fixes needs backport to 3.14 bugs and security fixes topic-repl Related to the interactive shell
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy