Index: Python/traceback.c =================================================================== --- Python/traceback.c (révision 66831) +++ Python/traceback.c (copie de travail) @@ -8,9 +8,15 @@ #include "structmember.h" #include "osdefs.h" #include "traceback.h" +#ifdef HAVE_FCNTL_H +#include +#endif #define OFF(x) offsetof(PyTracebackObject, x) +/* Method from Parser/tokenizer.c */ +extern char * PyTokenizer_FindEncoding(int); + static PyObject * tb_dir(PyTracebackObject *self) { @@ -132,15 +138,25 @@ _Py_DisplaySourceLine(PyObject *f, const char *filename, int lineno, int indent) { int err = 0; - FILE *xfp = NULL; - char linebuf[2000]; + int fd; int i; char namebuf[MAXPATHLEN+1]; + char *found_encoding; + char *encoding; + PyObject *fob = NULL; + PyObject *lineobj = NULL; +#ifdef O_BINARY + const int open_flags = O_RDONLY | O_BINARY; /* necessary for Windows */ +#else + const int open_flags = O_RDONLY; +#endif if (filename == NULL) - return -1; - xfp = fopen(filename, "r" PY_STDIOTEXTMODE); - if (xfp == NULL) { + return 0; + Py_BEGIN_ALLOW_THREADS + fd = open(filename, open_flags); + Py_END_ALLOW_THREADS + if (fd < 0 ) { /* Search tail of filename in sys.path before giving up */ PyObject *path; const char *tail = strrchr(filename, SEP); @@ -170,8 +186,10 @@ if (len > 0 && namebuf[len-1] != SEP) namebuf[len++] = SEP; strcpy(namebuf+len, tail); - xfp = fopen(namebuf, "r" PY_STDIOTEXTMODE); - if (xfp != NULL) { + Py_BEGIN_ALLOW_THREADS + fd = open(filename, open_flags); + Py_END_ALLOW_THREADS + if (0 <= fd) { filename = namebuf; break; } @@ -179,32 +197,49 @@ } } } - - if (xfp == NULL) - return err; - if (err != 0) { - fclose(xfp); - return err; + if (fd < 0) + return 0; + found_encoding = PyTokenizer_FindEncoding(fd); + encoding = (found_encoding != NULL) ? found_encoding : + (char*)PyUnicode_GetDefaultEncoding(); + lseek(fd, 0, 0); /* Reset position */ + fob = PyFile_FromFd(fd, (char*)filename, "r", -1, + (char*)encoding, NULL, NULL, 1); + if (fob == NULL) { + PyErr_Clear(); + close(fd); + PyMem_FREE(found_encoding); + return 0; } for (i = 0; i < lineno; i++) { - char* pLastChar = &linebuf[sizeof(linebuf)-2]; - do { - *pLastChar = '\0'; - if (Py_UniversalNewlineFgets(linebuf, sizeof linebuf, xfp, NULL) == NULL) + Py_XDECREF(lineobj); + lineobj = PyFile_GetLine(fob, -1); + if (!lineobj) { + err = -1; break; - /* fgets read *something*; if it didn't get as - far as pLastChar, it must have found a newline - or hit the end of the file; if pLastChar is \n, - it obviously found a newline; else we haven't - yet seen a newline, so must continue */ - } while (*pLastChar != '\0' && *pLastChar != '\n'); } - if (i == lineno) { + } + if (lineobj) { char buf[11]; - char *p = linebuf; - while (*p == ' ' || *p == '\t' || *p == '\014') + + Py_UNICODE *u = PyUnicode_AS_UNICODE(lineobj); + Py_ssize_t len = PyUnicode_GET_SIZE(lineobj); + Py_UNICODE *p = u; + + while (*p == ' ' || *p == '\t' || *p == '\014') { p++; + len--; + } + + if (u != p) { + PyObject *truncated; + truncated = PyUnicode_FromUnicode(p, len); + if (truncated) { + Py_DECREF(lineobj); + lineobj = truncated; + } + } /* Write some spaces before the line */ strcpy(buf, " "); @@ -219,11 +254,13 @@ } if (err == 0) - err = PyFile_WriteString(p, f); - if (err == 0 && strchr(p, '\n') == NULL) + err = PyFile_WriteObject(lineobj, f, Py_PRINT_RAW); + Py_DECREF(lineobj); + if (err == 0) err = PyFile_WriteString("\n", f); } - fclose(xfp); + Py_DECREF(fob); + PyMem_FREE(found_encoding); return err; }