diff -r f6e399ae670f Doc/library/readline.rst --- a/Doc/library/readline.rst Fri Jul 24 09:07:12 2015 +0300 +++ b/Doc/library/readline.rst Sun Aug 02 17:15:55 2015 +0100 @@ -114,6 +114,12 @@ line buffer. +.. function:: forced_update_display() + + Forcibly redisplay the line buffer and prompt, even if Readline thinks + they're displayed correctly. + + .. function:: set_startup_hook([function]) Set or remove the startup_hook function. If *function* is specified, it will be @@ -185,6 +191,20 @@ Append a line to the history buffer, as if it was the last line typed. + +.. function:: set_lock(lock) + + Tell the interpreter to acquire the given lock before attempting to + read a line of text, and release it on completion of the reading. If + the lock is None, then no lock is held during reading. + + +.. function:: get_lock() + + Returns the lock that the interpreter holds while it is reading a line, + or None if no lock is currently set. + + .. seealso:: Module :mod:`rlcompleter` diff -r f6e399ae670f Misc/ACKS --- a/Misc/ACKS Fri Jul 24 09:07:12 2015 +0300 +++ b/Misc/ACKS Sun Aug 02 17:15:55 2015 +0100 @@ -1355,6 +1355,7 @@ Michael Stone Serhiy Storchaka Ken Stox +Barney Stratford Dan Stromberg Donald Stufft Daniel Stutzbach diff -r f6e399ae670f Modules/readline.c --- a/Modules/readline.c Fri Jul 24 09:07:12 2015 +0300 +++ b/Modules/readline.c Sun Aug 02 17:15:55 2015 +0100 @@ -84,6 +84,7 @@ PyObject *completer; PyObject *begidx; PyObject *endidx; + PyObject *lock; } readlinestate; @@ -99,6 +100,7 @@ Py_CLEAR(state->completer); Py_CLEAR(state->begidx); Py_CLEAR(state->endidx); + Py_CLEAR(state->lock); return 0; } @@ -112,6 +114,7 @@ Py_VISIT(state->completer); Py_VISIT(state->begidx); Py_VISIT(state->endidx); + Py_VISIT(state->lock); return 0; } @@ -771,6 +774,117 @@ contents of the line buffer."); +/* Forcibly redisplay the line buffer */ + +static PyObject * +forced_update_display(PyObject *self, PyObject *noarg) +{ + rl_forced_update_display(); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(doc_forced_update_display, +"forced_update_display() -> None\n\ +Forcibly redraw the current line."); + + +static PyObject * +set_lock (PyObject *self, PyObject *args) +{ + PyObject *lock; + if (!PyArg_ParseTuple(args, "O", &lock)) + return NULL; + Py_XDECREF(readlinestate_global->lock); + readlinestate_global->lock = lock; + Py_INCREF(lock); + Py_RETURN_NONE; +} + +PyDoc_STRVAR(doc_set_lock, +"set_lock(lock) -> None\n\ +Instruct the interpreter to hold the lock when reading a line\n\ +If the lock is None, then do not hold a lock during reading."); + +static PyObject * +get_lock (PyObject *self, PyObject *noarg) +{ + if (readlinestate_global->lock == NULL) { + Py_RETURN_NONE; + } + Py_INCREF(readlinestate_global->lock); + return readlinestate_global->lock; +} + +PyDoc_STRVAR(doc_get_lock, +"get_lock() -> object\n\ +Returns the lock that the interpreter holds whenever it is reading a line."); + + +static void +acquire_lock (void) +{ +#ifdef WITH_THREAD + PyGILState_STATE gilstate = PyGILState_Ensure(); +#endif + PyObject *lock = NULL; + PyObject *acquire = NULL; + PyObject *args = NULL; + PyObject *result = NULL; + + lock = readlinestate_global->lock; + if (lock && lock != Py_None) + acquire = PyObject_GetAttrString(lock, "acquire"); + if (acquire) args = PyTuple_Pack (0); + if (args) result = PyObject_CallObject (acquire, args); + Py_XDECREF(acquire); + Py_XDECREF(args); + Py_XDECREF(result); + + if (!result) { + /* There's no sensible way to raise an exception here, for that + would cause the interpreter to become inoperable. */ + PyObject *err = PyErr_Occurred(); + if (err) PyErr_WriteUnraisable(err); + PyErr_Clear(); + } +#ifdef WITH_THREAD + PyGILState_Release(gilstate); +#endif +} + +static void +release_lock (void) +{ +#ifdef WITH_THREAD + PyGILState_STATE gilstate = PyGILState_Ensure(); +#endif + PyObject *lock = readlinestate_global->lock; + PyObject *acquire = NULL; + PyObject *args = NULL; + PyObject *result = NULL; + + lock = readlinestate_global->lock; + if (lock && lock != Py_None) + acquire = PyObject_GetAttrString(lock, "release"); + if (acquire) args = PyTuple_Pack (0); + if (args) result = PyObject_CallObject (acquire, args); + Py_XDECREF(acquire); + Py_XDECREF(args); + Py_XDECREF(result); + + if (!result) { + /* There's no sensible way to raise an exception here, for that + would cause the interpreter to become inoperable. */ + PyObject *err = PyErr_Occurred(); + if (err) PyErr_WriteUnraisable(err); + PyErr_Clear(); + } +#ifdef WITH_THREAD + PyGILState_Release(gilstate); +#endif +} + + /* Table of functions exported by the module */ static struct PyMethodDef readline_methods[] = @@ -779,6 +893,9 @@ {"get_line_buffer", get_line_buffer, METH_NOARGS, doc_get_line_buffer}, {"insert_text", insert_text, METH_VARARGS, doc_insert_text}, {"redisplay", redisplay, METH_NOARGS, doc_redisplay}, + {"forced_update_display", forced_update_display, METH_NOARGS, doc_forced_update_display}, + {"set_lock", set_lock, METH_VARARGS, doc_set_lock}, + {"get_lock", get_lock, METH_NOARGS, doc_get_lock}, {"read_init_file", read_init_file, METH_VARARGS, doc_read_init_file}, {"read_history_file", read_history_file, METH_VARARGS, doc_read_history_file}, @@ -1114,6 +1231,7 @@ rl_catch_signals = 0; #endif + acquire_lock(); rl_callback_handler_install (prompt, rlhandler); FD_ZERO(&selectset); @@ -1159,6 +1277,7 @@ } } } + release_lock(); return completed_input_string; } @@ -1186,6 +1305,7 @@ *signal = 0; + acquire_lock(); old_inthandler = PyOS_setsig(SIGINT, onintr); if (setjmp(jbuf)) { #ifdef HAVE_SIGRELSE @@ -1199,6 +1319,7 @@ rl_event_hook = PyOS_InputHook; p = readline(prompt); PyOS_setsig(SIGINT, old_inthandler); + release_lock(); return p; }