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

Skip to content

Commit 26817a8

Browse files
Issue #28512: Fixed setting the offset attribute of SyntaxError by
PyErr_SyntaxLocationEx() and PyErr_SyntaxLocationObject().
2 parents 2b27c2d + 8114f21 commit 26817a8

8 files changed

Lines changed: 56 additions & 60 deletions

File tree

Lib/test/support/__init__.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,9 +1060,16 @@ def make_bad_fd():
10601060
file.close()
10611061
unlink(TESTFN)
10621062

1063-
def check_syntax_error(testcase, statement):
1064-
testcase.assertRaises(SyntaxError, compile, statement,
1065-
'<test string>', 'exec')
1063+
def check_syntax_error(testcase, statement, *, lineno=None, offset=None):
1064+
with testcase.assertRaises(SyntaxError) as cm:
1065+
compile(statement, '<test string>', 'exec')
1066+
err = cm.exception
1067+
testcase.assertIsNotNone(err.lineno)
1068+
if lineno is not None:
1069+
testcase.assertEqual(err.lineno, lineno)
1070+
testcase.assertIsNotNone(err.offset)
1071+
if offset is not None:
1072+
testcase.assertEqual(err.offset, offset)
10661073

10671074
def open_urlresource(url, *args, **kw):
10681075
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(r'\((\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_global.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,15 @@ def wrong1():
2424
global a
2525
global b
2626
"""
27-
check_syntax_error(self, prog_text_1)
27+
check_syntax_error(self, prog_text_1, lineno=4, offset=4)
2828

2929
def test2(self):
3030
prog_text_2 = """\
3131
def wrong2():
3232
print(x)
3333
global x
3434
"""
35-
check_syntax_error(self, prog_text_2)
35+
check_syntax_error(self, prog_text_2, lineno=3, offset=4)
3636

3737
def test3(self):
3838
prog_text_3 = """\
@@ -41,7 +41,7 @@ def wrong3():
4141
x = 2
4242
global x
4343
"""
44-
check_syntax_error(self, prog_text_3)
44+
check_syntax_error(self, prog_text_3, lineno=4, offset=4)
4545

4646
def test4(self):
4747
prog_text_4 = """\

Lib/test/test_support.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ 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
with self.assertRaises(AssertionError):
245245
support.check_syntax_error(self, "x=1")
246246

Lib/test/test_symtable.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,15 +159,17 @@ def test_class_info(self):
159159
def test_filename_correct(self):
160160
### Bug tickler: SyntaxError file name correct whether error raised
161161
### while parsing or building symbol table.
162-
def checkfilename(brokencode):
162+
def checkfilename(brokencode, offset):
163163
try:
164164
symtable.symtable(brokencode, "spam", "exec")
165165
except SyntaxError as e:
166166
self.assertEqual(e.filename, "spam")
167+
self.assertEqual(e.lineno, 1)
168+
self.assertEqual(e.offset, offset)
167169
else:
168170
self.fail("no SyntaxError for %r" % (brokencode,))
169-
checkfilename("def f(x): foo)(") # parse-time
170-
checkfilename("def f(x): global x") # symtable-build-time
171+
checkfilename("def f(x): foo)(", 14) # parse-time
172+
checkfilename("def f(x): global x", 10) # symtable-build-time
171173
symtable.symtable("pass", b"spam", "exec")
172174
with self.assertWarns(DeprecationWarning), \
173175
self.assertRaises(TypeError):

Lib/test/test_syntax.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@
548548
class SyntaxTestCase(unittest.TestCase):
549549

550550
def _check_error(self, code, errtext,
551-
filename="<testcase>", mode="exec", subclass=None):
551+
filename="<testcase>", mode="exec", subclass=None, lineno=None, offset=None):
552552
"""Check that compiling code raises SyntaxError with errtext.
553553
554554
errtest is a regular expression that must be present in the
@@ -563,6 +563,11 @@ def _check_error(self, code, errtext,
563563
mo = re.search(errtext, str(err))
564564
if mo is None:
565565
self.fail("SyntaxError did not contain '%r'" % (errtext,))
566+
self.assertEqual(err.filename, filename)
567+
if lineno is not None:
568+
self.assertEqual(err.lineno, lineno)
569+
if offset is not None:
570+
self.assertEqual(err.offset, offset)
566571
else:
567572
self.fail("compile() did not raise SyntaxError")
568573

@@ -573,7 +578,7 @@ def test_assign_del(self):
573578
self._check_error("del f()", "delete")
574579

575580
def test_global_err_then_warn(self):
576-
# Bug tickler: The SyntaxError raised for one global statement
581+
# Bug #763201: The SyntaxError raised for one global statement
577582
# shouldn't be clobbered by a SyntaxWarning issued for a later one.
578583
source = """if 1:
579584
def error(a):

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ What's New in Python 3.7.0 alpha 1
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 #28918: Fix the cross compilation of xxlimited when Python has been
1417
built with Py_DEBUG defined.
1518

Python/errors.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1053,16 +1053,15 @@ PyErr_SyntaxLocationObject(PyObject *filename, int lineno, int col_offset)
10531053
PyErr_Clear();
10541054
Py_DECREF(tmp);
10551055
}
1056+
tmp = NULL;
10561057
if (col_offset >= 0) {
10571058
tmp = PyLong_FromLong(col_offset);
10581059
if (tmp == NULL)
10591060
PyErr_Clear();
1060-
else {
1061-
if (_PyObject_SetAttrId(v, &PyId_offset, tmp))
1062-
PyErr_Clear();
1063-
Py_DECREF(tmp);
1064-
}
10651061
}
1062+
if (_PyObject_SetAttrId(v, &PyId_offset, tmp ? tmp : Py_None))
1063+
PyErr_Clear();
1064+
Py_XDECREF(tmp);
10661065
if (filename != NULL) {
10671066
if (_PyObject_SetAttrId(v, &PyId_filename, filename))
10681067
PyErr_Clear();
@@ -1074,9 +1073,6 @@ PyErr_SyntaxLocationObject(PyObject *filename, int lineno, int col_offset)
10741073
Py_DECREF(tmp);
10751074
}
10761075
}
1077-
if (_PyObject_SetAttrId(v, &PyId_offset, Py_None)) {
1078-
PyErr_Clear();
1079-
}
10801076
if (exc != PyExc_SyntaxError) {
10811077
if (!_PyObject_HasAttrId(v, &PyId_msg)) {
10821078
tmp = PyObject_Str(v);

0 commit comments

Comments
 (0)