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