]> granicus.if.org Git - python/commitdiff
Issue #26870: Add readline.set_auto_history(), originally by Tyler Crompton
authorMartin Panter <vadmium+py@gmail.com>
Sun, 15 May 2016 01:26:25 +0000 (01:26 +0000)
committerMartin Panter <vadmium+py@gmail.com>
Sun, 15 May 2016 01:26:25 +0000 (01:26 +0000)
Doc/library/readline.rst
Doc/whatsnew/3.6.rst
Lib/test/test_readline.py
Misc/ACKS
Misc/NEWS
Modules/readline.c

index 42e0ad56a5e273769740a0b1a3166f01a20a2cb7..f77792030f9d8aa5fd5eb77d36abf7ae61161dae 100644 (file)
@@ -156,6 +156,20 @@ The following functions operate on a global history list:
    This calls :c:func:`add_history` in the underlying library.
 
 
+.. function:: set_auto_history(enabled)
+
+   Enable or disable automatic calls to :c:func:`add_history` when reading
+   input via readline.  The *enabled* argument should be a Boolean value
+   that when true, enables auto history, and that when False, disables
+   auto history.
+
+   .. versionadded:: 3.6
+
+   .. impl-detail::
+      Auto history is enabled by default, and changes to this do not persist
+      across multiple sessions.
+
+
 Startup hooks
 -------------
 
index 384e35a4caf8dfb045554be92caf780c79ca3f76..bad0f9e5cfe7ebd9d5681f64663f0aa04c32d4c2 100644 (file)
@@ -239,6 +239,14 @@ Protocol version 4 already supports this case.  (Contributed by Serhiy
 Storchaka in :issue:`24164`.)
 
 
+readline
+--------
+
+Added :func:`~readline.set_auto_history` to enable or disable
+automatic addition of input to the history list.  (Contributed by
+Tyler Crompton in :issue:`26870`.)
+
+
 rlcompleter
 -----------
 
index 35330ab0761029209afa2c87c67df6a077f5684b..84fd119e6a165488d871e7b0ade13da41394419a 100644 (file)
@@ -1,7 +1,11 @@
 """
 Very minimal unittests for parts of the readline module.
 """
+from errno import EIO
 import os
+import selectors
+import subprocess
+import sys
 import tempfile
 import unittest
 from test.support import import_module, unlink
@@ -96,6 +100,51 @@ class TestReadline(unittest.TestCase):
                                               TERM='xterm-256color')
         self.assertEqual(stdout, b'')
 
+    auto_history_script = """\
+import readline
+readline.set_auto_history({})
+input()
+print("History length:", readline.get_current_history_length())
+"""
+
+    def test_auto_history_enabled(self):
+        output = run_pty(self.auto_history_script.format(True))
+        self.assertIn(b"History length: 1\r\n", output)
+
+    def test_auto_history_disabled(self):
+        output = run_pty(self.auto_history_script.format(False))
+        self.assertIn(b"History length: 0\r\n", output)
+
+
+def run_pty(script, input=b"dummy input\r"):
+    pty = import_module('pty')
+    output = bytearray()
+    [master, slave] = pty.openpty()
+    args = (sys.executable, '-c', script)
+    proc = subprocess.Popen(args, stdin=slave, stdout=slave, stderr=slave)
+    os.close(slave)
+    with proc, selectors.DefaultSelector() as sel:
+        sel.register(master, selectors.EVENT_READ | selectors.EVENT_WRITE)
+        os.set_blocking(master, False)
+        while True:
+            for [_, events] in sel.select():
+                if events & selectors.EVENT_READ:
+                    try:
+                        chunk = os.read(master, 0x10000)
+                    except OSError as err:
+                        # Linux raises EIO when the slave is closed
+                        if err.errno != EIO:
+                            raise
+                        chunk = b""
+                    if not chunk:
+                        os.close(master)
+                        return output
+                    output.extend(chunk)
+                if events & selectors.EVENT_WRITE:
+                    input = input[os.write(master, input):]
+                    if not input:
+                        sel.modify(master, selectors.EVENT_READ)
+
 
 if __name__ == "__main__":
     unittest.main()
index ebc3fc614652d587c9ab0930944cc756d727ef62..65d70402a1f400536bcc9e6ebe5a2cb15be764e0 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -307,6 +307,7 @@ Ryan Coyner
 Christopher A. Craig
 Jeremy Craven
 Laura Creighton
+Tyler Crompton
 Simon Cross
 Felipe Cruz
 Drew Csillag
index bede515d9bab56d56280ae19e56e32ac313d2e54..80996bdcc1d513ceda811ae24e8aad164a61c4f0 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -277,6 +277,10 @@ Core and Builtins
 Library
 -------
 
+- Issue #26870: Added readline.set_auto_history(), which can stop entries
+  being automatically added to the history list.  Based on patch by Tyler
+  Crompton.
+
 - Issue #26039: zipfile.ZipFile.open() can now be used to write data into a ZIP
   file, as well as for extracting data.  Patch by Thomas Kluyver.
 
index a323b696228a801164759f1399efbc851f8e77a5..de1cc17d18c9cb86b34dddbbaffed226b6fcfb42 100644 (file)
@@ -575,6 +575,24 @@ PyDoc_STRVAR(doc_add_history,
 "add_history(string) -> None\n\
 add an item to the history buffer");
 
+static int should_auto_add_history = 1;
+
+/* Enable or disable automatic history */
+
+static PyObject *
+py_set_auto_history(PyObject *self, PyObject *args)
+{
+    if (!PyArg_ParseTuple(args, "p:set_auto_history",
+                          &should_auto_add_history)) {
+        return NULL;
+    }
+    Py_RETURN_NONE;
+}
+
+PyDoc_STRVAR(doc_set_auto_history,
+"set_auto_history(enabled) -> None\n\
+Enables or disables automatic history.");
+
 
 /* Get the tab-completion word-delimiters that readline uses */
 
@@ -791,6 +809,7 @@ static struct PyMethodDef readline_methods[] =
 
     {"set_completer_delims", set_completer_delims,
      METH_VARARGS, doc_set_completer_delims},
+    {"set_auto_history", py_set_auto_history, METH_VARARGS, doc_set_auto_history},
     {"add_history", py_add_history, METH_VARARGS, doc_add_history},
     {"remove_history_item", py_remove_history, METH_VARARGS, doc_remove_history},
     {"replace_history_item", py_replace_history, METH_VARARGS, doc_replace_history},
@@ -1266,7 +1285,7 @@ call_readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
 
     /* we have a valid line */
     n = strlen(p);
-    if (n > 0) {
+    if (should_auto_add_history && n > 0) {
         const char *line;
         int length = _py_get_history_length();
         if (length > 0)