Repository navigation
Event.raw being added to itself instead of to another event's .raw in UnixConsole.getpending #145886
Description
Activity
- addedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or errorstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directorytopic-replRelated to the interactive shellRelated to the interactive shell
on Mar 12, 2026 Since
.rawis never read by any consumer, it's dead code. This removes the field and all assignments to it:Yeah, I already did so for Windows in adb89ba and left a smiley on that typo #132440 (comment).
Tbh, I think it is time to remove
.rawaltogether instead of fixing the wrong-but-dead code path.The only thing I am concerned is the side effect of
flush_bufin
cpython/Lib/_pyrepl/base_eventqueue.py
Line 90 in 79b91e7
self.insert(Event('key', k, bytes(self.flush_buf())))
and
cpython/Lib/_pyrepl/base_eventqueue.py
Line 109 in 79b91e7
self.insert(Event('key', decoded, bytes(self.flush_buf())))
but I think, we can just simplifydef flush_buf(self): """ Flushes the buffer. """ self.buf = bytearray()
since the
rawmember is nowhere needed AFAICT ...Please let me know which solution is preferred and I can write a trivial PR to implement it.
@wavebyrd please don't open a PR when
- the OP already stated they're up for it
- and furthermore there even isn't a decision, yet
- added a commit that references this issue
on Mar 18, 2026 Hi, I opened a PR for this: #146097
I went with removing the
Event.rawfield entirely since it's not read anywhere, instead of just fixing the typo. Also cleaned up the tests.@chris-eibl would appreciate if you can take a look when you have time, thanks!
We did not decide whether to remove the field or not. Please do not open PRs
I think we need to keep the raw data. I might be necessary in the future to handle special key sequences that are not recognized. And if we were to expose the repl publicly it would also be a way for custom handlers to handle the event.
So I personally prefer fixing the typo rather than removing the field.
OTOH the Windows console has no more raw buffer. What was the rationale for removing it?
I didn't remove it, just not populate it anymore in the few code parts that did, while most did not, and there was no "user" of it.
So there was an inconsistency in how it is being populated you mean? if this the case, then ok for removing the field altogether. However could you check if pypi repos use the pyrepl private implementation? while clearly internal we should avoid breaking packages when possible (at least give them a heads up)
I'm not too attached to writing the PR, I just thought it would help. So feel free to reopen the PR that matches the agreed decision when one is made.
Thank you @HCYT and @wavebyrd for the interest and willingness to help, we just need to do things in an orderly way, like reaching a decision before firing up the PRs.
So there was an inconsistency in how it is being populated you mean?
For Windows, yes. And just not populating
Event.rawanymore at all in adb89ba about a year ago seems to have not caused any pain so far.However could you check if pypi repos use the pyrepl private implementation?
Ok. I've used @vstinner's search_pypi_top.py and searched for
_pyreplin the top 5000 packages, becauseconsoleorEventwould give too many false-positives. Strippingstdlib_list-0.12.0.tar.gzhits from the output results in only 37 occurrencesDetails
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: prefer_pyrepl = True
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: using_pyrepl = False # overwritten by find_pyrepl
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: def find_pyrepl(self):
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: import _pyrepl.completing_reader
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: import _pyrepl.readline
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: sys.modules["readline"] = _pyrepl.readline
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: self.using_pyrepl = True
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: return _pyrepl.readline, True
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: self.using_pyrepl = True
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: if self.prefer_pyrepl:
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: result = self.find_pyrepl()
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: readline.backend = "_pyrepl"
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: readline._setup(namespace or {}) # internal _pyrepl implementation
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: if config.using_pyrepl or sys.platform != "darwin":
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: def interact_pyrepl(namespace: dict | None = None):
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: from _pyrepl import readline
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: from _pyrepl.console import InteractiveColoredConsole
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: from _pyrepl.simple_interact import run_multiline_interactive_console
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: if completer.config.using_pyrepl and "pypy" not in sys.builtin_module_names:
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/fancycompleter/init.py: interact_pyrepl(namespace)
.\fancycompleter-0.11.1.tar.gz: fancycompleter-0.11.1/pyproject.toml: module = ["_pyrepl.", "pyrepl.", "pyreadline.*"]
.\mpmath-1.4.1.tar.gz: mpmath-1.4.1/mpmath/main.py: from _pyrepl.main import CAN_USE_PYREPL
.\mpmath-1.4.1.tar.gz: mpmath-1.4.1/mpmath/main.py: from _pyrepl.console import
.\mpmath-1.4.1.tar.gz: mpmath-1.4.1/mpmath/main.py: from _pyrepl.main import CAN_USE_PYREPL
.\mpmath-1.4.1.tar.gz: mpmath-1.4.1/mpmath/main.py: from _pyrepl.simple_interact import
.\pdbpp-0.12.1.tar.gz: pdbpp-0.12.1/src/pdbpp.py: def _patch_readline_for_pyrepl(self):
.\pdbpp-0.12.1.tar.gz: pdbpp-0.12.1/src/pdbpp.py: uses_pyrepl = self.fancycompleter.config.readline != sys.modules["readline"]
.\pdbpp-0.12.1.tar.gz: pdbpp-0.12.1/src/pdbpp.py: if not uses_pyrepl:
.\pdbpp-0.12.1.tar.gz: pdbpp-0.12.1/src/pdbpp.py: with self._patch_readline_for_pyrepl():
.\pdbpp-0.12.1.tar.gz: pdbpp-0.12.1/testing/conftest.py: ("pyrepl" if sys.version_info < (3, 13) else "_pyrepl"),
.\pdbpp-0.12.1.tar.gz: pdbpp-0.12.1/testing/conftest.py: m.setattr("fancycompleter.DefaultConfig.prefer_pyrepl", False)
.\pdbpp-0.12.1.tar.gz: pdbpp-0.12.1/testing/conftest.py: import _pyrepl.readline
.\pdbpp-0.12.1.tar.gz: pdbpp-0.12.1/testing/conftest.py: m.setattr("fancycompleter.DefaultConfig.prefer_pyrepl", True)
.\pdbpp-0.12.1.tar.gz: pdbpp-0.12.1/testing/conftest.py: elif readline_param == "_pyrepl":
.\pdbpp-0.12.1.tar.gz: pdbpp-0.12.1/testing/conftest.py: readline = "_pyrepl.readline"
.\pdbpp-0.12.1.tar.gz: pdbpp-0.12.1/testing/test_pdb.py: # and readline_param != "_pyrepl"
.\pdbpp-0.12.1.tar.gz: pdbpp-0.12.1/testing/test_pdb.py: prefer_pyrepl = Falsewhere the only line to investigate further
.\mpmath-1.4.1.tar.gz: mpmath-1.4.1/mpmath/__main__.py: from _pyrepl.console import \reveals that
https://github.com/mpmath/mpmath/blob/7b40a40cc6b8961cfa9d1697e6e7075d42f56f0a/mpmath/__main__.py#L113-L114from _pyrepl.console import \ InteractiveColoredConsole as InteractiveConsole
is harmless, too. So I could definitely not find a direct user of
Event.raw. To me, the hits do not even hint for any indirect users, but I might have overlooked some code paths.- marked _pyrepl: Fix raw buffer merge when coalescing pending input events #146589 as a duplicate of this issue
on Mar 29, 2026 @pablogsal has fixed the type in
getpending()in #146584.
I think we can close here?
Bug report
Bug description:
There is a small bug in
_pyrepl.unix_console.UnixConsole.getpending, where instead of adding the raw data of event 2, we add the raw data of event 1 to itself:cpython/Lib/_pyrepl/unix_console.py
Lines 540 to 546 in cd52172
We can just fix the typo:
e.raw += e.rawbecomese.raw += e2.raw. It's feasible to add a test for this.But
Event.rawisn't read anywhere and is untested. The 3 callers ofgetpending()only useev.dataorpending.data. The.rawfield is only written to, never consumed. So we can simply remove it fromEventand adapt some lines (summary below written with Claude Code).Please let me know which solution is preferred and I can write a trivial PR to implement it.
Since
.rawis never read by any consumer, it's dead code. This removes the field and all assignments to it:console.py— Removerawfrom the dataclass:unix_console.py— Remove allraw-related code in bothgetpendingvariants:Event("key", "", b"")→Event("key", "")e.raw += e.rawraw = .../data = str(raw, ...)→data = str(self.__read(amount), ...)e.raw += rawCPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Linked PRs