-
-
Notifications
You must be signed in to change notification settings - Fork 31.2k
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
cmd.py command completion does not work with libedit #102130
Comments
Thanks for your report. Alas, the differences between GNU Suggestions for improving the documentation or specific bugs when following the current suggestion in the docs would be welcomed. Otherwise, I'm not sure there is any action to be taken here. |
Thank you for that very helpful clue. A quick google later, reveals I can change my code to this: import cmd
import readline
if 'libedit' in readline.__doc__:
print("Found libedit readline")
readline.parse_and_bind("bind ^I rl_complete")
else:
print("Found gnu readline")
readline.parse_and_bind("tab: complete")
class MyShell(cmd.Cmd):
def do_command(self, _arg):
print(f"running {self}")
MyShell().cmdloop() And after that the tab completion works for both libraries. I have no idea why that works, but it does. The libedit version isn't quite right, because the first press of tab does nothing but sound the bell, then the second (and subsequent) presses work as I'd expect. A whole lot better than no completion, obviously. It would be nice if Python abstracted this away to make cmd.py work out of the box for both libraries. |
I am going with slightly different code in the end because I don't want the odd behaviour with libedit tab completion to change the user experience. So I've added gnureadline to required dependencies and am hooking the import: class MetaPathLoader:
def load_module(self, fullname):
if fullname in sys.modules:
return sys.modules[fullname]
gnu = importlib.import_module("gnureadline")
sys.modules["readline"] = gnu
return gnu
class MetaPathFinder:
def find_module(self, fullname, path=None):
if fullname is "readline":
return MetaPathLoader()
sys.meta_path.insert(0, MetaPathFinder()) I hope people agree, this is pretty horrible. |
To me this looks like a legitimate bug report for the The ideal course of action here would be to figure out the right code needed in If we achieve that, there may also be an argument for a follow-up feature where the |
@hugovk I think maybe we should not tag this bug as |
Makes sense, I've removed the label 👍 |
Whilst it would be great to fix cmd.py to make it perfect, I'd hate to chew through significant Python developer time to resolve all the issues with libedit readline. There are at least two: The first relating to history files, the second to tab completion. Once people start using it in earnest we may find more. Let's think for a moment who uses cmd.py. It's for command-line interfaces, so for people who are comfortable with that, implying developers or technical people. They won't think twice about installing a GNU dependency on their desktop machine. Let's also think who has a problem with a GNU dependency. That would be someone shipping a closed source product embedding Python with some kind of interactive configuration shell. pfSense or something like it comes to mind, but these kinds of apps/devices usually ship with web interfaces. It's all getting a bit niche. I don't think it's full libedit support that's needed here, just a straightforward route for application maintainers (such as myself) to get their users working. Adding the dependency on gnureadline is very easy for me. I guess it breaks some fundamental rule in Python if we refer directly to a third-party package in cmd.py, so the next best thing is to pass it in. If it's passed to the Cmd constructor, it could be used in preference to readline.
|
Also, the differences you note here aren't limited to the python |
Accepting that it's a valid bug is not a promise that core developers (or anyone else) will be able to prioritize fixing it, and it doesn't obligate anyone to use their time against their preferences. It just means that if someone comes along who is interested and motivated to fix it, they have some indication that a fix is desired and a good implementation of a fix is likely to be accepted.
Lots of open issues on CPython are niche :) If they are too niche for anyone to care, they will eventually be closed due to inactivity / lack of interest. But lots of niche issues do find a motivated developer within that niche to fix them.
You've provided some details on the tab completion issue; can you say more about the history issue (i.e. what doesn't work, have you discovered any pointers about how to go about fixing it?) We could open a separate issue for it, but I'd be inclined for now to just broaden this issue to generally cover
I don't think dependency-injecting an alternate |
That's a fair point. It would be nice to pull in https://pypi.org/project/pyreadline3/ into the standard python distribution as well. my install_requires for dealing with cmd.py requirements is now:
|
Some information about Python's history file format and libedit vs readline is in Homebrew/homebrew-core#113811 (comment) Another quirk referring to Python history search and libedit is #100610, which also probably should have the "OS-mac" label removed. |
I have a Mac and I've been through multiple OS updates, multiple Python updates, generally swapped between Homebrew and built-in Python so I don't understand the exact sequence of events, but attempting to read certain types of history files with libedit readline results in the error as described here: I went back to Python with gnu readline, wrote some history, back to libedit, read the files and it wasn't that simple. I didn't see the error. Maybe newer versions of gnureadline stopped writing something incompatible to the files.
Yes, I discovered this later on 👍 |
This comment was marked as outdated.
This comment was marked as outdated.
… site, and pdb." This reverts commit 1374212.
IMO, teaching cmd.py to work with libedit is a new feature, and thus shouldn't be backported. |
--- Co-authored-by: Tian Gao <gaogaotiantian@hotmail.com>
…-107748) --- Co-authored-by: Tian Gao <gaogaotiantian@hotmail.com>
Triage: can this be closed or is there more to do? |
Yes, thanks for noticing. |
…n load. Previously this would cause a crash with an opaque EINVAL OSError that doesn't come from a syscall. Related to python/cpython#102130.
Previously this would cause a crash with an opaque EINVAL OSError that doesn't come from a syscall. Related to python/cpython#102130.
Previously this would cause a crash with an opaque EINVAL OSError that doesn't come from a syscall. Related to python/cpython#102130.
Previously this would cause a crash with an opaque EINVAL OSError that doesn't come from a syscall. Related to python/cpython#102130.
Previously this would cause a crash with an opaque EINVAL OSError that doesn't come from a syscall. Related to python/cpython#102130.
…-107748) --- Co-authored-by: Tian Gao <gaogaotiantian@hotmail.com>
Bug report
As title, the Homebrew community has switched to libedit readline as of Python 3.11. There exists a gnureadline package which allows one to continue using the gnu readline, but unfortunately cmd.py will continue to use the libedit one, and that doesn't always work properly.
Your environment
Python 3.11 MacOs Ventura.
Here's some code that won't work with libedit readline:
Tab-completion appears to fail on Homebrew python 3.11, I suspect due to the libedit readline. The code works fine with Homebrew python versions up to 3.10 which use gnu readline. Also, if you install gnureadline and change all occurrences of
import readline
in cmd.py toimport gnureadline as readline
the cmd module works perfectly.So in summary could we fix cmd.py to work correctly with libedit as well as gnu readline? Or, failing that provide some fairly easy means of overriding the readline used by cmd.py without resorting to nasty monkey patching.
Linked PRs
The text was updated successfully, but these errors were encountered: