---
 pyflakes/test/test_api.py |   72 +++++++++++++++++++---------------------------
 1 file changed, 30 insertions(+), 42 deletions(-)

Index: pyflakes-2.1.1/pyflakes/test/test_api.py
===================================================================
--- pyflakes-2.1.1.orig/pyflakes/test/test_api.py	2019-02-28 20:10:37.000000000 +0100
+++ pyflakes-2.1.1/pyflakes/test/test_api.py	2025-04-02 02:40:51.672106891 +0200
@@ -4,6 +4,7 @@
 
 import contextlib
 import os
+import re
 import sys
 import shutil
 import subprocess
@@ -351,8 +352,20 @@
         """
         err = StringIO()
         count = withStderrTo(err, checkPath, path)
-        self.assertEqual(
-            (count, err.getvalue()), (len(errorList), ''.join(errorList)))
+        self.assertEqual(count, len(errorList))
+        observed = err.getvalue()
+        for expected in errorList:
+            with self.subTest(expected=expected):
+                try:
+                    is_pattern = isinstance(expected, re.Pattern)
+                except AttributeError:
+                    is_pattern = isinstance(expected, re._pattern_type)
+                if is_pattern:
+                    self.assertTrue(expected.search(observed) is not None,
+                                    "observed string:\n%s\ndoesn't match pattern\n%s" %
+                                    (observed, expected.pattern))
+                else:
+                    self.assertEqual(expected, observed)
 
     def getErrors(self, path):
         """
@@ -392,6 +405,7 @@
             [('unexpectedError', 'extremo', 'No such file or directory')])
 
     def test_multilineSyntaxError(self):
+        self.maxDiff = None
         """
         Source which includes a syntax error which results in the raised
         L{SyntaxError.text} containing multiple lines of source are reported
@@ -408,33 +422,28 @@
     '''quux'''
 """
 
+        if PYPY:
+            message = 'EOF while scanning triple-quoted string literal'
+        elif sys.version_info[:2] < (3, 7):
+            message = 'invalid syntax'
+        else:
+            message = 'unterminated triple-quoted string literal'
+
         # Sanity check - SyntaxError.text should be multiple lines, if it
         # isn't, something this test was unprepared for has happened.
         def evaluate(source):
             exec(source)
         try:
             evaluate(source)
-        except SyntaxError:
-            e = sys.exc_info()[1]
-            if not PYPY:
-                self.assertTrue(e.text.count('\n') > 1)
+        except SyntaxError as e:
+            self.assertTrue(message in str(e))
         else:
             self.fail()
 
         with self.makeTempFile(source) as sourcePath:
-            if PYPY:
-                message = 'EOF while scanning triple-quoted string literal'
-            else:
-                message = 'invalid syntax'
-
-            column = 8 if sys.version_info >= (3, 8) else 11
             self.assertHasErrors(
                 sourcePath,
-                ["""\
-%s:8:%d: %s
-    '''quux'''
-%s^
-""" % (sourcePath, column, message, ' ' * (column - 1))])
+                [re.compile(r"%s:8:\d+: %s.*\n\s+'''quux'''" % (sourcePath, message))])
 
     def test_eofSyntaxError(self):
         """
@@ -442,18 +451,7 @@
         syntax error reflects the cause for the syntax error.
         """
         with self.makeTempFile("def foo(") as sourcePath:
-            if PYPY:
-                result = """\
-%s:1:7: parenthesis is never closed
-def foo(
-      ^
-""" % (sourcePath,)
-            else:
-                result = """\
-%s:1:9: unexpected EOF while parsing
-def foo(
-        ^
-""" % (sourcePath,)
+            result = re.compile(r"(never closed|unexpected EOF while parsing)", flags=re.MULTILINE)
 
             self.assertHasErrors(
                 sourcePath,
@@ -495,10 +493,7 @@
                 last_line = columnstr = ''
             self.assertHasErrors(
                 sourcePath,
-                ["""\
-%s:1:%s non-default argument follows default argument
-def foo(bar=baz, bax):
-%s""" % (sourcePath, columnstr, last_line)])
+                [re.compile("%s:1:\d+: non-default argument follows default argument\ndef foo\(bar=baz, bax\):" % (sourcePath,))])
 
     def test_nonKeywordAfterKeywordSyntaxError(self):
         """
@@ -524,10 +519,7 @@
 
             self.assertHasErrors(
                 sourcePath,
-                ["""\
-%s:1:%s %s
-foo(bar=baz, bax)
-%s""" % (sourcePath, columnstr, message, last_line)])
+                [re.compile(r"%s:1:\d+: %s\nfoo\(bar=baz, bax\)" % (sourcePath, message))])
 
     def test_invalidEscape(self):
         """
@@ -553,11 +545,7 @@
                 else:
                     last_line = ''
 
-                decoding_error = """\
-%s:1:%d: (unicode error) 'unicodeescape' codec can't decode bytes \
-in position 0-%d: truncated \\xXX escape
-foo = '\\xyz'
-%s""" % (sourcePath, column, position_end, last_line)
+                decoding_error = re.compile(r"%s:1:\d+: \(unicode error\) 'unicodeescape' codec can't decode bytes in position 0-%d: truncated \\xXX escape\nfoo = '\\xyz'" % (sourcePath, position_end))
 
             self.assertHasErrors(
                 sourcePath, [decoding_error])
