mirror of
https://github.com/PyCQA/flake8.git
synced 2026-04-03 11:56:52 +00:00
Use the flake8 tool on the master branch
This commit is contained in:
parent
4f6d1eb6cc
commit
ed429af48c
9 changed files with 91 additions and 132 deletions
|
|
@ -10,6 +10,7 @@ import pep8
|
|||
|
||||
checker = __import__('flake8.checker').checker
|
||||
|
||||
|
||||
def check(codeString, filename):
|
||||
"""
|
||||
Check the Python source given by C{codeString} for flakes.
|
||||
|
|
@ -65,11 +66,13 @@ def check(codeString, filename):
|
|||
|
||||
return valid_warnings
|
||||
|
||||
|
||||
def _noqa(warning):
|
||||
# XXX quick dirty hack, just need to keep the line in the warning
|
||||
line = open(warning.filename).readlines()[warning.lineno-1]
|
||||
line = open(warning.filename).readlines()[warning.lineno - 1]
|
||||
return line.strip().lower().endswith('# noqa')
|
||||
|
||||
|
||||
def checkPath(filename):
|
||||
"""
|
||||
Check the given path, printing out any warnings detected.
|
||||
|
|
@ -105,5 +108,4 @@ def main():
|
|||
stdin = sys.stdin.read()
|
||||
warnings += check(stdin, '<stdin>')
|
||||
|
||||
|
||||
raise SystemExit(warnings > 0)
|
||||
|
|
|
|||
|
|
@ -14,10 +14,11 @@ try:
|
|||
import ast
|
||||
iter_child_nodes = ast.iter_child_nodes
|
||||
except (ImportError, AttributeError):
|
||||
|
||||
def iter_child_nodes(node, astcls=_ast.AST):
|
||||
"""
|
||||
Yield all direct child nodes of *node*, that is, all fields that are nodes
|
||||
and all items of fields that are lists of nodes.
|
||||
Yield all direct child nodes of *node*, that is, all fields that are
|
||||
nodes and all items of fields that are lists of nodes.
|
||||
"""
|
||||
for name in node._fields:
|
||||
field = getattr(node, name, None)
|
||||
|
|
@ -45,24 +46,21 @@ class Binding(object):
|
|||
self.source = source
|
||||
self.used = False
|
||||
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s object %r from line %r at 0x%x>' % (self.__class__.__name__,
|
||||
self.name,
|
||||
self.source.lineno,
|
||||
id(self))
|
||||
|
||||
return '<%s object %r from line %r at 0x%x>' % (
|
||||
self.__class__.__name__,
|
||||
self.name,
|
||||
self.source.lineno,
|
||||
id(self))
|
||||
|
||||
|
||||
class UnBinding(Binding):
|
||||
'''Created by the 'del' operator.'''
|
||||
|
||||
|
||||
|
||||
class Importation(Binding):
|
||||
"""
|
||||
A binding created by an import statement.
|
||||
|
|
@ -77,14 +75,12 @@ class Importation(Binding):
|
|||
super(Importation, self).__init__(name, source)
|
||||
|
||||
|
||||
|
||||
class Argument(Binding):
|
||||
"""
|
||||
Represents binding a name as an argument.
|
||||
"""
|
||||
|
||||
|
||||
|
||||
class Assignment(Binding):
|
||||
"""
|
||||
Represents binding a name with an explicit assignment.
|
||||
|
|
@ -95,12 +91,10 @@ class Assignment(Binding):
|
|||
"""
|
||||
|
||||
|
||||
|
||||
class FunctionDefinition(Binding):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class ExportBinding(Binding):
|
||||
"""
|
||||
A binding created by an C{__all__} assignment. If the names in the list
|
||||
|
|
@ -127,25 +121,22 @@ class ExportBinding(Binding):
|
|||
return names
|
||||
|
||||
|
||||
|
||||
class Scope(dict):
|
||||
importStarred = False # set to True when import * is found
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s at 0x%x %s>' % (self.__class__.__name__, id(self), dict.__repr__(self))
|
||||
|
||||
return '<%s at 0x%x %s>' % (self.__class__.__name__,
|
||||
id(self),
|
||||
dict.__repr__(self))
|
||||
|
||||
def __init__(self):
|
||||
super(Scope, self).__init__()
|
||||
|
||||
|
||||
|
||||
class ClassScope(Scope):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
class FunctionScope(Scope):
|
||||
"""
|
||||
I represent a name scope for a function.
|
||||
|
|
@ -157,7 +148,6 @@ class FunctionScope(Scope):
|
|||
self.globals = {}
|
||||
|
||||
|
||||
|
||||
class ModuleScope(Scope):
|
||||
pass
|
||||
|
||||
|
|
@ -166,7 +156,6 @@ class ModuleScope(Scope):
|
|||
_MAGIC_GLOBALS = ['__file__', '__builtins__']
|
||||
|
||||
|
||||
|
||||
class Checker(object):
|
||||
"""
|
||||
I check the cleanliness and sanity of Python code.
|
||||
|
|
@ -204,7 +193,6 @@ class Checker(object):
|
|||
self.popScope()
|
||||
self.check_dead_scopes()
|
||||
|
||||
|
||||
def deferFunction(self, callable):
|
||||
'''
|
||||
Schedule a function handler to be called just before completion.
|
||||
|
|
@ -216,7 +204,6 @@ class Checker(object):
|
|||
'''
|
||||
self._deferredFunctions.append((callable, self.scopeStack[:]))
|
||||
|
||||
|
||||
def deferAssignment(self, callable):
|
||||
"""
|
||||
Schedule an assignment handler to be called just after deferred
|
||||
|
|
@ -224,7 +211,6 @@ class Checker(object):
|
|||
"""
|
||||
self._deferredAssignments.append((callable, self.scopeStack[:]))
|
||||
|
||||
|
||||
def _runDeferred(self, deferred):
|
||||
"""
|
||||
Run the callables in C{deferred} using their associated scope stack.
|
||||
|
|
@ -233,7 +219,6 @@ class Checker(object):
|
|||
self.scopeStack = scope
|
||||
handler()
|
||||
|
||||
|
||||
def scope(self):
|
||||
return self.scopeStack[-1]
|
||||
scope = property(scope)
|
||||
|
|
@ -241,7 +226,6 @@ class Checker(object):
|
|||
def popScope(self):
|
||||
self.dead_scopes.append(self.scopeStack.pop())
|
||||
|
||||
|
||||
def check_dead_scopes(self):
|
||||
"""
|
||||
Look at scopes which have been fully examined and report names in them
|
||||
|
|
@ -271,7 +255,6 @@ class Checker(object):
|
|||
importation.source.lineno,
|
||||
importation.name)
|
||||
|
||||
|
||||
def pushFunctionScope(self):
|
||||
self.scopeStack.append(FunctionScope())
|
||||
|
||||
|
|
@ -352,18 +335,21 @@ class Checker(object):
|
|||
if (isinstance(self.scope.get(value.name), FunctionDefinition)
|
||||
and isinstance(value, FunctionDefinition)):
|
||||
self.report(messages.RedefinedFunction,
|
||||
lineno, value.name, self.scope[value.name].source.lineno)
|
||||
lineno, value.name,
|
||||
self.scope[value.name].source.lineno)
|
||||
|
||||
if not isinstance(self.scope, ClassScope):
|
||||
for scope in self.scopeStack[::-1]:
|
||||
existing = scope.get(value.name)
|
||||
if (isinstance(existing, Importation)
|
||||
and not existing.used
|
||||
and (not isinstance(value, Importation) or value.fullName == existing.fullName)
|
||||
and (not isinstance(value, Importation) \
|
||||
or value.fullName == existing.fullName)
|
||||
and reportRedef):
|
||||
|
||||
self.report(messages.RedefinedWhileUnused,
|
||||
lineno, value.name, scope[value.name].source.lineno)
|
||||
lineno, value.name,
|
||||
scope[value.name].source.lineno)
|
||||
|
||||
if isinstance(value, UnBinding):
|
||||
try:
|
||||
|
|
@ -400,6 +386,7 @@ class Checker(object):
|
|||
Process bindings for loop variables.
|
||||
"""
|
||||
vars = []
|
||||
|
||||
def collectLoopVars(n):
|
||||
if isinstance(n, _ast.Name):
|
||||
vars.append(n.id)
|
||||
|
|
@ -461,10 +448,14 @@ class Checker(object):
|
|||
# the special name __path__ is valid only in packages
|
||||
pass
|
||||
else:
|
||||
self.report(messages.UndefinedName, node.lineno, node.id)
|
||||
self.report(messages.UndefinedName,
|
||||
node.lineno,
|
||||
node.id)
|
||||
|
||||
elif isinstance(node.ctx, (_ast.Store, _ast.AugStore)):
|
||||
# if the name hasn't already been defined in the current scope
|
||||
if isinstance(self.scope, FunctionScope) and node.id not in self.scope:
|
||||
if isinstance(self.scope, FunctionScope) and \
|
||||
node.id not in self.scope:
|
||||
# for each function or module scope above us
|
||||
for scope in self.scopeStack[:-1]:
|
||||
if not isinstance(scope, (FunctionScope, ModuleScope)):
|
||||
|
|
@ -484,7 +475,10 @@ class Checker(object):
|
|||
break
|
||||
|
||||
if isinstance(node.parent,
|
||||
(_ast.For, _ast.comprehension, _ast.Tuple, _ast.List)):
|
||||
(_ast.For,
|
||||
_ast.comprehension,
|
||||
_ast.Tuple,
|
||||
_ast.List)):
|
||||
binding = Binding(node.id, node)
|
||||
elif (node.id == '__all__' and
|
||||
isinstance(self.scope, ModuleScope)):
|
||||
|
|
@ -501,12 +495,11 @@ class Checker(object):
|
|||
else:
|
||||
self.addBinding(node.lineno, UnBinding(node.id, node))
|
||||
else:
|
||||
# must be a Param context -- this only happens for names in function
|
||||
# arguments, but these aren't dispatched through here
|
||||
# must be a Param context -- this only happens for names
|
||||
# in function arguments, but these aren't dispatched through here
|
||||
raise RuntimeError(
|
||||
"Got impossible expression context: %r" % (node.ctx,))
|
||||
|
||||
|
||||
def FUNCTIONDEF(self, node):
|
||||
# the decorators attribute is called decorator_list as of Python 2.6
|
||||
if hasattr(node, 'decorators'):
|
||||
|
|
@ -543,7 +536,8 @@ class Checker(object):
|
|||
if node.args.kwarg:
|
||||
args.append(node.args.kwarg)
|
||||
for name in args:
|
||||
self.addBinding(node.lineno, Argument(name, node), reportRedef=False)
|
||||
self.addBinding(node.lineno, Argument(name, node),
|
||||
reportRedef=False)
|
||||
if isinstance(node.body, list):
|
||||
# case for FunctionDefs
|
||||
for stmt in node.body:
|
||||
|
|
@ -551,6 +545,7 @@ class Checker(object):
|
|||
else:
|
||||
# case for Lambdas
|
||||
self.handleNode(node.body, node)
|
||||
|
||||
def checkUnusedAssignments():
|
||||
"""
|
||||
Check to see if any assignments have not been used.
|
||||
|
|
@ -565,7 +560,6 @@ class Checker(object):
|
|||
|
||||
self.deferFunction(runFunction)
|
||||
|
||||
|
||||
def CLASSDEF(self, node):
|
||||
"""
|
||||
Check names used in a class definition, including its decorators, base
|
||||
|
|
@ -589,8 +583,9 @@ class Checker(object):
|
|||
self.handleNode(target, node)
|
||||
|
||||
def AUGASSIGN(self, node):
|
||||
# AugAssign is awkward: must set the context explicitly and visit twice,
|
||||
# once with AugLoad context, once with AugStore context
|
||||
# AugAssign is awkward: must set the context explicitly
|
||||
# and visit twice, once with AugLoad context, once with
|
||||
# AugStore context
|
||||
node.target.ctx = _ast.AugLoad()
|
||||
self.handleNode(node.target, node)
|
||||
self.handleNode(node.value, node)
|
||||
|
|
|
|||
|
|
@ -1,17 +1,22 @@
|
|||
# (c) 2005 Divmod, Inc. See LICENSE file for details
|
||||
|
||||
|
||||
class Message(object):
|
||||
message = ''
|
||||
message_args = ()
|
||||
|
||||
def __init__(self, filename, lineno):
|
||||
self.filename = filename
|
||||
self.lineno = lineno
|
||||
|
||||
def __str__(self):
|
||||
return '%s:%s: %s' % (self.filename, self.lineno, self.message % self.message_args)
|
||||
return '%s:%s: %s' % (self.filename, self.lineno,
|
||||
self.message % self.message_args)
|
||||
|
||||
|
||||
class UnusedImport(Message):
|
||||
message = '%r imported but unused'
|
||||
|
||||
def __init__(self, filename, lineno, name):
|
||||
Message.__init__(self, filename, lineno)
|
||||
self.message_args = (name,)
|
||||
|
|
@ -19,6 +24,7 @@ class UnusedImport(Message):
|
|||
|
||||
class RedefinedWhileUnused(Message):
|
||||
message = 'redefinition of unused %r from line %r'
|
||||
|
||||
def __init__(self, filename, lineno, name, orig_lineno):
|
||||
Message.__init__(self, filename, lineno)
|
||||
self.message_args = (name, orig_lineno)
|
||||
|
|
@ -26,6 +32,7 @@ class RedefinedWhileUnused(Message):
|
|||
|
||||
class ImportShadowedByLoopVar(Message):
|
||||
message = 'import %r from line %r shadowed by loop variable'
|
||||
|
||||
def __init__(self, filename, lineno, name, orig_lineno):
|
||||
Message.__init__(self, filename, lineno)
|
||||
self.message_args = (name, orig_lineno)
|
||||
|
|
@ -33,6 +40,7 @@ class ImportShadowedByLoopVar(Message):
|
|||
|
||||
class ImportStarUsed(Message):
|
||||
message = "'from %s import *' used; unable to detect undefined names"
|
||||
|
||||
def __init__(self, filename, lineno, modname):
|
||||
Message.__init__(self, filename, lineno)
|
||||
self.message_args = (modname,)
|
||||
|
|
@ -40,22 +48,24 @@ class ImportStarUsed(Message):
|
|||
|
||||
class UndefinedName(Message):
|
||||
message = 'undefined name %r'
|
||||
|
||||
def __init__(self, filename, lineno, name):
|
||||
Message.__init__(self, filename, lineno)
|
||||
self.message_args = (name,)
|
||||
|
||||
|
||||
|
||||
class UndefinedExport(Message):
|
||||
message = 'undefined name %r in __all__'
|
||||
|
||||
def __init__(self, filename, lineno, name):
|
||||
Message.__init__(self, filename, lineno)
|
||||
self.message_args = (name,)
|
||||
|
||||
|
||||
|
||||
class UndefinedLocal(Message):
|
||||
message = "local variable %r (defined in enclosing scope on line %r) referenced before assignment"
|
||||
message = "local variable %r (defined in enclosing scope on line %r) " \
|
||||
"referenced before assignment"
|
||||
|
||||
def __init__(self, filename, lineno, name, orig_lineno):
|
||||
Message.__init__(self, filename, lineno)
|
||||
self.message_args = (name, orig_lineno)
|
||||
|
|
@ -63,6 +73,7 @@ class UndefinedLocal(Message):
|
|||
|
||||
class DuplicateArgument(Message):
|
||||
message = 'duplicate argument %r in function definition'
|
||||
|
||||
def __init__(self, filename, lineno, name):
|
||||
Message.__init__(self, filename, lineno)
|
||||
self.message_args = (name,)
|
||||
|
|
@ -70,6 +81,7 @@ class DuplicateArgument(Message):
|
|||
|
||||
class RedefinedFunction(Message):
|
||||
message = 'redefinition of function %r from line %r'
|
||||
|
||||
def __init__(self, filename, lineno, name, orig_lineno):
|
||||
Message.__init__(self, filename, lineno)
|
||||
self.message_args = (name, orig_lineno)
|
||||
|
|
@ -77,6 +89,7 @@ class RedefinedFunction(Message):
|
|||
|
||||
class LateFutureImport(Message):
|
||||
message = 'future import(s) %r after other statements'
|
||||
|
||||
def __init__(self, filename, lineno, names):
|
||||
Message.__init__(self, filename, lineno)
|
||||
self.message_args = (names,)
|
||||
|
|
@ -89,6 +102,7 @@ class UnusedVariable(Message):
|
|||
"""
|
||||
|
||||
message = 'local variable %r is assigned to but never used'
|
||||
|
||||
def __init__(self, filename, lineno, names):
|
||||
Message.__init__(self, filename, lineno)
|
||||
self.message_args = (names,)
|
||||
|
|
|
|||
|
|
@ -985,6 +985,7 @@ def input_file(filename):
|
|||
message("%s: error %s not found" % (filename, code))
|
||||
return errors
|
||||
|
||||
|
||||
def input_dir(dirname):
|
||||
"""
|
||||
Check all Python source files in this directory and all subdirectories.
|
||||
|
|
|
|||
|
|
@ -23,5 +23,6 @@ for input:
|
|||
expected outputs:
|
||||
%s
|
||||
but got:
|
||||
%s''' % (input, repr(expectedOutputs), '\n'.join([str(o) for o in w.messages])))
|
||||
%s''' % (input, repr(expectedOutputs), '\n'.join(map(str, w.messages))))
|
||||
return w
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ from sys import version_info
|
|||
from pyflakes import messages as m
|
||||
from pyflakes.test import harness
|
||||
|
||||
|
||||
class Test(harness.Test):
|
||||
|
||||
def test_unusedImport(self):
|
||||
|
|
@ -11,8 +12,10 @@ class Test(harness.Test):
|
|||
self.flakes('from baz import fu, bar', m.UnusedImport, m.UnusedImport)
|
||||
|
||||
def test_aliasedImport(self):
|
||||
self.flakes('import fu as FU, bar as FU', m.RedefinedWhileUnused, m.UnusedImport)
|
||||
self.flakes('from moo import fu as FU, bar as FU', m.RedefinedWhileUnused, m.UnusedImport)
|
||||
self.flakes('import fu as FU, bar as FU',
|
||||
m.RedefinedWhileUnused, m.UnusedImport)
|
||||
self.flakes('from moo import fu as FU, bar as FU',
|
||||
m.RedefinedWhileUnused, m.UnusedImport)
|
||||
|
||||
def test_usedImport(self):
|
||||
self.flakes('import fu; print fu')
|
||||
|
|
@ -51,7 +54,6 @@ class Test(harness.Test):
|
|||
pass
|
||||
''', m.RedefinedWhileUnused)
|
||||
|
||||
|
||||
def test_redefinedBySubclass(self):
|
||||
"""
|
||||
If an imported name is redefined by a class statement which also uses
|
||||
|
|
@ -63,7 +65,6 @@ class Test(harness.Test):
|
|||
pass
|
||||
''')
|
||||
|
||||
|
||||
def test_redefinedInClass(self):
|
||||
"""
|
||||
Test that shadowing a global with a class attribute does not produce a
|
||||
|
|
@ -306,8 +307,8 @@ class Test(harness.Test):
|
|||
self.flakes('import fu; [1 for _ in range(1) if fu]')
|
||||
|
||||
def test_redefinedByListComp(self):
|
||||
self.flakes('import fu; [1 for fu in range(1)]', m.RedefinedWhileUnused)
|
||||
|
||||
self.flakes('import fu; [1 for fu in range(1)]',
|
||||
m.RedefinedWhileUnused)
|
||||
|
||||
def test_usedInTryFinally(self):
|
||||
self.flakes('''
|
||||
|
|
@ -390,7 +391,6 @@ class Test(harness.Test):
|
|||
def test_importStar(self):
|
||||
self.flakes('from fu import *', m.ImportStarUsed)
|
||||
|
||||
|
||||
def test_packageImport(self):
|
||||
"""
|
||||
If a dotted name is imported and used, no warning is reported.
|
||||
|
|
@ -400,7 +400,6 @@ class Test(harness.Test):
|
|||
fu.bar
|
||||
''')
|
||||
|
||||
|
||||
def test_unusedPackageImport(self):
|
||||
"""
|
||||
If a dotted name is imported and not used, an unused import warning is
|
||||
|
|
@ -408,7 +407,6 @@ class Test(harness.Test):
|
|||
"""
|
||||
self.flakes('import fu.bar', m.UnusedImport)
|
||||
|
||||
|
||||
def test_duplicateSubmoduleImport(self):
|
||||
"""
|
||||
If a submodule of a package is imported twice, an unused import warning
|
||||
|
|
@ -424,7 +422,6 @@ class Test(harness.Test):
|
|||
fu.bar
|
||||
''', m.RedefinedWhileUnused)
|
||||
|
||||
|
||||
def test_differentSubmoduleImport(self):
|
||||
"""
|
||||
If two different submodules of a package are imported, no duplicate
|
||||
|
|
@ -524,7 +521,6 @@ class Test(harness.Test):
|
|||
''', m.LateFutureImport)
|
||||
|
||||
|
||||
|
||||
class TestSpecialAll(harness.Test):
|
||||
"""
|
||||
Tests for suppression of unused import warnings by C{__all__}.
|
||||
|
|
@ -540,7 +536,6 @@ class TestSpecialAll(harness.Test):
|
|||
__all__ = ["bar"]
|
||||
''', m.UnusedImport, m.UnusedVariable)
|
||||
|
||||
|
||||
def test_ignoredInClass(self):
|
||||
"""
|
||||
An C{__all__} definition does not suppress unused import warnings in a
|
||||
|
|
@ -552,7 +547,6 @@ class TestSpecialAll(harness.Test):
|
|||
__all__ = ["bar"]
|
||||
''', m.UnusedImport)
|
||||
|
||||
|
||||
def test_warningSuppressed(self):
|
||||
"""
|
||||
If a name is imported and unused but is named in C{__all__}, no warning
|
||||
|
|
@ -563,7 +557,6 @@ class TestSpecialAll(harness.Test):
|
|||
__all__ = ["foo"]
|
||||
''')
|
||||
|
||||
|
||||
def test_unrecognizable(self):
|
||||
"""
|
||||
If C{__all__} is defined in a way that can't be recognized statically,
|
||||
|
|
@ -578,7 +571,6 @@ class TestSpecialAll(harness.Test):
|
|||
__all__ = [] + ["foo"]
|
||||
''', m.UnusedImport)
|
||||
|
||||
|
||||
def test_unboundExported(self):
|
||||
"""
|
||||
If C{__all__} includes a name which is not bound, a warning is emitted.
|
||||
|
|
@ -594,7 +586,6 @@ class TestSpecialAll(harness.Test):
|
|||
__all__ = ["foo"]
|
||||
''', filename=filename)
|
||||
|
||||
|
||||
def test_usedInGenExp(self):
|
||||
"""
|
||||
Using a global in a generator expression results in no warnings.
|
||||
|
|
@ -602,14 +593,13 @@ class TestSpecialAll(harness.Test):
|
|||
self.flakes('import fu; (fu for _ in range(1))')
|
||||
self.flakes('import fu; (1 for _ in range(1) if fu)')
|
||||
|
||||
|
||||
def test_redefinedByGenExp(self):
|
||||
"""
|
||||
Re-using a global name as the loop variable for a generator
|
||||
expression results in a redefinition warning.
|
||||
"""
|
||||
self.flakes('import fu; (1 for fu in range(1))', m.RedefinedWhileUnused)
|
||||
|
||||
self.flakes('import fu; (1 for fu in range(1))',
|
||||
m.RedefinedWhileUnused)
|
||||
|
||||
def test_usedAsDecorator(self):
|
||||
"""
|
||||
|
|
@ -645,7 +635,6 @@ class Python26Tests(harness.Test):
|
|||
if version_info < (2, 6):
|
||||
skip = "Python 2.6 required for class decorator tests."
|
||||
|
||||
|
||||
def test_usedAsClassDecorator(self):
|
||||
"""
|
||||
Using an imported name as a class decorator results in no warnings,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ class Test(harness.Test):
|
|||
a; a=1
|
||||
f()
|
||||
''', m.UndefinedName)
|
||||
test_localReferencedBeforeAssignment.todo = 'this requires finding all assignments in the function body first'
|
||||
test_localReferencedBeforeAssignment.todo = 'this requires finding all ' \
|
||||
'assignments in the function body first'
|
||||
|
||||
def test_redefinedFunction(self):
|
||||
"""
|
||||
|
|
@ -73,7 +74,6 @@ class Test(harness.Test):
|
|||
'''Don't die on unary +'''
|
||||
self.flakes('+1')
|
||||
|
||||
|
||||
def test_undefinedBaseClass(self):
|
||||
"""
|
||||
If a name in the base list of a class definition is undefined, a
|
||||
|
|
@ -84,7 +84,6 @@ class Test(harness.Test):
|
|||
pass
|
||||
''', m.UndefinedName)
|
||||
|
||||
|
||||
def test_classNameUndefinedInClassBody(self):
|
||||
"""
|
||||
If a class name is used in the body of that class's definition and
|
||||
|
|
@ -95,7 +94,6 @@ class Test(harness.Test):
|
|||
foo
|
||||
''', m.UndefinedName)
|
||||
|
||||
|
||||
def test_classNameDefinedPreviously(self):
|
||||
"""
|
||||
If a class name is used in the body of that class's definition and
|
||||
|
|
@ -108,7 +106,6 @@ class Test(harness.Test):
|
|||
foo
|
||||
''')
|
||||
|
||||
|
||||
def test_comparison(self):
|
||||
"""
|
||||
If a defined name is used on either side of any of the six comparison
|
||||
|
|
@ -125,7 +122,6 @@ class Test(harness.Test):
|
|||
x > y
|
||||
''')
|
||||
|
||||
|
||||
def test_identity(self):
|
||||
"""
|
||||
If a deefined name is used on either side of an identity test, no
|
||||
|
|
@ -138,7 +134,6 @@ class Test(harness.Test):
|
|||
x is not y
|
||||
''')
|
||||
|
||||
|
||||
def test_containment(self):
|
||||
"""
|
||||
If a defined name is used on either side of a containment test, no
|
||||
|
|
@ -151,7 +146,6 @@ class Test(harness.Test):
|
|||
x not in y
|
||||
''')
|
||||
|
||||
|
||||
def test_loopControl(self):
|
||||
"""
|
||||
break and continue statements are supported.
|
||||
|
|
@ -165,7 +159,6 @@ class Test(harness.Test):
|
|||
continue
|
||||
''')
|
||||
|
||||
|
||||
def test_ellipsis(self):
|
||||
"""
|
||||
Ellipsis in a slice is supported.
|
||||
|
|
@ -174,7 +167,6 @@ class Test(harness.Test):
|
|||
[1, 2][...]
|
||||
''')
|
||||
|
||||
|
||||
def test_extendedSlice(self):
|
||||
"""
|
||||
Extended slices are supported.
|
||||
|
|
@ -185,7 +177,6 @@ class Test(harness.Test):
|
|||
''')
|
||||
|
||||
|
||||
|
||||
class TestUnusedAssignment(harness.Test):
|
||||
"""
|
||||
Tests for warning about unused assignments.
|
||||
|
|
@ -201,7 +192,6 @@ class TestUnusedAssignment(harness.Test):
|
|||
b = 1
|
||||
''', m.UnusedVariable)
|
||||
|
||||
|
||||
def test_assignToGlobal(self):
|
||||
"""
|
||||
Assigning to a global and then not using that global is perfectly
|
||||
|
|
@ -214,7 +204,6 @@ class TestUnusedAssignment(harness.Test):
|
|||
b = 1
|
||||
''')
|
||||
|
||||
|
||||
def test_assignToMember(self):
|
||||
"""
|
||||
Assigning to a member of another object and then not using that member
|
||||
|
|
@ -230,7 +219,6 @@ class TestUnusedAssignment(harness.Test):
|
|||
b.foo = 1
|
||||
''')
|
||||
|
||||
|
||||
def test_assignInForLoop(self):
|
||||
"""
|
||||
Don't warn when a variable in a for loop is assigned to but not used.
|
||||
|
|
@ -241,7 +229,6 @@ class TestUnusedAssignment(harness.Test):
|
|||
pass
|
||||
''')
|
||||
|
||||
|
||||
def test_assignInListComprehension(self):
|
||||
"""
|
||||
Don't warn when a variable in a list comprehension is assigned to but
|
||||
|
|
@ -252,17 +239,16 @@ class TestUnusedAssignment(harness.Test):
|
|||
[None for i in range(10)]
|
||||
''')
|
||||
|
||||
|
||||
def test_generatorExpression(self):
|
||||
"""
|
||||
Don't warn when a variable in a generator expression is assigned to but not used.
|
||||
Don't warn when a variable in a generator expression is assigned to
|
||||
but not used.
|
||||
"""
|
||||
self.flakes('''
|
||||
def f():
|
||||
(None for i in range(10))
|
||||
''')
|
||||
|
||||
|
||||
def test_assignmentInsideLoop(self):
|
||||
"""
|
||||
Don't warn when a variable assignment occurs lexically after its use.
|
||||
|
|
@ -276,7 +262,6 @@ class TestUnusedAssignment(harness.Test):
|
|||
x = i * 2
|
||||
''')
|
||||
|
||||
|
||||
def test_tupleUnpacking(self):
|
||||
"""
|
||||
Don't warn when a variable included in tuple unpacking is unused. It's
|
||||
|
|
@ -288,7 +273,6 @@ class TestUnusedAssignment(harness.Test):
|
|||
(x, y) = 1, 2
|
||||
''')
|
||||
|
||||
|
||||
def test_listUnpacking(self):
|
||||
"""
|
||||
Don't warn when a variable included in list unpacking is unused.
|
||||
|
|
@ -298,7 +282,6 @@ class TestUnusedAssignment(harness.Test):
|
|||
[x, y] = [1, 2]
|
||||
''')
|
||||
|
||||
|
||||
def test_closedOver(self):
|
||||
"""
|
||||
Don't warn when the assignment is used in an inner function.
|
||||
|
|
@ -311,7 +294,6 @@ class TestUnusedAssignment(harness.Test):
|
|||
return bar
|
||||
''')
|
||||
|
||||
|
||||
def test_doubleClosedOver(self):
|
||||
"""
|
||||
Don't warn when the assignment is used in an inner function, even if
|
||||
|
|
@ -327,7 +309,6 @@ class TestUnusedAssignment(harness.Test):
|
|||
''')
|
||||
|
||||
|
||||
|
||||
class Python25Test(harness.Test):
|
||||
"""
|
||||
Tests for checking of syntax only available in Python 2.5 and newer.
|
||||
|
|
@ -343,7 +324,6 @@ class Python25Test(harness.Test):
|
|||
self.flakes("a = foo if True else 'oink'", m.UndefinedName)
|
||||
self.flakes("a = 'moo' if True else bar", m.UndefinedName)
|
||||
|
||||
|
||||
def test_withStatementNoNames(self):
|
||||
"""
|
||||
No warnings are emitted for using inside or after a nameless C{with}
|
||||
|
|
@ -369,7 +349,6 @@ class Python25Test(harness.Test):
|
|||
bar
|
||||
''')
|
||||
|
||||
|
||||
def test_withStatementAttributeName(self):
|
||||
"""
|
||||
No warnings are emitted for using an attribute as the target of a
|
||||
|
|
@ -382,7 +361,6 @@ class Python25Test(harness.Test):
|
|||
pass
|
||||
''')
|
||||
|
||||
|
||||
def test_withStatementSubscript(self):
|
||||
"""
|
||||
No warnings are emitted for using a subscript as the target of a
|
||||
|
|
@ -395,7 +373,6 @@ class Python25Test(harness.Test):
|
|||
pass
|
||||
''')
|
||||
|
||||
|
||||
def test_withStatementSubscriptUndefined(self):
|
||||
"""
|
||||
An undefined name warning is emitted if the subscript used as the
|
||||
|
|
@ -408,7 +385,6 @@ class Python25Test(harness.Test):
|
|||
pass
|
||||
''', m.UndefinedName)
|
||||
|
||||
|
||||
def test_withStatementTupleNames(self):
|
||||
"""
|
||||
No warnings are emitted for using any of the tuple of names defined by
|
||||
|
|
@ -421,7 +397,6 @@ class Python25Test(harness.Test):
|
|||
bar, baz
|
||||
''')
|
||||
|
||||
|
||||
def test_withStatementListNames(self):
|
||||
"""
|
||||
No warnings are emitted for using any of the list of names defined by a
|
||||
|
|
@ -434,7 +409,6 @@ class Python25Test(harness.Test):
|
|||
bar, baz
|
||||
''')
|
||||
|
||||
|
||||
def test_withStatementComplicatedTarget(self):
|
||||
"""
|
||||
If the target of a C{with} statement uses any or all of the valid forms
|
||||
|
|
@ -451,7 +425,6 @@ class Python25Test(harness.Test):
|
|||
a, b, c, d, e, g, h, i
|
||||
''')
|
||||
|
||||
|
||||
def test_withStatementSingleNameUndefined(self):
|
||||
"""
|
||||
An undefined name warning is emitted if the name first defined by a
|
||||
|
|
@ -464,7 +437,6 @@ class Python25Test(harness.Test):
|
|||
pass
|
||||
''', m.UndefinedName)
|
||||
|
||||
|
||||
def test_withStatementTupleNamesUndefined(self):
|
||||
"""
|
||||
An undefined name warning is emitted if a name first defined by a the
|
||||
|
|
@ -478,7 +450,6 @@ class Python25Test(harness.Test):
|
|||
pass
|
||||
''', m.UndefinedName)
|
||||
|
||||
|
||||
def test_withStatementSingleNameRedefined(self):
|
||||
"""
|
||||
A redefined name warning is emitted if a name bound by an import is
|
||||
|
|
@ -491,7 +462,6 @@ class Python25Test(harness.Test):
|
|||
pass
|
||||
''', m.RedefinedWhileUnused)
|
||||
|
||||
|
||||
def test_withStatementTupleNamesRedefined(self):
|
||||
"""
|
||||
A redefined name warning is emitted if a name bound by an import is
|
||||
|
|
@ -505,7 +475,6 @@ class Python25Test(harness.Test):
|
|||
pass
|
||||
''', m.RedefinedWhileUnused)
|
||||
|
||||
|
||||
def test_withStatementUndefinedInside(self):
|
||||
"""
|
||||
An undefined name warning is emitted if a name is used inside the
|
||||
|
|
@ -517,7 +486,6 @@ class Python25Test(harness.Test):
|
|||
baz
|
||||
''', m.UndefinedName)
|
||||
|
||||
|
||||
def test_withStatementNameDefinedInBody(self):
|
||||
"""
|
||||
A name defined in the body of a C{with} statement can be used after
|
||||
|
|
@ -530,7 +498,6 @@ class Python25Test(harness.Test):
|
|||
baz
|
||||
''')
|
||||
|
||||
|
||||
def test_withStatementUndefinedInExpression(self):
|
||||
"""
|
||||
An undefined name warning is emitted if a name in the I{test}
|
||||
|
|
@ -549,7 +516,6 @@ class Python25Test(harness.Test):
|
|||
''', m.UndefinedName)
|
||||
|
||||
|
||||
|
||||
class Python27Test(harness.Test):
|
||||
"""
|
||||
Tests for checking of syntax only available in Python 2.7 and newer.
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ 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}.
|
||||
|
|
@ -22,7 +23,6 @@ def withStderrTo(stderr, f):
|
|||
sys.stderr = outer
|
||||
|
||||
|
||||
|
||||
class CheckTests(TestCase):
|
||||
"""
|
||||
Tests for L{check} and L{checkPath} which check a file for flakes.
|
||||
|
|
@ -37,17 +37,16 @@ class CheckTests(TestCase):
|
|||
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(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
|
||||
|
|
@ -86,7 +85,6 @@ def baz():
|
|||
^
|
||||
""" % (sourcePath.path,))
|
||||
|
||||
|
||||
def test_eofSyntaxError(self):
|
||||
"""
|
||||
The error reported for source files which end prematurely causing a
|
||||
|
|
@ -106,7 +104,6 @@ def foo(
|
|||
^
|
||||
""" % (sourcePath.path,))
|
||||
|
||||
|
||||
def test_nonDefaultFollowsDefaultSyntaxError(self):
|
||||
"""
|
||||
Source which has a non-default argument following a default argument
|
||||
|
|
@ -129,7 +126,6 @@ def foo(bar=baz, bax):
|
|||
def foo(bar=baz, bax):
|
||||
""" % (sourcePath.path,))
|
||||
|
||||
|
||||
def test_nonKeywordAfterKeywordSyntaxError(self):
|
||||
"""
|
||||
Source which has a non-keyword argument after a keyword argument should
|
||||
|
|
@ -151,7 +147,6 @@ foo(bar=baz, bax)
|
|||
foo(bar=baz, bax)
|
||||
""" % (sourcePath.path,))
|
||||
|
||||
|
||||
def test_permissionDenied(self):
|
||||
"""
|
||||
If the a source file is not readable, this is reported on standard
|
||||
|
|
@ -166,7 +161,6 @@ foo(bar=baz, bax)
|
|||
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
|
||||
|
|
@ -182,4 +176,5 @@ x = "\N{SNOWMAN}"
|
|||
count = withStderrTo(err, lambda: checkPath(sourcePath.path))
|
||||
self.assertEquals(count, 1)
|
||||
self.assertEquals(
|
||||
err.getvalue(), "%s: problem decoding source\n" % (sourcePath.path,))
|
||||
err.getvalue(),
|
||||
"%s: problem decoding source\n" % (sourcePath.path,))
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ class Test(harness.Test):
|
|||
def test_definedInListComp(self):
|
||||
self.flakes('[a for a in range(10) if a]')
|
||||
|
||||
|
||||
def test_functionsNeedGlobalScope(self):
|
||||
self.flakes('''
|
||||
class a:
|
||||
|
|
@ -26,7 +25,6 @@ class Test(harness.Test):
|
|||
def test_builtins(self):
|
||||
self.flakes('range(10)')
|
||||
|
||||
|
||||
def test_magicGlobalsFile(self):
|
||||
"""
|
||||
Use of the C{__file__} magic global should not emit an undefined name
|
||||
|
|
@ -34,7 +32,6 @@ class Test(harness.Test):
|
|||
"""
|
||||
self.flakes('__file__')
|
||||
|
||||
|
||||
def test_magicGlobalsBuiltins(self):
|
||||
"""
|
||||
Use of the C{__builtins__} magic global should not emit an undefined
|
||||
|
|
@ -42,7 +39,6 @@ class Test(harness.Test):
|
|||
"""
|
||||
self.flakes('__builtins__')
|
||||
|
||||
|
||||
def test_magicGlobalsName(self):
|
||||
"""
|
||||
Use of the C{__name__} magic global should not emit an undefined name
|
||||
|
|
@ -50,7 +46,6 @@ class Test(harness.Test):
|
|||
"""
|
||||
self.flakes('__name__')
|
||||
|
||||
|
||||
def test_magicGlobalsPath(self):
|
||||
"""
|
||||
Use of the C{__path__} magic global should not emit an undefined name
|
||||
|
|
@ -59,13 +54,15 @@ class Test(harness.Test):
|
|||
self.flakes('__path__', m.UndefinedName)
|
||||
self.flakes('__path__', filename='package/__init__.py')
|
||||
|
||||
|
||||
def test_globalImportStar(self):
|
||||
'''Can't find undefined names with import *'''
|
||||
self.flakes('from fu import *; bar', m.ImportStarUsed)
|
||||
|
||||
def test_localImportStar(self):
|
||||
'''A local import * still allows undefined names to be found in upper scopes'''
|
||||
'''
|
||||
A local import * still allows undefined names to be found
|
||||
in upper scopes
|
||||
'''
|
||||
self.flakes('''
|
||||
def a():
|
||||
from fu import *
|
||||
|
|
@ -80,7 +77,10 @@ class Test(harness.Test):
|
|||
''')
|
||||
|
||||
def test_definedByGlobal(self):
|
||||
'''"global" can make an otherwise undefined name in another function defined'''
|
||||
'''
|
||||
"global" can make an otherwise undefined name
|
||||
in another function defined
|
||||
'''
|
||||
self.flakes('''
|
||||
def a(): global fu; fu = 1
|
||||
def b(): fu
|
||||
|
|
@ -153,13 +153,12 @@ class Test(harness.Test):
|
|||
return a
|
||||
''', m.UndefinedLocal)
|
||||
|
||||
|
||||
def test_intermediateClassScopeIgnored(self):
|
||||
"""
|
||||
If a name defined in an enclosing scope is shadowed by a local variable
|
||||
and the name is used locally before it is bound, an unbound local
|
||||
warning is emitted, even if there is a class scope between the enclosing
|
||||
scope and the local scope.
|
||||
warning is emitted, even if there is a class scope between
|
||||
the enclosing scope and the local scope.
|
||||
"""
|
||||
self.flakes('''
|
||||
def f():
|
||||
|
|
@ -172,7 +171,6 @@ class Test(harness.Test):
|
|||
print x
|
||||
''', m.UndefinedLocal)
|
||||
|
||||
|
||||
def test_doubleNestingReportsClosestName(self):
|
||||
"""
|
||||
Test that referencing a local name in a nested scope that shadows a
|
||||
|
|
@ -194,7 +192,6 @@ class Test(harness.Test):
|
|||
''', m.UndefinedLocal).messages[0]
|
||||
self.assertEqual(exc.message_args, ('x', 5))
|
||||
|
||||
|
||||
def test_laterRedefinedGlobalFromNestedScope3(self):
|
||||
"""
|
||||
Test that referencing a local name in a nested scope that shadows a
|
||||
|
|
@ -249,15 +246,14 @@ class Test(harness.Test):
|
|||
self.flakes('(a for a in xrange(10) if a)')
|
||||
|
||||
|
||||
|
||||
class NameTests(TestCase):
|
||||
"""
|
||||
Tests for some extra cases of name handling.
|
||||
"""
|
||||
def test_impossibleContext(self):
|
||||
"""
|
||||
A Name node with an unrecognized context results in a RuntimeError being
|
||||
raised.
|
||||
A Name node with an unrecognized context results in a RuntimeError
|
||||
being raised.
|
||||
"""
|
||||
tree = compile("x = 10", "<test>", "exec", PyCF_ONLY_AST)
|
||||
# Make it into something unrecognizable.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue