Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2bd59da

Browse files
Issue #2382: SyntaxError cursor "^" now is written at correct position in most
cases when multibyte characters are in line (before "^"). This still not works correctly with wide East Asian characters.
2 parents 567b26e + 65fd059 commit 2bd59da

4 files changed

Lines changed: 38 additions & 2 deletions

File tree

Lib/test/test_exceptions.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,19 @@ def ckmsg(src, msg):
148148
ckmsg(s, "'continue' not properly in loop")
149149
ckmsg("continue\n", "'continue' not properly in loop")
150150

151+
def testSyntaxErrorOffset(self):
152+
def check(src, lineno, offset):
153+
with self.assertRaises(SyntaxError) as cm:
154+
compile(src, '<fragment>', 'exec')
155+
self.assertEqual(cm.exception.lineno, lineno)
156+
self.assertEqual(cm.exception.offset, offset)
157+
158+
check('def fact(x):\n\treturn x!\n', 2, 10)
159+
check('1 +\n', 1, 4)
160+
check('def spam():\n print(1)\n print(2)', 3, 10)
161+
check('Python = "Python" +', 1, 20)
162+
check('Python = "\u1e54\xfd\u0163\u0125\xf2\xf1" +', 1, 20)
163+
151164
@cpython_only
152165
def testSettingException(self):
153166
# test that setting an exception at the C level works even if the

Lib/test/test_traceback.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ def syntax_error_with_caret_2(self):
3232
def syntax_error_bad_indentation(self):
3333
compile("def spam():\n print(1)\n print(2)", "?", "exec")
3434

35+
def syntax_error_with_caret_non_ascii(self):
36+
compile('Python = "\u1e54\xfd\u0163\u0125\xf2\xf1" +', "?", "exec")
37+
3538
def test_caret(self):
3639
err = self.get_exception_format(self.syntax_error_with_caret,
3740
SyntaxError)
@@ -46,6 +49,12 @@ def test_caret(self):
4649
self.assertTrue(err[2].count('\n') == 1) # and no additional newline
4750
self.assertTrue(err[1].find("+") == err[2].find("^")) # in the right place
4851

52+
err = self.get_exception_format(self.syntax_error_with_caret_non_ascii,
53+
SyntaxError)
54+
self.assertIn("^", err[2]) # third line has caret
55+
self.assertTrue(err[2].count('\n') == 1) # and no additional newline
56+
self.assertTrue(err[1].find("+") == err[2].find("^")) # in the right place
57+
4958
def test_nocaret(self):
5059
exc = SyntaxError("error", ("x.py", 23, None, "bad syntax"))
5160
err = traceback.format_exception_only(SyntaxError, exc)

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ Release date: 2014-01-19
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #2382: SyntaxError cursor "^" is now written at correct position in most
14+
cases when multibyte characters are in line (before "^"). This still not
15+
works correctly with wide East Asian characters.
16+
1317
- Issue #18960: The first line of Python script could be executed twice when
1418
the source encoding was specified on the second line. Now the source encoding
1519
declaration on the second line isn't effective if the first line contains

Python/pythonrun.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2470,6 +2470,7 @@ err_input(perrdetail *err)
24702470
PyObject *v, *w, *errtype, *errtext;
24712471
PyObject *msg_obj = NULL;
24722472
char *msg = NULL;
2473+
int offset = err->offset;
24732474

24742475
errtype = PyExc_SyntaxError;
24752476
switch (err->error) {
@@ -2554,11 +2555,20 @@ err_input(perrdetail *err)
25542555
errtext = Py_None;
25552556
Py_INCREF(Py_None);
25562557
} else {
2557-
errtext = PyUnicode_DecodeUTF8(err->text, strlen(err->text),
2558+
errtext = PyUnicode_DecodeUTF8(err->text, err->offset,
25582559
"replace");
2560+
if (errtext != NULL) {
2561+
Py_ssize_t len = strlen(err->text);
2562+
offset = (int)PyUnicode_GET_LENGTH(errtext);
2563+
if (len != err->offset) {
2564+
Py_DECREF(errtext);
2565+
errtext = PyUnicode_DecodeUTF8(err->text, len,
2566+
"replace");
2567+
}
2568+
}
25592569
}
25602570
v = Py_BuildValue("(OiiN)", err->filename,
2561-
err->lineno, err->offset, errtext);
2571+
err->lineno, offset, errtext);
25622572
if (v != NULL) {
25632573
if (msg_obj)
25642574
w = Py_BuildValue("(OO)", msg_obj, v);

0 commit comments

Comments
 (0)