-
-
Notifications
You must be signed in to change notification settings - Fork 30.4k
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
readline.set_history_length
corrupts history files when used in a libedit build
#121160
Comments
For posterity, here is the workaround I came up with for the incompatible format of the history files: import re
import os
import errno
import logging
import readline
logger = logging.getLogger(__loader__.name)
history_filename = os.path.expanduser("~/.history")
def _is_using_libedit():
if hasattr(readline, "backend"):
return readline.backend == "editline"
else:
return "libedit" in readline.__doc__
# to load:
try:
readline.read_history_file(history_filename)
except OSError as exc:
if exc.errno == errno.EINVAL: # (screaming internally)
assert _is_using_libedit()
with open(history_filename, "r") as f:
history = f.readlines()
assert history[:1] != ["_HiStOrY_V2_"], \
"History file has already been converted"
assert not history or any(" " in line for line in history), \
"Pre-conversion history file is expected to contain space characters"
backup_filename = f"{history_filename}~"
if not os.path.exists(backup_filename):
with open(backup_filename, "w") as f:
f.writelines(history)
else:
logger.warning(f"history backup {backup_filename} exists, leaving it intact")
new_filename = f"{history_filename}.new"
with open(f"{history_filename}.new", "w") as f:
f.write("_HiStOrY_V2_\n")
f.writelines([
re.sub(r"[ \\]", lambda m: f"\\{ord(m[0]):03o}", line)
for line in history
])
os.rename(new_filename, history_filename)
logger.warning(f"this Python distribution uses libedit instead of GNU readline, "
f"and their history file formats are not compatible")
logger.warning(f"REPL history file has been converted from the GNU readline format "
f"to the libedit format; backup saved to {backup_filename}")
readline.read_history_file(history_filename)
# to save:
readline.set_history_length(1000)
if _is_using_libedit():
readline.replace_history_item(
max(0, readline.get_current_history_length() - readline.get_history_length()),
"_HiStOrY_V2_")
readline.write_history_file(history_filename) In my view, the |
Hello @whitequark! Thanks for reporting this. I'm not sure I know what you mean by “libedit transition”? CPython supports building with libedit, and the support was improved gradually over the years, but I'm not aware of a “transition”. (1.) This is a tough one :( If we go for transparently converting history files, we also need a way to get back, or at least ensure that libedit's The workaround looks like a pain to maintain in the long term -- poking too deep into internals. I couldn't find much documentation on the IMO (based on my current understanding), I think this kind of transition code should be in (2.) Hmm. Perhaps (3.) As you say, I'm afraid |
Oh, I see in the other issue:
Yeah, that sounds like a bad move :/ |
So what happened is that I ran into this issue headfirst with PDM's cpython builds (which are from python-build-standalone project, where since 3.12 it uses libedit for reasons unknown to me), it had disrupted my workflow in the middle of something else, and I attempted to research something I had absolutely no context for. I found some issues where Homebrew users hit the same issue, with roughly the same version range, where also the Python build was moved to libedit. From this, the knowledge that people sometimes avoid GNU packages due to their licensing, and the fact that it seemed unthinkable to me (after noticing how incompatible the implementations are) that someone would be willing to disrupt people's workflows this much without a good reason I had concluded that there is a concerted effort behind, and the effort is to move to libedit while doing away with GNU readline entirely. As it's clear to me now, it is wrong, and this is just an issue that fell through the cracks that happened to be very visibly disruptive to end users, which got triggered by a few seemingly independent packager decisions. Sometimes it really is just a coincidence! I'll edit my original post. |
I could definitely implement a backward transformation, and will do it the moment I encounter the reverse issue (which is probably soon, unfortunately).
I completely agree. (But couldn't the same be said about the dual readline/editline build in first place?) In any case, it seems to me to boil down to a question of who spends the effort to work around it, and it seems more useful to coordinate 'more upstream' in the CPython codebase.
I don't disagree but isn't
I was initially under impression that
Yeah, such things happen. I acknowledge both of these things. I have to work around already around some issues that only affect |
… formats. This is not something we can do too much about, without help from the underlying libraries.
We're missing a test for I also sent a PR for the docs.
That's ... a reason for you (or your redistributor) to avoid that library, or patch it, rather than fix its bugs elsewhere. (But note that I'm not certain if the bug is there; it could be in CPython or in build settings.)
Yeah, it seems GNU history is a separate library. That itself might cause some of the trouble. |
Oh, that's a good call. I think that would be enough from my perspective. |
Thanks for the two PRs! |
…onGH-121326) (cherry picked from commit 263c7e6) Co-authored-by: Petr Viktorin <[email protected]>
…onGH-121326) (cherry picked from commit 263c7e6) Co-authored-by: Petr Viktorin <[email protected]>
…121326) (GH-121856) (cherry picked from commit 263c7e6) Co-authored-by: Petr Viktorin <[email protected]>
…121326) (GH-121857) (cherry picked from commit 263c7e6) Co-authored-by: Petr Viktorin <[email protected]>
Reported to python-build-standalone: indygreg/python-build-standalone#281 |
…ts. (GH-121327) This is not something we can do too much about, without help from the underlying libraries.
… formats. (pythonGH-121327) This is not something we can do too much about, without help from the underlying libraries. (cherry picked from commit 709db44) Co-authored-by: Petr Viktorin <[email protected]>
…history formats. (pythonGH-121327) This is not something we can do too much about, without help from the underlying libraries. (cherry picked from commit 709db44) Co-authored-by: Petr Viktorin <[email protected]>
…y formats. (GH-121327) (GH-122030) This is not something we can do too much about, without help from the underlying libraries. (cherry picked from commit 709db44) Co-authored-by: Petr Viktorin <[email protected]>
This is about as much as we can do on the CPython side. If anyone has more ideas, let's reopen. |
Thanks again for handling this! It wasn't my proposed solution but as a maintainer I recognize that mine wasn't really viable for CPython. |
Python 3.12.5 is failing a newer ptest for reading/writing limited history. Skip it for now until a proper fix (if any) is determined. The new test was added in python/cpython@263c7e6 The GitHub issue is here: python/cpython#121160 The aforementioned bug report suggests that OSErrors like that show up when using the GNU readline-based readline module if a workaround isn't also incorporated. It also mentions a new readline backend will be available in 3.13 that might help, but that won't be available for a year. (From OE-Core rev: 20d7b78b18907dab0ca193a597b5da221b774a00) Signed-off-by: Trevor Gamblin <[email protected]> Signed-off-by: Richard Purdie <[email protected]>
Python 3.12.5 is failing a newer ptest for reading/writing limited history. Skip it for now until a proper fix (if any) is determined. The new test was added in python/cpython@263c7e6 The GitHub issue is here: python/cpython#121160 The aforementioned bug report suggests that OSErrors like that show up when using the GNU readline-based readline module if a workaround isn't also incorporated. It also mentions a new readline backend will be available in 3.13 that might help, but that won't be available for a year. Signed-off-by: Trevor Gamblin <[email protected]> Signed-off-by: Richard Purdie <[email protected]>
Python 3.12.5 is failing a newer ptest for reading/writing limited history. Skip it for now until a proper fix (if any) is determined. The new test was added in python/cpython@263c7e6 The GitHub issue is here: python/cpython#121160 The aforementioned bug report suggests that OSErrors like that show up when using the GNU readline-based readline module if a workaround isn't also incorporated. It also mentions a new readline backend will be available in 3.13 that might help, but that won't be available for a year. (From OE-Core rev: 6c2dffdfd3c9e4bb4248be92c4e350265094dacd) Signed-off-by: Trevor Gamblin <[email protected]> Signed-off-by: Richard Purdie <[email protected]>
Python 3.12.5 is failing a newer ptest for reading/writing limited history. Skip it for now until a proper fix (if any) is determined. The new test was added in python/cpython@263c7e6 The GitHub issue is here: python/cpython#121160 The aforementioned bug report suggests that OSErrors like that show up when using the GNU readline-based readline module if a workaround isn't also incorporated. It also mentions a new readline backend will be available in 3.13 that might help, but that won't be available for a year. Signed-off-by: Trevor Gamblin <[email protected]> Signed-off-by: Richard Purdie <[email protected]>
Python 3.12.5 is failing a newer ptest for reading/writing limited history. Skip it for now until a proper fix (if any) is determined. The new test was added in python/cpython@263c7e6 The GitHub issue is here: python/cpython#121160 The aforementioned bug report suggests that OSErrors like that show up when using the GNU readline-based readline module if a workaround isn't also incorporated. It also mentions a new readline backend will be available in 3.13 that might help, but that won't be available for a year. (From OE-Core rev: 6c2dffdfd3c9e4bb4248be92c4e350265094dacd) Signed-off-by: Trevor Gamblin <[email protected]> Signed-off-by: Richard Purdie <[email protected]>
Python 3.12.5 is failing a newer ptest for reading/writing limited history. Skip it for now until a proper fix (if any) is determined. The new test was added in python/cpython@263c7e6 The GitHub issue is here: python/cpython#121160 The aforementioned bug report suggests that OSErrors like that show up when using the GNU readline-based readline module if a workaround isn't also incorporated. It also mentions a new readline backend will be available in 3.13 that might help, but that won't be available for a year. (From OE-Core rev: 32c9b4c0e6dbbae3d1eb91c65484d82f7ee596c2) Signed-off-by: Trevor Gamblin <[email protected]> Signed-off-by: Richard Purdie <[email protected]>
Python 3.12.5 is failing a newer ptest for reading/writing limited history. Skip it for now until a proper fix (if any) is determined. The new test was added in python/cpython@263c7e6 The GitHub issue is here: python/cpython#121160 The aforementioned bug report suggests that OSErrors like that show up when using the GNU readline-based readline module if a workaround isn't also incorporated. It also mentions a new readline backend will be available in 3.13 that might help, but that won't be available for a year. Signed-off-by: Trevor Gamblin <[email protected]> Signed-off-by: Richard Purdie <[email protected]>
Bug report
Bug description:
Since the libedit transition(correction: If an end user switches from a GNU readline build of Python to an editline build of Python), several important functions related to history files are broken.readline
module are unreadable and result in a rather confusingOSError
withexc.errno == errno.EINVAL
(without a corresponding operating system routine that returns such an error), but a workaround intercepting thisOSError
can be written that converts the old format to the new one. This has been covered before, e.g. in The New REPL Does Not Load My Command History #120766.readline
module are unreadable by itself whenset_history_length
is used, as demonstrated by the code below.readline.backend
for the backendreadline
uses #112510 becomes available in a release), your only option is"libedit" in readline.__doc__
, which I expect will be what many people will leave in the codebase even oncereadline.backend
becomes available.Reproducer:
Workaround:
CPython versions tested on:
3.12
Operating systems tested on:
Linux
Linked PRs
The text was updated successfully, but these errors were encountered: