Index: Python/pythonrun.c
===================================================================
--- Python/pythonrun.c (révision 67973)
+++ Python/pythonrun.c (copie de travail)
@@ -84,6 +84,7 @@
int Py_FrozenFlag; /* Needed by getpath.c */
int Py_IgnoreEnvironmentFlag; /* e.g. PYTHONPATH, PYTHONHOME */
int Py_NoUserSiteDirectory = 0; /* for -s and site.py */
+int Py_UnbufferedStdoutFlag = 0; /* Unbuffered binary std{out,err} */
/* PyModule_GetWarningsModule is no longer necessary as of 2.6
since _warnings is builtin. This API should not be used. */
@@ -259,7 +260,7 @@
if (install_sigs)
initsigs(); /* Signal handling stuff, including initintr() */
-
+
/* Initialize warnings. */
_PyWarnings_Init();
if (PySys_HasWarnOptions()) {
@@ -724,6 +725,49 @@
}
}
+static PyObject*
+create_stdio(int fd, char* name, char* encoding, char* errors)
+{
+ PyObject *io = NULL, *buf = NULL, *stream = NULL, *mode = NULL;
+
+ if (!Py_UnbufferedStdoutFlag) {
+ return PyFile_FromFd(fd, name, "w",
+ -1,
+ encoding, errors, "\n", 0);
+ }
+
+ io = PyImport_ImportModule("io");
+ if (io == NULL)
+ goto error;
+
+ buf = PyObject_CallMethod(io, "open", "isiOOOi",
+ fd, "wb", 0,
+ Py_None, Py_None, Py_None, 0);
+ if (buf == NULL)
+ goto error;
+
+ stream = PyObject_CallMethod(io, "TextIOWrapper", "OsssO",
+ buf, encoding, errors,
+ "\n", Py_True);
+ Py_CLEAR(io);
+ Py_CLEAR(buf);
+ if (stream == NULL)
+ goto error;
+
+ mode = PyUnicode_FromString("w");
+ if (!mode || PyObject_SetAttrString(stream, "mode", mode) < 0)
+ goto error;
+ Py_CLEAR(mode);
+ return stream;
+
+error:
+ Py_XDECREF(io);
+ Py_XDECREF(buf);
+ Py_XDECREF(stream);
+ Py_XDECREF(mode);
+ return NULL;
+}
+
/* Initialize sys.stdin, stdout, stderr and builtins.open */
static int
initstdio(void)
@@ -790,7 +834,7 @@
#endif
}
else {
- if (!(std = PyFile_FromFd(fd, "", "r", -1, encoding,
+ if (!(std = PyFile_FromFd(fd, "", "r", -1, encoding,
errors, "\n", 0))) {
goto error;
}
@@ -810,8 +854,7 @@
#endif
}
else {
- if (!(std = PyFile_FromFd(fd, "", "w", -1, encoding,
- errors, "\n", 0))) {
+ if (!(std = create_stdio(fd, "", encoding, errors))) {
goto error;
}
} /* if (fd < 0) */
@@ -831,8 +874,7 @@
#endif
}
else {
- if (!(std = PyFile_FromFd(fd, "", "w", -1, encoding,
- "backslashreplace", "\n", 0))) {
+ if (!(std = create_stdio(fd, "", encoding, "backslashreplace"))) {
goto error;
}
} /* if (fd < 0) */
@@ -2036,7 +2078,7 @@
alloca(PYOS_STACK_MARGIN * sizeof(void*));
return 0;
} __except (GetExceptionCode() == STATUS_STACK_OVERFLOW ?
- EXCEPTION_EXECUTE_HANDLER :
+ EXCEPTION_EXECUTE_HANDLER :
EXCEPTION_CONTINUE_SEARCH) {
int errcode = _resetstkoflw();
if (errcode == 0)
Index: Include/pydebug.h
===================================================================
--- Include/pydebug.h (révision 67973)
+++ Include/pydebug.h (copie de travail)
@@ -18,6 +18,7 @@
PyAPI_DATA(int) Py_DivisionWarningFlag;
PyAPI_DATA(int) Py_DontWriteBytecodeFlag;
PyAPI_DATA(int) Py_NoUserSiteDirectory;
+PyAPI_DATA(int) Py_UnbufferedStdoutFlag;
/* this is a wrapper around getenv() that pays attention to
Py_IgnoreEnvironmentFlag. It should be used for getting variables like
Index: Lib/test/test_cmd_line.py
===================================================================
--- Lib/test/test_cmd_line.py (révision 67973)
+++ Lib/test/test_cmd_line.py (copie de travail)
@@ -142,7 +142,24 @@
self.exit_code('-c', command),
0)
+ def test_unbuffered(self):
+ # Test expected operation of the '-u' switch
+ for stream in ('stdout', 'stderr'):
+ # Binary is unbuffered
+ code = ("import os, sys; sys.%s.buffer.write(b'x'); os._exit(0)"
+ % stream)
+ data, rc = self.start_python_and_exit_code('-u', '-c', code)
+ self.assertEqual(rc, 0)
+ self.assertEqual(data, b'x', "binary %s not unbuffered" % stream)
+ # Text is line-buffered
+ code = ("import os, sys; sys.%s.write('x\\n'); os._exit(0)"
+ % stream)
+ data, rc = self.start_python_and_exit_code('-u', '-c', code)
+ self.assertEqual(rc, 0)
+ self.assertEqual(data.strip(), b'x',
+ "text %s not line-buffered" % stream)
+
def test_main():
test.support.run_unittest(CmdLineTest)
test.support.reap_children()
Index: Modules/main.c
===================================================================
--- Modules/main.c (révision 67973)
+++ Modules/main.c (copie de travail)
@@ -292,7 +292,6 @@
wchar_t *module = NULL;
FILE *fp = stdin;
char *p;
- int unbuffered = 0;
int skipfirstline = 0;
int stdin_is_interactive = 0;
int help = 0;
@@ -374,7 +373,7 @@
break;
case 'u':
- unbuffered++;
+ Py_UnbufferedStdoutFlag++;
saw_unbuffered_flag = 1;
break;
@@ -423,7 +422,7 @@
Py_InspectFlag = 1;
if (!saw_unbuffered_flag &&
(p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0')
- unbuffered = 1;
+ Py_UnbufferedStdoutFlag = 1;
if (!Py_NoUserSiteDirectory &&
(p = Py_GETENV("PYTHONNOUSERSITE")) && *p != '\0')
@@ -444,7 +443,7 @@
stdin_is_interactive = Py_FdIsInteractive(stdin, (char *)0);
- if (unbuffered) {
+ if (Py_UnbufferedStdoutFlag) {
#if defined(MS_WINDOWS) || defined(__CYGWIN__)
_setmode(fileno(stdin), O_BINARY);
_setmode(fileno(stdout), O_BINARY);