Index: Python/pythonrun.c =================================================================== --- Python/pythonrun.c (revision 85857) +++ Python/pythonrun.c (working copy) @@ -1342,27 +1342,36 @@ static void print_error_text(PyObject *f, int offset, const char *text) { + static const char* leading_whitespace = " "; char *nl; + if (offset >= 0) { - for (;;) { - nl = strchr(text, '\n'); - if (nl == NULL || nl-text >= offset) - break; - offset -= (int)(nl+1-text); - text = nl+1; - } + /* Remove any newline at the end of the string, if offset points there. */ + if (offset > 0 && offset == (int)strlen(text) && text[offset-1] == '\n') + offset--; + + /* Skip past any newlines, but not past offset. */ + nl = strrchr(text+offset, '\n'); + if (!(nl == NULL || nl-text >= offset)) { + offset -= (int)(nl+1-text); + text = nl+1; + } + + /* Skip any whitespace. */ while (*text == ' ' || *text == '\t') { text++; offset--; } } - PyFile_WriteString(" ", f); + PyFile_WriteString(leading_whitespace, f); PyFile_WriteString(text, f); if (*text == '\0' || text[strlen(text)-1] != '\n') PyFile_WriteString("\n", f); if (offset == -1) return; - PyFile_WriteString(" ", f); + + /* Point (with a caret) at the error. */ + PyFile_WriteString(leading_whitespace, f); while (--offset) PyFile_WriteString(" ", f); PyFile_WriteString("^\n", f); Index: Lib/test/test_traceback.py =================================================================== --- Lib/test/test_traceback.py (revision 85857) +++ Lib/test/test_traceback.py (working copy) @@ -296,7 +296,14 @@ msg = self.get_report(e).splitlines() self.assertEqual(msg[-2], " ^") + def test_syntax_error_offset_at_newline(self): + # See #10206 + def e(): + raise SyntaxError('', ('', 0, 2, "'\n")) + msg = self.get_report(e).splitlines() + self.assertEqual(msg[-2], " ^") + class PyExcReportingTests(BaseExceptionReportingTests, unittest.TestCase): # # This checks reporting through the 'traceback' module, with both