[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Steffen Daode Nurpmeso sdao...@googlemail.com added the comment: I've opened it and it's fixed, so i'll close it now. If someone finds the single bug in 11650.termios-1.diff in termios_resume() and also has an idea of how to call termios_suspend() in case Python crashes or gives back the terminal in any other way i would vote for reopening this and using my version, because it is better. Take care otherwise. Thanks, haypo. -- status: open - closed ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Steffen Daode Nurpmeso sdao...@googlemail.com added the comment: On Sat, Apr 09, 2011 at 02:18:01PM +, STINNER Victor wrote: I noticied a strange behaviour: Still fun, but this one could even make it except for termios flags, multibyte and the real problem, signal handling. Hm. -- Added file: http://bugs.python.org/file21605/11650.termios-1.diff ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___diff --git a/Parser/myreadline.c b/Parser/myreadline.c --- a/Parser/myreadline.c +++ b/Parser/myreadline.c @@ -10,6 +10,10 @@ */ #include Python.h +#ifdef Py_PYPORT_H +# define __USE_TERMIOS +# include signal.h +#endif #ifdef MS_WINDOWS #define WIN32_LEAN_AND_MEAN #include windows.h @@ -19,6 +23,18 @@ extern char* vms__StdioReadline(FILE *sys_stdin, FILE *sys_stdout, char *prompt); #endif +typedef struct Args { +char*input; +FILE*fp; +int tios_fd; +int tios_is_init; +#ifdef __USE_TERMIOS +int tios_is_set; +int __align; +struct termios tios_old; +struct termios tios_new; +#endif +} Args; PyThreadState* _PyOS_ReadlineTState; @@ -29,117 +45,230 @@ int (*PyOS_InputHook)(void) = NULL; -/* This function restarts a fgets() after an EINTR error occurred - except if PyOS_InterruptOccurred() returns true. */ +/* This function restarts a fgetc() after an EINTR error occurred + * except if PyOS_InterruptOccurred() returns true */ +static int my_fgets(Args *args); +#ifdef __USE_TERMIOS +static void termios_resume(Args *args); +static void termios_suspend(Args *args); +#endif + +#ifdef __USE_TERMIOS +static void +termios_resume(Args *args) +{ +if (!args-tios_is_init) { +args-tios_is_init = 1; + +while (tcgetattr(args-tios_fd, args-tios_old) != 0) +if (errno != EINTR) { +args-tios_fd = -1; +goto jleave; +} + +memcpy(args-tios_new, args-tios_old, sizeof(args-tios_old)); +args-tios_new.c_lflag = ~(/*ECHOCTL |*/ ICANON); +args-tios_new.c_cc[VMIN] = 1; +} + +if (args-tios_fd 0) +goto jleave; + +while (tcsetattr(args-tios_fd, TCSAFLUSH, args-tios_new) != 0) +; +args-tios_is_set = 1; + +jleave: +return; +} + +static void +termios_suspend(Args *args) +{ +if (args-tios_is_init args-tios_is_set) { +while (tcsetattr(args-tios_fd, TCSANOW, args-tios_old) != 0) +; +args-tios_is_set = 0; +} +return; +} +#endif static int -my_fgets(char *buf, int len, FILE *fp) +my_fgets(Args *args) { -char *p; +int estat; +char *buf, *cursor; +size_t buf_len; + +buf = (char*)PyMem_MALLOC(2*80); +estat = 1; +if (buf == NULL) +goto jreturn; + +cursor = buf; +buf_len = 2*80 - 2; +jrestart_input: +estat = 0; + +if (PyOS_InputHook != NULL) +(void)(PyOS_InputHook)(); +#ifdef __USE_TERMIOS +termios_resume(args); +#endif + +/* Fetch bytes until error or newline */ +errno = 0; while (1) { -if (PyOS_InputHook != NULL) -(void)(PyOS_InputHook)(); -errno = 0; -p = fgets(buf, len, fp); -if (p != NULL) -return 0; /* No error */ +int c = fgetc(args-fp); +#ifdef __USE_TERMIOS +if (!isprint(c)) +switch (c) { +case '\x04': +c = EOF; +/* FALLTHROUGH */ +default: +break; +case '\x03': +estat = SIGINT; +goto j_sigit; +case '\x1A': +estat = SIGTSTP; +goto j_sigit; +case '\x1C': +estat = SIGQUIT; +/* FALLTHROUGH */ +j_sigit:termios_suspend(args); +kill(getpid(), estat); +errno = EINTR; +goto jcheck_fail; +} +#endif +if (c == EOF) +goto jcheck_fail; +*(cursor++) = (char)c; +if (c == '\n') +break; + +if ((size_t)(cursor-buf) = buf_len) { +buf_len += 2+32; +cursor = buf = (char*)PyMem_REALLOC(buf, buf_len); +if (buf == NULL) { +estat = 1; +goto jreturn; +} +buf_len -= 2+32; +cursor += buf_len; +buf_len += 32; +} +} + +*cursor = '\0'; +args-input = buf; +jreturn: +#ifdef __USE_TERMIOS +termios_suspend(args); +#endif +return estat; + +jcheck_fail: #ifdef MS_WINDOWS -/* In the case of a Ctrl+C or some other external event - interrupting the operation: - Win2k/NT: ERROR_OPERATION_ABORTED is the most recent Win32 - error code (and feof() returns TRUE). - Win9x: Ctrl+C seems to have no effect on
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Steffen Daode Nurpmeso sdao...@googlemail.com added the comment: Ping! Note that whatever reason caused jesstess, to name a few, to drop that loop (and the continue), Charles-Francois posted a correctly working patch! I have no idea why such a severe bug could sleep in code which is executed for each and every input(), but it needs to be fixed! Do you want a robot test? I've tested it dozens of times and it still works fine!! It's idiot-proof! (And i definitely have no time in my free-time to write an automated test which fiddles around with timeout values and such to simulate user input. To me all of this is mystic. There are almost 14000 *registered* Python users here!!) -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Roundup Robot devnull@devnull added the comment: New changeset f343ac51 by Victor Stinner in branch '3.1': Issue #11650: PyOS_StdioReadline() retries fgets() if it was interrupted http://hg.python.org/cpython/rev/f343ac51 New changeset fc2f251e660a by Victor Stinner in branch '3.2': (Merge 3.1) Issue #11650: PyOS_StdioReadline() retries fgets() if it was http://hg.python.org/cpython/rev/fc2f251e660a New changeset 64de1ded0744 by Victor Stinner in branch 'default': (Merge 3.2) Issue #11650: PyOS_StdioReadline() retries fgets() if it was http://hg.python.org/cpython/rev/64de1ded0744 -- nosy: +python-dev ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Roundup Robot devnull@devnull added the comment: New changeset 7febd5ef7619 by Victor Stinner in branch '2.7': (Merge 3.1) Issue #11650: PyOS_StdioReadline() retries fgets() if it was http://hg.python.org/cpython/rev/7febd5ef7619 -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Steffen Daode Nurpmeso sdao...@googlemail.com added the comment: Merci, STINNER Victor! -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
STINNER Victor victor.stin...@haypocalc.com added the comment: I emulated Mac OS X behaviour on Linux by hacking my_fgets(): do { p=NULL; errno = EINTR; }, only after the first call to fgets(). Without the patch, Python does exit immediatly. With the patch, Python doesn't exit. I applied neologix's patch to 3.1, 3.2, 3.3 and 2.7: thank you Charles-Francois! Can someone retest on Mac OS X? I noticied a strange behaviour: -- $ python 1+^Z [1]+ Stopped ./python $ fg ./python 2ENTER 2 -- 1+2 input becomes 2. But we can not do better because buf doesn't contain 1+\0 when fgets() is interrupted. Note: If the readline module is available, it is used, and readline doesn't have this issue. And 1+^Z(...)2 gives 3 with readline. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Davide Rizzo sor...@gmail.com added the comment: Victor, I have neither OS X nor Linux available right now, but if I remember correctly the same happens on both systems when programs call input() (but not from the REPL). See also my previous message with python -c tests and my second remark. What about the Pexpect based tests? Could it be interesting to Python to test the behavior on the terminal? About the committed patch: is it the right thing to do to call PyOS_InputHook at every restart? Thank you! -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Steffen Daode Nurpmeso sdao...@googlemail.com added the comment: On Sat, Apr 09, 2011 at 02:18:01PM +, STINNER Victor wrote: I noticied a strange behaviour: So forget all this girlie s...! Here is a real man's patch!! You'll notice mysterious function calls with a Py prefix - they're necessary in this environment, but anyway sorry for that. (L'ascenseur est là , à gauche. And i'll hope to come to lesson 2 soon...) P.S.: this is very simple minded in respect to multibyte characters; our terminal library does something like this (and the complete picture is even more complicated): jnext: uni = s_textcodec_decode_single(_sterm_io_codec, cbuf, cbuf_len, bytes_consumed); cbuf += bytes_consumed; cbuf_len -= bytes_consumed; if (s_PREDICT_FALSE(uni 0)) { if (uni == -s_ERROR_INPROGRESS) { seq_cpl = s_FAL0; goto jleave; } /*if (uni == -s_ERROR_ILSEQ || uni == -s_ERROR_INVAL) {*/ cbuf_len = 0; uni = sterm_KEY_UNKNOWN; goto jemit; /*}*/ } -- Added file: http://bugs.python.org/file21593/11650.termios.diff ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___diff --git a/Parser/myreadline.c b/Parser/myreadline.c --- a/Parser/myreadline.c +++ b/Parser/myreadline.c @@ -10,6 +10,9 @@ */ #include Python.h +#ifdef Py_PYPORT_H +# include signal.h +#endif #ifdef MS_WINDOWS #define WIN32_LEAN_AND_MEAN #include windows.h @@ -29,117 +32,187 @@ int (*PyOS_InputHook)(void) = NULL; -/* This function restarts a fgets() after an EINTR error occurred +/* This function restarts a fgetc() after an EINTR error occurred except if PyOS_InterruptOccurred() returns true. */ +static int +my_fgets(char **store, FILE *fp) +{ +int estat; +char *buf, *cursor; +size_t buf_len; -static int -my_fgets(char *buf, int len, FILE *fp) -{ -char *p; +buf = (char*)PyMem_MALLOC(2*80); +estat = 1; +if (buf == NULL) +goto jreturn; + +cursor = buf; +buf_len = 2*80 - 2; +jrestart_input: +estat = 0; + +if (PyOS_InputHook != NULL) +(void)(PyOS_InputHook)(); + +/* Fetch bytes until error or newline */ +errno = 0; while (1) { -if (PyOS_InputHook != NULL) -(void)(PyOS_InputHook)(); -errno = 0; -p = fgets(buf, len, fp); -if (p != NULL) -return 0; /* No error */ +int c = fgetc(fp); +#ifdef Py_PYPORT_H +if (!isprint(c)) +switch (c) { +case '': +c = EOF; +/* FALLTHROUGH */ +default: +break; +case '': +estat = SIGINT; +goto j_sigit; +case '': +estat = SIGTSTP; +goto j_sigit; +case '': +estat = SIGQUIT; +/* FALLTHROUGH */ +j_sigit:kill(getpid(), estat); +errno = EINTR; +goto jcheck_fail; +} +#endif +if (c == EOF) +goto jcheck_fail; +*(cursor++) = (char)c; +if (c == '\n') +break; + +if ((size_t)(cursor-buf) = buf_len) { +buf_len += 2+32; +cursor = buf = (char*)PyMem_REALLOC(buf, buf_len); +if (buf == NULL) { +estat = 1; +goto jreturn; +} +buf_len -= 2+32; +cursor += buf_len; +buf_len += 32; +} +} + +*cursor = '\0'; +*store = buf; +jreturn: +return estat; + +jcheck_fail: #ifdef MS_WINDOWS -/* In the case of a Ctrl+C or some other external event - interrupting the operation: - Win2k/NT: ERROR_OPERATION_ABORTED is the most recent Win32 - error code (and feof() returns TRUE). - Win9x: Ctrl+C seems to have no effect on fgets() returning - early - the signal handler is called, but the fgets() - only returns normally (ie, when Enter hit or feof()) +/* In the case of a Ctrl+C or some other external event + interrupting the operation: + Win2k/NT: ERROR_OPERATION_ABORTED is the most recent Win32 + error code (and feof() returns TRUE). + Win9x: Ctrl+C seems to have no effect on fgets() returning + early - the signal handler is called, but the fgets() + only returns normally (ie, when Enter hit or feof()) +*/ +if (GetLastError()==ERROR_OPERATION_ABORTED) { +/* Signals come asynchronously, so we sleep a brief + moment before checking if the handler has been + triggered (we cant just return 1 before the + signal handler has been called, as the
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Davide Rizzo sor...@gmail.com added the comment: An effective way to automate user interaction tests is by using pseudo-terminals. The attached test uses Pexpect and bash as tools to test the issue and demonstrates the bug on affected builds/platforms. There are a number of (possibly related) other issues that may require similar testing. Pexpect is a nice tool to automate testing over ptys, but it is Python 2. I had to run the test on Python 3.3 through the installed Python 2 interpter. My thought: the smallest useful subset of Pexpect can be ported to Py3 and maintained within Python. Or alternatively an equally useful minimal implementation of the same features. Note that most of Pexpect is already tested. I've used bash to test this one issue because it was ready and I could rely on bash jobs handling. I don't know how good is to expect bash to be on the system or whether any sh-like shell is compatible. There is a WinPexpect which supposedly does the same thing on Windows in a native way. I couldn't get the time to try it out, but it includes a modified version of Pexpect and claims Py3 compatibility. Also, I don't really understand sdaoden ascii art messages. Let me know if someone wants to work on this with me. :) -- Added file: http://bugs.python.org/file21450/testrepl.py ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Steffen Daode Nurpmeso sdao...@googlemail.com added the comment: \|/ _ . | = Yes!? -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Davide Rizzo sor...@gmail.com added the comment: The bugs seems not to be limited to the REPL. # Python 2.6 with readline on Mac OS X $ python -c raw_input() ^Z [1]+ Stopped python -c raw_input() $ fg python -c raw_input() Traceback (most recent call last): File string, line 1, in module EOFError # Python 3.1 on Debian Linux $ python3.1 -c print(input()) ^Z [1]+ Stopped python3.1 -c print(input()) $ fg python3.1 -c print(input()) hello hello # Python 3.3(267578b2422d) without readline, OS X (I've put two extra printfs around fgets in myreadline.c) $ ./python.exe -c print(input()) Entering fgets ^Z [1]+ Stopped ./python.exe -c print(input()) $ fg ./python.exe -c print(input()) fgets returned 0 Traceback (most recent call last): File string, line 1, in module EOFError [36537 refs] # same as before with Charles-Francois patch applied $ ./python.exe -c print(input()) ^Z [1]+ Stopped ./python.exe -c print(input()) $ fg ./python.exe -c print(input()) hello hello [36538 refs] Some remarks here: 1) the bug is in all tested versions running on OS X, and the patch does fix it. 2) I tested with and without GNU readline and input()'s behavior doesn't change when running with python -c (i.e. it uses myreadline.c instead of GNU readline). Though, if run interactively, input() uses readline. Isn't input() supposed to use readline whenever reading from a tty, not only if called from the REPL? Or even if it were to fallback, shouldn't that be on TextIOWrapper(sys.stdin).readline()? 3) io module seems to be doing it right already. sys.stdin.read() raises an IOError (not an EOFError as input() incorrectly does, this is acceptable as a platform quirk) when interrupted, while sys.stdin.readline() handles the interruption without complaining at all. Maybe myreadline.c is too old and wants to be replaced (or backed) by io in 3.3? -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Steffen Daode Nurpmeso sdao...@googlemail.com added the comment: On Fri, Mar 25, 2011 at 12:25:21PM +, Davide Rizzo wrote: Some remarks here: 1) the patch does fix it. Yes! I can't comment the rest except for what .. function:: input([prompt]) states, which Davide surely have read himself. Anyway it seems to be a good idea to replace parts of the code where such severe bugs can sleep for such a long time. This code will not be used automatically on, yes, *all* modern UNIX platforms (don't let me think on what modern means here). So if there are no dependencies i don't know of (but even without knowing i would think there should be none - this is readline), it seems that providing a simple Python-based fallback implementation, which will use functions which themselves will be used daily in real life, is a good idea. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Changes by Davide Rizzo sor...@gmail.com: -- nosy: +mwh ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Steffen Daode Nurpmeso sdao...@googlemail.com added the comment: On Thu, Mar 23, 2011 at 21:50:42PM +, Davide Rizzo wrote: Steffen, on a side note, I got readline working with brew. Say - readline not libedit which does not take care of .inputrc? Without permanently modifying GNU autoconf stuff? How do you do that? -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Michael Hudson m...@users.sourceforge.net added the comment: To be clear, I have no idea why the patch for issue 960406 removed the continue from my_fgets. It may have been simply a mistake. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Changes by Steffen Daode Nurpmeso sdao...@googlemail.com: -- nosy: +jesstess ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Changes by Steffen Daode Nurpmeso sdao...@googlemail.com: -- components: -IO nosy: +akuchling title: CTRL-Z causes interpreter exit - Faulty RESTART/EINTR handling in Parser/myreadline.c versions: +Python 2.7, Python 3.1, Python 3.2 ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Steffen Daode Nurpmeso sdao...@googlemail.com added the comment: (Oh - when will i get this tracker right? Is there somewhere *real* documentation which applies to what actually happens?? Sorry once again, all of you!) -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Davide Rizzo sor...@gmail.com added the comment: The faulty behavior was presumably introduced in r36346, when the continue statement was removed. I already linked the relevant discussion, but I'm not sure whether that was a desired change or just an oversight. I'm inclined to believe the latter, as it wouldn't have made much sense to leave the loop there otherwise. In this case a patch like the already posted one would do the fix. Steffen, on a side note, I got readline working with brew. -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
STINNER Victor victor.stin...@haypocalc.com added the comment: Sorry to ask that, but would it be possible to write an automated test for this issue? -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue11650] Faulty RESTART/EINTR handling in Parser/myreadline.c
Davide Rizzo sor...@gmail.com added the comment: I couldn't get an automated test to fail on the bug with subprocess. Apparently an interpreter launched with Popen is not subject to the bug as it is when launched directly from the shell (i.e. fgets is not interrupted by a SIGSTOP sent by the parent process), so I may be getting something wrong here. However I don't believe the important thing is to test this particular issue (which may be unimportant by itself if nobody noticed it for seven years, and not many build Python without readline) but rather make sure it doesn't break things elsewhere. As I understand it the code in r36346 didn't have proper tests, so we can only guess? -- ___ Python tracker rep...@bugs.python.org http://bugs.python.org/issue11650 ___ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com