Adding new stuff
This commit is contained in:
parent
3d621f7993
commit
91c18a10da
449 changed files with 2 additions and 1 deletions
|
|
@ -0,0 +1 @@
|
|||
__version__ = '0.9.2'
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
from pyflakes.api import main
|
||||
|
||||
# python -m pyflakes (with Python >= 2.7)
|
||||
if __name__ == '__main__':
|
||||
main(prog='pyflakes')
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
175
vim-plugins/bundle/python-mode/pymode/libs/pyflakes/api.py
Normal file
175
vim-plugins/bundle/python-mode/pymode/libs/pyflakes/api.py
Normal file
|
|
@ -0,0 +1,175 @@
|
|||
"""
|
||||
API for the command-line I{pyflakes} tool.
|
||||
"""
|
||||
from __future__ import with_statement
|
||||
|
||||
import sys
|
||||
import os
|
||||
import _ast
|
||||
|
||||
from pyflakes import checker, __version__
|
||||
from pyflakes import reporter as modReporter
|
||||
|
||||
__all__ = ['check', 'checkPath', 'checkRecursive', 'iterSourceCode', 'main']
|
||||
|
||||
|
||||
def check(codeString, filename, reporter=None):
|
||||
"""
|
||||
Check the Python source given by C{codeString} for flakes.
|
||||
|
||||
@param codeString: The Python source to check.
|
||||
@type codeString: C{str}
|
||||
|
||||
@param filename: The name of the file the source came from, used to report
|
||||
errors.
|
||||
@type filename: C{str}
|
||||
|
||||
@param reporter: A L{Reporter} instance, where errors and warnings will be
|
||||
reported.
|
||||
|
||||
@return: The number of warnings emitted.
|
||||
@rtype: C{int}
|
||||
"""
|
||||
if reporter is None:
|
||||
reporter = modReporter._makeDefaultReporter()
|
||||
# First, compile into an AST and handle syntax errors.
|
||||
try:
|
||||
tree = compile(codeString, filename, "exec", _ast.PyCF_ONLY_AST)
|
||||
except SyntaxError:
|
||||
value = sys.exc_info()[1]
|
||||
msg = value.args[0]
|
||||
|
||||
(lineno, offset, text) = value.lineno, value.offset, value.text
|
||||
|
||||
# If there's an encoding problem with the file, the text is None.
|
||||
if text is None:
|
||||
# Avoid using msg, since for the only known case, it contains a
|
||||
# bogus message that claims the encoding the file declared was
|
||||
# unknown.
|
||||
reporter.unexpectedError(filename, 'problem decoding source')
|
||||
else:
|
||||
reporter.syntaxError(filename, msg, lineno, offset, text)
|
||||
return 1
|
||||
except Exception:
|
||||
reporter.unexpectedError(filename, 'problem decoding source')
|
||||
return 1
|
||||
# Okay, it's syntactically valid. Now check it.
|
||||
w = checker.Checker(tree, filename)
|
||||
w.messages.sort(key=lambda m: m.lineno)
|
||||
for warning in w.messages:
|
||||
reporter.flake(warning)
|
||||
return len(w.messages)
|
||||
|
||||
|
||||
def checkPath(filename, reporter=None):
|
||||
"""
|
||||
Check the given path, printing out any warnings detected.
|
||||
|
||||
@param reporter: A L{Reporter} instance, where errors and warnings will be
|
||||
reported.
|
||||
|
||||
@return: the number of warnings printed
|
||||
"""
|
||||
if reporter is None:
|
||||
reporter = modReporter._makeDefaultReporter()
|
||||
try:
|
||||
# in Python 2.6, compile() will choke on \r\n line endings. In later
|
||||
# versions of python it's smarter, and we want binary mode to give
|
||||
# compile() the best opportunity to do the right thing WRT text
|
||||
# encodings.
|
||||
if sys.version_info < (2, 7):
|
||||
mode = 'rU'
|
||||
else:
|
||||
mode = 'rb'
|
||||
|
||||
with open(filename, mode) as f:
|
||||
codestr = f.read()
|
||||
if sys.version_info < (2, 7):
|
||||
codestr += '\n' # Work around for Python <= 2.6
|
||||
except UnicodeError:
|
||||
reporter.unexpectedError(filename, 'problem decoding source')
|
||||
return 1
|
||||
except IOError:
|
||||
msg = sys.exc_info()[1]
|
||||
reporter.unexpectedError(filename, msg.args[1])
|
||||
return 1
|
||||
return check(codestr, filename, reporter)
|
||||
|
||||
|
||||
def iterSourceCode(paths):
|
||||
"""
|
||||
Iterate over all Python source files in C{paths}.
|
||||
|
||||
@param paths: A list of paths. Directories will be recursed into and
|
||||
any .py files found will be yielded. Any non-directories will be
|
||||
yielded as-is.
|
||||
"""
|
||||
for path in paths:
|
||||
if os.path.isdir(path):
|
||||
for dirpath, dirnames, filenames in os.walk(path):
|
||||
for filename in filenames:
|
||||
if filename.endswith('.py'):
|
||||
yield os.path.join(dirpath, filename)
|
||||
else:
|
||||
yield path
|
||||
|
||||
|
||||
def checkRecursive(paths, reporter):
|
||||
"""
|
||||
Recursively check all source files in C{paths}.
|
||||
|
||||
@param paths: A list of paths to Python source files and directories
|
||||
containing Python source files.
|
||||
@param reporter: A L{Reporter} where all of the warnings and errors
|
||||
will be reported to.
|
||||
@return: The number of warnings found.
|
||||
"""
|
||||
warnings = 0
|
||||
for sourcePath in iterSourceCode(paths):
|
||||
warnings += checkPath(sourcePath, reporter)
|
||||
return warnings
|
||||
|
||||
|
||||
def _exitOnSignal(sigName, message):
|
||||
"""Handles a signal with sys.exit.
|
||||
|
||||
Some of these signals (SIGPIPE, for example) don't exist or are invalid on
|
||||
Windows. So, ignore errors that might arise.
|
||||
"""
|
||||
import signal
|
||||
|
||||
try:
|
||||
sigNumber = getattr(signal, sigName)
|
||||
except AttributeError:
|
||||
# the signal constants defined in the signal module are defined by
|
||||
# whether the C library supports them or not. So, SIGPIPE might not
|
||||
# even be defined.
|
||||
return
|
||||
|
||||
def handler(sig, f):
|
||||
sys.exit(message)
|
||||
|
||||
try:
|
||||
signal.signal(sigNumber, handler)
|
||||
except ValueError:
|
||||
# It's also possible the signal is defined, but then it's invalid. In
|
||||
# this case, signal.signal raises ValueError.
|
||||
pass
|
||||
|
||||
|
||||
def main(prog=None):
|
||||
"""Entry point for the script "pyflakes"."""
|
||||
import optparse
|
||||
|
||||
# Handle "Keyboard Interrupt" and "Broken pipe" gracefully
|
||||
_exitOnSignal('SIGINT', '... stopped')
|
||||
_exitOnSignal('SIGPIPE', 1)
|
||||
|
||||
parser = optparse.OptionParser(prog=prog, version=__version__)
|
||||
(__, args) = parser.parse_args()
|
||||
reporter = modReporter._makeDefaultReporter()
|
||||
if args:
|
||||
warnings = checkRecursive(args, reporter)
|
||||
else:
|
||||
warnings = check(sys.stdin.read(), '<stdin>', reporter)
|
||||
raise SystemExit(warnings > 0)
|
||||
925
vim-plugins/bundle/python-mode/pymode/libs/pyflakes/checker.py
Normal file
925
vim-plugins/bundle/python-mode/pymode/libs/pyflakes/checker.py
Normal file
|
|
@ -0,0 +1,925 @@
|
|||
"""
|
||||
Main module.
|
||||
|
||||
Implement the central Checker class.
|
||||
Also, it models the Bindings and Scopes.
|
||||
"""
|
||||
import doctest
|
||||
import os
|
||||
import sys
|
||||
|
||||
PY2 = sys.version_info < (3, 0)
|
||||
PY32 = sys.version_info < (3, 3) # Python 2.5 to 3.2
|
||||
PY33 = sys.version_info < (3, 4) # Python 2.5 to 3.3
|
||||
builtin_vars = dir(__import__('__builtin__' if PY2 else 'builtins'))
|
||||
|
||||
try:
|
||||
import ast
|
||||
except ImportError: # Python 2.5
|
||||
import _ast as ast
|
||||
|
||||
if 'decorator_list' not in ast.ClassDef._fields:
|
||||
# Patch the missing attribute 'decorator_list'
|
||||
ast.ClassDef.decorator_list = ()
|
||||
ast.FunctionDef.decorator_list = property(lambda s: s.decorators)
|
||||
|
||||
from pyflakes import messages
|
||||
|
||||
|
||||
if PY2:
|
||||
def getNodeType(node_class):
|
||||
# workaround str.upper() which is locale-dependent
|
||||
return str(unicode(node_class.__name__).upper())
|
||||
else:
|
||||
def getNodeType(node_class):
|
||||
return node_class.__name__.upper()
|
||||
|
||||
# Python >= 3.3 uses ast.Try instead of (ast.TryExcept + ast.TryFinally)
|
||||
if PY32:
|
||||
def getAlternatives(n):
|
||||
if isinstance(n, (ast.If, ast.TryFinally)):
|
||||
return [n.body]
|
||||
if isinstance(n, ast.TryExcept):
|
||||
return [n.body + n.orelse] + [[hdl] for hdl in n.handlers]
|
||||
else:
|
||||
def getAlternatives(n):
|
||||
if isinstance(n, ast.If):
|
||||
return [n.body]
|
||||
if isinstance(n, ast.Try):
|
||||
return [n.body + n.orelse] + [[hdl] for hdl in n.handlers]
|
||||
|
||||
|
||||
class _FieldsOrder(dict):
|
||||
"""Fix order of AST node fields."""
|
||||
|
||||
def _get_fields(self, node_class):
|
||||
# handle iter before target, and generators before element
|
||||
fields = node_class._fields
|
||||
if 'iter' in fields:
|
||||
key_first = 'iter'.find
|
||||
elif 'generators' in fields:
|
||||
key_first = 'generators'.find
|
||||
else:
|
||||
key_first = 'value'.find
|
||||
return tuple(sorted(fields, key=key_first, reverse=True))
|
||||
|
||||
def __missing__(self, node_class):
|
||||
self[node_class] = fields = self._get_fields(node_class)
|
||||
return fields
|
||||
|
||||
|
||||
def iter_child_nodes(node, omit=None, _fields_order=_FieldsOrder()):
|
||||
"""
|
||||
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 _fields_order[node.__class__]:
|
||||
if name == omit:
|
||||
continue
|
||||
field = getattr(node, name, None)
|
||||
if isinstance(field, ast.AST):
|
||||
yield field
|
||||
elif isinstance(field, list):
|
||||
for item in field:
|
||||
yield item
|
||||
|
||||
|
||||
class Binding(object):
|
||||
"""
|
||||
Represents the binding of a value to a name.
|
||||
|
||||
The checker uses this to keep track of which names have been bound and
|
||||
which names have not. See L{Assignment} for a special type of binding that
|
||||
is checked with stricter rules.
|
||||
|
||||
@ivar used: pair of (L{Scope}, line-number) indicating the scope and
|
||||
line number that this binding was last used
|
||||
"""
|
||||
|
||||
def __init__(self, name, source):
|
||||
self.name = name
|
||||
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))
|
||||
|
||||
def redefines(self, other):
|
||||
return isinstance(other, Definition) and self.name == other.name
|
||||
|
||||
|
||||
class Definition(Binding):
|
||||
"""
|
||||
A binding that defines a function or a class.
|
||||
"""
|
||||
|
||||
|
||||
class Importation(Definition):
|
||||
"""
|
||||
A binding created by an import statement.
|
||||
|
||||
@ivar fullName: The complete name given to the import statement,
|
||||
possibly including multiple dotted components.
|
||||
@type fullName: C{str}
|
||||
"""
|
||||
|
||||
def __init__(self, name, source):
|
||||
self.fullName = name
|
||||
self.redefined = []
|
||||
name = name.split('.')[0]
|
||||
super(Importation, self).__init__(name, source)
|
||||
|
||||
def redefines(self, other):
|
||||
if isinstance(other, Importation):
|
||||
return self.fullName == other.fullName
|
||||
return isinstance(other, Definition) and self.name == other.name
|
||||
|
||||
|
||||
class Argument(Binding):
|
||||
"""
|
||||
Represents binding a name as an argument.
|
||||
"""
|
||||
|
||||
|
||||
class Assignment(Binding):
|
||||
"""
|
||||
Represents binding a name with an explicit assignment.
|
||||
|
||||
The checker will raise warnings for any Assignment that isn't used. Also,
|
||||
the checker does not consider assignments in tuple/list unpacking to be
|
||||
Assignments, rather it treats them as simple Bindings.
|
||||
"""
|
||||
|
||||
|
||||
class FunctionDefinition(Definition):
|
||||
pass
|
||||
|
||||
|
||||
class ClassDefinition(Definition):
|
||||
pass
|
||||
|
||||
|
||||
class ExportBinding(Binding):
|
||||
"""
|
||||
A binding created by an C{__all__} assignment. If the names in the list
|
||||
can be determined statically, they will be treated as names for export and
|
||||
additional checking applied to them.
|
||||
|
||||
The only C{__all__} assignment that can be recognized is one which takes
|
||||
the value of a literal list containing literal strings. For example::
|
||||
|
||||
__all__ = ["foo", "bar"]
|
||||
|
||||
Names which are imported and not otherwise used but appear in the value of
|
||||
C{__all__} will not have an unused import warning reported for them.
|
||||
"""
|
||||
|
||||
def __init__(self, name, source, scope):
|
||||
if '__all__' in scope and isinstance(source, ast.AugAssign):
|
||||
self.names = list(scope['__all__'].names)
|
||||
else:
|
||||
self.names = []
|
||||
if isinstance(source.value, (ast.List, ast.Tuple)):
|
||||
for node in source.value.elts:
|
||||
if isinstance(node, ast.Str):
|
||||
self.names.append(node.s)
|
||||
super(ExportBinding, self).__init__(name, source)
|
||||
|
||||
|
||||
class Scope(dict):
|
||||
importStarred = False # set to True when import * is found
|
||||
|
||||
def __repr__(self):
|
||||
scope_cls = self.__class__.__name__
|
||||
return '<%s at 0x%x %s>' % (scope_cls, id(self), dict.__repr__(self))
|
||||
|
||||
|
||||
class ClassScope(Scope):
|
||||
pass
|
||||
|
||||
|
||||
class FunctionScope(Scope):
|
||||
"""
|
||||
I represent a name scope for a function.
|
||||
|
||||
@ivar globals: Names declared 'global' in this function.
|
||||
"""
|
||||
usesLocals = False
|
||||
alwaysUsed = set(['__tracebackhide__',
|
||||
'__traceback_info__', '__traceback_supplement__'])
|
||||
|
||||
def __init__(self):
|
||||
super(FunctionScope, self).__init__()
|
||||
# Simplify: manage the special locals as globals
|
||||
self.globals = self.alwaysUsed.copy()
|
||||
self.returnValue = None # First non-empty return
|
||||
self.isGenerator = False # Detect a generator
|
||||
|
||||
def unusedAssignments(self):
|
||||
"""
|
||||
Return a generator for the assignments which have not been used.
|
||||
"""
|
||||
for name, binding in self.items():
|
||||
if (not binding.used and name not in self.globals
|
||||
and not self.usesLocals
|
||||
and isinstance(binding, Assignment)):
|
||||
yield name, binding
|
||||
|
||||
|
||||
class GeneratorScope(Scope):
|
||||
pass
|
||||
|
||||
|
||||
class ModuleScope(Scope):
|
||||
pass
|
||||
|
||||
|
||||
# Globally defined names which are not attributes of the builtins module, or
|
||||
# are only present on some platforms.
|
||||
_MAGIC_GLOBALS = ['__file__', '__builtins__', 'WindowsError']
|
||||
|
||||
|
||||
def getNodeName(node):
|
||||
# Returns node.id, or node.name, or None
|
||||
if hasattr(node, 'id'): # One of the many nodes with an id
|
||||
return node.id
|
||||
if hasattr(node, 'name'): # a ExceptHandler node
|
||||
return node.name
|
||||
|
||||
|
||||
class Checker(object):
|
||||
"""
|
||||
I check the cleanliness and sanity of Python code.
|
||||
|
||||
@ivar _deferredFunctions: Tracking list used by L{deferFunction}. Elements
|
||||
of the list are two-tuples. The first element is the callable passed
|
||||
to L{deferFunction}. The second element is a copy of the scope stack
|
||||
at the time L{deferFunction} was called.
|
||||
|
||||
@ivar _deferredAssignments: Similar to C{_deferredFunctions}, but for
|
||||
callables which are deferred assignment checks.
|
||||
"""
|
||||
|
||||
nodeDepth = 0
|
||||
offset = None
|
||||
traceTree = False
|
||||
|
||||
builtIns = set(builtin_vars).union(_MAGIC_GLOBALS)
|
||||
_customBuiltIns = os.environ.get('PYFLAKES_BUILTINS')
|
||||
if _customBuiltIns:
|
||||
builtIns.update(_customBuiltIns.split(','))
|
||||
del _customBuiltIns
|
||||
|
||||
def __init__(self, tree, filename='(none)', builtins=None,
|
||||
withDoctest='PYFLAKES_DOCTEST' in os.environ):
|
||||
self._nodeHandlers = {}
|
||||
self._deferredFunctions = []
|
||||
self._deferredAssignments = []
|
||||
self.deadScopes = []
|
||||
self.messages = []
|
||||
self.filename = filename
|
||||
if builtins:
|
||||
self.builtIns = self.builtIns.union(builtins)
|
||||
self.withDoctest = withDoctest
|
||||
self.scopeStack = [ModuleScope()]
|
||||
self.exceptHandlers = [()]
|
||||
self.futuresAllowed = True
|
||||
self.root = tree
|
||||
self.handleChildren(tree)
|
||||
self.runDeferred(self._deferredFunctions)
|
||||
# Set _deferredFunctions to None so that deferFunction will fail
|
||||
# noisily if called after we've run through the deferred functions.
|
||||
self._deferredFunctions = None
|
||||
self.runDeferred(self._deferredAssignments)
|
||||
# Set _deferredAssignments to None so that deferAssignment will fail
|
||||
# noisily if called after we've run through the deferred assignments.
|
||||
self._deferredAssignments = None
|
||||
del self.scopeStack[1:]
|
||||
self.popScope()
|
||||
self.checkDeadScopes()
|
||||
|
||||
def deferFunction(self, callable):
|
||||
"""
|
||||
Schedule a function handler to be called just before completion.
|
||||
|
||||
This is used for handling function bodies, which must be deferred
|
||||
because code later in the file might modify the global scope. When
|
||||
`callable` is called, the scope at the time this is called will be
|
||||
restored, however it will contain any new bindings added to it.
|
||||
"""
|
||||
self._deferredFunctions.append((callable, self.scopeStack[:], self.offset))
|
||||
|
||||
def deferAssignment(self, callable):
|
||||
"""
|
||||
Schedule an assignment handler to be called just after deferred
|
||||
function handlers.
|
||||
"""
|
||||
self._deferredAssignments.append((callable, self.scopeStack[:], self.offset))
|
||||
|
||||
def runDeferred(self, deferred):
|
||||
"""
|
||||
Run the callables in C{deferred} using their associated scope stack.
|
||||
"""
|
||||
for handler, scope, offset in deferred:
|
||||
self.scopeStack = scope
|
||||
self.offset = offset
|
||||
handler()
|
||||
|
||||
@property
|
||||
def scope(self):
|
||||
return self.scopeStack[-1]
|
||||
|
||||
def popScope(self):
|
||||
self.deadScopes.append(self.scopeStack.pop())
|
||||
|
||||
def checkDeadScopes(self):
|
||||
"""
|
||||
Look at scopes which have been fully examined and report names in them
|
||||
which were imported but unused.
|
||||
"""
|
||||
for scope in self.deadScopes:
|
||||
if isinstance(scope.get('__all__'), ExportBinding):
|
||||
all_names = set(scope['__all__'].names)
|
||||
if not scope.importStarred and \
|
||||
os.path.basename(self.filename) != '__init__.py':
|
||||
# Look for possible mistakes in the export list
|
||||
undefined = all_names.difference(scope)
|
||||
for name in undefined:
|
||||
self.report(messages.UndefinedExport,
|
||||
scope['__all__'].source, name)
|
||||
else:
|
||||
all_names = []
|
||||
|
||||
# Look for imported names that aren't used.
|
||||
for value in scope.values():
|
||||
if isinstance(value, Importation):
|
||||
used = value.used or value.name in all_names
|
||||
if not used:
|
||||
messg = messages.UnusedImport
|
||||
self.report(messg, value.source, value.name)
|
||||
for node in value.redefined:
|
||||
if isinstance(self.getParent(node), ast.For):
|
||||
messg = messages.ImportShadowedByLoopVar
|
||||
elif used:
|
||||
continue
|
||||
else:
|
||||
messg = messages.RedefinedWhileUnused
|
||||
self.report(messg, node, value.name, value.source)
|
||||
|
||||
def pushScope(self, scopeClass=FunctionScope):
|
||||
self.scopeStack.append(scopeClass())
|
||||
|
||||
def report(self, messageClass, *args, **kwargs):
|
||||
self.messages.append(messageClass(self.filename, *args, **kwargs))
|
||||
|
||||
def getParent(self, node):
|
||||
# Lookup the first parent which is not Tuple, List or Starred
|
||||
while True:
|
||||
node = node.parent
|
||||
if not hasattr(node, 'elts') and not hasattr(node, 'ctx'):
|
||||
return node
|
||||
|
||||
def getCommonAncestor(self, lnode, rnode, stop):
|
||||
if stop in (lnode, rnode) or not (hasattr(lnode, 'parent') and
|
||||
hasattr(rnode, 'parent')):
|
||||
return None
|
||||
if lnode is rnode:
|
||||
return lnode
|
||||
|
||||
if (lnode.depth > rnode.depth):
|
||||
return self.getCommonAncestor(lnode.parent, rnode, stop)
|
||||
if (lnode.depth < rnode.depth):
|
||||
return self.getCommonAncestor(lnode, rnode.parent, stop)
|
||||
return self.getCommonAncestor(lnode.parent, rnode.parent, stop)
|
||||
|
||||
def descendantOf(self, node, ancestors, stop):
|
||||
for a in ancestors:
|
||||
if self.getCommonAncestor(node, a, stop):
|
||||
return True
|
||||
return False
|
||||
|
||||
def differentForks(self, lnode, rnode):
|
||||
"""True, if lnode and rnode are located on different forks of IF/TRY"""
|
||||
ancestor = self.getCommonAncestor(lnode, rnode, self.root)
|
||||
parts = getAlternatives(ancestor)
|
||||
if parts:
|
||||
for items in parts:
|
||||
if self.descendantOf(lnode, items, ancestor) ^ \
|
||||
self.descendantOf(rnode, items, ancestor):
|
||||
return True
|
||||
return False
|
||||
|
||||
def addBinding(self, node, value):
|
||||
"""
|
||||
Called when a binding is altered.
|
||||
|
||||
- `node` is the statement responsible for the change
|
||||
- `value` is the new value, a Binding instance
|
||||
"""
|
||||
# assert value.source in (node, node.parent):
|
||||
for scope in self.scopeStack[::-1]:
|
||||
if value.name in scope:
|
||||
break
|
||||
existing = scope.get(value.name)
|
||||
|
||||
if existing and not self.differentForks(node, existing.source):
|
||||
|
||||
parent_stmt = self.getParent(value.source)
|
||||
if isinstance(existing, Importation) and isinstance(parent_stmt, ast.For):
|
||||
self.report(messages.ImportShadowedByLoopVar,
|
||||
node, value.name, existing.source)
|
||||
|
||||
elif scope is self.scope:
|
||||
if (isinstance(parent_stmt, ast.comprehension) and
|
||||
not isinstance(self.getParent(existing.source),
|
||||
(ast.For, ast.comprehension))):
|
||||
self.report(messages.RedefinedInListComp,
|
||||
node, value.name, existing.source)
|
||||
elif not existing.used and value.redefines(existing):
|
||||
self.report(messages.RedefinedWhileUnused,
|
||||
node, value.name, existing.source)
|
||||
|
||||
elif isinstance(existing, Importation) and value.redefines(existing):
|
||||
existing.redefined.append(node)
|
||||
|
||||
if value.name in self.scope:
|
||||
# then assume the rebound name is used as a global or within a loop
|
||||
value.used = self.scope[value.name].used
|
||||
|
||||
self.scope[value.name] = value
|
||||
|
||||
def getNodeHandler(self, node_class):
|
||||
try:
|
||||
return self._nodeHandlers[node_class]
|
||||
except KeyError:
|
||||
nodeType = getNodeType(node_class)
|
||||
self._nodeHandlers[node_class] = handler = getattr(self, nodeType)
|
||||
return handler
|
||||
|
||||
def handleNodeLoad(self, node):
|
||||
name = getNodeName(node)
|
||||
if not name:
|
||||
return
|
||||
# try local scope
|
||||
try:
|
||||
self.scope[name].used = (self.scope, node)
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
return
|
||||
|
||||
scopes = [scope for scope in self.scopeStack[:-1]
|
||||
if isinstance(scope, (FunctionScope, ModuleScope, GeneratorScope))]
|
||||
if isinstance(self.scope, GeneratorScope) and scopes[-1] != self.scopeStack[-2]:
|
||||
scopes.append(self.scopeStack[-2])
|
||||
|
||||
# try enclosing function scopes and global scope
|
||||
importStarred = self.scope.importStarred
|
||||
for scope in reversed(scopes):
|
||||
importStarred = importStarred or scope.importStarred
|
||||
try:
|
||||
scope[name].used = (self.scope, node)
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
return
|
||||
|
||||
# look in the built-ins
|
||||
if importStarred or name in self.builtIns:
|
||||
return
|
||||
if name == '__path__' and os.path.basename(self.filename) == '__init__.py':
|
||||
# the special name __path__ is valid only in packages
|
||||
return
|
||||
|
||||
# protected with a NameError handler?
|
||||
if 'NameError' not in self.exceptHandlers[-1]:
|
||||
self.report(messages.UndefinedName, node, name)
|
||||
|
||||
def handleNodeStore(self, node):
|
||||
name = getNodeName(node)
|
||||
if not name:
|
||||
return
|
||||
# if the name hasn't already been defined in the current scope
|
||||
if isinstance(self.scope, FunctionScope) and name not in self.scope:
|
||||
# for each function or module scope above us
|
||||
for scope in self.scopeStack[:-1]:
|
||||
if not isinstance(scope, (FunctionScope, ModuleScope)):
|
||||
continue
|
||||
# if the name was defined in that scope, and the name has
|
||||
# been accessed already in the current scope, and hasn't
|
||||
# been declared global
|
||||
used = name in scope and scope[name].used
|
||||
if used and used[0] is self.scope and name not in self.scope.globals:
|
||||
# then it's probably a mistake
|
||||
self.report(messages.UndefinedLocal,
|
||||
scope[name].used[1], name, scope[name].source)
|
||||
break
|
||||
|
||||
parent_stmt = self.getParent(node)
|
||||
if isinstance(parent_stmt, (ast.For, ast.comprehension)) or (
|
||||
parent_stmt != node.parent and
|
||||
not self.isLiteralTupleUnpacking(parent_stmt)):
|
||||
binding = Binding(name, node)
|
||||
elif name == '__all__' and isinstance(self.scope, ModuleScope):
|
||||
binding = ExportBinding(name, node.parent, self.scope)
|
||||
else:
|
||||
binding = Assignment(name, node)
|
||||
self.addBinding(node, binding)
|
||||
|
||||
def handleNodeDelete(self, node):
|
||||
|
||||
def on_conditional_branch():
|
||||
"""
|
||||
Return `True` if node is part of a conditional body.
|
||||
"""
|
||||
current = getattr(node, 'parent', None)
|
||||
while current:
|
||||
if isinstance(current, (ast.If, ast.While, ast.IfExp)):
|
||||
return True
|
||||
current = getattr(current, 'parent', None)
|
||||
return False
|
||||
|
||||
name = getNodeName(node)
|
||||
if not name:
|
||||
return
|
||||
|
||||
if on_conditional_branch():
|
||||
# We can not predict if this conditional branch is going to
|
||||
# be executed.
|
||||
return
|
||||
|
||||
if isinstance(self.scope, FunctionScope) and name in self.scope.globals:
|
||||
self.scope.globals.remove(name)
|
||||
else:
|
||||
try:
|
||||
del self.scope[name]
|
||||
except KeyError:
|
||||
self.report(messages.UndefinedName, node, name)
|
||||
|
||||
def handleChildren(self, tree, omit=None):
|
||||
for node in iter_child_nodes(tree, omit=omit):
|
||||
self.handleNode(node, tree)
|
||||
|
||||
def isLiteralTupleUnpacking(self, node):
|
||||
if isinstance(node, ast.Assign):
|
||||
for child in node.targets + [node.value]:
|
||||
if not hasattr(child, 'elts'):
|
||||
return False
|
||||
return True
|
||||
|
||||
def isDocstring(self, node):
|
||||
"""
|
||||
Determine if the given node is a docstring, as long as it is at the
|
||||
correct place in the node tree.
|
||||
"""
|
||||
return isinstance(node, ast.Str) or (isinstance(node, ast.Expr) and
|
||||
isinstance(node.value, ast.Str))
|
||||
|
||||
def getDocstring(self, node):
|
||||
if isinstance(node, ast.Expr):
|
||||
node = node.value
|
||||
if not isinstance(node, ast.Str):
|
||||
return (None, None)
|
||||
# Computed incorrectly if the docstring has backslash
|
||||
doctest_lineno = node.lineno - node.s.count('\n') - 1
|
||||
return (node.s, doctest_lineno)
|
||||
|
||||
def handleNode(self, node, parent):
|
||||
if node is None:
|
||||
return
|
||||
if self.offset and getattr(node, 'lineno', None) is not None:
|
||||
node.lineno += self.offset[0]
|
||||
node.col_offset += self.offset[1]
|
||||
if self.traceTree:
|
||||
print(' ' * self.nodeDepth + node.__class__.__name__)
|
||||
if self.futuresAllowed and not (isinstance(node, ast.ImportFrom) or
|
||||
self.isDocstring(node)):
|
||||
self.futuresAllowed = False
|
||||
self.nodeDepth += 1
|
||||
node.depth = self.nodeDepth
|
||||
node.parent = parent
|
||||
try:
|
||||
handler = self.getNodeHandler(node.__class__)
|
||||
handler(node)
|
||||
finally:
|
||||
self.nodeDepth -= 1
|
||||
if self.traceTree:
|
||||
print(' ' * self.nodeDepth + 'end ' + node.__class__.__name__)
|
||||
|
||||
_getDoctestExamples = doctest.DocTestParser().get_examples
|
||||
|
||||
def handleDoctests(self, node):
|
||||
try:
|
||||
(docstring, node_lineno) = self.getDocstring(node.body[0])
|
||||
examples = docstring and self._getDoctestExamples(docstring)
|
||||
except (ValueError, IndexError):
|
||||
# e.g. line 6 of the docstring for <string> has inconsistent
|
||||
# leading whitespace: ...
|
||||
return
|
||||
if not examples:
|
||||
return
|
||||
node_offset = self.offset or (0, 0)
|
||||
self.pushScope()
|
||||
underscore_in_builtins = '_' in self.builtIns
|
||||
if not underscore_in_builtins:
|
||||
self.builtIns.add('_')
|
||||
for example in examples:
|
||||
try:
|
||||
tree = compile(example.source, "<doctest>", "exec", ast.PyCF_ONLY_AST)
|
||||
except SyntaxError:
|
||||
e = sys.exc_info()[1]
|
||||
position = (node_lineno + example.lineno + e.lineno,
|
||||
example.indent + 4 + (e.offset or 0))
|
||||
self.report(messages.DoctestSyntaxError, node, position)
|
||||
else:
|
||||
self.offset = (node_offset[0] + node_lineno + example.lineno,
|
||||
node_offset[1] + example.indent + 4)
|
||||
self.handleChildren(tree)
|
||||
self.offset = node_offset
|
||||
if not underscore_in_builtins:
|
||||
self.builtIns.remove('_')
|
||||
self.popScope()
|
||||
|
||||
def ignore(self, node):
|
||||
pass
|
||||
|
||||
# "stmt" type nodes
|
||||
DELETE = PRINT = FOR = ASYNCFOR = WHILE = IF = WITH = WITHITEM = \
|
||||
ASYNCWITH = ASYNCWITHITEM = RAISE = TRYFINALLY = ASSERT = EXEC = \
|
||||
EXPR = ASSIGN = handleChildren
|
||||
|
||||
CONTINUE = BREAK = PASS = ignore
|
||||
|
||||
# "expr" type nodes
|
||||
BOOLOP = BINOP = UNARYOP = IFEXP = DICT = SET = \
|
||||
COMPARE = CALL = REPR = ATTRIBUTE = SUBSCRIPT = LIST = TUPLE = \
|
||||
STARRED = NAMECONSTANT = handleChildren
|
||||
|
||||
NUM = STR = BYTES = ELLIPSIS = ignore
|
||||
|
||||
# "slice" type nodes
|
||||
SLICE = EXTSLICE = INDEX = handleChildren
|
||||
|
||||
# expression contexts are node instances too, though being constants
|
||||
LOAD = STORE = DEL = AUGLOAD = AUGSTORE = PARAM = ignore
|
||||
|
||||
# same for operators
|
||||
AND = OR = ADD = SUB = MULT = DIV = MOD = POW = LSHIFT = RSHIFT = \
|
||||
BITOR = BITXOR = BITAND = FLOORDIV = INVERT = NOT = UADD = USUB = \
|
||||
EQ = NOTEQ = LT = LTE = GT = GTE = IS = ISNOT = IN = NOTIN = ignore
|
||||
|
||||
# additional node types
|
||||
COMPREHENSION = KEYWORD = handleChildren
|
||||
|
||||
def GLOBAL(self, node):
|
||||
"""
|
||||
Keep track of globals declarations.
|
||||
"""
|
||||
# In doctests, the global scope is an anonymous function at index 1.
|
||||
global_scope_index = 1 if self.withDoctest else 0
|
||||
global_scope = self.scopeStack[global_scope_index]
|
||||
|
||||
# Ignore 'global' statement in global scope.
|
||||
if self.scope is not global_scope:
|
||||
|
||||
# One 'global' statement can bind multiple (comma-delimited) names.
|
||||
for node_name in node.names:
|
||||
node_value = Assignment(node_name, node)
|
||||
|
||||
# Remove UndefinedName messages already reported for this name.
|
||||
self.messages = [
|
||||
m for m in self.messages if not
|
||||
isinstance(m, messages.UndefinedName) and not
|
||||
m.message_args[0] == node_name]
|
||||
|
||||
# Bind name to global scope if it doesn't exist already.
|
||||
global_scope.setdefault(node_name, node_value)
|
||||
|
||||
# Bind name to non-global scopes, but as already "used".
|
||||
node_value.used = (global_scope, node)
|
||||
for scope in self.scopeStack[global_scope_index + 1:]:
|
||||
scope[node_name] = node_value
|
||||
|
||||
NONLOCAL = GLOBAL
|
||||
|
||||
def GENERATOREXP(self, node):
|
||||
self.pushScope(GeneratorScope)
|
||||
self.handleChildren(node)
|
||||
self.popScope()
|
||||
|
||||
LISTCOMP = handleChildren if PY2 else GENERATOREXP
|
||||
|
||||
DICTCOMP = SETCOMP = GENERATOREXP
|
||||
|
||||
def NAME(self, node):
|
||||
"""
|
||||
Handle occurrence of Name (which can be a load/store/delete access.)
|
||||
"""
|
||||
# Locate the name in locals / function / globals scopes.
|
||||
if isinstance(node.ctx, (ast.Load, ast.AugLoad)):
|
||||
self.handleNodeLoad(node)
|
||||
if (node.id == 'locals' and isinstance(self.scope, FunctionScope)
|
||||
and isinstance(node.parent, ast.Call)):
|
||||
# we are doing locals() call in current scope
|
||||
self.scope.usesLocals = True
|
||||
elif isinstance(node.ctx, (ast.Store, ast.AugStore)):
|
||||
self.handleNodeStore(node)
|
||||
elif isinstance(node.ctx, ast.Del):
|
||||
self.handleNodeDelete(node)
|
||||
else:
|
||||
# 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 RETURN(self, node):
|
||||
if isinstance(self.scope, ClassScope):
|
||||
self.report(messages.ReturnOutsideFunction, node)
|
||||
return
|
||||
|
||||
if (
|
||||
node.value and
|
||||
hasattr(self.scope, 'returnValue') and
|
||||
not self.scope.returnValue
|
||||
):
|
||||
self.scope.returnValue = node.value
|
||||
self.handleNode(node.value, node)
|
||||
|
||||
def YIELD(self, node):
|
||||
self.scope.isGenerator = True
|
||||
self.handleNode(node.value, node)
|
||||
|
||||
AWAIT = YIELDFROM = YIELD
|
||||
|
||||
def FUNCTIONDEF(self, node):
|
||||
for deco in node.decorator_list:
|
||||
self.handleNode(deco, node)
|
||||
self.LAMBDA(node)
|
||||
self.addBinding(node, FunctionDefinition(node.name, node))
|
||||
if self.withDoctest:
|
||||
self.deferFunction(lambda: self.handleDoctests(node))
|
||||
|
||||
ASYNCFUNCTIONDEF = FUNCTIONDEF
|
||||
|
||||
def LAMBDA(self, node):
|
||||
args = []
|
||||
annotations = []
|
||||
|
||||
if PY2:
|
||||
def addArgs(arglist):
|
||||
for arg in arglist:
|
||||
if isinstance(arg, ast.Tuple):
|
||||
addArgs(arg.elts)
|
||||
else:
|
||||
args.append(arg.id)
|
||||
addArgs(node.args.args)
|
||||
defaults = node.args.defaults
|
||||
else:
|
||||
for arg in node.args.args + node.args.kwonlyargs:
|
||||
args.append(arg.arg)
|
||||
annotations.append(arg.annotation)
|
||||
defaults = node.args.defaults + node.args.kw_defaults
|
||||
|
||||
# Only for Python3 FunctionDefs
|
||||
is_py3_func = hasattr(node, 'returns')
|
||||
|
||||
for arg_name in ('vararg', 'kwarg'):
|
||||
wildcard = getattr(node.args, arg_name)
|
||||
if not wildcard:
|
||||
continue
|
||||
args.append(wildcard if PY33 else wildcard.arg)
|
||||
if is_py3_func:
|
||||
if PY33: # Python 2.5 to 3.3
|
||||
argannotation = arg_name + 'annotation'
|
||||
annotations.append(getattr(node.args, argannotation))
|
||||
else: # Python >= 3.4
|
||||
annotations.append(wildcard.annotation)
|
||||
|
||||
if is_py3_func:
|
||||
annotations.append(node.returns)
|
||||
|
||||
if len(set(args)) < len(args):
|
||||
for (idx, arg) in enumerate(args):
|
||||
if arg in args[:idx]:
|
||||
self.report(messages.DuplicateArgument, node, arg)
|
||||
|
||||
for child in annotations + defaults:
|
||||
if child:
|
||||
self.handleNode(child, node)
|
||||
|
||||
def runFunction():
|
||||
|
||||
self.pushScope()
|
||||
for name in args:
|
||||
self.addBinding(node, Argument(name, node))
|
||||
if isinstance(node.body, list):
|
||||
# case for FunctionDefs
|
||||
for stmt in node.body:
|
||||
self.handleNode(stmt, node)
|
||||
else:
|
||||
# case for Lambdas
|
||||
self.handleNode(node.body, node)
|
||||
|
||||
def checkUnusedAssignments():
|
||||
"""
|
||||
Check to see if any assignments have not been used.
|
||||
"""
|
||||
for name, binding in self.scope.unusedAssignments():
|
||||
self.report(messages.UnusedVariable, binding.source, name)
|
||||
self.deferAssignment(checkUnusedAssignments)
|
||||
|
||||
if PY32:
|
||||
def checkReturnWithArgumentInsideGenerator():
|
||||
"""
|
||||
Check to see if there is any return statement with
|
||||
arguments but the function is a generator.
|
||||
"""
|
||||
if self.scope.isGenerator and self.scope.returnValue:
|
||||
self.report(messages.ReturnWithArgsInsideGenerator,
|
||||
self.scope.returnValue)
|
||||
self.deferAssignment(checkReturnWithArgumentInsideGenerator)
|
||||
self.popScope()
|
||||
|
||||
self.deferFunction(runFunction)
|
||||
|
||||
def CLASSDEF(self, node):
|
||||
"""
|
||||
Check names used in a class definition, including its decorators, base
|
||||
classes, and the body of its definition. Additionally, add its name to
|
||||
the current scope.
|
||||
"""
|
||||
for deco in node.decorator_list:
|
||||
self.handleNode(deco, node)
|
||||
for baseNode in node.bases:
|
||||
self.handleNode(baseNode, node)
|
||||
if not PY2:
|
||||
for keywordNode in node.keywords:
|
||||
self.handleNode(keywordNode, node)
|
||||
self.pushScope(ClassScope)
|
||||
if self.withDoctest:
|
||||
self.deferFunction(lambda: self.handleDoctests(node))
|
||||
for stmt in node.body:
|
||||
self.handleNode(stmt, node)
|
||||
self.popScope()
|
||||
self.addBinding(node, ClassDefinition(node.name, node))
|
||||
|
||||
def AUGASSIGN(self, node):
|
||||
self.handleNodeLoad(node.target)
|
||||
self.handleNode(node.value, node)
|
||||
self.handleNode(node.target, node)
|
||||
|
||||
def IMPORT(self, node):
|
||||
for alias in node.names:
|
||||
name = alias.asname or alias.name
|
||||
importation = Importation(name, node)
|
||||
self.addBinding(node, importation)
|
||||
|
||||
def IMPORTFROM(self, node):
|
||||
if node.module == '__future__':
|
||||
if not self.futuresAllowed:
|
||||
self.report(messages.LateFutureImport,
|
||||
node, [n.name for n in node.names])
|
||||
else:
|
||||
self.futuresAllowed = False
|
||||
|
||||
for alias in node.names:
|
||||
if alias.name == '*':
|
||||
self.scope.importStarred = True
|
||||
self.report(messages.ImportStarUsed, node, node.module)
|
||||
continue
|
||||
name = alias.asname or alias.name
|
||||
importation = Importation(name, node)
|
||||
if node.module == '__future__':
|
||||
importation.used = (self.scope, node)
|
||||
self.addBinding(node, importation)
|
||||
|
||||
def TRY(self, node):
|
||||
handler_names = []
|
||||
# List the exception handlers
|
||||
for handler in node.handlers:
|
||||
if isinstance(handler.type, ast.Tuple):
|
||||
for exc_type in handler.type.elts:
|
||||
handler_names.append(getNodeName(exc_type))
|
||||
elif handler.type:
|
||||
handler_names.append(getNodeName(handler.type))
|
||||
# Memorize the except handlers and process the body
|
||||
self.exceptHandlers.append(handler_names)
|
||||
for child in node.body:
|
||||
self.handleNode(child, node)
|
||||
self.exceptHandlers.pop()
|
||||
# Process the other nodes: "except:", "else:", "finally:"
|
||||
self.handleChildren(node, omit='body')
|
||||
|
||||
TRYEXCEPT = TRY
|
||||
|
||||
def EXCEPTHANDLER(self, node):
|
||||
# 3.x: in addition to handling children, we must handle the name of
|
||||
# the exception, which is not a Name node, but a simple string.
|
||||
if isinstance(node.name, str):
|
||||
self.handleNodeStore(node)
|
||||
self.handleChildren(node)
|
||||
134
vim-plugins/bundle/python-mode/pymode/libs/pyflakes/messages.py
Normal file
134
vim-plugins/bundle/python-mode/pymode/libs/pyflakes/messages.py
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
"""
|
||||
Provide the class Message and its subclasses.
|
||||
"""
|
||||
|
||||
|
||||
class Message(object):
|
||||
message = ''
|
||||
message_args = ()
|
||||
|
||||
def __init__(self, filename, loc):
|
||||
self.filename = filename
|
||||
self.lineno = loc.lineno
|
||||
self.col = getattr(loc, 'col_offset', 0)
|
||||
|
||||
def __str__(self):
|
||||
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, loc, name):
|
||||
Message.__init__(self, filename, loc)
|
||||
self.message_args = (name,)
|
||||
|
||||
|
||||
class RedefinedWhileUnused(Message):
|
||||
message = 'redefinition of unused %r from line %r'
|
||||
|
||||
def __init__(self, filename, loc, name, orig_loc):
|
||||
Message.__init__(self, filename, loc)
|
||||
self.message_args = (name, orig_loc.lineno)
|
||||
|
||||
|
||||
class RedefinedInListComp(Message):
|
||||
message = 'list comprehension redefines %r from line %r'
|
||||
|
||||
def __init__(self, filename, loc, name, orig_loc):
|
||||
Message.__init__(self, filename, loc)
|
||||
self.message_args = (name, orig_loc.lineno)
|
||||
|
||||
|
||||
class ImportShadowedByLoopVar(Message):
|
||||
message = 'import %r from line %r shadowed by loop variable'
|
||||
|
||||
def __init__(self, filename, loc, name, orig_loc):
|
||||
Message.__init__(self, filename, loc)
|
||||
self.message_args = (name, orig_loc.lineno)
|
||||
|
||||
|
||||
class ImportStarUsed(Message):
|
||||
message = "'from %s import *' used; unable to detect undefined names"
|
||||
|
||||
def __init__(self, filename, loc, modname):
|
||||
Message.__init__(self, filename, loc)
|
||||
self.message_args = (modname,)
|
||||
|
||||
|
||||
class UndefinedName(Message):
|
||||
message = 'undefined name %r'
|
||||
|
||||
def __init__(self, filename, loc, name):
|
||||
Message.__init__(self, filename, loc)
|
||||
self.message_args = (name,)
|
||||
|
||||
|
||||
class DoctestSyntaxError(Message):
|
||||
message = 'syntax error in doctest'
|
||||
|
||||
def __init__(self, filename, loc, position=None):
|
||||
Message.__init__(self, filename, loc)
|
||||
if position:
|
||||
(self.lineno, self.col) = position
|
||||
self.message_args = ()
|
||||
|
||||
|
||||
class UndefinedExport(Message):
|
||||
message = 'undefined name %r in __all__'
|
||||
|
||||
def __init__(self, filename, loc, name):
|
||||
Message.__init__(self, filename, loc)
|
||||
self.message_args = (name,)
|
||||
|
||||
|
||||
class UndefinedLocal(Message):
|
||||
message = ('local variable %r (defined in enclosing scope on line %r) '
|
||||
'referenced before assignment')
|
||||
|
||||
def __init__(self, filename, loc, name, orig_loc):
|
||||
Message.__init__(self, filename, loc)
|
||||
self.message_args = (name, orig_loc.lineno)
|
||||
|
||||
|
||||
class DuplicateArgument(Message):
|
||||
message = 'duplicate argument %r in function definition'
|
||||
|
||||
def __init__(self, filename, loc, name):
|
||||
Message.__init__(self, filename, loc)
|
||||
self.message_args = (name,)
|
||||
|
||||
|
||||
class LateFutureImport(Message):
|
||||
message = 'future import(s) %r after other statements'
|
||||
|
||||
def __init__(self, filename, loc, names):
|
||||
Message.__init__(self, filename, loc)
|
||||
self.message_args = (names,)
|
||||
|
||||
|
||||
class UnusedVariable(Message):
|
||||
"""
|
||||
Indicates that a variable has been explicity assigned to but not actually
|
||||
used.
|
||||
"""
|
||||
message = 'local variable %r is assigned to but never used'
|
||||
|
||||
def __init__(self, filename, loc, names):
|
||||
Message.__init__(self, filename, loc)
|
||||
self.message_args = (names,)
|
||||
|
||||
|
||||
class ReturnWithArgsInsideGenerator(Message):
|
||||
"""
|
||||
Indicates a return statement with arguments inside a generator.
|
||||
"""
|
||||
message = '\'return\' with argument inside generator'
|
||||
|
||||
|
||||
class ReturnOutsideFunction(Message):
|
||||
"""
|
||||
Indicates a return statement outside of a function/method.
|
||||
"""
|
||||
message = '\'return\' outside function'
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
"""
|
||||
Provide the Reporter class.
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
class Reporter(object):
|
||||
"""
|
||||
Formats the results of pyflakes checks to users.
|
||||
"""
|
||||
|
||||
def __init__(self, warningStream, errorStream):
|
||||
"""
|
||||
Construct a L{Reporter}.
|
||||
|
||||
@param warningStream: A file-like object where warnings will be
|
||||
written to. The stream's C{write} method must accept unicode.
|
||||
C{sys.stdout} is a good value.
|
||||
@param errorStream: A file-like object where error output will be
|
||||
written to. The stream's C{write} method must accept unicode.
|
||||
C{sys.stderr} is a good value.
|
||||
"""
|
||||
self._stdout = warningStream
|
||||
self._stderr = errorStream
|
||||
|
||||
def unexpectedError(self, filename, msg):
|
||||
"""
|
||||
An unexpected error occurred trying to process C{filename}.
|
||||
|
||||
@param filename: The path to a file that we could not process.
|
||||
@ptype filename: C{unicode}
|
||||
@param msg: A message explaining the problem.
|
||||
@ptype msg: C{unicode}
|
||||
"""
|
||||
self._stderr.write("%s: %s\n" % (filename, msg))
|
||||
|
||||
def syntaxError(self, filename, msg, lineno, offset, text):
|
||||
"""
|
||||
There was a syntax errror in C{filename}.
|
||||
|
||||
@param filename: The path to the file with the syntax error.
|
||||
@ptype filename: C{unicode}
|
||||
@param msg: An explanation of the syntax error.
|
||||
@ptype msg: C{unicode}
|
||||
@param lineno: The line number where the syntax error occurred.
|
||||
@ptype lineno: C{int}
|
||||
@param offset: The column on which the syntax error occurred, or None.
|
||||
@ptype offset: C{int}
|
||||
@param text: The source code containing the syntax error.
|
||||
@ptype text: C{unicode}
|
||||
"""
|
||||
line = text.splitlines()[-1]
|
||||
if offset is not None:
|
||||
offset = offset - (len(text) - len(line))
|
||||
self._stderr.write('%s:%d:%d: %s\n' %
|
||||
(filename, lineno, offset + 1, msg))
|
||||
else:
|
||||
self._stderr.write('%s:%d: %s\n' % (filename, lineno, msg))
|
||||
self._stderr.write(line)
|
||||
self._stderr.write('\n')
|
||||
if offset is not None:
|
||||
self._stderr.write(re.sub(r'\S', ' ', line[:offset]) +
|
||||
"^\n")
|
||||
|
||||
def flake(self, message):
|
||||
"""
|
||||
pyflakes found something wrong with the code.
|
||||
|
||||
@param: A L{pyflakes.messages.Message}.
|
||||
"""
|
||||
self._stdout.write(str(message))
|
||||
self._stdout.write('\n')
|
||||
|
||||
|
||||
def _makeDefaultReporter():
|
||||
"""
|
||||
Make a reporter that can be used when no reporter is specified.
|
||||
"""
|
||||
return Reporter(sys.stdout, sys.stderr)
|
||||
Loading…
Add table
Add a link
Reference in a new issue