parent
aacfcccdc3
commit
33f8f15bdd
|
@ -59,6 +59,14 @@ The :mod:`readline` module defines the following functions:
|
|||
Save a readline history file. The default filename is :file:`~/.history`.
|
||||
|
||||
|
||||
.. function:: append_history_file(nelements[, filename])
|
||||
|
||||
Append the last *nelements* of history to a file. The default filename is
|
||||
:file:`~/.history`. The file must already exist.
|
||||
|
||||
.. versionadded:: 3.5
|
||||
|
||||
|
||||
.. function:: clear_history()
|
||||
|
||||
Clear the current history. (Note: this function is not available if the
|
||||
|
@ -209,6 +217,26 @@ from the user's :envvar:`PYTHONSTARTUP` file. ::
|
|||
This code is actually automatically run when Python is run in
|
||||
:ref:`interactive mode <tut-interactive>` (see :ref:`rlcompleter-config`).
|
||||
|
||||
The following example achieves the same goal but supports concurrent interactive
|
||||
sessions, by only appending the new history. ::
|
||||
|
||||
import atexit
|
||||
import os
|
||||
import realine
|
||||
histfile = os.path.join(os.path.expanduser("~"), ".python_history")
|
||||
|
||||
try:
|
||||
readline.read_history_file(histfile)
|
||||
h_len = readline.get_history_length()
|
||||
except FileNotFoundError:
|
||||
open(histfile, 'wb').close()
|
||||
h_len = 0
|
||||
|
||||
def save(prev_h_len, histfile):
|
||||
new_h_len = readline.get_history_length()
|
||||
readline.append_history_file(new_h_len - prev_h_len, histfile)
|
||||
atexit.register(save, h_len, histfile)
|
||||
|
||||
The following example extends the :class:`code.InteractiveConsole` class to
|
||||
support history save/restore. ::
|
||||
|
||||
|
@ -234,4 +262,3 @@ support history save/restore. ::
|
|||
|
||||
def save_history(self, histfile):
|
||||
readline.write_history_file(histfile)
|
||||
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
Very minimal unittests for parts of the readline module.
|
||||
"""
|
||||
import os
|
||||
import tempfile
|
||||
import unittest
|
||||
from test.support import run_unittest, import_module
|
||||
from test.support import run_unittest, import_module, unlink
|
||||
from test.script_helper import assert_python_ok
|
||||
|
||||
# Skip tests if there is no readline module
|
||||
|
@ -42,6 +43,43 @@ class TestHistoryManipulation (unittest.TestCase):
|
|||
|
||||
self.assertEqual(readline.get_current_history_length(), 1)
|
||||
|
||||
def test_write_read_append(self):
|
||||
hfile = tempfile.NamedTemporaryFile(delete=False)
|
||||
hfile.close()
|
||||
hfilename = hfile.name
|
||||
self.addCleanup(unlink, hfilename)
|
||||
|
||||
# test write-clear-read == nop
|
||||
readline.clear_history()
|
||||
readline.add_history("first line")
|
||||
readline.add_history("second line")
|
||||
readline.write_history_file(hfilename)
|
||||
|
||||
readline.clear_history()
|
||||
self.assertEqual(readline.get_current_history_length(), 0)
|
||||
|
||||
readline.read_history_file(hfilename)
|
||||
self.assertEqual(readline.get_current_history_length(), 2)
|
||||
self.assertEqual(readline.get_history_item(1), "first line")
|
||||
self.assertEqual(readline.get_history_item(2), "second line")
|
||||
|
||||
# test append
|
||||
readline.append_history_file(1, hfilename)
|
||||
readline.clear_history()
|
||||
readline.read_history_file(hfilename)
|
||||
self.assertEqual(readline.get_current_history_length(), 3)
|
||||
self.assertEqual(readline.get_history_item(1), "first line")
|
||||
self.assertEqual(readline.get_history_item(2), "second line")
|
||||
self.assertEqual(readline.get_history_item(3), "second line")
|
||||
|
||||
# test 'no such file' behaviour
|
||||
os.unlink(hfilename)
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
readline.append_history_file(1, hfilename)
|
||||
|
||||
# write_history_file can create the target
|
||||
readline.write_history_file(hfilename)
|
||||
|
||||
|
||||
class TestReadline(unittest.TestCase):
|
||||
|
||||
|
|
|
@ -191,6 +191,8 @@ Core and Builtins
|
|||
Library
|
||||
-------
|
||||
|
||||
- Issue #22940: Add readline.append_history_file.
|
||||
|
||||
- Issue #19676: Added the "namereplace" error handler.
|
||||
|
||||
- Issue #22788: Add *context* parameter to logging.handlers.HTTPHandler.
|
||||
|
|
|
@ -237,6 +237,41 @@ Save a readline history file.\n\
|
|||
The default filename is ~/.history.");
|
||||
|
||||
|
||||
/* Exported function to save part of a readline history file */
|
||||
|
||||
static PyObject *
|
||||
append_history_file(PyObject *self, PyObject *args)
|
||||
{
|
||||
int nelements;
|
||||
PyObject *filename_obj = Py_None, *filename_bytes;
|
||||
char *filename;
|
||||
int err;
|
||||
if (!PyArg_ParseTuple(args, "i|O:append_history_file", &nelements, &filename_obj))
|
||||
return NULL;
|
||||
if (filename_obj != Py_None) {
|
||||
if (!PyUnicode_FSConverter(filename_obj, &filename_bytes))
|
||||
return NULL;
|
||||
filename = PyBytes_AsString(filename_bytes);
|
||||
} else {
|
||||
filename_bytes = NULL;
|
||||
filename = NULL;
|
||||
}
|
||||
errno = err = append_history(nelements, filename);
|
||||
if (!err && _history_length >= 0)
|
||||
history_truncate_file(filename, _history_length);
|
||||
Py_XDECREF(filename_bytes);
|
||||
errno = err;
|
||||
if (errno)
|
||||
return PyErr_SetFromErrno(PyExc_IOError);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(doc_append_history_file,
|
||||
"append_history_file(nelements[, filename]) -> None\n\
|
||||
Append the last nelements of the history list to file.\n\
|
||||
The default filename is ~/.history.");
|
||||
|
||||
|
||||
/* Set history length */
|
||||
|
||||
static PyObject*
|
||||
|
@ -747,6 +782,8 @@ static struct PyMethodDef readline_methods[] =
|
|||
METH_VARARGS, doc_read_history_file},
|
||||
{"write_history_file", write_history_file,
|
||||
METH_VARARGS, doc_write_history_file},
|
||||
{"append_history_file", append_history_file,
|
||||
METH_VARARGS, doc_append_history_file},
|
||||
{"get_history_item", get_history_item,
|
||||
METH_VARARGS, doc_get_history_item},
|
||||
{"get_current_history_length", (PyCFunction)get_current_history_length,
|
||||
|
|
Loading…
Reference in New Issue