comparison Python/sysmodule.c @ 66719:ba709ad3ff4c

Issue #10601: sys.displayhook uses 'backslashreplace' error handler on UnicodeEncodeError.
author Victor Stinner <victor.stinner@haypocalc.com>
date Sat, 04 Dec 2010 17:24:33 +0000
parents 724920a015f7
children b7be652daf6e
comparison
equal deleted inserted replaced
66717:779a23a08d8c 66719:ba709ad3ff4c
63 } 63 }
64 else 64 else
65 return PyDict_SetItemString(sd, name, v); 65 return PyDict_SetItemString(sd, name, v);
66 } 66 }
67 67
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
68 static PyObject * 130 static PyObject *
69 sys_displayhook(PyObject *self, PyObject *o) 131 sys_displayhook(PyObject *self, PyObject *o)
70 { 132 {
71 PyObject *outf; 133 PyObject *outf;
72 PyInterpreterState *interp = PyThreadState_GET()->interp; 134 PyInterpreterState *interp = PyThreadState_GET()->interp;
73 PyObject *modules = interp->modules; 135 PyObject *modules = interp->modules;
74 PyObject *builtins = PyDict_GetItemString(modules, "builtins"); 136 PyObject *builtins = PyDict_GetItemString(modules, "builtins");
137 int err;
75 138
76 if (builtins == NULL) { 139 if (builtins == NULL) {
77 PyErr_SetString(PyExc_RuntimeError, "lost builtins module"); 140 PyErr_SetString(PyExc_RuntimeError, "lost builtins module");
78 return NULL; 141 return NULL;
79 } 142 }
90 outf = PySys_GetObject("stdout"); 153 outf = PySys_GetObject("stdout");
91 if (outf == NULL || outf == Py_None) { 154 if (outf == NULL || outf == Py_None) {
92 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout"); 155 PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
93 return NULL; 156 return NULL;
94 } 157 }
95 if (PyFile_WriteObject(o, outf, 0) != 0) 158 if (PyFile_WriteObject(o, outf, 0) != 0) {
96 return NULL; 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 }
97 if (PyFile_WriteString("\n", outf) != 0) 171 if (PyFile_WriteString("\n", outf) != 0)
98 return NULL; 172 return NULL;
99 if (PyObject_SetAttrString(builtins, "_", o) != 0) 173 if (PyObject_SetAttrString(builtins, "_", o) != 0)
100 return NULL; 174 return NULL;
101 Py_INCREF(Py_None); 175 Py_INCREF(Py_None);