]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-48752: Add readline.get_pre_input_hook() function (#141586)
authorSanyam Khurana <8039608+CuriousLearner@users.noreply.github.com>
Fri, 5 Dec 2025 12:18:54 +0000 (07:18 -0500)
committerGitHub <noreply@github.com>
Fri, 5 Dec 2025 12:18:54 +0000 (13:18 +0100)
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.

Doc/library/readline.rst
Lib/test/test_readline.py
Misc/NEWS.d/next/Library/2025-11-15-11-10-16.gh-issue-48752.aB3xYz.rst [new file with mode: 0644]
Modules/clinic/readline.c.h
Modules/readline.c

index 75db832c546b64f1d7a5a8bc4cdc891495cf3d4f..780cc77340366a9fc918488a024b6435e9362432 100644 (file)
@@ -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
index 45192fe508270ddb13dadb2a19838c90f506e878..3982686dd10aecf683cd3a8c8436d39af1e67320 100644 (file)
@@ -413,6 +413,24 @@ readline.write_history_file(history_file)
         # 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 (file)
index 0000000..37b9119
--- /dev/null
@@ -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.
index 696475f7d00f5be929f174c30f8264e88f481c6d..dc9381e4b976acd3c0e10ba66a1b08b4ac73e7e9 100644 (file)
@@ -349,6 +349,28 @@ exit:
 
 #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]*/
index e89755b0cb4b2af8da233bf457bf64b33fc8de3e..cc84eb6229e66d5f889deb3e81fa40c9564ab0c1 100644 (file)
@@ -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