comparison Python/traceback.c @ 62393:fa830371c724 3.1

Merged revisions 82059,82061 via svnmerge from svn+ssh://pythondev@svn.python.org/python/branches/py3k ........ r82059 | victor.stinner | 2010-06-18 01:08:50 +0200 (ven., 18 juin 2010) | 5 lines Issue #6543: Write the traceback in the terminal encoding instead of utf-8. Fix the encoding of the modules filename. Reindent also traceback.h, just because I hate tabs :-) ........ r82061 | victor.stinner | 2010-06-18 01:17:37 +0200 (ven., 18 juin 2010) | 2 lines Issue #6543: Mention the author of the patch, Amaury Forgeot d'Arc ........
author Victor Stinner <victor.stinner@haypocalc.com>
date Thu, 17 Jun 2010 23:23:37 +0000
parents f197407bdba2
children 6296632ad2cb
comparison
equal deleted inserted replaced
62392:07449b367935 62393:fa830371c724
132 tstate->curexc_traceback = (PyObject *)tb; 132 tstate->curexc_traceback = (PyObject *)tb;
133 Py_XDECREF(oldtb); 133 Py_XDECREF(oldtb);
134 return 0; 134 return 0;
135 } 135 }
136 136
137 static int 137 static PyObject *
138 _Py_FindSourceFile(const char* filename, char* namebuf, size_t namelen, int open_flags) 138 _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *io)
139 { 139 {
140 int i; 140 Py_ssize_t i;
141 int fd = -1; 141 PyObject *binary;
142 PyObject *v; 142 PyObject *v;
143 Py_ssize_t _npath; 143 Py_ssize_t npath;
144 int npath;
145 size_t taillen; 144 size_t taillen;
146 PyObject *syspath; 145 PyObject *syspath;
147 const char* path; 146 const char* path;
148 const char* tail; 147 const char* tail;
148 const char* filepath;
149 Py_ssize_t len; 149 Py_ssize_t len;
150 150
151 filepath = _PyUnicode_AsString(filename);
152 if (filepath == NULL) {
153 PyErr_Clear();
154 return NULL;
155 }
156
151 /* Search tail of filename in sys.path before giving up */ 157 /* Search tail of filename in sys.path before giving up */
152 tail = strrchr(filename, SEP); 158 tail = strrchr(filepath, SEP);
153 if (tail == NULL) 159 if (tail == NULL)
154 tail = filename; 160 tail = filepath;
155 else 161 else
156 tail++; 162 tail++;
157 taillen = strlen(tail); 163 taillen = strlen(tail);
158 164
159 syspath = PySys_GetObject("path"); 165 syspath = PySys_GetObject("path");
160 if (syspath == NULL || !PyList_Check(syspath)) 166 if (syspath == NULL || !PyList_Check(syspath))
161 return -1; 167 return NULL;
162 _npath = PyList_Size(syspath); 168 npath = PyList_Size(syspath);
163 npath = Py_SAFE_DOWNCAST(_npath, Py_ssize_t, int);
164 169
165 for (i = 0; i < npath; i++) { 170 for (i = 0; i < npath; i++) {
166 v = PyList_GetItem(syspath, i); 171 v = PyList_GetItem(syspath, i);
167 if (v == NULL) { 172 if (v == NULL) {
168 PyErr_Clear(); 173 PyErr_Clear();
169 break; 174 break;
170 } 175 }
171 if (!PyUnicode_Check(v)) 176 if (!PyUnicode_Check(v))
172 continue; 177 continue;
173 path = _PyUnicode_AsStringAndSize(v, &len); 178 path = _PyUnicode_AsStringAndSize(v, &len);
179 if (path == NULL) {
180 PyErr_Clear();
181 continue;
182 }
174 if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) 183 if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1)
175 continue; /* Too long */ 184 continue; /* Too long */
176 strcpy(namebuf, path); 185 strcpy(namebuf, path);
177 if (strlen(namebuf) != len) 186 if (strlen(namebuf) != len)
178 continue; /* v contains '\0' */ 187 continue; /* v contains '\0' */
179 if (len > 0 && namebuf[len-1] != SEP) 188 if (len > 0 && namebuf[len-1] != SEP)
180 namebuf[len++] = SEP; 189 namebuf[len++] = SEP;
181 strcpy(namebuf+len, tail); 190 strcpy(namebuf+len, tail);
182 Py_BEGIN_ALLOW_THREADS 191
183 fd = open(namebuf, open_flags); 192 binary = PyObject_CallMethod(io, "open", "ss", namebuf, "rb");
184 Py_END_ALLOW_THREADS 193 if (binary != NULL)
185 if (0 <= fd) { 194 return binary;
186 return fd; 195 PyErr_Clear();
187 } 196 }
188 } 197 return NULL;
189 return -1;
190 } 198 }
191 199
192 int 200 int
193 _Py_DisplaySourceLine(PyObject *f, const char *filename, int lineno, int indent) 201 _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent)
194 { 202 {
195 int err = 0; 203 int err = 0;
196 int fd; 204 int fd;
197 int i; 205 int i;
198 char *found_encoding; 206 char *found_encoding;
199 char *encoding; 207 char *encoding;
208 PyObject *io;
209 PyObject *binary;
200 PyObject *fob = NULL; 210 PyObject *fob = NULL;
201 PyObject *lineobj = NULL; 211 PyObject *lineobj = NULL;
202 #ifdef O_BINARY
203 const int open_flags = O_RDONLY | O_BINARY; /* necessary for Windows */
204 #else
205 const int open_flags = O_RDONLY;
206 #endif
207 char buf[MAXPATHLEN+1]; 212 char buf[MAXPATHLEN+1];
208 Py_UNICODE *u, *p; 213 Py_UNICODE *u, *p;
209 Py_ssize_t len; 214 Py_ssize_t len;
210 215
211 /* open the file */ 216 /* open the file */
212 if (filename == NULL) 217 if (filename == NULL)
213 return 0; 218 return 0;
214 Py_BEGIN_ALLOW_THREADS 219
215 fd = open(filename, open_flags); 220 io = PyImport_ImportModuleNoBlock("io");
216 Py_END_ALLOW_THREADS 221 if (io == NULL)
217 if (fd < 0) { 222 return -1;
218 fd = _Py_FindSourceFile(filename, buf, sizeof(buf), open_flags); 223 binary = PyObject_CallMethod(io, "open", "Os", filename, "rb");
219 if (fd < 0) 224
225 if (binary == NULL) {
226 binary = _Py_FindSourceFile(filename, buf, sizeof(buf), io);
227 if (binary == NULL) {
228 Py_DECREF(io);
220 return 0; 229 return 0;
221 filename = buf; 230 }
222 } 231 }
223 232
224 /* use the right encoding to decode the file as unicode */ 233 /* use the right encoding to decode the file as unicode */
234 fd = PyObject_AsFileDescriptor(binary);
225 found_encoding = PyTokenizer_FindEncoding(fd); 235 found_encoding = PyTokenizer_FindEncoding(fd);
226 encoding = (found_encoding != NULL) ? found_encoding : 236 encoding = (found_encoding != NULL) ? found_encoding : "utf-8";
227 (char*)PyUnicode_GetDefaultEncoding();
228 lseek(fd, 0, 0); /* Reset position */ 237 lseek(fd, 0, 0); /* Reset position */
229 fob = PyFile_FromFd(fd, (char*)filename, "r", -1, (char*)encoding, 238 fob = PyObject_CallMethod(io, "TextIOWrapper", "Os", binary, encoding);
230 NULL, NULL, 1); 239 Py_DECREF(io);
240 Py_DECREF(binary);
231 PyMem_FREE(found_encoding); 241 PyMem_FREE(found_encoding);
242
232 if (fob == NULL) { 243 if (fob == NULL) {
233 PyErr_Clear(); 244 PyErr_Clear();
234 close(fd);
235 return 0; 245 return 0;
236 } 246 }
237 247
238 /* get the line number lineno */ 248 /* get the line number lineno */
239 for (i = 0; i < lineno; i++) { 249 for (i = 0; i < lineno; i++) {
286 err = PyFile_WriteString("\n", f); 296 err = PyFile_WriteString("\n", f);
287 return err; 297 return err;
288 } 298 }
289 299
290 static int 300 static int
291 tb_displayline(PyObject *f, const char *filename, int lineno, const char *name) 301 tb_displayline(PyObject *f, PyObject *filename, int lineno, PyObject *name)
292 { 302 {
293 int err = 0; 303 int err;
294 char linebuf[2000]; 304 PyObject *line;
295 305
296 if (filename == NULL || name == NULL) 306 if (filename == NULL || name == NULL)
297 return -1; 307 return -1;
298 /* This is needed by Emacs' compile command */ 308 line = PyUnicode_FromFormat(" File \"%U\", line %d, in %U\n",
299 #define FMT " File \"%.500s\", line %d, in %.500s\n" 309 filename, lineno, name);
300 PyOS_snprintf(linebuf, sizeof(linebuf), FMT, filename, lineno, name); 310 if (line == NULL)
301 err = PyFile_WriteString(linebuf, f); 311 return -1;
312 err = PyFile_WriteObject(line, f, Py_PRINT_RAW);
313 Py_DECREF(line);
302 if (err != 0) 314 if (err != 0)
303 return err; 315 return err;
304 return _Py_DisplaySourceLine(f, filename, lineno, 4); 316 return _Py_DisplaySourceLine(f, filename, lineno, 4);
305 } 317 }
306 318
315 tb1 = tb1->tb_next; 327 tb1 = tb1->tb_next;
316 } 328 }
317 while (tb != NULL && err == 0) { 329 while (tb != NULL && err == 0) {
318 if (depth <= limit) { 330 if (depth <= limit) {
319 err = tb_displayline(f, 331 err = tb_displayline(f,
320 _PyUnicode_AsString( 332 tb->tb_frame->f_code->co_filename,
321 tb->tb_frame->f_code->co_filename), 333 tb->tb_lineno,
322 tb->tb_lineno, 334 tb->tb_frame->f_code->co_name);
323 _PyUnicode_AsString(tb->tb_frame->f_code->co_name));
324 } 335 }
325 depth--; 336 depth--;
326 tb = tb->tb_next; 337 tb = tb->tb_next;
327 if (err == 0) 338 if (err == 0)
328 err = PyErr_CheckSignals(); 339 err = PyErr_CheckSignals();