Skip to content

Commit

Permalink
pythongh-112510: Add readline.backend for the backend readline uses (
Browse files Browse the repository at this point in the history
…pythonGH-112511)


Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Donghee Na <[email protected]>
  • Loading branch information
3 people authored and Glyphack committed Jan 27, 2024
1 parent 19e1561 commit 3ce43cc
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 12 deletions.
15 changes: 10 additions & 5 deletions Doc/library/readline.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,28 @@ Readline library in general.
.. note::

The underlying Readline library API may be implemented by
the ``libedit`` library instead of GNU readline.
the ``editline`` (``libedit``) library instead of GNU readline.
On macOS the :mod:`readline` module detects which library is being used
at run time.

The configuration file for ``libedit`` is different from that
The configuration file for ``editline`` is different from that
of GNU readline. If you programmatically load configuration strings
you can check for the text "libedit" in :const:`readline.__doc__`
to differentiate between GNU readline and libedit.
you can use :data:`backend` to determine which library is being used.

If you use *editline*/``libedit`` readline emulation on macOS, the
If you use ``editline``/``libedit`` readline emulation on macOS, the
initialization file located in your home directory is named
``.editrc``. For example, the following content in ``~/.editrc`` will
turn ON *vi* keybindings and TAB completion::

python:bind -v
python:bind ^I rl_complete

.. data:: backend

The name of the underlying Readline library being used, either
``"readline"`` or ``"editline"``.

.. versionadded:: 3.13

Init file
---------
Expand Down
3 changes: 1 addition & 2 deletions Lib/site.py
Original file line number Diff line number Diff line change
Expand Up @@ -444,8 +444,7 @@ def register_readline():

# Reading the initialization (config) file may not be enough to set a
# completion key, so we set one first and then read the file.
readline_doc = getattr(readline, '__doc__', '')
if readline_doc is not None and 'libedit' in readline_doc:
if readline.backend == 'editline':
readline.parse_and_bind('bind ^I rl_complete')
else:
readline.parse_and_bind('tab: complete')
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_pdb.py
Original file line number Diff line number Diff line change
Expand Up @@ -3293,7 +3293,7 @@ def setUpClass():
# Ensure that the readline module is loaded
# If this fails, the test is skipped because SkipTest will be raised
readline = import_module('readline')
if readline.__doc__ and "libedit" in readline.__doc__:
if readline.backend == "editline":
raise unittest.SkipTest("libedit readline is not supported for pdb")

def test_basic_completion(self):
Expand Down
9 changes: 6 additions & 3 deletions Lib/test/test_readline.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
if hasattr(readline, "_READLINE_LIBRARY_VERSION"):
is_editline = ("EditLine wrapper" in readline._READLINE_LIBRARY_VERSION)
else:
is_editline = (readline.__doc__ and "libedit" in readline.__doc__)
is_editline = readline.backend == "editline"


def setUpModule():
Expand Down Expand Up @@ -145,6 +145,9 @@ def test_init(self):
TERM='xterm-256color')
self.assertEqual(stdout, b'')

def test_backend(self):
self.assertIn(readline.backend, ("readline", "editline"))

auto_history_script = """\
import readline
readline.set_auto_history({})
Expand All @@ -171,7 +174,7 @@ def complete(text, state):
if state == 0 and text == "$":
return "$complete"
return None
if "libedit" in getattr(readline, "__doc__", ""):
if readline.backend == "editline":
readline.parse_and_bind(r'bind "\\t" rl_complete')
else:
readline.parse_and_bind(r'"\\t": complete')
Expand All @@ -198,7 +201,7 @@ def test_nonascii(self):

script = r"""import readline
is_editline = readline.__doc__ and "libedit" in readline.__doc__
is_editline = readline.backend == "editline"
inserted = "[\xEFnserted]"
macro = "|t\xEB[after]"
set_pre_input_hook = getattr(readline, "set_pre_input_hook", None)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add :data:`readline.backend` for the backend readline uses (``editline`` or ``readline``)
9 changes: 8 additions & 1 deletion Modules/readline.c
Original file line number Diff line number Diff line change
Expand Up @@ -1538,15 +1538,18 @@ static struct PyModuleDef readlinemodule = {
PyMODINIT_FUNC
PyInit_readline(void)
{
const char *backend = "readline";
PyObject *m;
readlinestate *mod_state;

if (strncmp(rl_library_version, libedit_version_tag, strlen(libedit_version_tag)) == 0) {
using_libedit_emulation = 1;
}

if (using_libedit_emulation)
if (using_libedit_emulation) {
readlinemodule.m_doc = doc_module_le;
backend = "editline";
}


m = PyModule_Create(&readlinemodule);
Expand All @@ -1568,6 +1571,10 @@ PyInit_readline(void)
goto error;
}

if (PyModule_AddStringConstant(m, "backend", backend) < 0) {
goto error;
}

mod_state = (readlinestate *) PyModule_GetState(m);
if (mod_state == NULL){
goto error;
Expand Down

0 comments on commit 3ce43cc

Please sign in to comment.