https://github.com/python/cpython/commit/4238a975d78a0cc8f1751cfc63b3030b94b46aa8
commit: 4238a975d78a0cc8f1751cfc63b3030b94b46aa8
branch: main
author: Sanyam Khurana <[email protected]>
committer: vstinner <[email protected]>
date: 2025-12-05T13:18:54+01:00
summary:
gh-48752: Add readline.get_pre_input_hook() function (#141586)
Add readline.get_pre_input_hook() to retrieve the current pre-input
hook. This allows applications to save and restore the hook without
overwriting user settings.
files:
A Misc/NEWS.d/next/Library/2025-11-15-11-10-16.gh-issue-48752.aB3xYz.rst
M Doc/library/readline.rst
M Lib/test/test_readline.py
M Modules/clinic/readline.c.h
M Modules/readline.c
diff --git a/Doc/library/readline.rst b/Doc/library/readline.rst
index 75db832c546b64..780cc77340366a 100644
--- a/Doc/library/readline.rst
+++ b/Doc/library/readline.rst
@@ -246,6 +246,15 @@ Startup hooks
if Python was compiled for a version of the library that supports it.
+.. function:: get_pre_input_hook()
+
+ Get the current pre-input hook function, or ``None`` if no pre-input hook
+ function has been set. This function only exists if Python was compiled
+ for a version of the library that supports it.
+
+ .. versionadded:: next
+
+
.. _readline-completion:
Completion
diff --git a/Lib/test/test_readline.py b/Lib/test/test_readline.py
index 45192fe508270d..3982686dd10aec 100644
--- a/Lib/test/test_readline.py
+++ b/Lib/test/test_readline.py
@@ -413,6 +413,24 @@ def test_write_read_limited_history(self):
# So, we've only tested that the read did not fail.
# See TestHistoryManipulation for the full test.
+ @unittest.skipUnless(hasattr(readline, "get_pre_input_hook"),
+ "get_pre_input_hook not available")
+ def test_get_pre_input_hook(self):
+ # Save and restore the original hook to avoid side effects
+ original_hook = readline.get_pre_input_hook()
+ self.addCleanup(readline.set_pre_input_hook, original_hook)
+
+ # Test that get_pre_input_hook returns None when no hook is set
+ readline.set_pre_input_hook(None)
+ self.assertIsNone(readline.get_pre_input_hook())
+
+ # Set a hook and verify we can retrieve it
+ def my_hook():
+ pass
+
+ readline.set_pre_input_hook(my_hook)
+ self.assertIs(readline.get_pre_input_hook(), my_hook)
+
@unittest.skipUnless(support.Py_GIL_DISABLED, 'these tests can only possibly
fail with GIL disabled')
class FreeThreadingTest(unittest.TestCase):
diff --git
a/Misc/NEWS.d/next/Library/2025-11-15-11-10-16.gh-issue-48752.aB3xYz.rst
b/Misc/NEWS.d/next/Library/2025-11-15-11-10-16.gh-issue-48752.aB3xYz.rst
new file mode 100644
index 00000000000000..37b91196658589
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-11-15-11-10-16.gh-issue-48752.aB3xYz.rst
@@ -0,0 +1,3 @@
+Add :func:`readline.get_pre_input_hook` function to retrieve the current
+pre-input hook. This allows applications to save and restore the hook
+without overwriting user settings. Patch by Sanyam Khurana.
diff --git a/Modules/clinic/readline.c.h b/Modules/clinic/readline.c.h
index 696475f7d00f5b..dc9381e4b976ac 100644
--- a/Modules/clinic/readline.c.h
+++ b/Modules/clinic/readline.c.h
@@ -349,6 +349,28 @@ readline_set_pre_input_hook(PyObject *module, PyObject
*const *args, Py_ssize_t
#endif /* defined(HAVE_RL_PRE_INPUT_HOOK) */
+#if defined(HAVE_RL_PRE_INPUT_HOOK)
+
+PyDoc_STRVAR(readline_get_pre_input_hook__doc__,
+"get_pre_input_hook($module, /)\n"
+"--\n"
+"\n"
+"Get the current pre-input hook function.");
+
+#define READLINE_GET_PRE_INPUT_HOOK_METHODDEF \
+ {"get_pre_input_hook", (PyCFunction)readline_get_pre_input_hook,
METH_NOARGS, readline_get_pre_input_hook__doc__},
+
+static PyObject *
+readline_get_pre_input_hook_impl(PyObject *module);
+
+static PyObject *
+readline_get_pre_input_hook(PyObject *module, PyObject *Py_UNUSED(ignored))
+{
+ return readline_get_pre_input_hook_impl(module);
+}
+
+#endif /* defined(HAVE_RL_PRE_INPUT_HOOK) */
+
PyDoc_STRVAR(readline_get_completion_type__doc__,
"get_completion_type($module, /)\n"
"--\n"
@@ -794,7 +816,11 @@ readline_redisplay(PyObject *module, PyObject
*Py_UNUSED(ignored))
#define READLINE_SET_PRE_INPUT_HOOK_METHODDEF
#endif /* !defined(READLINE_SET_PRE_INPUT_HOOK_METHODDEF) */
+#ifndef READLINE_GET_PRE_INPUT_HOOK_METHODDEF
+ #define READLINE_GET_PRE_INPUT_HOOK_METHODDEF
+#endif /* !defined(READLINE_GET_PRE_INPUT_HOOK_METHODDEF) */
+
#ifndef READLINE_CLEAR_HISTORY_METHODDEF
#define READLINE_CLEAR_HISTORY_METHODDEF
#endif /* !defined(READLINE_CLEAR_HISTORY_METHODDEF) */
-/*[clinic end generated code: output=88d9812b6caa2102 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=4bd95070973cd0e2 input=a9049054013a1b77]*/
diff --git a/Modules/readline.c b/Modules/readline.c
index e89755b0cb4b2a..cc84eb6229e66d 100644
--- a/Modules/readline.c
+++ b/Modules/readline.c
@@ -572,6 +572,26 @@ readline_set_pre_input_hook_impl(PyObject *module,
PyObject *function)
return set_hook("pre_input_hook", &state->pre_input_hook,
function);
}
+
+/* Get pre-input hook */
+
+/*[clinic input]
+readline.get_pre_input_hook
+
+Get the current pre-input hook function.
+[clinic start generated code]*/
+
+static PyObject *
+readline_get_pre_input_hook_impl(PyObject *module)
+/*[clinic end generated code: output=ad56b77a8e8981ca input=fb1e1b1fbd94e4e5]*/
+{
+ readlinestate *state = get_readline_state(module);
+ if (state->pre_input_hook == NULL) {
+ Py_RETURN_NONE;
+ }
+ return Py_NewRef(state->pre_input_hook);
+}
+
#endif
@@ -1074,6 +1094,7 @@ static struct PyMethodDef readline_methods[] =
READLINE_SET_STARTUP_HOOK_METHODDEF
#ifdef HAVE_RL_PRE_INPUT_HOOK
READLINE_SET_PRE_INPUT_HOOK_METHODDEF
+ READLINE_GET_PRE_INPUT_HOOK_METHODDEF
#endif
#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER
READLINE_CLEAR_HISTORY_METHODDEF
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]