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

Skip to content

Commit 8b58339

Browse files
Issue #28512: Fixed setting the offset attribute of SyntaxError by
PyErr_SyntaxLocationEx() and PyErr_SyntaxLocationObject().
1 parent 49c14d8 commit 8b58339

7 files changed

Lines changed: 56 additions & 58 deletions

File tree

Lib/test/support/__init__.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,9 +1041,16 @@ def make_bad_fd():
10411041
file.close()
10421042
unlink(TESTFN)
10431043

1044-
def check_syntax_error(testcase, statement):
1045-
testcase.assertRaises(SyntaxError, compile, statement,
1046-
'<test string>', 'exec')
1044+
def check_syntax_error(testcase, statement, *, lineno=None, offset=None):
1045+
with testcase.assertRaises(SyntaxError) as cm:
1046+
compile(statement, '<test string>', 'exec')
1047+
err = cm.exception
1048+
testcase.assertIsNotNone(err.lineno)
1049+
if lineno is not None:
1050+
testcase.assertEqual(err.lineno, lineno)
1051+
testcase.assertIsNotNone(err.offset)
1052+
if offset is not None:
1053+
testcase.assertEqual(err.offset, offset)
10471054

10481055
def open_urlresource(url, *args, **kw):
10491056
import urllib.request, urllib.parse

Lib/test/test_future.py

Lines changed: 23 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import unittest
44
from test import support
5+
import os
56
import re
67

78
rx = re.compile('\((\S+).py, line (\d+)')
@@ -12,6 +13,12 @@ def get_error_location(msg):
1213

1314
class FutureTest(unittest.TestCase):
1415

16+
def check_syntax_error(self, err, basename, lineno, offset=0):
17+
self.assertIn('%s.py, line %d' % (basename, lineno), str(err))
18+
self.assertEqual(os.path.basename(err.filename), basename + '.py')
19+
self.assertEqual(err.lineno, lineno)
20+
self.assertEqual(err.offset, offset)
21+
1522
def test_future1(self):
1623
with support.CleanImport('future_test1'):
1724
from test import future_test1
@@ -27,68 +34,44 @@ def test_future3(self):
2734
from test import test_future3
2835

2936
def test_badfuture3(self):
30-
try:
37+
with self.assertRaises(SyntaxError) as cm:
3138
from test import badsyntax_future3
32-
except SyntaxError as msg:
33-
self.assertEqual(get_error_location(msg), ("badsyntax_future3", '3'))
34-
else:
35-
self.fail("expected exception didn't occur")
39+
self.check_syntax_error(cm.exception, "badsyntax_future3", 3)
3640

3741
def test_badfuture4(self):
38-
try:
42+
with self.assertRaises(SyntaxError) as cm:
3943
from test import badsyntax_future4
40-
except SyntaxError as msg:
41-
self.assertEqual(get_error_location(msg), ("badsyntax_future4", '3'))
42-
else:
43-
self.fail("expected exception didn't occur")
44+
self.check_syntax_error(cm.exception, "badsyntax_future4", 3)
4445

4546
def test_badfuture5(self):
46-
try:
47+
with self.assertRaises(SyntaxError) as cm:
4748
from test import badsyntax_future5
48-
except SyntaxError as msg:
49-
self.assertEqual(get_error_location(msg), ("badsyntax_future5", '4'))
50-
else:
51-
self.fail("expected exception didn't occur")
49+
self.check_syntax_error(cm.exception, "badsyntax_future5", 4)
5250

5351
def test_badfuture6(self):
54-
try:
52+
with self.assertRaises(SyntaxError) as cm:
5553
from test import badsyntax_future6
56-
except SyntaxError as msg:
57-
self.assertEqual(get_error_location(msg), ("badsyntax_future6", '3'))
58-
else:
59-
self.fail("expected exception didn't occur")
54+
self.check_syntax_error(cm.exception, "badsyntax_future6", 3)
6055

6156
def test_badfuture7(self):
62-
try:
57+
with self.assertRaises(SyntaxError) as cm:
6358
from test import badsyntax_future7
64-
except SyntaxError as msg:
65-
self.assertEqual(get_error_location(msg), ("badsyntax_future7", '3'))
66-
else:
67-
self.fail("expected exception didn't occur")
59+
self.check_syntax_error(cm.exception, "badsyntax_future7", 3, 53)
6860

6961
def test_badfuture8(self):
70-
try:
62+
with self.assertRaises(SyntaxError) as cm:
7163
from test import badsyntax_future8
72-
except SyntaxError as msg:
73-
self.assertEqual(get_error_location(msg), ("badsyntax_future8", '3'))
74-
else:
75-
self.fail("expected exception didn't occur")
64+
self.check_syntax_error(cm.exception, "badsyntax_future8", 3)
7665

7766
def test_badfuture9(self):
78-
try:
67+
with self.assertRaises(SyntaxError) as cm:
7968
from test import badsyntax_future9
80-
except SyntaxError as msg:
81-
self.assertEqual(get_error_location(msg), ("badsyntax_future9", '3'))
82-
else:
83-
self.fail("expected exception didn't occur")
69+
self.check_syntax_error(cm.exception, "badsyntax_future9", 3, 0)
8470

8571
def test_badfuture10(self):
86-
try:
72+
with self.assertRaises(SyntaxError) as cm:
8773
from test import badsyntax_future10
88-
except SyntaxError as msg:
89-
self.assertEqual(get_error_location(msg), ("badsyntax_future10", '3'))
90-
else:
91-
self.fail("expected exception didn't occur")
74+
self.check_syntax_error(cm.exception, "badsyntax_future10", 3, 0)
9275

9376
def test_parserhack(self):
9477
# test that the parser.c::future_hack function works as expected

Lib/test/test_support.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,10 @@ def test_make_bad_fd(self):
240240
self.assertEqual(cm.exception.errno, errno.EBADF)
241241

242242
def test_check_syntax_error(self):
243-
support.check_syntax_error(self, "def class")
243+
support.check_syntax_error(self, "def class", lineno=1, offset=9)
244244
self.assertRaises(AssertionError, support.check_syntax_error, self, "1")
245+
#with self.assertRaises(AssertionError):
246+
#support.check_syntax_error(self, "x=1")
245247

246248
def test_CleanImport(self):
247249
import importlib

Lib/test/test_symtable.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,15 +148,17 @@ def test_class_info(self):
148148
def test_filename_correct(self):
149149
### Bug tickler: SyntaxError file name correct whether error raised
150150
### while parsing or building symbol table.
151-
def checkfilename(brokencode):
151+
def checkfilename(brokencode, offset):
152152
try:
153153
symtable.symtable(brokencode, "spam", "exec")
154154
except SyntaxError as e:
155155
self.assertEqual(e.filename, "spam")
156+
self.assertEqual(e.lineno, 1)
157+
self.assertEqual(e.offset, offset)
156158
else:
157159
self.fail("no SyntaxError for %r" % (brokencode,))
158-
checkfilename("def f(x): foo)(") # parse-time
159-
checkfilename("def f(x): global x") # symtable-build-time
160+
checkfilename("def f(x): foo)(", 14) # parse-time
161+
checkfilename("def f(x): global x", 10) # symtable-build-time
160162
symtable.symtable("pass", b"spam", "exec")
161163
with self.assertRaises(TypeError):
162164
symtable.symtable("pass", bytearray(b"spam"), "exec")

Lib/test/test_syntax.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@
540540
class SyntaxTestCase(unittest.TestCase):
541541

542542
def _check_error(self, code, errtext,
543-
filename="<testcase>", mode="exec", subclass=None):
543+
filename="<testcase>", mode="exec", subclass=None, lineno=None, offset=None):
544544
"""Check that compiling code raises SyntaxError with errtext.
545545
546546
errtest is a regular expression that must be present in the
@@ -555,6 +555,11 @@ def _check_error(self, code, errtext,
555555
mo = re.search(errtext, str(err))
556556
if mo is None:
557557
self.fail("SyntaxError did not contain '%r'" % (errtext,))
558+
self.assertEqual(err.filename, filename)
559+
if lineno is not None:
560+
self.assertEqual(err.lineno, lineno)
561+
if offset is not None:
562+
self.assertEqual(err.offset, offset)
558563
else:
559564
self.fail("compile() did not raise SyntaxError")
560565

@@ -565,7 +570,7 @@ def test_assign_del(self):
565570
self._check_error("del f()", "delete")
566571

567572
def test_global_err_then_warn(self):
568-
# Bug tickler: The SyntaxError raised for one global statement
573+
# Bug #763201: The SyntaxError raised for one global statement
569574
# shouldn't be clobbered by a SyntaxWarning issued for a later one.
570575
source = """if 1:
571576
def error(a):
@@ -575,7 +580,7 @@ def warning():
575580
global b # SyntaxWarning
576581
"""
577582
warnings.filterwarnings(action='ignore', category=SyntaxWarning)
578-
self._check_error(source, "global")
583+
self._check_error(source, "global", lineno=3, offset=16)
579584
warnings.filters.pop(0)
580585

581586
def test_break_outside_loop(self):

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ Release date: TBA
1010
Core and Builtins
1111
-----------------
1212

13+
- Issue #28512: Fixed setting the offset attribute of SyntaxError by
14+
PyErr_SyntaxLocationEx() and PyErr_SyntaxLocationObject().
15+
1316
- Issue #5322: Fixed setting __new__ to a PyCFunction inside Python code.
1417
Original patch by Andreas Stührk.
1518

Python/errors.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,16 +1009,15 @@ PyErr_SyntaxLocationObject(PyObject *filename, int lineno, int col_offset)
10091009
PyErr_Clear();
10101010
Py_DECREF(tmp);
10111011
}
1012+
tmp = NULL;
10121013
if (col_offset >= 0) {
10131014
tmp = PyLong_FromLong(col_offset);
10141015
if (tmp == NULL)
10151016
PyErr_Clear();
1016-
else {
1017-
if (_PyObject_SetAttrId(v, &PyId_offset, tmp))
1018-
PyErr_Clear();
1019-
Py_DECREF(tmp);
1020-
}
10211017
}
1018+
if (_PyObject_SetAttrId(v, &PyId_offset, tmp ? tmp : Py_None))
1019+
PyErr_Clear();
1020+
Py_XDECREF(tmp);
10221021
if (filename != NULL) {
10231022
if (_PyObject_SetAttrId(v, &PyId_filename, filename))
10241023
PyErr_Clear();
@@ -1030,9 +1029,6 @@ PyErr_SyntaxLocationObject(PyObject *filename, int lineno, int col_offset)
10301029
Py_DECREF(tmp);
10311030
}
10321031
}
1033-
if (_PyObject_SetAttrId(v, &PyId_offset, Py_None)) {
1034-
PyErr_Clear();
1035-
}
10361032
if (exc != PyExc_SyntaxError) {
10371033
if (!_PyObject_HasAttrId(v, &PyId_msg)) {
10381034
tmp = PyObject_Str(v);

0 commit comments

Comments
 (0)