@@ -88,6 +88,7 @@ int Py_UseClassExceptionsFlag = 1; /* Needed by bltinmodule.c: deprecated */
8888int Py_FrozenFlag ; /* Needed by getpath.c */
8989int Py_IgnoreEnvironmentFlag ; /* e.g. PYTHONPATH, PYTHONHOME */
9090int Py_NoUserSiteDirectory = 0 ; /* for -s and site.py */
91+ int Py_UnbufferedStdioFlag = 0 ; /* Unbuffered binary std{in,out,err} */
9192
9293/* PyModule_GetWarningsModule is no longer necessary as of 2.6
9394since _warnings is builtin. This API should not be used. */
@@ -728,6 +729,75 @@ initsite(void)
728729 }
729730}
730731
732+ static PyObject *
733+ create_stdio (PyObject * io ,
734+ int fd , int write_mode , char * name ,
735+ char * encoding , char * errors )
736+ {
737+ PyObject * buf = NULL , * stream = NULL , * text = NULL , * raw = NULL ;
738+ const char * mode ;
739+ const PyObject * line_buffering ;
740+ int buffering ;
741+
742+ if (Py_UnbufferedStdioFlag )
743+ buffering = 0 ;
744+ else
745+ buffering = -1 ;
746+ if (write_mode )
747+ mode = "wb" ;
748+ else
749+ mode = "rb" ;
750+ buf = PyObject_CallMethod (io , "open" , "isiOOOi" ,
751+ fd , mode , buffering ,
752+ Py_None , Py_None , Py_None , 0 );
753+ if (buf == NULL )
754+ goto error ;
755+
756+ if (!Py_UnbufferedStdioFlag ) {
757+ raw = PyObject_GetAttrString (buf , "raw" );
758+ if (raw == NULL )
759+ goto error ;
760+ }
761+ else {
762+ raw = buf ;
763+ Py_INCREF (raw );
764+ }
765+
766+ text = PyUnicode_FromString (name );
767+ if (text == NULL || PyObject_SetAttrString (raw , "_name" , text ) < 0 )
768+ goto error ;
769+ Py_CLEAR (raw );
770+ Py_CLEAR (text );
771+
772+ if (Py_UnbufferedStdioFlag )
773+ line_buffering = Py_True ;
774+ else
775+ line_buffering = Py_False ;
776+ stream = PyObject_CallMethod (io , "TextIOWrapper" , "OsssO" ,
777+ buf , encoding , errors ,
778+ "\n" , line_buffering );
779+ Py_CLEAR (buf );
780+ if (stream == NULL )
781+ goto error ;
782+
783+ if (write_mode )
784+ mode = "w" ;
785+ else
786+ mode = "r" ;
787+ text = PyUnicode_FromString (mode );
788+ if (!text || PyObject_SetAttrString (stream , "mode" , text ) < 0 )
789+ goto error ;
790+ Py_CLEAR (text );
791+ return stream ;
792+
793+ error :
794+ Py_XDECREF (buf );
795+ Py_XDECREF (stream );
796+ Py_XDECREF (text );
797+ Py_XDECREF (raw );
798+ return NULL ;
799+ }
800+
731801/* Initialize sys.stdin, stdout, stderr and builtins.open */
732802static int
733803initstdio (void )
@@ -794,10 +864,9 @@ initstdio(void)
794864#endif
795865 }
796866 else {
797- if (!( std = PyFile_FromFd ( fd , "<stdin>" , "r" , -1 , encoding ,
798- errors , "\n" , 0 ))) {
867+ std = create_stdio ( iomod , fd , 0 , "<stdin>" , encoding , errors );
868+ if ( std == NULL )
799869 goto error ;
800- }
801870 } /* if (fd < 0) */
802871 PySys_SetObject ("__stdin__" , std );
803872 PySys_SetObject ("stdin" , std );
@@ -814,10 +883,9 @@ initstdio(void)
814883#endif
815884 }
816885 else {
817- if (!( std = PyFile_FromFd ( fd , "<stdout>" , "w" , -1 , encoding ,
818- errors , "\n" , 0 ))) {
886+ std = create_stdio ( iomod , fd , 1 , "<stdout>" , encoding , errors );
887+ if ( std == NULL )
819888 goto error ;
820- }
821889 } /* if (fd < 0) */
822890 PySys_SetObject ("__stdout__" , std );
823891 PySys_SetObject ("stdout" , std );
@@ -835,10 +903,9 @@ initstdio(void)
835903#endif
836904 }
837905 else {
838- if (!( std = PyFile_FromFd ( fd , "<stderr>" , "w" , -1 , encoding ,
839- "backslashreplace" , "\n" , 0 ))) {
906+ std = create_stdio ( iomod , fd , 1 , "<stderr>" , encoding , "backslashreplace" );
907+ if ( std == NULL )
840908 goto error ;
841- }
842909 } /* if (fd < 0) */
843910
844911 /* Same as hack above, pre-import stderr's codec to avoid recursion
0 commit comments