|
28 | 28 | # if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 5
|
29 | 29 | # define Py_DecodeLocale _Py_char2wchar
|
30 | 30 | # endif
|
| 31 | + |
| 32 | +# include "structmember.h" |
31 | 33 | #endif
|
32 | 34 |
|
33 | 35 | /* 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) {
|
343 | 345 | #endif
|
344 | 346 | }
|
345 | 347 |
|
| 348 | +/** |
| 349 | + * Sets the line_buffering property on a TextIOWrapper object. |
| 350 | + */ |
| 351 | +#if PY_MAJOR_VERSION >= 3 |
| 352 | +static int enable_line_buffering(PyObject *file) { |
| 353 | +#if PY_VERSION_HEX >= 0x03070000 |
| 354 | + /* Python 3.7 has a useful reconfigure() method. */ |
| 355 | + PyObject *kwargs = _PyDict_NewPresized(1); |
| 356 | + PyDict_SetItemString(kwargs, "line_buffering", Py_True); |
| 357 | + PyObject *args = PyTuple_New(0); |
| 358 | + |
| 359 | + PyObject *method = PyObject_GetAttrString(file, "reconfigure"); |
| 360 | + if (method != NULL) { |
| 361 | + PyObject *result = PyObject_Call(method, args, kwargs); |
| 362 | + Py_DECREF(method); |
| 363 | + if (result != NULL) { |
| 364 | + Py_DECREF(result); |
| 365 | + } else { |
| 366 | + PyErr_Clear(); |
| 367 | + return 0; |
| 368 | + } |
| 369 | + } |
| 370 | + Py_DECREF(kwargs); |
| 371 | + Py_DECREF(args); |
| 372 | +#else |
| 373 | + /* Older versions just don't expose a way to reconfigure(), but it's still |
| 374 | + safe to override the property; we just have to use a hack to do it, |
| 375 | + because it's officially marked "readonly". */ |
| 376 | + |
| 377 | + PyTypeObject *type = Py_TYPE(file); |
| 378 | + PyMemberDef *member = type->tp_members; |
| 379 | + |
| 380 | + while (member != NULL && member->name != NULL) { |
| 381 | + if (strcmp(member->name, "line_buffering") == 0) { |
| 382 | + *((char *)file + member->offset) = 1; |
| 383 | + return 1; |
| 384 | + } |
| 385 | + ++member; |
| 386 | + } |
| 387 | + fflush(stdout); |
| 388 | +#endif |
| 389 | + return 1; |
| 390 | +} |
| 391 | +#endif |
| 392 | + |
346 | 393 | /* Main program */
|
347 | 394 |
|
348 | 395 | #ifdef WIN_UNICODE
|
@@ -483,6 +530,24 @@ int Py_FrozenMain(int argc, char **argv)
|
483 | 530 | }
|
484 | 531 | #endif
|
485 | 532 |
|
| 533 | +#if defined(MS_WINDOWS) && PY_VERSION_HEX >= 0x03040000 |
| 534 | + /* Ensure that line buffering is enabled on the output streams. */ |
| 535 | + if (!unbuffered) { |
| 536 | + /* Python 3.7 has a useful reconfigure() method. */ |
| 537 | + PyObject *sys_stream; |
| 538 | + sys_stream = PySys_GetObject("__stdout__"); |
| 539 | + if (sys_stream && !enable_line_buffering(sys_stream)) { |
| 540 | + fprintf(stderr, "Failed to enable line buffering on sys.stdout\n"); |
| 541 | + fflush(stderr); |
| 542 | + } |
| 543 | + sys_stream = PySys_GetObject("__stderr__"); |
| 544 | + if (sys_stream && !enable_line_buffering(sys_stream)) { |
| 545 | + fprintf(stderr, "Failed to enable line buffering on sys.stderr\n"); |
| 546 | + fflush(stderr); |
| 547 | + } |
| 548 | + } |
| 549 | +#endif |
| 550 | + |
486 | 551 | if (Py_VerboseFlag)
|
487 | 552 | fprintf(stderr, "Python %s\n%s\n",
|
488 | 553 | Py_GetVersion(), Py_GetCopyright());
|
|
0 commit comments