|
@@ -28,6 +28,8 @@
|
|
|
# if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 5
|
|
# if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 5
|
|
|
# define Py_DecodeLocale _Py_char2wchar
|
|
# define Py_DecodeLocale _Py_char2wchar
|
|
|
# endif
|
|
# endif
|
|
|
|
|
+
|
|
|
|
|
+# include "structmember.h"
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
/* Leave room for future expansion. We only read pointer 0, but there are
|
|
/* Leave room for future expansion. We only read pointer 0, but there are
|
|
@@ -343,6 +345,51 @@ static int setup_logging(const char *path, int append) {
|
|
|
#endif
|
|
#endif
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * Sets the line_buffering property on a TextIOWrapper object.
|
|
|
|
|
+ */
|
|
|
|
|
+#if PY_MAJOR_VERSION >= 3
|
|
|
|
|
+static int enable_line_buffering(PyObject *file) {
|
|
|
|
|
+#if PY_VERSION_HEX >= 0x03070000
|
|
|
|
|
+ /* Python 3.7 has a useful reconfigure() method. */
|
|
|
|
|
+ PyObject *kwargs = _PyDict_NewPresized(1);
|
|
|
|
|
+ PyDict_SetItemString(kwargs, "line_buffering", Py_True);
|
|
|
|
|
+ PyObject *args = PyTuple_New(0);
|
|
|
|
|
+
|
|
|
|
|
+ PyObject *method = PyObject_GetAttrString(file, "reconfigure");
|
|
|
|
|
+ if (method != NULL) {
|
|
|
|
|
+ PyObject *result = PyObject_Call(method, args, kwargs);
|
|
|
|
|
+ Py_DECREF(method);
|
|
|
|
|
+ if (result != NULL) {
|
|
|
|
|
+ Py_DECREF(result);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ PyErr_Clear();
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ Py_DECREF(kwargs);
|
|
|
|
|
+ Py_DECREF(args);
|
|
|
|
|
+#else
|
|
|
|
|
+ /* Older versions just don't expose a way to reconfigure(), but it's still
|
|
|
|
|
+ safe to override the property; we just have to use a hack to do it,
|
|
|
|
|
+ because it's officially marked "readonly". */
|
|
|
|
|
+
|
|
|
|
|
+ PyTypeObject *type = Py_TYPE(file);
|
|
|
|
|
+ PyMemberDef *member = type->tp_members;
|
|
|
|
|
+
|
|
|
|
|
+ while (member != NULL && member->name != NULL) {
|
|
|
|
|
+ if (strcmp(member->name, "line_buffering") == 0) {
|
|
|
|
|
+ *((char *)file + member->offset) = 1;
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ ++member;
|
|
|
|
|
+ }
|
|
|
|
|
+ fflush(stdout);
|
|
|
|
|
+#endif
|
|
|
|
|
+ return 1;
|
|
|
|
|
+}
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
/* Main program */
|
|
/* Main program */
|
|
|
|
|
|
|
|
#ifdef WIN_UNICODE
|
|
#ifdef WIN_UNICODE
|
|
@@ -483,6 +530,24 @@ int Py_FrozenMain(int argc, char **argv)
|
|
|
}
|
|
}
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
|
|
+#if defined(MS_WINDOWS) && PY_VERSION_HEX >= 0x03040000
|
|
|
|
|
+ /* Ensure that line buffering is enabled on the output streams. */
|
|
|
|
|
+ if (!unbuffered) {
|
|
|
|
|
+ /* Python 3.7 has a useful reconfigure() method. */
|
|
|
|
|
+ PyObject *sys_stream;
|
|
|
|
|
+ sys_stream = PySys_GetObject("__stdout__");
|
|
|
|
|
+ if (sys_stream && !enable_line_buffering(sys_stream)) {
|
|
|
|
|
+ fprintf(stderr, "Failed to enable line buffering on sys.stdout\n");
|
|
|
|
|
+ fflush(stderr);
|
|
|
|
|
+ }
|
|
|
|
|
+ sys_stream = PySys_GetObject("__stderr__");
|
|
|
|
|
+ if (sys_stream && !enable_line_buffering(sys_stream)) {
|
|
|
|
|
+ fprintf(stderr, "Failed to enable line buffering on sys.stderr\n");
|
|
|
|
|
+ fflush(stderr);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
if (Py_VerboseFlag)
|
|
if (Py_VerboseFlag)
|
|
|
fprintf(stderr, "Python %s\n%s\n",
|
|
fprintf(stderr, "Python %s\n%s\n",
|
|
|
Py_GetVersion(), Py_GetCopyright());
|
|
Py_GetVersion(), Py_GetCopyright());
|