Index: Parser/tokenizer.c =================================================================== --- Parser/tokenizer.c (révision 66831) +++ Parser/tokenizer.c (copie de travail) @@ -461,6 +461,14 @@ readline = PyObject_GetAttrString(stream, "readline"); tok->decoding_readline = readline; + /* The file has been reopened; parsing will restart from + * the beginning of the file, we have to reset the line number. + * But this function has been called from inside tok_nextc() which + * will increment lineno before it returns. So we set it -1 so that + * the next call to tok_nextc() will start with tok->lineno == 0. + */ + tok->lineno = -1; + cleanup: Py_XDECREF(stream); Py_XDECREF(io); Index: Lib/test/test_traceback.py =================================================================== --- Lib/test/test_traceback.py (révision 66831) +++ Lib/test/test_traceback.py (copie de travail) @@ -90,6 +90,40 @@ err = traceback.format_exception_only(None, None) self.assertEqual(err, ['None\n']) + def test_lineno(self): + import tempfile, sys, subprocess, os + def do_test(firstlines, message, charset, lineno): + handle, path = tempfile.mkstemp() + output = open(handle, "w", encoding=charset) + output.write("""{0}import sys, traceback +raise RuntimeError("{1}") +""".format(firstlines, message)) + output.close() + process = subprocess.Popen([sys.executable, path], + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + stdout, stderr = process.communicate() + os.remove(path) + message_ascii = str(message.encode('ASCII', 'backslashreplace'), 'ASCII') + err_line = 'raise RuntimeError("{0}")'.format(message_ascii) + err_msg = 'RuntimeError: {0}'.format(message_ascii) + stdout = str(stdout, "UTF-8") + stdout = stdout.splitlines() + self.assert_(("line %s" % lineno) in stdout[1], + "Invalid line number: {0!r} instead of {1}".format(stdout[1], lineno)) + self.assert_(stdout[2].endswith(err_line), + "Invalid traceback line: {0!r} instead of {1!r}".format(stdout[2], err_line)) + self.assert_(stdout[3] == err_msg, + "Invalid error message: {0!r} instead of {1!r}".format(stdout[3], err_msg)) + do_test("", "foo", "ascii", 2) + for charset in ("ascii", "iso-8859-1", "utf-8", "GBK"): + if charset == "ascii": + text = "foo" + elif charset == "GBK": + text = "\u4E02\u5100" + else: + text = "h\xe9 ho" + do_test("# coding: {0}\n".format(charset), text, charset, 3) + do_test("#!shebang\n# coding: {0}\n".format(charset), text, charset, 4) class TracebackFormatTests(unittest.TestCase):