[Python-checkins] r74970 - in python/trunk: Doc/library/readline.rst Lib/test/test_readline.py Misc/NEWS Modules/readline.c setup.py
ronald.oussoren
python-checkins at python.org
Sun Sep 20 16:18:16 CEST 2009
Author: ronald.oussoren
Date: Sun Sep 20 16:18:15 2009
New Revision: 74970
Log:
Issue 6877: this patch makes it possible to link the readline extension
to the libedit emulation of the readline API on OSX 10.5 or later.
This also adds a minimal testsuite for readline to check that the
history manipuation functions have the same interface with both
C libraries.
Added:
python/trunk/Lib/test/test_readline.py (contents, props changed)
Modified:
python/trunk/Doc/library/readline.rst
python/trunk/Misc/NEWS
python/trunk/Modules/readline.c
python/trunk/setup.py
Modified: python/trunk/Doc/library/readline.rst
==============================================================================
--- python/trunk/Doc/library/readline.rst (original)
+++ python/trunk/Doc/library/readline.rst Sun Sep 20 16:18:15 2009
@@ -14,6 +14,17 @@
interactive prompt and the prompts offered by the :func:`raw_input` and
:func:`input` built-in functions.
+..note::
+
+ On MacOS X the :mod:`readline` module can be implemented using
+ the ``libedit`` library instead of GNU readline.
+
+ The configuration file for ``libedit`` is different from that
+ of GNU readline. If you programmaticly load configuration strings
+ you can check for the text "libedit" in :const:`readline.__doc__`
+ to differentiate between GNU readline and libedit.
+
+
The :mod:`readline` module defines the following functions:
@@ -181,7 +192,6 @@
Append a line to the history buffer, as if it was the last line typed.
-
.. seealso::
Module :mod:`rlcompleter`
Added: python/trunk/Lib/test/test_readline.py
==============================================================================
--- (empty file)
+++ python/trunk/Lib/test/test_readline.py Sun Sep 20 16:18:15 2009
@@ -0,0 +1,42 @@
+"""
+Very minimal unittests for parts of the readline module.
+
+These tests were added to check that the libedit emulation on OSX and
+the "real" readline have the same interface for history manipulation. That's
+why the tests cover only a small subset of the interface.
+"""
+import unittest
+from test.test_support import run_unittest
+
+import readline
+
+class TestHistoryManipulation (unittest.TestCase):
+ def testHistoryUpdates(self):
+ readline.clear_history()
+
+ readline.add_history("first line")
+ readline.add_history("second line")
+
+ self.assertEqual(readline.get_history_item(0), None)
+ self.assertEqual(readline.get_history_item(1), "first line")
+ self.assertEqual(readline.get_history_item(2), "second line")
+
+ readline.replace_history_item(0, "replaced line")
+ self.assertEqual(readline.get_history_item(0), None)
+ self.assertEqual(readline.get_history_item(1), "replaced line")
+ self.assertEqual(readline.get_history_item(2), "second line")
+
+ self.assertEqual(readline.get_current_history_length(), 2)
+
+ readline.remove_history_item(0)
+ self.assertEqual(readline.get_history_item(0), None)
+ self.assertEqual(readline.get_history_item(1), "second line")
+
+ self.assertEqual(readline.get_current_history_length(), 1)
+
+
+def test_main():
+ run_unittest(TestHistoryManipulation)
+
+if __name__ == "__main__":
+ test_main()
Modified: python/trunk/Misc/NEWS
==============================================================================
--- python/trunk/Misc/NEWS (original)
+++ python/trunk/Misc/NEWS Sun Sep 20 16:18:15 2009
@@ -1335,6 +1335,9 @@
Extension Modules
-----------------
+- Issue #6877: Make it possible to link the readline extension to libedit
+ on OSX.
+
- Issue #6944: Fix a SystemError when socket.getnameinfo() was called
with something other than a tuple as first argument.
Modified: python/trunk/Modules/readline.c
==============================================================================
--- python/trunk/Modules/readline.c (original)
+++ python/trunk/Modules/readline.c Sun Sep 20 16:18:15 2009
@@ -42,6 +42,25 @@
#endif
#endif
+#ifdef __APPLE__
+/*
+ * It is possible to link the readline module to the readline
+ * emulation library of editline/libedit.
+ *
+ * On OSX this emulation library is not 100% API compatible
+ * with the "real" readline and cannot be detected at compile-time,
+ * hence we use a runtime check to detect if we're using libedit
+ *
+ * Currently there is one know API incompatibility:
+ * - 'get_history' has a 1-based index with GNU readline, and a 0-based
+ * index with libedit's emulation.
+ * - Note that replace_history and remove_history use a 0-based index
+ * with both implementation.
+ */
+static int using_libedit_emulation = 0;
+static const char libedit_version_tag[] = "EditLine wrapper";
+#endif /* __APPLE__ */
+
static void
on_completion_display_matches_hook(char **matches,
int num_matches, int max_length);
@@ -478,6 +497,29 @@
if (!PyArg_ParseTuple(args, "i:index", &idx))
return NULL;
+#ifdef __APPLE__
+ if (using_libedit_emulation) {
+ /* Libedit emulation uses 0-based indexes,
+ * the real one uses 1-based indexes,
+ * adjust the index to ensure that Python
+ * code doesn't have to worry about the
+ * difference.
+ */
+ HISTORY_STATE *hist_st;
+ hist_st = history_get_history_state();
+
+ idx --;
+
+ /*
+ * Apple's readline emulation crashes when
+ * the index is out of range, therefore
+ * test for that and fail gracefully.
+ */
+ if (idx < 0 || idx >= hist_st->length) {
+ Py_RETURN_NONE;
+ }
+ }
+#endif /* __APPLE__ */
if ((hist_ent = history_get(idx)))
return PyString_FromString(hist_ent->line);
else {
@@ -978,6 +1020,15 @@
char *line;
HISTORY_STATE *state = history_get_history_state();
if (state->length > 0)
+#ifdef __APPLE__
+ if (using_libedit_emulation) {
+ /*
+ * Libedit's emulation uses 0-based indexes,
+ * the real readline uses 1-based indexes.
+ */
+ line = history_get(state->length - 1)->line;
+ } else
+#endif /* __APPLE__ */
line = history_get(state->length)->line;
else
line = "";
@@ -1011,16 +1062,35 @@
PyDoc_STRVAR(doc_module,
"Importing this module enables command line editing using GNU readline.");
+#ifdef __APPLE__
+PyDoc_STRVAR(doc_module_le,
+"Importing this module enables command line editing using libedit readline.");
+#endif /* __APPLE__ */
+
PyMODINIT_FUNC
initreadline(void)
{
PyObject *m;
+#ifdef __APPLE__
+ if (strncmp(rl_library_version, libedit_version_tag, strlen(libedit_version_tag)) == 0) {
+ using_libedit_emulation = 1;
+ }
+
+ if (using_libedit_emulation)
+ m = Py_InitModule4("readline", readline_methods, doc_module_le,
+ (PyObject *)NULL, PYTHON_API_VERSION);
+ else
+
+#endif /* __APPLE__ */
+
m = Py_InitModule4("readline", readline_methods, doc_module,
(PyObject *)NULL, PYTHON_API_VERSION);
if (m == NULL)
return;
+
+
PyOS_ReadlineFunctionPointer = call_readline;
setup_readline();
}
Modified: python/trunk/setup.py
==============================================================================
--- python/trunk/setup.py (original)
+++ python/trunk/setup.py Sun Sep 20 16:18:15 2009
@@ -546,16 +546,16 @@
# readline
do_readline = self.compiler_obj.find_library_file(lib_dirs, 'readline')
- if platform == 'darwin': # and os.uname()[2] < '9.':
- # MacOSX 10.4 has a broken readline. Don't try to build
- # the readline module unless the user has installed a fixed
- # readline package
- # FIXME: The readline emulation on 10.5 is better, but the
- # readline module doesn't compile out of the box.
- if find_file('readline/rlconf.h', inc_dirs, []) is None:
- do_readline = False
+ if platform == 'darwin':
+ os_release = int(os.uname()[2].split('.')[0])
+ if os_release < 9:
+ # MacOSX 10.4 has a broken readline. Don't try to build
+ # the readline module unless the user has installed a fixed
+ # readline package
+ if find_file('readline/rlconf.h', inc_dirs, []) is None:
+ do_readline = False
if do_readline:
- if sys.platform == 'darwin':
+ if platform == 'darwin' and os_release < 9:
# In every directory on the search path search for a dynamic
# library and then a static library, instead of first looking
# for dynamic libraries on the entiry path.
More information about the Python-checkins
mailing list