summaryrefslogtreecommitdiff
path: root/pyflakes/test/test_api.py
diff options
context:
space:
mode:
Diffstat (limited to 'pyflakes/test/test_api.py')
-rw-r--r--pyflakes/test/test_api.py215
1 files changed, 72 insertions, 143 deletions
diff --git a/pyflakes/test/test_api.py b/pyflakes/test/test_api.py
index 3d93591..d0795a0 100644
--- a/pyflakes/test/test_api.py
+++ b/pyflakes/test/test_api.py
@@ -3,6 +3,7 @@ Tests for L{pyflakes.scripts.pyflakes}.
"""
import contextlib
+import io
import os
import sys
import shutil
@@ -20,14 +21,6 @@ from pyflakes.api import (
)
from pyflakes.test.harness import TestCase, skipIf
-if sys.version_info < (3,):
- from cStringIO import StringIO
-else:
- from io import StringIO
- unichr = chr
-
-ERROR_HAS_COL_NUM = ERROR_HAS_LAST_LINE = sys.version_info >= (3, 2) or PYPY
-
def withStderrTo(stderr, f, *args, **kwargs):
"""
@@ -40,7 +33,7 @@ def withStderrTo(stderr, f, *args, **kwargs):
sys.stderr = outer
-class Node(object):
+class Node:
"""
Mock an AST node.
"""
@@ -49,32 +42,14 @@ class Node(object):
self.col_offset = col_offset
-class SysStreamCapturing(object):
-
- """
- Context manager capturing sys.stdin, sys.stdout and sys.stderr.
+class SysStreamCapturing:
+ """Context manager capturing sys.stdin, sys.stdout and sys.stderr.
The file handles are replaced with a StringIO object.
- On environments that support it, the StringIO object uses newlines
- set to os.linesep. Otherwise newlines are converted from \\n to
- os.linesep during __exit__.
"""
- def _create_StringIO(self, buffer=None):
- # Python 3 has a newline argument
- try:
- return StringIO(buffer, newline=os.linesep)
- except TypeError:
- self._newline = True
- # Python 2 creates an input only stream when buffer is not None
- if buffer is None:
- return StringIO()
- else:
- return StringIO(buffer)
-
def __init__(self, stdin):
- self._newline = False
- self._stdin = self._create_StringIO(stdin or '')
+ self._stdin = io.StringIO(stdin or '', newline=os.linesep)
def __enter__(self):
self._orig_stdin = sys.stdin
@@ -82,8 +57,8 @@ class SysStreamCapturing(object):
self._orig_stderr = sys.stderr
sys.stdin = self._stdin
- sys.stdout = self._stdout_stringio = self._create_StringIO()
- sys.stderr = self._stderr_stringio = self._create_StringIO()
+ sys.stdout = self._stdout_stringio = io.StringIO(newline=os.linesep)
+ sys.stderr = self._stderr_stringio = io.StringIO(newline=os.linesep)
return self
@@ -91,16 +66,12 @@ class SysStreamCapturing(object):
self.output = self._stdout_stringio.getvalue()
self.error = self._stderr_stringio.getvalue()
- if self._newline and os.linesep != '\n':
- self.output = self.output.replace('\n', os.linesep)
- self.error = self.error.replace('\n', os.linesep)
-
sys.stdin = self._orig_stdin
sys.stdout = self._orig_stdout
sys.stderr = self._orig_stderr
-class LoggingReporter(object):
+class LoggingReporter:
"""
Implementation of Reporter that just appends any error to a list.
"""
@@ -190,10 +161,6 @@ class TestIterSourceCode(TestCase):
with open(os.path.join(self.tempdir, 'c'), 'w') as fd:
fd.write('hello\nworld\n')
- python2 = os.path.join(self.tempdir, 'd')
- with open(python2, 'w') as fd:
- fd.write('#!/usr/bin/env python2\n')
-
python3 = os.path.join(self.tempdir, 'e')
with open(python3, 'w') as fd:
fd.write('#!/usr/bin/env python3\n')
@@ -206,10 +173,6 @@ class TestIterSourceCode(TestCase):
with open(python3args, 'w') as fd:
fd.write('#!/usr/bin/python3 -u\n')
- python2u = os.path.join(self.tempdir, 'h')
- with open(python2u, 'w') as fd:
- fd.write('#!/usr/bin/python2u\n')
-
python3d = os.path.join(self.tempdir, 'i')
with open(python3d, 'w') as fd:
fd.write('#!/usr/local/bin/python3d\n')
@@ -218,10 +181,6 @@ class TestIterSourceCode(TestCase):
with open(python38m, 'w') as fd:
fd.write('#! /usr/bin/env python3.8m\n')
- python27 = os.path.join(self.tempdir, 'k')
- with open(python27, 'w') as fd:
- fd.write('#!/usr/bin/python2.7 \n')
-
# Should NOT be treated as Python source
notfirst = os.path.join(self.tempdir, 'l')
with open(notfirst, 'w') as fd:
@@ -229,8 +188,10 @@ class TestIterSourceCode(TestCase):
self.assertEqual(
sorted(iterSourceCode([self.tempdir])),
- sorted([python, python2, python3, pythonw, python3args, python2u,
- python3d, python38m, python27]))
+ sorted([
+ python, python3, pythonw, python3args, python3d,
+ python38m,
+ ]))
def test_multipleDirectories(self):
"""
@@ -269,7 +230,7 @@ class TestReporter(TestCase):
number, error message, actual line of source and a caret pointing to
where the error is.
"""
- err = StringIO()
+ err = io.StringIO()
reporter = Reporter(None, err)
reporter.syntaxError('foo.py', 'a problem', 3,
8 if sys.version_info >= (3, 8) else 7,
@@ -285,7 +246,7 @@ class TestReporter(TestCase):
C{syntaxError} doesn't include a caret pointing to the error if
C{offset} is passed as C{None}.
"""
- err = StringIO()
+ err = io.StringIO()
reporter = Reporter(None, err)
reporter.syntaxError('foo.py', 'a problem', 3, None,
'bad line of source')
@@ -300,7 +261,7 @@ class TestReporter(TestCase):
line. The offset is adjusted so that it is relative to the start of
the last line.
"""
- err = StringIO()
+ err = io.StringIO()
lines = [
'bad line of source',
'more bad lines of source',
@@ -319,7 +280,7 @@ class TestReporter(TestCase):
"""
C{unexpectedError} reports an error processing a source file.
"""
- err = StringIO()
+ err = io.StringIO()
reporter = Reporter(None, err)
reporter.unexpectedError('source.py', 'error message')
self.assertEqual('source.py: error message\n', err.getvalue())
@@ -329,11 +290,11 @@ class TestReporter(TestCase):
C{flake} reports a code warning from Pyflakes. It is exactly the
str() of a L{pyflakes.messages.Message}.
"""
- out = StringIO()
+ out = io.StringIO()
reporter = Reporter(out, None)
message = UnusedImport('foo.py', Node(42), 'bar')
reporter.flake(message)
- self.assertEqual(out.getvalue(), "%s\n" % (message,))
+ self.assertEqual(out.getvalue(), f"{message}\n")
class CheckTests(TestCase):
@@ -363,7 +324,7 @@ class CheckTests(TestCase):
@param path: A path to a file to check.
@param errorList: A list of errors expected to be printed to stderr.
"""
- err = StringIO()
+ err = io.StringIO()
count = withStderrTo(err, checkPath, path)
self.assertEqual(
(count, err.getvalue()), (len(errorList), ''.join(errorList)))
@@ -496,10 +457,10 @@ def baz():
self.assertHasErrors(
sourcePath,
["""\
-%s:2:%s: invalid syntax
+{}:2:{}: invalid syntax
\tfoo =
-%s
-""" % (sourcePath, column, last_line)])
+{}
+""".format(sourcePath, column, last_line)])
def test_nonDefaultFollowsDefaultSyntaxError(self):
"""
@@ -512,27 +473,24 @@ def foo(bar=baz, bax):
pass
"""
with self.makeTempFile(source) as sourcePath:
- if ERROR_HAS_LAST_LINE:
- if PYPY:
- column = 7
- elif sys.version_info >= (3, 10):
- column = 18
- elif sys.version_info >= (3, 9):
- column = 21
- elif sys.version_info >= (3, 8):
- column = 9
- else:
- column = 8
- last_line = ' ' * (column - 1) + '^\n'
- columnstr = '%d:' % column
+ if PYPY:
+ column = 7
+ elif sys.version_info >= (3, 10):
+ column = 18
+ elif sys.version_info >= (3, 9):
+ column = 21
+ elif sys.version_info >= (3, 8):
+ column = 9
else:
- last_line = columnstr = ''
+ column = 8
+ last_line = ' ' * (column - 1) + '^\n'
+ columnstr = '%d:' % column
self.assertHasErrors(
sourcePath,
["""\
-%s:1:%s non-default argument follows default argument
+{}:1:{} non-default argument follows default argument
def foo(bar=baz, bax):
-%s""" % (sourcePath, columnstr, last_line)])
+{}""".format(sourcePath, columnstr, last_line)])
def test_nonKeywordAfterKeywordSyntaxError(self):
"""
@@ -544,59 +502,43 @@ def foo(bar=baz, bax):
foo(bar=baz, bax)
"""
with self.makeTempFile(source) as sourcePath:
- if ERROR_HAS_LAST_LINE:
- if PYPY:
- column = 12
- elif sys.version_info >= (3, 9):
- column = 17
- elif sys.version_info >= (3, 8):
- column = 14
- else:
- column = 13
- last_line = ' ' * (column - 1) + '^\n'
- columnstr = '%d:' % column
+ if PYPY:
+ column = 12
+ elif sys.version_info >= (3, 9):
+ column = 17
+ elif sys.version_info >= (3, 8):
+ column = 14
else:
- last_line = columnstr = ''
+ column = 13
+ last_line = ' ' * (column - 1) + '^\n'
+ columnstr = '%d:' % column
- if sys.version_info >= (3, 5):
- message = 'positional argument follows keyword argument'
- else:
- message = 'non-keyword arg after keyword arg'
+ message = 'positional argument follows keyword argument'
self.assertHasErrors(
sourcePath,
["""\
-%s:1:%s %s
+{}:1:{} {}
foo(bar=baz, bax)
-%s""" % (sourcePath, columnstr, message, last_line)])
+{}""".format(sourcePath, columnstr, message, last_line)])
def test_invalidEscape(self):
"""
The invalid escape syntax raises ValueError in Python 2
"""
- ver = sys.version_info
# ValueError: invalid \x escape
with self.makeTempFile(r"foo = '\xyz'") as sourcePath:
- if ver < (3,):
- decoding_error = "%s: problem decoding source\n" % (sourcePath,)
+ position_end = 1
+ if PYPY:
+ column = 5
+ elif sys.version_info >= (3, 9):
+ column = 13
else:
- position_end = 1
- if PYPY:
- column = 5
- elif ver >= (3, 9):
- column = 13
- else:
- column = 7
- # Column has been "fixed" since 3.2.4 and 3.3.1
- if ver < (3, 2, 4) or ver[:3] == (3, 3, 0):
- position_end = 2
-
- if ERROR_HAS_LAST_LINE:
- last_line = '%s^\n' % (' ' * (column - 1))
- else:
- last_line = ''
-
- decoding_error = """\
+ column = 7
+
+ last_line = '%s^\n' % (' ' * (column - 1))
+
+ decoding_error = """\
%s:1:%d: (unicode error) 'unicodeescape' codec can't decode bytes \
in position 0-%d: truncated \\xXX escape
foo = '\\xyz'
@@ -637,7 +579,7 @@ foo = '\\xyz'
"""
If source file declares the correct encoding, no error is reported.
"""
- SNOWMAN = unichr(0x2603)
+ SNOWMAN = chr(0x2603)
source = ("""\
# coding: utf-8
x = "%s"
@@ -657,40 +599,28 @@ x = "%s"
If a source file contains bytes which cannot be decoded, this is
reported on stderr.
"""
- SNOWMAN = unichr(0x2603)
+ SNOWMAN = chr(0x2603)
source = ("""\
# coding: ascii
x = "%s"
""" % SNOWMAN).encode('utf-8')
with self.makeTempFile(source) as sourcePath:
- if PYPY and sys.version_info < (3, ):
- message = ('\'ascii\' codec can\'t decode byte 0xe2 '
- 'in position 21: ordinal not in range(128)')
- result = """\
-%s:0:0: %s
-x = "\xe2\x98\x83"
- ^\n""" % (sourcePath, message)
-
- else:
- message = 'problem decoding source'
- result = "%s: problem decoding source\n" % (sourcePath,)
-
self.assertHasErrors(
- sourcePath, [result])
+ sourcePath, [f"{sourcePath}: problem decoding source\n"])
def test_misencodedFileUTF16(self):
"""
If a source file contains bytes which cannot be decoded, this is
reported on stderr.
"""
- SNOWMAN = unichr(0x2603)
+ SNOWMAN = chr(0x2603)
source = ("""\
# coding: ascii
x = "%s"
""" % SNOWMAN).encode('utf-16')
with self.makeTempFile(source) as sourcePath:
self.assertHasErrors(
- sourcePath, ["%s: problem decoding source\n" % (sourcePath,)])
+ sourcePath, [f"{sourcePath}: problem decoding source\n"])
def test_checkRecursive(self):
"""
@@ -702,10 +632,10 @@ x = "%s"
os.mkdir(os.path.join(tempdir, 'foo'))
file1 = os.path.join(tempdir, 'foo', 'bar.py')
with open(file1, 'wb') as fd:
- fd.write("import baz\n".encode('ascii'))
+ fd.write(b"import baz\n")
file2 = os.path.join(tempdir, 'baz.py')
with open(file2, 'wb') as fd:
- fd.write("import contraband".encode('ascii'))
+ fd.write(b"import contraband")
log = []
reporter = LoggingReporter(log)
warnings = checkRecursive([tempdir], reporter)
@@ -760,9 +690,8 @@ class IntegrationTests(TestCase):
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = p.communicate()
rv = p.wait()
- if sys.version_info >= (3,):
- stdout = stdout.decode('utf-8')
- stderr = stderr.decode('utf-8')
+ stdout = stdout.decode('utf-8')
+ stderr = stderr.decode('utf-8')
return (stdout, stderr, rv)
def test_goodFile(self):
@@ -780,10 +709,10 @@ class IntegrationTests(TestCase):
and the warnings are printed to stdout.
"""
with open(self.tempfilepath, 'wb') as fd:
- fd.write("import contraband\n".encode('ascii'))
+ fd.write(b"import contraband\n")
d = self.runPyflakes([self.tempfilepath])
expected = UnusedImport(self.tempfilepath, Node(1), 'contraband')
- self.assertEqual(d, ("%s%s" % (expected, os.linesep), '', 1))
+ self.assertEqual(d, (f"{expected}{os.linesep}", '', 1))
def test_errors_io(self):
"""
@@ -792,8 +721,8 @@ class IntegrationTests(TestCase):
printed to stderr.
"""
d = self.runPyflakes([self.tempfilepath])
- error_msg = '%s: No such file or directory%s' % (self.tempfilepath,
- os.linesep)
+ error_msg = '{}: No such file or directory{}'.format(self.tempfilepath,
+ os.linesep)
self.assertEqual(d, ('', error_msg, 1))
def test_errors_syntax(self):
@@ -803,7 +732,7 @@ class IntegrationTests(TestCase):
printed to stderr.
"""
with open(self.tempfilepath, 'wb') as fd:
- fd.write("import".encode('ascii'))
+ fd.write(b"import")
d = self.runPyflakes([self.tempfilepath])
error_msg = '{0}:1:{2}: invalid syntax{1}import{1} {3}^{1}'.format(
self.tempfilepath, os.linesep, 6 if PYPY else 7, '' if PYPY else ' ')
@@ -815,7 +744,7 @@ class IntegrationTests(TestCase):
"""
d = self.runPyflakes([], stdin='import contraband')
expected = UnusedImport('<stdin>', Node(1), 'contraband')
- self.assertEqual(d, ("%s%s" % (expected, os.linesep), '', 1))
+ self.assertEqual(d, (f"{expected}{os.linesep}", '', 1))
class TestMain(IntegrationTests):