Sun, 05 Jan 2014 22:45:29 +0100
Update pyflakes to 0.7.3
--- a/Plugins/CheckerPlugins/SyntaxChecker/SyntaxCheck.py Sat Jan 04 22:14:38 2014 +0100 +++ b/Plugins/CheckerPlugins/SyntaxChecker/SyntaxCheck.py Sun Jan 05 22:45:29 2014 +0100 @@ -143,8 +143,6 @@ error = detail.msg return (True, fn, int(line), index, code, error, []) except ValueError as detail: - index = 0 - code = "" try: fn = detail.filename line = detail.lineno @@ -153,15 +151,13 @@ fn = filename line = 1 error = str(detail) - return (True, fn, line, index, code, error, []) + return (True, fn, line, 0, "", error, []) except Exception as detail: try: fn = detail.filename line = detail.lineno - index = 0 - code = "" error = detail.msg - return (True, fn, line, index, code, error, []) + return (True, fn, line, 0, "", error, []) except: # this catchall is intentional pass @@ -179,16 +175,16 @@ isinstance(warning, ImportStarUsed): continue - _fn, lineno, message, msg_args = warning.getMessageData() + _fn, lineno, col, message, msg_args = warning.getMessageData() if "__IGNORE_WARNING__" not in extractLineFlags( lines[lineno - 1].strip()): strings.append([ - "FLAKES_WARNING", _fn, lineno, message, msg_args]) + "FLAKES_WARNING", _fn, lineno, col, message, msg_args]) except SyntaxError as err: if err.text.strip(): msg = err.text.strip() else: msg = err.msg - strings.append(["FLAKES_ERROR", filename, err.lineno, msg, ()]) + strings.append(["FLAKES_ERROR", filename, err.lineno, 0, msg, ()]) return (False, "", -1, -1, "", "", strings)
--- a/Plugins/CheckerPlugins/SyntaxChecker/SyntaxCheckerDialog.py Sat Jan 04 22:14:38 2014 +0100 +++ b/Plugins/CheckerPlugins/SyntaxChecker/SyntaxCheckerDialog.py Sun Jan 05 22:45:29 2014 +0100 @@ -241,7 +241,7 @@ @param code the part of the code where the error occured (str) @param error the name of the error (str) @param warnings a list of strings containing the warnings - (marker, file name, line number, message) + (marker, file name, line number, col, message) """ # Check if it's the requested file, otherwise ignore signal if fn != self.filename: @@ -253,12 +253,10 @@ fname, line, index, error, code.strip(), False) else: source = self.source.splitlines() - for warning in warnings: + for marker, _fn, lineno, col, msg in warnings: self.noResults = False - scr_line = source[warning[2] - 1].strip() - self.__createResultItem( - warning[1], warning[2], 0, - warning[3], scr_line, True) + scr_line = source[lineno - 1].strip() + self.__createResultItem(_fn, lineno, col, msg, scr_line, True) self.progress += 1 self.checkProgress.setValue(self.progress) self.checkProgressLabel.setPath("")
--- a/Plugins/CheckerPlugins/SyntaxChecker/pyflakes/__init__.py Sat Jan 04 22:14:38 2014 +0100 +++ b/Plugins/CheckerPlugins/SyntaxChecker/pyflakes/__init__.py Sun Jan 05 22:45:29 2014 +0100 @@ -1,10 +1,10 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2010 - 2013 Detlev Offenbach <detlev@die-offenbachs.de> +# Copyright (c) 2010 - 2014 Detlev Offenbach <detlev@die-offenbachs.de> # """ -Package containg the pyflakes Python2 port adapted for Qt. +Package containg pyflakes adapted for Qt. """ """ License @@ -32,6 +32,40 @@ """ """ Changes +0.7.3 (2013-07-02): + - Do not report undefined name for generator expression and dict or + set comprehension at class level. + - Deprecate `Checker.pushFunctionScope` and `Checker.pushClassScope`: + use `Checker.pushScope` instead. + - Remove dependency on Unittest2 for the tests. + +0.7.2 (2013-04-24): + - Fix computation of `DoctestSyntaxError.lineno` and `col`. + - Add boolean attribute `Checker.withDoctest` to ignore doctests. + - If environment variable `PYFLAKES_NODOCTEST` is set, skip doctests. + - Environment variable `PYFLAKES_BUILTINS` accepts a comma-separated + list of additional built-in names. + +0.7.1 (2013-04-23): + - File `bin/pyflakes` was missing in tarball generated with distribute. + - Fix reporting errors in non-ASCII filenames (Python 2.x). + +0.7.0 (2013-04-17): + - Add --version and --help options. + - Support `python -m pyflakes` (Python 2.7 and Python 3.x). + - Add attribute `Message.col` to report column offset. + - Do not report redefinition of variable for a variable used in a list + comprehension in a conditional. + - Do not report redefinition of variable for generator expressions and + set or dict comprehensions. + - Do not report undefined name when the code is protected with a + `NameError` exception handler. + - Do not report redefinition of variable when unassigning a module imported + for its side-effect. + - Support special locals like `__tracebackhide__` for py.test. + - Support checking doctests. + - Fix issue with Turkish locale where `'i'.upper() == 'i'` in Python 2. + 0.6.1 (2013-01-29): - Fix detection of variables in augmented assignments. @@ -59,4 +93,4 @@ - Make sure class names don't get bound until after class definition. """ -__version__ = '0.6.1' +__version__ = '0.7.3'
--- a/Plugins/CheckerPlugins/SyntaxChecker/pyflakes/checker.py Sat Jan 04 22:14:38 2014 +0100 +++ b/Plugins/CheckerPlugins/SyntaxChecker/pyflakes/checker.py Sun Jan 05 22:45:29 2014 +0100 @@ -1,34 +1,45 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2010 - 2013 Detlev Offenbach <detlev@die-offenbachs.de> +# Copyright (c) 2010 - 2014 Detlev Offenbach <detlev@die-offenbachs.de> # # Original (c) 2005-2010 Divmod, Inc. # -# This module is based on pyflakes for Python2 but was modified to -# work with eric5 +# This module is based on pyflakes but was modified to work with eric5 +""" +Main module. -import os.path +Implement the central Checker class. +Also, it models the Bindings and Scopes. +""" +import doctest +import os +import sys try: - import builtins + builtin_vars = dir(__import__('builtins')) PY2 = False except ImportError: - import __builtin__ as builtins #__IGNORE_WARNING__ + builtin_vars = dir(__import__('__builtin__')) PY2 = True try: import ast iter_child_nodes = ast.iter_child_nodes -except (ImportError, AttributeError): # Python 2.5 +except ImportError: # Python 2.5 import _ast as ast - def iter_child_nodes(node, astcls=ast.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) + + def iter_child_nodes(node): """ - Yield all direct child nodes of *node*, that is, all fields that are nodes - and all items of fields that are lists of nodes. + Yield all direct child nodes of *node*, that is, all fields that + are nodes and all items of fields that are lists of nodes. """ for name in node._fields: field = getattr(node, name, None) - if isinstance(field, astcls): + if isinstance(field, ast.AST): yield field elif isinstance(field, list): for item in field: @@ -44,6 +55,15 @@ from . import messages +if PY2: + def getNodeType(node_class): + # workaround str.upper() which is locale-dependent + return str(unicode(node_class.__name__).upper()) # __IGNORE_WARNING__ +else: + def getNodeType(node_class): + return node_class.__name__.upper() + + class Binding(object): """ Represents the binding of a value to a name. @@ -51,6 +71,9 @@ 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): @@ -68,13 +91,13 @@ id(self)) -class UnBinding(Binding): - """Created by the 'del' operator.""" - - class Importation(Binding): """ 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 @@ -140,10 +163,10 @@ class Scope(dict): importStarred = False # set to True when import * is found - usesLocals = False def __repr__(self): - return '<%s at 0x%x %s>' % (self.__class__.__name__, id(self), dict.__repr__(self)) + scope_cls = self.__class__.__name__ + return '<%s at 0x%x %s>' % (scope_cls, id(self), dict.__repr__(self)) class ClassScope(Scope): @@ -153,10 +176,31 @@ 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__() - self.globals = {} + # Simplify: manage the special locals as globals + self.globals = self.alwaysUsed.copy() + + 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): @@ -179,13 +223,29 @@ 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(dir(builtins)) | set(_MAGIC_GLOBALS) + withDoctest = ('PYFLAKES_NODOCTEST' not in os.environ) + + 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): + self._nodeHandlers = {} self._deferredFunctions = [] self._deferredAssignments = [] self.deadScopes = [] @@ -194,6 +254,7 @@ if builtins: self.builtIns = self.builtIns.union(builtins) self.scopeStack = [ModuleScope()] + self.exceptHandlers = [()] self.futuresAllowed = True self.root = tree self.handleChildren(tree) @@ -218,21 +279,22 @@ `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._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._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 in deferred: + for handler, scope, offset in deferred: self.scopeStack = scope + self.offset = offset handler() @property @@ -251,12 +313,13 @@ export = isinstance(scope.get('__all__'), ExportBinding) if export: all = scope['__all__'].names() - if not scope.importStarred and os.path.basename(self.filename) != '__init__.py': + if not scope.importStarred and \ + os.path.basename(self.filename) != '__init__.py': # Look for possible mistakes in the export list undefined = set(all) - set(scope) for name in undefined: self.report(messages.UndefinedExport, - scope['__all__'].source.lineno, name) + scope['__all__'].source, name) else: all = [] @@ -265,13 +328,16 @@ if isinstance(importation, Importation): if not importation.used and importation.name not in all: self.report(messages.UnusedImport, - importation.source.lineno, importation.name) + importation.source, importation.name) + + def pushScope(self, scopeClass=FunctionScope): + self.scopeStack.append(scopeClass()) - def pushFunctionScope(self): - self.scopeStack.append(FunctionScope()) + def pushFunctionScope(self): # XXX Deprecated + self.pushScope(FunctionScope) - def pushClassScope(self): - self.scopeStack.append(ClassScope()) + def pushClassScope(self): # XXX Deprecated + self.pushScope(ClassScope) def report(self, messageClass, *args, **kwargs): self.messages.append(messageClass(self.filename, *args, **kwargs)) @@ -341,69 +407,76 @@ existing = scope.get(value.name) if (isinstance(existing, Importation) and not existing.used - and (not isinstance(value, Importation) or value.fullName == existing.fullName) + and (not isinstance(value, Importation) or + value.fullName == existing.fullName) and reportRedef and not self.differentForks(node, existing.source)): redefinedWhileUnused = True self.report(messages.RedefinedWhileUnused, - node.lineno, value.name, existing.source.lineno) + node, value.name, existing.source) existing = self.scope.get(value.name) if not redefinedWhileUnused and self.hasParent(value.source, ast.ListComp): if (existing and reportRedef - and not self.hasParent(existing.source, (ast.For, ast.ListComp))): + and not self.hasParent(existing.source, (ast.For, ast.ListComp)) + and not self.differentForks(node, existing.source)): self.report(messages.RedefinedInListComp, - node.lineno, value.name, existing.source.lineno) + node, value.name, existing.source) - if isinstance(value, UnBinding): - try: - del self.scope[value.name] - except KeyError: - self.report(messages.UndefinedName, node.lineno, value.name) - elif (isinstance(existing, Definition) - and not existing.used - and not self.differentForks(node, existing.source)): + if (isinstance(existing, Definition) + and not existing.used + and not self.differentForks(node, existing.source)): self.report(messages.RedefinedWhileUnused, - node.lineno, value.name, existing.source.lineno) + node, value.name, existing.source) else: 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 - importStarred = self.scope.importStarred try: - self.scope[name].used = (self.scope, node.lineno) + self.scope[name].used = (self.scope, node) except KeyError: pass else: return - # try enclosing function scopes - for scope in self.scopeStack[-2:0:-1]: + scopes = [scope for scope in self.scopeStack[:-1] + if isinstance(scope, (FunctionScope, ModuleScope))] + 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 - if not isinstance(scope, FunctionScope): - continue try: - scope[name].used = (self.scope, node.lineno) + scope[name].used = (self.scope, node) except KeyError: pass else: return - # try global scope - importStarred = importStarred or self.scopeStack[0].importStarred - try: - self.scopeStack[0][name].used = (self.scope, node.lineno) - except KeyError: - if not importStarred and name not in self.builtIns: - if (os.path.basename(self.filename) == '__init__.py' and name == '__path__'): - # the special name __path__ is valid only in packages - pass - else: - self.report(messages.UndefinedName, node.lineno, name) + # 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) @@ -418,17 +491,18 @@ # 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 - if (name in scope and scope[name].used and scope[name].used[0] is self.scope - and name not in self.scope.globals): + 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.lineno) + scope[name].used[1], name, scope[name].source) break parent = getattr(node, 'parent', None) if isinstance(parent, (ast.For, ast.comprehension, ast.Tuple, ast.List)): binding = Binding(name, node) - elif parent is not None and name == '__all__' and isinstance(self.scope, ModuleScope): + elif (parent is not None and name == '__all__' and + isinstance(self.scope, ModuleScope)): binding = ExportBinding(name, parent.value) else: binding = Assignment(name, node) @@ -441,9 +515,12 @@ if not name: return if isinstance(self.scope, FunctionScope) and name in self.scope.globals: - del self.scope.globals[name] + self.scope.globals.remove(name) else: - self.addBinding(node, UnBinding(name, node)) + try: + del self.scope[name] + except KeyError: + self.report(messages.UndefinedName, node, name) def handleChildren(self, tree): for node in iter_child_nodes(tree): @@ -457,32 +534,72 @@ 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 - node.parent = parent + 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__) - self.nodeDepth += 1 if self.futuresAllowed and not (isinstance(node, ast.ImportFrom) or self.isDocstring(node)): self.futuresAllowed = False - nodeType = node.__class__.__name__.upper() + self.nodeDepth += 1 node.level = self.nodeDepth + node.parent = parent try: - handler = getattr(self, nodeType) + 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]) + if not docstring: + return + examples = self._getDoctestExamples(docstring) + except (ValueError, IndexError): + # e.g. line 6 of the docstring for <string> has inconsistent + # leading whitespace: ... + return + node_offset = self.offset or (0, 0) + self.pushScope() + 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) + 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 + self.popScope() + def ignore(self, node): pass # "stmt" type nodes RETURN = DELETE = PRINT = WHILE = IF = WITH = WITHITEM = RAISE = \ - TRYEXCEPT = TRYFINALLY = TRY = ASSERT = EXEC = EXPR = handleChildren + TRYFINALLY = ASSERT = EXEC = EXPR = handleChildren CONTINUE = BREAK = PASS = ignore @@ -512,7 +629,7 @@ Keep track of globals declarations. """ if isinstance(self.scope, FunctionScope): - self.scope.globals.update(dict.fromkeys(node.names)) + self.scope.globals.update(node.names) NONLOCAL = GLOBAL @@ -522,13 +639,23 @@ self.handleNode(gen, node) self.handleNode(node.elt, node) - GENERATOREXP = SETCOMP = LISTCOMP + def GENERATOREXP(self, node): + self.pushScope(GeneratorScope) + # handle generators before element + for gen in node.generators: + self.handleNode(gen, node) + self.handleNode(node.elt, node) + self.popScope() + + SETCOMP = GENERATOREXP def DICTCOMP(self, node): + self.pushScope(GeneratorScope) for gen in node.generators: self.handleNode(gen, node) self.handleNode(node.key, node) self.handleNode(node.value, node) + self.popScope() def FOR(self, node): """ @@ -551,7 +678,7 @@ # unused ones will get an unused import warning and self.scope[varn].used): self.report(messages.ImportShadowedByLoopVar, - node.lineno, varn, self.scope[varn].source.lineno) + node, varn, self.scope[varn].source) self.handleChildren(node) @@ -559,12 +686,13 @@ """ Handle occurrence of Name (which can be a load/store/delete access.) """ - if node.id == 'locals' and isinstance(node.parent, ast.Call): - # we are doing locals() call in current scope - self.scope.usesLocals = True # 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): @@ -575,12 +703,12 @@ raise RuntimeError("Got impossible expression context: %r" % (node.ctx,)) def FUNCTIONDEF(self, node): - if not hasattr(node, 'decorator_list'): # Python 2.5 - node.decorator_list = node.decorators for deco in node.decorator_list: self.handleNode(deco, node) self.addBinding(node, FunctionDefinition(node.name, node)) self.LAMBDA(node) + if self.withDoctest: + self.deferFunction(lambda: self.handleDoctests(node)) def LAMBDA(self, node): args = [] @@ -593,7 +721,7 @@ else: if arg.id in args: self.report(messages.DuplicateArgument, - node.lineno, arg.id) + node, arg.id) args.append(arg.id) addArgs(node.args.args) defaults = node.args.defaults @@ -601,7 +729,7 @@ for arg in node.args.args + node.args.kwonlyargs: if arg.arg in args: self.report(messages.DuplicateArgument, - node.lineno, arg.arg) + node, arg.arg) args.append(arg.arg) self.handleNode(arg.annotation, node) if hasattr(node, 'returns'): # Only for FunctionDefs @@ -615,14 +743,14 @@ if not wildcard: continue if wildcard in args: - self.report(messages.DuplicateArgument, node.lineno, wildcard) + self.report(messages.DuplicateArgument, node, wildcard) args.append(wildcard) for default in defaults: self.handleNode(default, node) def runFunction(): - self.pushFunctionScope() + self.pushScope() for name in args: self.addBinding(node, Argument(name, node), reportRedef=False) if isinstance(node.body, list): @@ -637,12 +765,8 @@ """ Check to see if any assignments have not been used. """ - for name, binding in self.scope.items(): - if (not binding.used and name not in self.scope.globals - and not self.scope.usesLocals - and isinstance(binding, Assignment)): - self.report(messages.UnusedVariable, - binding.source.lineno, name) + for name, binding in self.scope.unusedAssignments(): + self.report(messages.UnusedVariable, binding.source, name) self.deferAssignment(checkUnusedAssignments) self.popScope() @@ -654,15 +778,16 @@ classes, and the body of its definition. Additionally, add its name to the current scope. """ - # no class decorator in Python 2.5 - for deco in getattr(node, 'decorator_list', ''): + 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.pushClassScope() + self.pushScope(ClassScope) + if self.withDoctest: + self.deferFunction(lambda: self.handleDoctests(node)) for stmt in node.body: self.handleNode(stmt, node) self.popScope() @@ -688,21 +813,42 @@ if node.module == '__future__': if not self.futuresAllowed: self.report(messages.LateFutureImport, - node.lineno, [n.name for n in node.names]) + 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.lineno, node.module) + 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.lineno) + 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:" + for child in iter_child_nodes(node): + if child not in node.body: + self.handleNode(child, node) + + 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.
--- a/Plugins/CheckerPlugins/SyntaxChecker/pyflakes/messages.py Sat Jan 04 22:14:38 2014 +0100 +++ b/Plugins/CheckerPlugins/SyntaxChecker/pyflakes/messages.py Sun Jan 05 22:45:29 2014 +0100 @@ -1,14 +1,14 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2010 - 2013 Detlev Offenbach <detlev@die-offenbachs.de> +# Copyright (c) 2010 - 2014 Detlev Offenbach <detlev@die-offenbachs.de> # -# Original (c) 2005 Divmod, Inc. See LICENSE file for details +# Original (c) 2005 Divmod, Inc. See __init__.py file for details # -# This module is based on pyflakes for Python2 but was heavily hacked to +# This module is based on pyflakes but was heavily hacked to # work within Eric5 and Qt (translatable messages) """ -Module implementing the messages for pyflakes. +Provide the class Message and its subclasses. """ # Tell 'lupdate' which strings to keep for translation. @@ -21,25 +21,26 @@ """ message = '' message_args = () - - def __init__(self, filename, lineno): + + def __init__(self, filename, loc): """ Constructor @param filename name of the file (string) - @param lineno line number (integer) + @param loc location of warning (object) """ self.filename = filename - self.lineno = lineno - + self.lineno = loc.lineno + self.col = getattr(loc, 'col_offset', 0) + def __str__(self): """ Special method return a string representation of the instance object. @return string representation of the object (string) """ - 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) def getMessageData(self): """ @@ -48,7 +49,8 @@ @return tuple containing file name, line number and message (string, integer, string) """ - return (self.filename, self.lineno, self.message, self.message_args) + return (self.filename, self.lineno, self.col, self.message, + self.message_args) class UnusedImport(Message): @@ -58,16 +60,16 @@ message = QT_TRANSLATE_NOOP( 'py3Flakes', '{0!r} imported but unused.') - - def __init__(self, filename, lineno, name): + + def __init__(self, filename, loc, name): """ Constructor @param filename name of the file (string) - @param lineno line number (integer) + @param loc location of warning (object) @param name name of the unused import (string) """ - Message.__init__(self, filename, lineno) + Message.__init__(self, filename, loc) self.message_args = (name,) @@ -79,17 +81,17 @@ 'py3Flakes', 'Redefinition of unused {0!r} from line {1!r}.') - def __init__(self, filename, lineno, name, orig_lineno): + def __init__(self, filename, loc, name, orig_loc): """ Constructor @param filename name of the file (string) - @param lineno line number (integer) + @param loc location of warning (object) @param name name of the redefined object (string) - @param orig_lineno line number of the original definition (integer) + @param orig_loc location of the original definition (object) """ - Message.__init__(self, filename, lineno) - self.message_args = (name, orig_lineno) + Message.__init__(self, filename, loc) + self.message_args = (name, orig_loc.lineno) class RedefinedInListComp(Message): @@ -100,17 +102,17 @@ 'py3Flakes', 'List comprehension redefines {0!r} from line {1!r}.') - def __init__(self, filename, lineno, name, orig_lineno): + def __init__(self, filename, loc, name, orig_loc): """ Constructor @param filename name of the file (string) - @param lineno line number (integer) + @param loc location of warning (object) @param name name of the redefined object (string) - @param orig_lineno line number of the original definition (integer) + @param orig_loc location of the original definition (object) """ - Message.__init__(self, filename, lineno) - self.message_args = (name, orig_lineno) + Message.__init__(self, filename, loc) + self.message_args = (name, orig_loc.lineno) class ImportShadowedByLoopVar(Message): @@ -120,18 +122,18 @@ message = QT_TRANSLATE_NOOP( 'py3Flakes', 'Import {0!r} from line {1!r} shadowed by loop variable.') - - def __init__(self, filename, lineno, name, orig_lineno): + + def __init__(self, filename, loc, name, orig_loc): """ Constructor @param filename name of the file (string) - @param lineno line number (integer) + @param loc location of warning (object) @param name name of the shadowed import (string) - @param orig_lineno line number of the import (integer) + @param orig_loc location of the import (object) """ - Message.__init__(self, filename, lineno) - self.message_args = (name, orig_lineno) + Message.__init__(self, filename, loc) + self.message_args = (name, orig_loc.lineno) class ImportStarUsed(Message): @@ -141,16 +143,16 @@ message = QT_TRANSLATE_NOOP( 'py3Flakes', "'from {0} import *' used; unable to detect undefined names.") - - def __init__(self, filename, lineno, modname): + + def __init__(self, filename, loc, modname): """ Constructor @param filename name of the file (string) - @param lineno line number (integer) + @param loc location of warning (object) @param modname name of the module imported using star import (string) """ - Message.__init__(self, filename, lineno) + Message.__init__(self, filename, loc) self.message_args = (modname,) @@ -159,19 +161,39 @@ Class defining the "Undefined Name" message. """ message = QT_TRANSLATE_NOOP('py3Flakes', 'Undefined name {0!r}.') - - def __init__(self, filename, lineno, name): + + def __init__(self, filename, loc, name): """ Constructor @param filename name of the file (string) - @param lineno line number (integer) + @param loc location of warning (object) @param name undefined name (string) """ - Message.__init__(self, filename, lineno) + Message.__init__(self, filename, loc) self.message_args = (name,) +class DoctestSyntaxError(Message): + """ + Class defining the "Syntax error in doctest" message. + """ + message = QT_TRANSLATE_NOOP('py3Flakes', 'Syntax error in doctest.') + + def __init__(self, filename, loc, position=None): + """ + Constructor + + @param filename name of the file (string) + @param loc location of warning (object) + @keyparam position of warning if existent (object) + """ + Message.__init__(self, filename, loc) + if position: + (self.lineno, self.col) = position + self.message_args = () + + class UndefinedExport(Message): """ Class defining the "Undefined Export" message. @@ -179,16 +201,16 @@ message = QT_TRANSLATE_NOOP( 'py3Flakes', 'Undefined name {0!r} in __all__.') - - def __init__(self, filename, lineno, name): + + def __init__(self, filename, loc, name): """ Constructor @param filename name of the file (string) - @param lineno line number (integer) + @param loc location of warning (object) @param name undefined exported name (string) """ - Message.__init__(self, filename, lineno) + Message.__init__(self, filename, loc) self.message_args = (name,) @@ -200,18 +222,18 @@ 'py3Flakes', "Local variable {0!r} (defined in enclosing scope on line {1!r})" " referenced before assignment.") - - def __init__(self, filename, lineno, name, orig_lineno): + + def __init__(self, filename, loc, name, orig_loc): """ Constructor @param filename name of the file (string) - @param lineno line number (integer) + @param loc location of warning (object) @param name name of the prematurely referenced variable (string) - @param orig_lineno line number of the variable definition (integer) + @param orig_loc location of the variable definition (object) """ - Message.__init__(self, filename, lineno) - self.message_args = (name, orig_lineno) + Message.__init__(self, filename, loc) + self.message_args = (name, orig_loc.lineno) class DuplicateArgument(Message): @@ -221,16 +243,16 @@ message = QT_TRANSLATE_NOOP( 'py3Flakes', 'Duplicate argument {0!r} in function definition.') - - def __init__(self, filename, lineno, name): + + def __init__(self, filename, loc, name): """ Constructor @param filename name of the file (string) - @param lineno line number (integer) + @param loc location of warning (object) @param name name of the duplicate argument (string) """ - Message.__init__(self, filename, lineno) + Message.__init__(self, filename, loc) self.message_args = (name,) @@ -241,18 +263,18 @@ message = QT_TRANSLATE_NOOP( 'py3Flakes', 'Redefinition of {0!r} from line {1!r}.') - - def __init__(self, filename, lineno, name, orig_lineno): + + def __init__(self, filename, loc, name, orig_loc): """ Constructor @param filename name of the file (string) - @param lineno line number (integer) + @param loc location of warning (object) @param name name of the redefined function (string) - @param orig_lineno line number of the original definition (integer) + @param orig_loc location of the original definition (object) """ - Message.__init__(self, filename, lineno) - self.message_args = (name, orig_lineno) + Message.__init__(self, filename, loc) + self.message_args = (name, orig_loc.lineno) class LateFutureImport(Message): @@ -262,16 +284,16 @@ message = QT_TRANSLATE_NOOP( 'py3Flakes', 'Future import(s) {0!r} after other statements.') - - def __init__(self, filename, lineno, names): + + def __init__(self, filename, loc, names): """ Constructor @param filename name of the file (string) - @param lineno line number (integer) + @param loc location of warning (object) @param names names of the imported futures (string) """ - Message.__init__(self, filename, lineno) + Message.__init__(self, filename, loc) self.message_args = (names,) @@ -285,14 +307,14 @@ message = QT_TRANSLATE_NOOP( 'py3Flakes', 'Local variable {0!r} is assigned to but never used.') - - def __init__(self, filename, lineno, names): + + def __init__(self, filename, loc, names): """ Constructor @param filename name of the file (string) - @param lineno line number (integer) + @param loc location of warning (object) @param names names of the unused variable (string) """ - Message.__init__(self, filename, lineno) + Message.__init__(self, filename, loc) self.message_args = (names,)
--- a/QScintilla/Editor.py Sat Jan 04 22:14:38 2014 +0100 +++ b/QScintilla/Editor.py Sun Jan 05 22:45:29 2014 +0100 @@ -8,9 +8,9 @@ """ from __future__ import unicode_literals try: - str = unicode # __IGNORE_WARNING__ - chr = unichr # __IGNORE_WARNING__ -except (NameError): + str = unicode + chr = unichr +except NameError: pass import os @@ -4994,7 +4994,7 @@ @param code the part of the code where the error occured (str) @param error the name of the error (str) @param warnings a list of strings containing the warnings - (marker, file name, line number, message) + (marker, file name, line number, col, message) """ # Check if it's the requested file, otherwise ignore signal if fn != self.fileName and ( @@ -5007,8 +5007,8 @@ if nok: self.toggleSyntaxError(line, index, True, error) else: - for warning in warnings: - self.toggleWarning(warning[2], True, warning[3]) + for marker, _fn, lineno, col, msg in warnings: + self.toggleWarning(lineno, True, msg) def __initOnlineSyntaxCheck(self): """
--- a/Utilities/InternalServices.py Sat Jan 04 22:14:38 2014 +0100 +++ b/Utilities/InternalServices.py Sun Jan 05 22:45:29 2014 +0100 @@ -83,17 +83,17 @@ @param code the part of the code where the error occured (str) @param error the name of the error (str) @param warnings a list of strings containing the warnings - (marker, file name, line number, message) + (marker, file name, line number, col, message, list(msg_args)) """ for warning in warnings: # Translate messages msg_args = warning.pop() translated = QApplication.translate( - 'py3Flakes', warning[3]).format(*msg_args) + 'py3Flakes', warning[4]).format(*msg_args) # Avoid leading "u" at Python2 unicode strings if translated.startswith("u'"): translated = translated[1:] - warning[3] = translated.replace(" u'", " '") + warning[4] = translated.replace(" u'", " '") self.syntaxChecked.emit( fn, nok, fname, line, index, code, error, warnings)