@@ -65,13 +65,76 @@ PySys_SetObject(const char *name, PyObject *v)
6565 return PyDict_SetItemString (sd , name , v );
6666}
6767
68+ /* Write repr(o) to sys.stdout using sys.stdout.encoding and 'backslashreplace'
69+ error handler. If sys.stdout has a buffer attribute, use
70+ sys.stdout.buffer.write(encoded), otherwise redecode the string and use
71+ sys.stdout.write(redecoded).
72+
73+ Helper function for sys_displayhook(). */
74+ static int
75+ sys_displayhook_unencodable (PyObject * outf , PyObject * o )
76+ {
77+ PyObject * stdout_encoding = NULL ;
78+ PyObject * encoded , * escaped_str , * repr_str , * buffer , * result ;
79+ char * stdout_encoding_str ;
80+ int ret ;
81+
82+ stdout_encoding = PyObject_GetAttrString (outf , "encoding" );
83+ if (stdout_encoding == NULL )
84+ goto error ;
85+ stdout_encoding_str = _PyUnicode_AsString (stdout_encoding );
86+ if (stdout_encoding_str == NULL )
87+ goto error ;
88+
89+ repr_str = PyObject_Repr (o );
90+ if (repr_str == NULL )
91+ goto error ;
92+ encoded = PyUnicode_AsEncodedString (repr_str ,
93+ stdout_encoding_str ,
94+ "backslashreplace" );
95+ Py_DECREF (repr_str );
96+ if (encoded == NULL )
97+ goto error ;
98+
99+ buffer = PyObject_GetAttrString (outf , "buffer" );
100+ if (buffer ) {
101+ result = PyObject_CallMethod (buffer , "write" , "(O)" , encoded );
102+ Py_DECREF (buffer );
103+ Py_DECREF (encoded );
104+ if (result == NULL )
105+ goto error ;
106+ Py_DECREF (result );
107+ }
108+ else {
109+ PyErr_Clear ();
110+ escaped_str = PyUnicode_FromEncodedObject (encoded ,
111+ stdout_encoding_str ,
112+ "strict" );
113+ Py_DECREF (encoded );
114+ if (PyFile_WriteObject (escaped_str , outf , Py_PRINT_RAW ) != 0 ) {
115+ Py_DECREF (escaped_str );
116+ goto error ;
117+ }
118+ Py_DECREF (escaped_str );
119+ }
120+ ret = 0 ;
121+ goto finally ;
122+
123+ error :
124+ ret = -1 ;
125+ finally :
126+ Py_XDECREF (stdout_encoding );
127+ return ret ;
128+ }
129+
68130static PyObject *
69131sys_displayhook (PyObject * self , PyObject * o )
70132{
71133 PyObject * outf ;
72134 PyInterpreterState * interp = PyThreadState_GET ()-> interp ;
73135 PyObject * modules = interp -> modules ;
74136 PyObject * builtins = PyDict_GetItemString (modules , "builtins" );
137+ int err ;
75138
76139 if (builtins == NULL ) {
77140 PyErr_SetString (PyExc_RuntimeError , "lost builtins module" );
@@ -92,8 +155,19 @@ sys_displayhook(PyObject *self, PyObject *o)
92155 PyErr_SetString (PyExc_RuntimeError , "lost sys.stdout" );
93156 return NULL ;
94157 }
95- if (PyFile_WriteObject (o , outf , 0 ) != 0 )
96- return NULL ;
158+ if (PyFile_WriteObject (o , outf , 0 ) != 0 ) {
159+ if (PyErr_ExceptionMatches (PyExc_UnicodeEncodeError )) {
160+ /* repr(o) is not encodable to sys.stdout.encoding with
161+ * sys.stdout.errors error handler (which is probably 'strict') */
162+ PyErr_Clear ();
163+ err = sys_displayhook_unencodable (outf , o );
164+ if (err )
165+ return NULL ;
166+ }
167+ else {
168+ return NULL ;
169+ }
170+ }
97171 if (PyFile_WriteString ("\n" , outf ) != 0 )
98172 return NULL ;
99173 if (PyObject_SetAttrString (builtins , "_" , o ) != 0 )
0 commit comments