-
-
Notifications
You must be signed in to change notification settings - Fork 33.2k
Closed
Closed
Copy link
Labels
topic-replRelated to the interactive shellRelated to the interactive shelltype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
Description
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.
- It is inconvenient enough that history files written by GNU readline based
readlinemodule are unreadable and result in a rather confusingOSErrorwithexc.errno == errno.EINVAL(without a corresponding operating system routine that returns such an error), but a workaround intercepting thisOSErrorcan 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. - More importantly, history files written by libedit based
readlinemodule are unreadable by itself whenset_history_lengthis used, as demonstrated by the code below. - While a workaround for that is also possible (also below), as far as I can tell, until 3.13, so until a year from now (?) (whenever Add
readline.backendfor the backendreadlineuses #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.backendbecomes available.
Reproducer:
import readline
readline.add_history("foo bar")
readline.add_history("nope nope")
readline.write_history_file("history-works")
# this works:
readline.read_history_file("history-works")
readline.set_history_length(2)
readline.write_history_file("history-breaks")
# this breaks:
readline.read_history_file("history-breaks")Workaround:
def _is_using_libedit():
if hasattr(readline, "backend"):
return readline.backend == "editline"
else:
return "libedit" in readline.__doc__
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_")CPython versions tested on:
3.12
Operating systems tested on:
Linux
Linked PRs
- gh-121160: Add a test for readline.set_history_length #121326
- gh-121160: Note that readline libraries using different history formats. #121327
- [3.13] gh-121160: Add some tests for readline.set_history_length (GH-121326) #121856
- [3.12] gh-121160: Add some tests for readline.set_history_length (GH-121326) #121857
- [3.13] gh-121160: Note that readline libraries using different history formats. (GH-121327) #122030
- [3.12] gh-121160: Note that readline libraries using different history formats. (GH-121327) #122031
Metadata
Metadata
Assignees
Labels
topic-replRelated to the interactive shellRelated to the interactive shelltype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error