bpo-40176: Improve error messages for unclosed string literals (GH-19346)



Automerge-Triggered-By: GH:isidentical
diff --git a/Lib/test/test_eof.py b/Lib/test/test_eof.py
index 2cf263d..b370e27 100644
--- a/Lib/test/test_eof.py
+++ b/Lib/test/test_eof.py
@@ -7,23 +7,25 @@
 import unittest
 
 class EOFTestCase(unittest.TestCase):
-    def test_EOFC(self):
-        expect = "EOL while scanning string literal (<string>, line 1)"
-        try:
-            eval("""'this is a test\
-            """)
-        except SyntaxError as msg:
-            self.assertEqual(str(msg), expect)
-        else:
-            raise support.TestFailed
+    def test_EOF_single_quote(self):
+        expect = "unterminated string literal (detected at line 1) (<string>, line 1)"
+        for quote in ("'", "\""):
+            try:
+                eval(f"""{quote}this is a test\
+                """)
+            except SyntaxError as msg:
+                self.assertEqual(str(msg), expect)
+                self.assertEqual(msg.offset, 1)
+            else:
+                raise support.TestFailed
 
     def test_EOFS(self):
-        expect = ("EOF while scanning triple-quoted string literal "
-                  "(<string>, line 1)")
+        expect = ("unterminated triple-quoted string literal (detected at line 1) (<string>, line 1)")
         try:
             eval("""'''this is a test""")
         except SyntaxError as msg:
             self.assertEqual(str(msg), expect)
+            self.assertEqual(msg.offset, 1)
         else:
             raise support.TestFailed
 
diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py
index eb70d7b..21878c3 100644
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -206,7 +206,7 @@ def testSyntaxErrorOffset(self):
         check(b'# -*- coding: cp1251 -*-\nPython = "\xcf\xb3\xf2\xee\xed" +',
               2, 19, encoding='cp1251')
         check(b'Python = "\xcf\xb3\xf2\xee\xed" +', 1, 18)
-        check('x = "a', 1, 7)
+        check('x = "a', 1, 5)
         check('lambda x: x = 2', 1, 1)
         check('f{a + b + c}', 1, 2)
         check('[file for str(file) in []\n])', 1, 11)
@@ -238,7 +238,7 @@ def bar():
 
             def baz():
                 '''quux'''
-            """, 9, 20)
+            """, 9, 24)
         check("pass\npass\npass\n(1+)\npass\npass\npass", 4, 4)
         check("(1+)", 1, 4)
 
diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py
index 2345832..7ca1512 100644
--- a/Lib/test/test_fstring.py
+++ b/Lib/test/test_fstring.py
@@ -661,7 +661,7 @@ def test_parens_in_expressions(self):
                             ["f'{3)+(4}'",
                              ])
 
-        self.assertAllRaise(SyntaxError, 'EOL while scanning string literal',
+        self.assertAllRaise(SyntaxError, 'unterminated string literal',
                             ["f'{\n}'",
                              ])