Arrow key history broken when stdin is passed explicitly on pdb
Bug report
Bug description:
Description:
When using pdb through pytest (or any tool that passes stdin explicitly), arrow key history doesn't work even when stdin is a real TTY. And currently, we assume readline.backend exists even on windows where pyreadline3 doesn't have readline.backend
https://github.com/astral-sh/uv/issues/17174 directly related to this.
CPython versions tested on:
CPython main branch
Operating systems tested on:
Windows
Linked PRs
- gh-143083
I believe the general rule of thumb is that if you want to monkeypatch the standard libraray, you are on your own. readline is a standard library and pdb uses a new attribute of readline. pyreadline3 is a 3rd party library that tries to replace the standard readline. It's impossible for us to check every single newly added attribute on standard library because the code will be full of hasattr().
We don't remove attributes from a standard library without a deprecation phase, but we add new stuff to the standard library and we don't check if that newly added attribute exists just because a 3rd party library could've replaced the standard library in a magic way.
The TTY thing is a separate issue. I have doubts about this change. If stdin is given to pdb and it's a TTY, we just read from the default sys.stdin? That feels off to me. Is it possible that the stdin given is not sys.stdin? It could be a different tty interface I think?
I believe the general rule of thumb is that if you want to monkeypatch the standard libraray, you are on your own.
readlineis a standard library andpdbuses a new attribute ofreadline.pyreadline3is a 3rd party library that tries to replace the standardreadline. It's impossible for us to check every single newly added attribute on standard library because the code will be full ofhasattr().We don't remove attributes from a standard library without a deprecation phase, but we add new stuff to the standard library and we don't check if that newly added attribute exists just because a 3rd party library could've replaced the standard library in a magic way.
The TTY thing is a separate issue. I have doubts about this change. If
stdinis given topdband it's aTTY, we just read from the defaultsys.stdin? That feels off to me. Is it possible that thestdingiven is notsys.stdin? It could be a differentttyinterface I think?
I completely agree with your points but I have few questions that I want to solve.
I believe the general rule of thumb is that if you want to monkeypatch the standard libraray, you are on your own. readline is a standard library and pdb uses a new attribute of readline. pyreadline3 is a 3rd party library that tries to replace the standard readline. It's impossible for us to check every single newly added attribute on standard library because the code will be full of hasattr().
I agree with the pyreadline3 being one of the problems but the issue here is mostly there is no readline standard library for windows, it just doesn't work. That's why people like me, the ones who want to use windows natively with python needs to just use pyreadline3 no matter what. (Please do correct me if there is a way around this though, as i didn't find any after testing) So the fix, in this case, would be very much a special case because its simply needed for windows compability. But the PR's fix on this is just a byproduct of the main issue, I can move that part to them and try to solve with them, it's okay on that part. Please do tell me what you think on that.
The TTY thing is a separate issue. I have doubts about this change. If stdin is given to pdb and it's a TTY, we just read from the default sys.stdin? That feels off to me. Is it possible that the stdin given is not sys.stdin? It could be a different tty interface I think?
This is the start of the fix by the way. The issue is very Windows-specific. On Windows, input() uses the proper Windows Console API which supports arrow keys and history natively. When pdb switches to stdin.readline() (even on the same sys.stdin), it bypasses this console handling, breaking arrow key support. I debugged this through uv and pytest, both pass valid stdin handles, but the problem is that pdb then uses .readline() on it instead of input(). The stdin itself is fine, it's the method of reading struggles on Windows. The pr on this issue is about when stdin IS the real sys.stdin (a TTY), we use input() which preserves Windows console functionality. This doesn't ignore the passed stdin, it just uses the correct reading method for it. (Again, this is very specific to windows and its console features) (Using this will expose the readline code change i did by the way)
So the last commit of pyreadline3 is from 2 years ago. Not only it's a 3rd party library, it's an unmaintained library. I don't think we should make effort to support it, even though it was used by a certain amount of people. If it is well-maintained, it should be easy enough for them to add backend attribute.
The other change to check if stdin is sys.stdin is very reasonable. If sys.stdin is explicitly passed to pdb, we should use input() to keep as much capability of readline as possible.
So if you can revert the changes to readline.backend, I can merge your other change to main.
However, if you have a strong opinion on the part that I disagree, you can also reach out to other core devs and ask their opinions about it.
So the last commit of
pyreadline3is from 2 years ago. Not only it's a 3rd party library, it's an unmaintained library. I don't think we should make effort to support it, even though it was used by a certain amount of people. If it is well-maintained, it should be easy enough for them to addbackendattribute.The other change to check if
stdinissys.stdinis very reasonable. Ifsys.stdinis explicitly passed to pdb, we should useinput()to keep as much capability of readline as possible.So if you can revert the changes to
readline.backend, I can merge your other change to main.However, if you have a strong opinion on the part that I disagree, you can also reach out to other core devs and ask their opinions about it.
Oh, I completely missed the fact that last commit of them was from 2 years ago. I reverted that part of the PR in order to keep the stdin change. It should be good to merge.