-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
gh-130660: Revert sys.ps1 and sys.ps2 after code.interact #130661
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
gh-130660: Revert sys.ps1 and sys.ps2 after code.interact #130661
Conversation
I'm fully aware that this is a 28-year old behavior - which I still think should be fixed. But maybe the original author @gvanrossum can share some thoughts about it? |
I don't particularly care whether we fix this or not -- if someone actually checks the presence of I have one suggestion: Instead of trying to set There's also logic in the new REPL to reset (Another bug in the new REPL seems to be that if I set |
Yeah I can do that.
Do you mean that if the user changes The reason I looked at this is that pdb recently added a check for whether the user is in interactive mode. Basically if the user starts the interactive interpreter and do |
You're right that checking But are there docs that suggest checking Next we'll see users setting Note that IDLE has a shell that has its own ps1 and ps2, which are initialized from sys.ps1 etc., but if you start it directly from the unix shell (instead of from the Python REPL), sys.ps1 is not set. In that case, even though it is clearly an interactive shell, sys.ps1 never gets set. I suppose this should be filed as an IDLE bug. (Additionally, I cannot actually start an IDLE shell in a way that does inherit sys.ps1 -- it always uses the defaults. But that may be my lack of IDLE-fu.) |
Well, pdb has its own interactive interface and it does not set I don't know if there's a documentation about how |
This should be fixed by #130503 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Lib/test/test_code_module.py
Outdated
self.assertEqual(self.sysmod.ps1, '>>> ') | ||
output = ''.join(''.join(call[1]) for call in self.stdout.method_calls) | ||
self.assertIn('>>> ', output) | ||
self.assertFalse(hasattr(self.sysmod, 'ps1')) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assertNotHasAttr
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it depends on whether we consider this a bug fix and backport it. assertNotHasAttr
is new in 3.14 which would cause issues when we backport the test. If we only want to fix this in 3.14 (which is fine by me because I only need this in 3.14), then sure we can use the latest method.
@gvanrossum do you think we should backport this? Or just leave it be for the previous versions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These methods were backported as private helpers in test.support
. You will need to add an import and a mix-in, but you will get clearer testing code with better error reporting.
No, I can still repro it. I will make a separate bug report. Regarding IDLE, its shell window definitely is (intended to be) an interpreter (I should know because I started the project long ago). Anyway, the behavior of pdb there is a bit confusing -- pdb warns that exiting will end the process, but if I select Yes there, it just goes back to the IDLE shell with a fresh prompt. So you don't have to fix anything there. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't backport this. It's an utter edge case but it does change observable behavior.
Ah, okay. So if IDLE sets |
The "problem" is that IDLE doesn't set sys.ps1, but somehow handles SystemExit differently (by simply ignoring it). So pdb says it is going to kill the process, but it doesn't. I think we can live with that, I don't think pdb needs to have a special case for IDLE (which has a built-in visual debugger anyway). |
Yeah that makes sense. |
"if IDLE sets sys.ps1": IDLE never sets sys.ps1 in either the UI process or the default-mode user-code execution process. If the user sets it in the execution process, it can affect other code run by the user, such as pdb. But sys.ps1 in the UI process is not affected. When we moved the primary (I opened a draft issue on IDLE Issues (view) to fix IDLE's failure when sys.ps1 is not a string. If IDLE continues to read it, it should treat it as information to be displayed separately from the >>> and ... prompts.) In the REPL, indentation no longer looks right if a user changes the length of ps1 but not ps2. Does anyone know, briefly, what sorts of non-default prompts are used? |
The sys.ps1/2 doc says "These are only defined if the interpreter is in interactive mode." This literally only prohibits setting in batch mode, which is the subject of this issue. Guido's comment #130661 (comment) suggests that it is also meant to require setting. And I agree that being consistent here with the REPL would be good. But it does not seem very easy. I added draft issue "IDLE: set execution process sys.ps1/2 when interactive" to the Run section of IDLE Issues. |
About pdb not exiting: the IDLE process was designed, before me, to survive anything user code does to the execution process. A user who wants a clean subprocess can explicitly request one on the Shell menu (or use the restart hotkey). A restart is also done if the user process does somehow die. I agree that pdb should not try to force that. |
Oh, so this means the UI process cannot see changes to sys.ps1 in the run process. Fair enough.
So you read sys.ps1 in the UI but it ends up not being used... Searching the code I found where it was read but didn't realize it wasn't actually used because of the change to move the shell prompt to a separate UI column (that was a good call BTW, solves a lot of problems).
What would happen if you just removed the code that reads it?
Honestly I have no idea. I imagine many folks of the hacking persuasion have ended up coding something in there that shows dynamic data, like people put in bash prompts all the time (bash even has a mini-language for that purpose). In Python you can just do it by writing an object with a dynamic
I think from that sentence you can also infer that they are always defined in interactive mode -- it doesn't say "These may only be defined if ...", it says "These are only defined if ...".
Yeah, now that I'm reminded of the separation between UI and run process, I agree it might not be so easy. Perhaps the part of the run process that talks to the UI process could just set >>> sys.ps1 = "~~> "
>>> code.interact()
Python 3.14...
Type "help", ...
(InteractiveConsole)
~~> ^D
>>> |
I'd consider this as a bug fix as the current behavior does not match what we documented. However, it's a behavior that has been in the code base for a while (in a relatively dark corner), so I'm still open to suggestions.