186 lines
5.2 KiB
Python
186 lines
5.2 KiB
Python
|
|
"""
|
|
Tests for L{pyflakes.scripts.pyflakes}.
|
|
"""
|
|
|
|
import sys
|
|
from StringIO import StringIO
|
|
|
|
from twisted.python.filepath import FilePath
|
|
from twisted.trial.unittest import TestCase
|
|
|
|
from pyflakes.scripts.pyflakes import checkPath
|
|
|
|
def withStderrTo(stderr, f):
|
|
"""
|
|
Call C{f} with C{sys.stderr} redirected to C{stderr}.
|
|
"""
|
|
(outer, sys.stderr) = (sys.stderr, stderr)
|
|
try:
|
|
return f()
|
|
finally:
|
|
sys.stderr = outer
|
|
|
|
|
|
|
|
class CheckTests(TestCase):
|
|
"""
|
|
Tests for L{check} and L{checkPath} which check a file for flakes.
|
|
"""
|
|
def test_missingTrailingNewline(self):
|
|
"""
|
|
Source which doesn't end with a newline shouldn't cause any
|
|
exception to be raised nor an error indicator to be returned by
|
|
L{check}.
|
|
"""
|
|
fName = self.mktemp()
|
|
FilePath(fName).setContent("def foo():\n\tpass\n\t")
|
|
self.assertFalse(checkPath(fName))
|
|
|
|
|
|
def test_checkPathNonExisting(self):
|
|
"""
|
|
L{checkPath} handles non-existing files.
|
|
"""
|
|
err = StringIO()
|
|
count = withStderrTo(err, lambda: checkPath('extremo'))
|
|
self.assertEquals(err.getvalue(), 'extremo: No such file or directory\n')
|
|
self.assertEquals(count, 1)
|
|
|
|
|
|
def test_multilineSyntaxError(self):
|
|
"""
|
|
Source which includes a syntax error which results in the raised
|
|
L{SyntaxError.text} containing multiple lines of source are reported
|
|
with only the last line of that source.
|
|
"""
|
|
source = """\
|
|
def foo():
|
|
'''
|
|
|
|
def bar():
|
|
pass
|
|
|
|
def baz():
|
|
'''quux'''
|
|
"""
|
|
|
|
# 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
|
|
exc = self.assertRaises(SyntaxError, evaluate, source)
|
|
self.assertTrue(exc.text.count('\n') > 1)
|
|
|
|
sourcePath = FilePath(self.mktemp())
|
|
sourcePath.setContent(source)
|
|
err = StringIO()
|
|
count = withStderrTo(err, lambda: checkPath(sourcePath.path))
|
|
self.assertEqual(count, 1)
|
|
|
|
self.assertEqual(
|
|
err.getvalue(),
|
|
"""\
|
|
%s:8: invalid syntax
|
|
'''quux'''
|
|
^
|
|
""" % (sourcePath.path,))
|
|
|
|
|
|
def test_eofSyntaxError(self):
|
|
"""
|
|
The error reported for source files which end prematurely causing a
|
|
syntax error reflects the cause for the syntax error.
|
|
"""
|
|
source = "def foo("
|
|
sourcePath = FilePath(self.mktemp())
|
|
sourcePath.setContent(source)
|
|
err = StringIO()
|
|
count = withStderrTo(err, lambda: checkPath(sourcePath.path))
|
|
self.assertEqual(count, 1)
|
|
self.assertEqual(
|
|
err.getvalue(),
|
|
"""\
|
|
%s:1: unexpected EOF while parsing
|
|
def foo(
|
|
^
|
|
""" % (sourcePath.path,))
|
|
|
|
|
|
def test_nonDefaultFollowsDefaultSyntaxError(self):
|
|
"""
|
|
Source which has a non-default argument following a default argument
|
|
should include the line number of the syntax error. However these
|
|
exceptions do not include an offset.
|
|
"""
|
|
source = """\
|
|
def foo(bar=baz, bax):
|
|
pass
|
|
"""
|
|
sourcePath = FilePath(self.mktemp())
|
|
sourcePath.setContent(source)
|
|
err = StringIO()
|
|
count = withStderrTo(err, lambda: checkPath(sourcePath.path))
|
|
self.assertEqual(count, 1)
|
|
self.assertEqual(
|
|
err.getvalue(),
|
|
"""\
|
|
%s:1: non-default argument follows default argument
|
|
def foo(bar=baz, bax):
|
|
""" % (sourcePath.path,))
|
|
|
|
|
|
def test_nonKeywordAfterKeywordSyntaxError(self):
|
|
"""
|
|
Source which has a non-keyword argument after a keyword argument should
|
|
include the line number of the syntax error. However these exceptions
|
|
do not include an offset.
|
|
"""
|
|
source = """\
|
|
foo(bar=baz, bax)
|
|
"""
|
|
sourcePath = FilePath(self.mktemp())
|
|
sourcePath.setContent(source)
|
|
err = StringIO()
|
|
count = withStderrTo(err, lambda: checkPath(sourcePath.path))
|
|
self.assertEqual(count, 1)
|
|
self.assertEqual(
|
|
err.getvalue(),
|
|
"""\
|
|
%s:1: non-keyword arg after keyword arg
|
|
foo(bar=baz, bax)
|
|
""" % (sourcePath.path,))
|
|
|
|
|
|
def test_permissionDenied(self):
|
|
"""
|
|
If the a source file is not readable, this is reported on standard
|
|
error.
|
|
"""
|
|
sourcePath = FilePath(self.mktemp())
|
|
sourcePath.setContent('')
|
|
sourcePath.chmod(0)
|
|
err = StringIO()
|
|
count = withStderrTo(err, lambda: checkPath(sourcePath.path))
|
|
self.assertEquals(count, 1)
|
|
self.assertEquals(
|
|
err.getvalue(), "%s: Permission denied\n" % (sourcePath.path,))
|
|
|
|
|
|
def test_misencodedFile(self):
|
|
"""
|
|
If a source file contains bytes which cannot be decoded, this is
|
|
reported on stderr.
|
|
"""
|
|
source = u"""\
|
|
# coding: ascii
|
|
x = "\N{SNOWMAN}"
|
|
""".encode('utf-8')
|
|
sourcePath = FilePath(self.mktemp())
|
|
sourcePath.setContent(source)
|
|
err = StringIO()
|
|
count = withStderrTo(err, lambda: checkPath(sourcePath.path))
|
|
self.assertEquals(count, 1)
|
|
self.assertEquals(
|
|
err.getvalue(), "%s: problem decoding source\n" % (sourcePath.path,))
|