diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2015-08-25 21:06:19 +0300 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2015-08-25 21:06:19 +0300 |
commit | 5c8afd6b7472767e4fa4ab7d97b51a9afb80d3b2 (patch) | |
tree | 95fe7a46ee994e27542fb42f31e7b54935ad5aac | |
parent | 489e01057de4028887af7b6842621914816abea5 (diff) | |
download | pylint-5c8afd6b7472767e4fa4ab7d97b51a9afb80d3b2.tar.gz |
Update pylint to use the new astroid AST names and methods
Also improve a couple of imports and added support for the
old visit_ names. Priority will have the old visit_ names, such
as visit_discard over visit_expr, visit_callfunc over visit_call
etc.
-rw-r--r-- | pylint/checkers/base.py | 71 | ||||
-rw-r--r-- | pylint/checkers/classes.py | 58 | ||||
-rw-r--r-- | pylint/checkers/exceptions.py | 37 | ||||
-rw-r--r-- | pylint/checkers/imports.py | 6 | ||||
-rw-r--r-- | pylint/checkers/logging.py | 8 | ||||
-rw-r--r-- | pylint/checkers/newstyle.py | 8 | ||||
-rw-r--r-- | pylint/checkers/python3.py | 8 | ||||
-rw-r--r-- | pylint/checkers/stdlib.py | 6 | ||||
-rw-r--r-- | pylint/checkers/strings.py | 8 | ||||
-rw-r--r-- | pylint/checkers/typecheck.py | 64 | ||||
-rw-r--r-- | pylint/checkers/utils.py | 39 | ||||
-rw-r--r-- | pylint/checkers/variables.py | 81 | ||||
-rw-r--r-- | pylint/pyreverse/diadefslib.py | 6 | ||||
-rw-r--r-- | pylint/pyreverse/diagrams.py | 6 | ||||
-rw-r--r-- | pylint/pyreverse/inspector.py | 20 | ||||
-rw-r--r-- | pylint/test/extensions/test_check_docs.py | 4 | ||||
-rw-r--r-- | pylint/test/unittest_pyreverse_diadefs.py | 2 | ||||
-rw-r--r-- | pylint/test/unittest_pyreverse_inspector.py | 2 | ||||
-rw-r--r-- | pylint/utils.py | 41 |
19 files changed, 252 insertions, 223 deletions
diff --git a/pylint/checkers/base.py b/pylint/checkers/base.py index 1f0b5b3..b9387b4 100644 --- a/pylint/checkers/base.py +++ b/pylint/checkers/base.py @@ -98,7 +98,7 @@ def _redefines_import(node): if not current or not error_of_type(current.parent, ImportError): return False try_block = current.parent.parent - for import_node in try_block.nodes_of_class((astroid.From, astroid.Import)): + for import_node in try_block.nodes_of_class((astroid.ImportFrom, astroid.Import)): for name, alias in import_node.names: if alias: if alias == node.name: @@ -112,7 +112,7 @@ def in_loop(node): parent = node.parent while parent is not None: if isinstance(parent, (astroid.For, astroid.ListComp, astroid.SetComp, - astroid.DictComp, astroid.GenExpr)): + astroid.DictComp, astroid.GeneratorExp)): return True parent = parent.parent return False @@ -175,14 +175,14 @@ def _determine_function_name_type(node): # If the function is a property (decorated with @property # or @abc.abstractproperty), the name type is 'attr'. if (isinstance(decorator, astroid.Name) or - (isinstance(decorator, astroid.Getattr) and + (isinstance(decorator, astroid.Attribute) and decorator.attrname == 'abstractproperty')): infered = helpers.safe_infer(decorator) if infered and infered.qname() in PROPERTY_CLASSES: return 'attr' # If the function is decorated using the prop_method.{setter,getter} # form, treat it like an attribute as well. - elif (isinstance(decorator, astroid.Getattr) and + elif (isinstance(decorator, astroid.Attribute) and decorator.attrname in ('setter', 'deleter')): return 'attr' return 'method' @@ -250,7 +250,7 @@ def redefined_by_decorator(node): """ if node.decorators: for decorator in node.decorators.nodes: - if (isinstance(decorator, astroid.Getattr) and + if (isinstance(decorator, astroid.Attribute) and getattr(decorator.expr, 'name', None) == node.name): return True return False @@ -365,7 +365,8 @@ class BasicErrorChecker(_BasicChecker): self._check_redefinition(node.is_method() and 'method' or 'function', node) # checks for max returns, branch, return in __init__ returns = node.nodes_of_class(astroid.Return, - skip_klass=(astroid.Function, astroid.Class)) + skip_klass=(astroid.FunctionDef, + astroid.ClassDef)) if node.is_method() and node.name == '__init__': if node.is_generator(): self.add_message('init-is-generator', node=node) @@ -412,7 +413,7 @@ class BasicErrorChecker(_BasicChecker): @check_messages('return-outside-function') def visit_return(self, node): - if not isinstance(node.frame(), astroid.Function): + if not isinstance(node.frame(), astroid.FunctionDef): self.add_message('return-outside-function', node=node) @check_messages('yield-outside-function') @@ -456,7 +457,7 @@ class BasicErrorChecker(_BasicChecker): infered = next(node.func.infer()) except astroid.InferenceError: return - if not isinstance(infered, astroid.Class): + if not isinstance(infered, astroid.ClassDef): return # __init__ was called metaclass = infered.metaclass() @@ -477,7 +478,7 @@ class BasicErrorChecker(_BasicChecker): node=node) def _check_yield_outside_func(self, node): - if not isinstance(node.frame(), (astroid.Function, astroid.Lambda)): + if not isinstance(node.frame(), (astroid.FunctionDef, astroid.Lambda)): self.add_message('yield-outside-function', node=node) def _check_else_on_loop(self, node): @@ -497,7 +498,7 @@ class BasicErrorChecker(_BasicChecker): if node not in _node.orelse: return - if isinstance(_node, (astroid.Class, astroid.Function)): + if isinstance(_node, (astroid.ClassDef, astroid.FunctionDef)): break if (isinstance(_node, astroid.TryFinally) and node in _node.finalbody @@ -655,8 +656,8 @@ functions, methods def _check_using_constant_test(self, node, test): const_nodes = ( astroid.Module, - astroid.scoped_nodes.GenExpr, - astroid.Lambda, astroid.Function, astroid.Class, + astroid.scoped_nodes.GeneratorExp, + astroid.Lambda, astroid.FunctionDef, astroid.ClassDef, astroid.bases.Generator, astroid.UnboundMethod, astroid.BoundMethod, astroid.Module) structs = (astroid.Dict, astroid.Tuple, astroid.Set) @@ -667,7 +668,7 @@ functions, methods # Getattr, which is excepted because the conditional statement # can be used to verify that the attribute was set inside a class, # which is definitely a valid use case. - except_nodes = (astroid.Getattr, astroid.CallFunc, + except_nodes = (astroid.Attribute, astroid.Call, astroid.BinOp, astroid.BoolOp, astroid.UnaryOp, astroid.Subscript) inferred = None @@ -691,7 +692,7 @@ functions, methods @check_messages('pointless-statement', 'pointless-string-statement', 'expression-not-assigned') - def visit_discard(self, node): + def visit_expr(self, node): """check for various kind of statements without effect""" expr = node.value if isinstance(expr, astroid.Const) and isinstance(expr.value, @@ -701,8 +702,8 @@ functions, methods # An attribute docstring is defined as being a string right after # an assignment at the module level, class level or __init__ level. scope = expr.scope() - if isinstance(scope, (astroid.Class, astroid.Module, astroid.Function)): - if isinstance(scope, astroid.Function) and scope.name != '__init__': + if isinstance(scope, (astroid.ClassDef, astroid.Module, astroid.FunctionDef)): + if isinstance(scope, astroid.FunctionDef) and scope.name != '__init__': pass else: sibling = expr.previous_sibling() @@ -717,11 +718,11 @@ functions, methods # * a yield (which are wrapped by a discard node in _ast XXX) # warn W0106 if we have any underlying function call (we can't predict # side effects), else pointless-statement - if (isinstance(expr, (astroid.Yield, astroid.CallFunc)) or + if (isinstance(expr, (astroid.Yield, astroid.Call)) or (isinstance(node.parent, astroid.TryExcept) and node.parent.body == [node])): return - if any(expr.nodes_of_class(astroid.CallFunc)): + if any(expr.nodes_of_class(astroid.Call)): self.add_message('expression-not-assigned', node=node, args=expr.as_string()) else: @@ -742,7 +743,7 @@ functions, methods # of the lambda. return call = node.body - if not isinstance(call, astroid.CallFunc): + if not isinstance(call, astroid.Call): # The body of the lambda must be a function call expression # for the lambda to be unnecessary. return @@ -784,8 +785,8 @@ functions, methods return if node.args.args[i].name != call.args[i].name: return - if (isinstance(node.body.func, astroid.Getattr) and - isinstance(node.body.func.expr, astroid.CallFunc)): + if (isinstance(node.body.func, astroid.Attribute) and + isinstance(node.body.func.expr, astroid.Call)): # Chained call, the intermediate call might # return something else (but we don't check that, yet). return @@ -825,7 +826,7 @@ functions, methods # or a dict. if is_iterable(default): msg = value.pytype() - elif isinstance(default, astroid.CallFunc): + elif isinstance(default, astroid.Call): msg = '%s() (%s)' % (value.name, value.qname()) else: msg = '%s (%s)' % (default.as_string(), value.qname()) @@ -846,7 +847,7 @@ functions, methods """ self._check_unreachable(node) # Is it inside final body of a try...finally bloc ? - self._check_not_in_finally(node, 'return', (astroid.Function,)) + self._check_not_in_finally(node, 'return', (astroid.FunctionDef,)) @check_messages('unreachable') def visit_continue(self, node): @@ -967,7 +968,7 @@ functions, methods if argument is None: # Nothing was infered. # Try to see if we have iter(). - if isinstance(node.args[0], astroid.CallFunc): + if isinstance(node.args[0], astroid.Call): try: func = next(node.args[0].func.infer()) except InferenceError: @@ -1025,8 +1026,8 @@ functions, methods prev_pair = None for pair in pairs: if prev_pair is not None: - if (isinstance(prev_pair[1], astroid.AssName) and - (pair[1] is None and not isinstance(pair[0], astroid.CallFunc))): + if (isinstance(prev_pair[1], astroid.AssignName) and + (pair[1] is None and not isinstance(pair[0], astroid.Call))): # don't emit a message if the second is a function call # there's no way that can be mistaken for a name assignment if PY3K or node.lineno == node.parent.lineno: @@ -1177,12 +1178,12 @@ class NameChecker(_BasicChecker): def visit_assname(self, node): """check module level assigned names""" frame = node.frame() - ass_type = node.ass_type() + ass_type = node.assign_type() if isinstance(ass_type, astroid.Comprehension): self._check_name('inlinevar', node.name, node) elif isinstance(frame, astroid.Module): if isinstance(ass_type, astroid.Assign) and not in_loop(ass_type): - if isinstance(helpers.safe_infer(ass_type.value), astroid.Class): + if isinstance(helpers.safe_infer(ass_type.value), astroid.ClassDef): self._check_name('class', node.name, node) else: if not _redefines_import(node): @@ -1191,19 +1192,19 @@ class NameChecker(_BasicChecker): self._check_name('const', node.name, node) elif isinstance(ass_type, astroid.ExceptHandler): self._check_name('variable', node.name, node) - elif isinstance(frame, astroid.Function): + elif isinstance(frame, astroid.FunctionDef): # global introduced variable aren't in the function locals if node.name in frame and node.name not in frame.argnames(): if not _redefines_import(node): self._check_name('variable', node.name, node) - elif isinstance(frame, astroid.Class): + elif isinstance(frame, astroid.ClassDef): if not list(frame.local_attr_ancestors(node.name)): self._check_name('class_attribute', node.name, node) def _recursive_check_names(self, args, node): """check names in a possibly recursive list <arg>""" for arg in args: - if isinstance(arg, astroid.AssName): + if isinstance(arg, astroid.AssignName): self._check_name('argument', arg.name, node) else: self._recursive_check_names(arg.elts, node) @@ -1291,14 +1292,14 @@ class DocStringChecker(_BasicChecker): def visit_function(self, node): if self.config.no_docstring_rgx.match(node.name) is None: ftype = node.is_method() and 'method' or 'function' - if isinstance(node.parent.frame(), astroid.Class): + if isinstance(node.parent.frame(), astroid.ClassDef): overridden = False confidence = (INFERENCE if helpers.has_known_bases(node.parent.frame()) else INFERENCE_FAILURE) # check if node is from a method overridden by its ancestor for ancestor in node.parent.frame().ancestors(): if node.name in ancestor and \ - isinstance(ancestor[node.name], astroid.Function): + isinstance(ancestor[node.name], astroid.FunctionDef): overridden = True break self._check_docstring(ftype, node, @@ -1328,8 +1329,8 @@ class DocStringChecker(_BasicChecker): if node_type != 'module' and max_lines > -1 and lines < max_lines: return self.stats['undocumented_'+node_type] += 1 - if (node.body and isinstance(node.body[0], astroid.Discard) and - isinstance(node.body[0].value, astroid.CallFunc)): + if (node.body and isinstance(node.body[0], astroid.Expr) and + isinstance(node.body[0].value, astroid.Call)): # Most likely a string with a format call. Let's see. func = helpers.safe_infer(node.body[0].value.func) if (isinstance(func, astroid.BoundMethod) diff --git a/pylint/checkers/classes.py b/pylint/checkers/classes.py index edbc36b..e573153 100644 --- a/pylint/checkers/classes.py +++ b/pylint/checkers/classes.py @@ -21,7 +21,6 @@ import sys from collections import defaultdict import astroid -from astroid import YES, Instance, are_exclusive, AssAttr, Class from astroid.bases import Generator, BUILTINS from astroid.exceptions import InconsistentMroError, DuplicateBasesError from astroid import objects @@ -62,7 +61,7 @@ def _called_in_methods(func, klass, methods): """ Check if the func was called in any of the given methods, belonging to the *klass*. Returns True if so, False otherwise. """ - if not isinstance(func, astroid.Function): + if not isinstance(func, astroid.FunctionDef): return False for method in methods: try: @@ -70,7 +69,7 @@ def _called_in_methods(func, klass, methods): except astroid.NotFoundError: continue for infer_method in infered: - for callfunc in infer_method.nodes_of_class(astroid.CallFunc): + for callfunc in infer_method.nodes_of_class(astroid.Call): try: bound = next(callfunc.func.infer()) except (astroid.InferenceError, StopIteration): @@ -115,7 +114,7 @@ def _is_attribute_property(name, klass): infered = next(attr.infer()) except astroid.InferenceError: continue - if (isinstance(infered, astroid.Function) and + if (isinstance(infered, astroid.FunctionDef) and decorated_with_property(infered)): return True if infered.pytype() == property_name: @@ -258,7 +257,7 @@ class ClassChecker(BaseChecker): priority = -2 # configuration options options = (('ignore-iface-methods', - # TODO(cpopa): remove this in Pylint 1.7. + # TODO(cpopa): remove this in Pylint 1.6. deprecated_option(opt_type="csv", help_msg="This is deprecated, because " "it is not used anymore.") @@ -337,13 +336,13 @@ a metaclass class method.'} """ for base in node.bases: ancestor = helpers.safe_infer(base) - if ancestor in (YES, None): + if ancestor in (astroid.YES, None): continue if (isinstance(ancestor, astroid.Instance) and ancestor.is_subtype_of('%s.type' % (BUILTINS,))): continue - if (not isinstance(ancestor, astroid.Class) or + if (not isinstance(ancestor, astroid.ClassDef) or _is_invalid_base_class(ancestor)): self.add_message('inherit-non-class', args=base.as_string(), node=node) @@ -433,13 +432,13 @@ a metaclass class method.'} # dictionary. # This may happen with astroid build from living objects continue - if not isinstance(meth_node, astroid.Function): + if not isinstance(meth_node, astroid.FunctionDef): continue self._check_signature(node, meth_node, 'overridden', klass) break if node.decorators: for decorator in node.decorators.nodes: - if isinstance(decorator, astroid.Getattr) and \ + if isinstance(decorator, astroid.Attribute) and \ decorator.attrname in ('getter', 'setter', 'deleter'): # attribute affectation will call this method, not hiding it return @@ -451,10 +450,10 @@ a metaclass class method.'} try: overridden = klass.instance_attr(node.name)[0] # XXX overridden_frame = overridden.frame() - if (isinstance(overridden_frame, astroid.Function) + if (isinstance(overridden_frame, astroid.FunctionDef) and overridden_frame.type == 'method'): overridden_frame = overridden_frame.parent.frame() - if (isinstance(overridden_frame, Class) + if (isinstance(overridden_frame, astroid.ClassDef) and klass.is_subtype_of(overridden_frame.qname())): args = (overridden.root().name, overridden.fromlineno) self.add_message('method-hidden', args=args, node=node) @@ -487,7 +486,7 @@ a metaclass class method.'} values = [item[0] for item in slots.items] else: values = slots.itered() - if values is YES: + if values is astroid.YES: return for elt in values: @@ -498,7 +497,7 @@ a metaclass class method.'} def _check_slots_elt(self, elt): for infered in elt.infer(): - if infered is YES: + if infered is astroid.YES: continue if (not isinstance(infered, astroid.Const) or not isinstance(infered.value, six.string_types)): @@ -547,7 +546,7 @@ a metaclass class method.'} self._check_protected_attribute_access(node) def visit_assattr(self, node): - if isinstance(node.ass_type(), astroid.AugAssign) and self.is_first_attr(node): + if isinstance(node.assign_type(), astroid.AugAssign) and self.is_first_attr(node): self._accessed[-1][node.attrname].append(node) self._check_in_slots(node) @@ -556,7 +555,7 @@ a metaclass class method.'} is defined in the class slots. """ infered = helpers.safe_infer(node.expr) - if infered and isinstance(infered, Instance): + if infered and isinstance(infered, astroid.Instance): klass = infered._proxied if '__slots__' not in klass.locals or not klass.newstyle: return @@ -585,7 +584,7 @@ a metaclass class method.'} @check_messages('protected-access') def visit_assign(self, assign_node): node = assign_node.targets[0] - if not isinstance(node, AssAttr): + if not isinstance(node, astroid.AssignAttr): return if self.is_first_attr(node): @@ -621,7 +620,7 @@ a metaclass class method.'} return # If the expression begins with a call to super, that's ok. - if isinstance(node.expr, astroid.CallFunc) and \ + if isinstance(node.expr, astroid.Call) and \ isinstance(node.expr.func, astroid.Name) and \ node.expr.func.name == 'super': return @@ -639,7 +638,7 @@ a metaclass class method.'} try: if (isinstance(stmt, astroid.Assign) and (stmt in klass.body or klass.parent_of(stmt)) and - isinstance(stmt.value, astroid.CallFunc) and + isinstance(stmt.value, astroid.Call) and isinstance(stmt.value.func, astroid.Name) and stmt.value.func.name == 'property' and is_builtin_object(next(stmt.value.func.infer(), None))): @@ -659,6 +658,7 @@ a metaclass class method.'} def _check_accessed_members(self, node, accessed): """check that accessed members are defined""" # XXX refactor, probably much simpler now that E0201 is in type checker + excs = ('AttributeError', 'Exception', 'BaseException') for attr, nodes in six.iteritems(accessed): try: # is it a class attribute ? @@ -701,8 +701,7 @@ a metaclass class method.'} lno = defstmt.fromlineno for _node in nodes: if _node.frame() is frame and _node.fromlineno < lno \ - and not are_exclusive(_node.statement(), defstmt, - ('AttributeError', 'Exception', 'BaseException')): + and not astroid.are_exclusive(_node.statement(), defstmt, excs): self.add_message('access-member-before-definition', node=_node, args=(attr, lno)) @@ -808,19 +807,19 @@ a metaclass class method.'} klass_node = node.parent.frame() to_call = _ancestors_to_call(klass_node) not_called_yet = dict(to_call) - for stmt in node.nodes_of_class(astroid.CallFunc): + for stmt in node.nodes_of_class(astroid.Call): expr = stmt.func - if not isinstance(expr, astroid.Getattr) \ + if not isinstance(expr, astroid.Attribute) \ or expr.attrname != '__init__': continue # skip the test if using super - if isinstance(expr.expr, astroid.CallFunc) and \ + if isinstance(expr.expr, astroid.Call) and \ isinstance(expr.expr.func, astroid.Name) and \ expr.expr.func.name == 'super': return try: for klass in expr.expr.infer(): - if klass is YES: + if klass is astroid.YES: continue # The infered klass can be super(), which was # assigned to a variable and the `__init__` @@ -830,7 +829,7 @@ a metaclass class method.'} # base.__init__(...) if (isinstance(klass, astroid.Instance) and - isinstance(klass._proxied, astroid.Class) and + isinstance(klass._proxied, astroid.ClassDef) and is_builtin_object(klass._proxied) and klass._proxied.name == 'super'): return @@ -852,8 +851,8 @@ a metaclass class method.'} def _check_signature(self, method1, refmethod, class_type, cls): """check that the signature of the two given methods match """ - if not (isinstance(method1, astroid.Function) - and isinstance(refmethod, astroid.Function)): + if not (isinstance(method1, astroid.FunctionDef) + and isinstance(refmethod, astroid.FunctionDef)): self.add_message('method-check-failed', args=(method1, refmethod), node=method1) return @@ -875,7 +874,7 @@ a metaclass class method.'} # which shouldn't be taken in consideration. if method1.decorators: for decorator in method1.decorators.nodes: - if (isinstance(decorator, astroid.Getattr) and + if (isinstance(decorator, astroid.Attribute) and decorator.attrname == 'setter'): return @@ -982,7 +981,7 @@ class SpecialMethodsChecker(BaseChecker): return for infered_node in infered: - if (infered_node is YES + if (infered_node is astroid.YES or isinstance(infered_node, Generator)): continue if isinstance(infered_node, astroid.Instance): @@ -1020,4 +1019,3 @@ def register(linter): """required method to auto register this checker """ linter.register_checker(ClassChecker(linter)) linter.register_checker(SpecialMethodsChecker(linter)) - diff --git a/pylint/checkers/exceptions.py b/pylint/checkers/exceptions.py index 9020d5f..00bd214 100644 --- a/pylint/checkers/exceptions.py +++ b/pylint/checkers/exceptions.py @@ -18,7 +18,6 @@ import inspect import sys import astroid -from astroid import YES, Instance, unpack_infer, List, Tuple from astroid import helpers from six.moves import builtins import six @@ -47,14 +46,14 @@ def _annotated_unpack_infer(stmt, context=None): Returns an iterator which yields tuples in the format ('original node', 'infered node'). """ - if isinstance(stmt, (List, Tuple)): + if isinstance(stmt, (astroid.List, astroid.Tuple)): for elt in stmt.elts: inferred = helpers.safe_infer(elt) - if inferred and inferred is not YES: + if inferred and inferred is not astroid.YES: yield elt, inferred return for infered in stmt.infer(context): - if infered is YES: + if infered is astroid.YES: continue yield stmt, infered @@ -157,7 +156,7 @@ class ExceptionsChecker(BaseChecker): return else: try: - value = next(unpack_infer(expr)) + value = next(astroid.unpack_infer(expr)) except astroid.InferenceError: return self._check_raise_value(node, value) @@ -168,13 +167,13 @@ class ExceptionsChecker(BaseChecker): An exception context can be only `None` or an exception. """ cause = helpers.safe_infer(node.cause) - if cause in (YES, None): + if cause in (astroid.YES, None): return if isinstance(cause, astroid.Const): if cause.value is not None: self.add_message('bad-exception-context', node=node) - elif (not isinstance(cause, astroid.Class) and + elif (not isinstance(cause, astroid.ClassDef) and not inherit_from_std_ex(cause)): self.add_message('bad-exception-context', node=node) @@ -192,7 +191,7 @@ class ExceptionsChecker(BaseChecker): elif ((isinstance(expr, astroid.Name) and expr.name in ('None', 'True', 'False')) or isinstance(expr, (astroid.List, astroid.Dict, astroid.Tuple, - astroid.Module, astroid.Function))): + astroid.Module, astroid.FunctionDef))): emit = True if not PY3K and isinstance(expr, astroid.Tuple) and expr.elts: # On Python 2, using the following is not an error: @@ -204,11 +203,11 @@ class ExceptionsChecker(BaseChecker): # the scope of this check. first = expr.elts[0] inferred = helpers.safe_infer(first) - if isinstance(inferred, Instance): + if isinstance(inferred, astroid.Instance): # pylint: disable=protected-access inferred = inferred._proxied - if (inferred is YES or - isinstance(inferred, astroid.Class) + if (inferred is astroid.YES or + isinstance(inferred, astroid.ClassDef) and inherit_from_std_ex(inferred)): emit = False if emit: @@ -216,15 +215,15 @@ class ExceptionsChecker(BaseChecker): node=node, args=expr.name) elif ((isinstance(expr, astroid.Name) and expr.name == 'NotImplemented') - or (isinstance(expr, astroid.CallFunc) and + or (isinstance(expr, astroid.Call) and isinstance(expr.func, astroid.Name) and expr.func.name == 'NotImplemented')): self.add_message('notimplemented-raised', node=node) - elif isinstance(expr, (Instance, astroid.Class)): - if isinstance(expr, Instance): + elif isinstance(expr, (astroid.Instance, astroid.ClassDef)): + if isinstance(expr, astroid.Instance): # pylint: disable=protected-access expr = expr._proxied - if (isinstance(expr, astroid.Class) and + if (isinstance(expr, astroid.ClassDef) and not inherit_from_std_ex(expr) and helpers.has_known_bases(expr)): if expr.newstyle: @@ -248,7 +247,7 @@ class ExceptionsChecker(BaseChecker): for node in inferred): return - if not isinstance(exc, astroid.Class): + if not isinstance(exc, astroid.ClassDef): # Don't emit the warning if the infered stmt # is None, but the exception handler is something else, # maybe it was redefined. @@ -303,7 +302,7 @@ class ExceptionsChecker(BaseChecker): except astroid.InferenceError: continue for part, exc in excs: - if exc is YES: + if exc is astroid.YES: continue if (isinstance(exc, astroid.Instance) and inherit_from_std_ex(exc)): @@ -312,11 +311,11 @@ class ExceptionsChecker(BaseChecker): self._check_catching_non_exception(handler, exc, part) - if not isinstance(exc, astroid.Class): + if not isinstance(exc, astroid.ClassDef): continue exc_ancestors = [anc for anc in exc.ancestors() - if isinstance(anc, astroid.Class)] + if isinstance(anc, astroid.ClassDef)] for previous_exc in exceptions_classes: if previous_exc in exc_ancestors: msg = '%s is an ancestor class of %s' % ( diff --git a/pylint/checkers/imports.py b/pylint/checkers/imports.py index dc35d79..a70f7ce 100644 --- a/pylint/checkers/imports.py +++ b/pylint/checkers/imports.py @@ -41,7 +41,7 @@ def _get_import_name(importnode, modname): for debugging. Otherwise, the initial module name is returned unchanged. """ - if isinstance(importnode, astroid.From): + if isinstance(importnode, astroid.ImportFrom): if importnode.level: root = importnode.root() if isinstance(root, astroid.Module): @@ -66,7 +66,7 @@ def get_first_import(node, context, name, base, level): if any(fullname == iname[0] for iname in first.names): found = True break - elif isinstance(first, astroid.From): + elif isinstance(first, astroid.ImportFrom): if level == first.level and any( fullname == '%s.%s' % (first.modname, iname[0]) for iname in first.names): @@ -275,7 +275,7 @@ given file (report RP0402 must not be disabled)'} prev = node.previous_sibling() if prev: # consecutive future statements are possible - if not (isinstance(prev, astroid.From) + if not (isinstance(prev, astroid.ImportFrom) and prev.modname == '__future__'): self.add_message('misplaced-future', node=node) return diff --git a/pylint/checkers/logging.py b/pylint/checkers/logging.py index e074a18..ddfdc29 100644 --- a/pylint/checkers/logging.py +++ b/pylint/checkers/logging.py @@ -78,7 +78,7 @@ def is_method_call(callfunc_node, types=(), methods=()): True, if the node represents a method call for the given type and method names, False otherwise. """ - if not isinstance(callfunc_node, astroid.CallFunc): + if not isinstance(callfunc_node, astroid.Call): return False func = helpers.safe_infer(callfunc_node.func) return (isinstance(func, astroid.BoundMethod) @@ -139,7 +139,7 @@ class LoggingChecker(checkers.BaseChecker): def visit_callfunc(self, node): """Checks calls to logging methods.""" def is_logging_name(): - return (isinstance(node.func, astroid.Getattr) and + return (isinstance(node.func, astroid.Attribute) and isinstance(node.func.expr, astroid.Name) and node.func.expr.name in self._logging_names) @@ -148,7 +148,7 @@ class LoggingChecker(checkers.BaseChecker): for inferred in node.func.infer(): if isinstance(inferred, astroid.BoundMethod): parent = inferred._proxied.parent - if (isinstance(parent, astroid.Class) and + if (isinstance(parent, astroid.ClassDef) and (parent.qname() == 'logging.Logger' or any(ancestor.qname() == 'logging.Logger' for ancestor in parent.ancestors()))): @@ -184,7 +184,7 @@ class LoggingChecker(checkers.BaseChecker): if isinstance(node.args[format_pos], astroid.BinOp) and node.args[format_pos].op == '%': self.add_message('logging-not-lazy', node=node) - elif isinstance(node.args[format_pos], astroid.CallFunc): + elif isinstance(node.args[format_pos], astroid.Call): self._check_call_func(node.args[format_pos]) elif isinstance(node.args[format_pos], astroid.Const): self._check_format_string(node, format_pos) diff --git a/pylint/checkers/newstyle.py b/pylint/checkers/newstyle.py index 035aea2..5e88a32 100644 --- a/pylint/checkers/newstyle.py +++ b/pylint/checkers/newstyle.py @@ -98,7 +98,7 @@ class NewStyleConflictChecker(BaseChecker): def visit_callfunc(self, node): """check property usage""" parent = node.parent.frame() - if (isinstance(parent, astroid.Class) and + if (isinstance(parent, astroid.ClassDef) and not parent.newstyle and isinstance(node.func, astroid.Name)): confidence = (INFERENCE if helpers.has_known_bases(parent) @@ -115,16 +115,16 @@ class NewStyleConflictChecker(BaseChecker): if not node.is_method(): return klass = node.parent.frame() - for stmt in node.nodes_of_class(astroid.CallFunc): + for stmt in node.nodes_of_class(astroid.Call): if node_frame_class(stmt) != node_frame_class(node): # Don't look down in other scopes. continue expr = stmt.func - if not isinstance(expr, astroid.Getattr): + if not isinstance(expr, astroid.Attribute): continue call = expr.expr # skip the test if using super - if isinstance(call, astroid.CallFunc) and \ + if isinstance(call, astroid.Call) and \ isinstance(call.func, astroid.Name) and \ call.func.name == 'super': confidence = (INFERENCE if helpers.has_known_bases(klass) diff --git a/pylint/checkers/python3.py b/pylint/checkers/python3.py index 96df851..ead2f03 100644 --- a/pylint/checkers/python3.py +++ b/pylint/checkers/python3.py @@ -73,12 +73,12 @@ def _in_iterating_context(node): return True # Various built-ins can take in an iterable or list and lead to the same # value. - elif isinstance(parent, astroid.CallFunc): + elif isinstance(parent, astroid.Call): if isinstance(parent.func, astroid.Name): parent_scope = parent.func.lookup(parent.func.name)[0] if _is_builtin(parent_scope) and parent.func.name in _ACCEPTS_ITERATOR: return True - elif isinstance(parent.func, astroid.Getattr): + elif isinstance(parent.func, astroid.Attribute): if parent.func.attrname == 'join': return True # If the call is in an unpacking, there's no need to warn, @@ -446,7 +446,7 @@ class Python3Checker(checkers.BaseChecker): def _check_cmp_argument(self, node): # Check that the `cmp` argument is used kwargs = [] - if (isinstance(node.func, astroid.Getattr) + if (isinstance(node.func, astroid.Attribute) and node.func.attrname == 'sort'): inferred = helpers.safe_infer(node.func.expr) if not inferred: @@ -475,7 +475,7 @@ class Python3Checker(checkers.BaseChecker): def visit_callfunc(self, node): self._check_cmp_argument(node) - if isinstance(node.func, astroid.Getattr): + if isinstance(node.func, astroid.Attribute): if any([node.args, node.starargs, node.kwargs, node.keywords]): return if node.func.attrname == 'next': diff --git a/pylint/checkers/stdlib.py b/pylint/checkers/stdlib.py index 0e444af..af50a19 100644 --- a/pylint/checkers/stdlib.py +++ b/pylint/checkers/stdlib.py @@ -84,7 +84,7 @@ def _is_one_arg_pos_call(call): """Is this a call with exactly 1 argument, where that argument is positional? """ - return (isinstance(call, astroid.CallFunc) + return (isinstance(call, astroid.Call) and len(call.args) == 1 and not call.keywords) @@ -195,13 +195,13 @@ class StdlibChecker(BaseChecker): def _check_type_x_is_y(self, node, left, operator, right): """Check for expressions like type(x) == Y.""" left_func = helpers.safe_infer(left.func) - if not (isinstance(left_func, astroid.Class) + if not (isinstance(left_func, astroid.ClassDef) and left_func.qname() == TYPE_QNAME): return if operator in ('is', 'is not') and _is_one_arg_pos_call(right): right_func = helpers.safe_infer(right.func) - if (isinstance(right_func, astroid.Class) + if (isinstance(right_func, astroid.ClassDef) and right_func.qname() == TYPE_QNAME): # type(x) == type(a) right_arg = helpers.safe_infer(right.args[0]) diff --git a/pylint/checkers/strings.py b/pylint/checkers/strings.py index cfa1a01..90f760c 100644 --- a/pylint/checkers/strings.py +++ b/pylint/checkers/strings.py @@ -115,9 +115,9 @@ MSGS = { {'minversion': (2, 7)}) } -OTHER_NODES = (astroid.Const, astroid.List, astroid.Backquote, - astroid.Lambda, astroid.Function, - astroid.ListComp, astroid.SetComp, astroid.GenExpr) +OTHER_NODES = (astroid.Const, astroid.List, astroid.Repr, + astroid.Lambda, astroid.FunctionDef, + astroid.ListComp, astroid.SetComp, astroid.GeneratorExp) if _PY3K: import _string @@ -361,7 +361,7 @@ class StringMethodsChecker(BaseChecker): # # fmt = 'some string {}'.format # fmt('arg') - if (isinstance(node.func, astroid.Getattr) + if (isinstance(node.func, astroid.Attribute) and not isinstance(node.func.expr, astroid.Const)): return try: diff --git a/pylint/checkers/typecheck.py b/pylint/checkers/typecheck.py index a0f1e5e..dd9e55a 100644 --- a/pylint/checkers/typecheck.py +++ b/pylint/checkers/typecheck.py @@ -24,11 +24,7 @@ import sys import astroid import astroid.context -from astroid import ( - InferenceError, NotFoundError, - MroError, SuperError, YES, Instance -) -from astroid.bases import BUILTINS +from astroid import exceptions from astroid import objects from astroid import helpers import six @@ -44,6 +40,7 @@ from pylint import utils _ZOPE_DEPRECATED = ( "This option is deprecated. Use generated-members instead." ) +BUILTINS = six.moves.builtins.__name__ def _unflatten(iterable): @@ -172,9 +169,9 @@ def _emit_no_member(node, owner, owner_name, ignored_mixins): return False if ignored_mixins and owner_name[-5:].lower() == 'mixin': return False - if isinstance(owner, astroid.Function) and owner.decorators: + if isinstance(owner, astroid.FunctionDef) and owner.decorators: return False - if isinstance(owner, Instance): + if isinstance(owner, astroid.Instance): if owner.has_dynamic_getattr() or not helpers.has_known_bases(owner): return False if isinstance(owner, objects.Super): @@ -184,7 +181,7 @@ def _emit_no_member(node, owner, owner_name, ignored_mixins): # MRO is invalid. try: owner.super_mro() - except (MroError, SuperError): + except (exceptions.MroError, exceptions.SuperError): return False if not all(map(helpers.has_known_bases, owner.type.mro())): return False @@ -199,11 +196,11 @@ def _determine_callable(callable_obj): return callable_obj, 1, callable_obj.type elif isinstance(callable_obj, astroid.UnboundMethod): return callable_obj, 0, 'unbound method' - elif isinstance(callable_obj, astroid.Function): + elif isinstance(callable_obj, astroid.FunctionDef): return callable_obj, 0, callable_obj.type elif isinstance(callable_obj, astroid.Lambda): return callable_obj, 0, 'lambda' - elif isinstance(callable_obj, astroid.Class): + elif isinstance(callable_obj, astroid.ClassDef): # Class instantiation, lookup __new__ instead. # If we only find object.__new__, we can safely check __init__ # instead. If __new__ belongs to builtins, then we look @@ -212,7 +209,7 @@ def _determine_callable(callable_obj): try: # Use the last definition of __new__. new = callable_obj.local_attr('__new__')[-1] - except astroid.NotFoundError: + except exceptions.NotFoundError: new = None from_object = new and new.parent.scope().name == 'object' @@ -222,13 +219,13 @@ def _determine_callable(callable_obj): try: # Use the last definition of __init__. callable_obj = callable_obj.local_attr('__init__')[-1] - except astroid.NotFoundError: + except exceptions.NotFoundError: # do nothing, covered by no-init. raise ValueError else: callable_obj = new - if not isinstance(callable_obj, astroid.Function): + if not isinstance(callable_obj, astroid.FunctionDef): raise ValueError # both have an extra implicit 'cls'/'self' argument. return callable_obj, 1, 'constructor' @@ -292,7 +289,7 @@ accessed. Python regular expressions are accepted.'} self.generated_members = list(self.config.generated_members) def visit_assattr(self, node): - if isinstance(node.ass_type(), astroid.AugAssign): + if isinstance(node.assign_type(), astroid.AugAssign): self.visit_getattr(node) def visit_delattr(self, node): @@ -322,14 +319,14 @@ accessed. Python regular expressions are accepted.'} return try: infered = list(node.expr.infer()) - except InferenceError: + except exceptions.InferenceError: return # list of (node, nodename) which are missing the attribute missingattr = set() inference_failure = False for owner in infered: # skip yes object - if owner is YES: + if owner is astroid.YES: inference_failure = True continue @@ -346,7 +343,7 @@ accessed. Python regular expressions are accepted.'} except AttributeError: # XXX method / function continue - except NotFoundError: + except exceptions.NotFoundError: # This can't be moved before the actual .getattr call, # because there can be more values inferred and we are # stopping after the first one which has the attribute in question. @@ -366,7 +363,7 @@ accessed. Python regular expressions are accepted.'} # message for infered nodes done = set() for owner, name in missingattr: - if isinstance(owner, Instance): + if isinstance(owner, astroid.Instance): actual = owner._proxied else: actual = owner @@ -384,18 +381,18 @@ accessed. Python regular expressions are accepted.'} """check that if assigning to a function call, the function is possibly returning something valuable """ - if not isinstance(node.value, astroid.CallFunc): + if not isinstance(node.value, astroid.Call): return function_node = helpers.safe_infer(node.value.func) # skip class, generator and incomplete function definition - if not (isinstance(function_node, astroid.Function) and + if not (isinstance(function_node, astroid.FunctionDef) and function_node.root().fully_defined()): return if function_node.is_generator() \ or function_node.is_abstract(pass_is_abstract=False): return returns = list(function_node.nodes_of_class(astroid.Return, - skip_klass=astroid.Function)) + skip_klass=astroid.FunctionDef)) if len(returns) == 0: self.add_message('assignment-from-no-return', node=node) else: @@ -412,7 +409,7 @@ accessed. Python regular expressions are accepted.'} Check that the given uninferable CallFunc node does not call an actual function. """ - if not isinstance(node.func, astroid.Getattr): + if not isinstance(node.func, astroid.Attribute): return # Look for properties. First, obtain @@ -431,13 +428,13 @@ accessed. Python regular expressions are accepted.'} try: attrs = klass._proxied.getattr(node.func.attrname) - except astroid.NotFoundError: + except exceptions.NotFoundError: return for attr in attrs: if attr is astroid.YES: continue - if not isinstance(attr, astroid.Function): + if not isinstance(attr, astroid.FunctionDef): continue # Decorated, see if it is decorated with a property. @@ -496,7 +493,7 @@ accessed. Python regular expressions are accepted.'} # Don't store any parameter names within the tuple, since those # are not assignable from keyword arguments. else: - assert isinstance(arg, astroid.AssName) + assert isinstance(arg, astroid.AssignName) # This occurs with: # def f( (a), (b) ): pass name = arg.name @@ -512,7 +509,7 @@ accessed. Python regular expressions are accepted.'} if isinstance(arg, astroid.Keyword): name = arg.arg else: - assert isinstance(arg, astroid.AssName) + assert isinstance(arg, astroid.AssignName) name = arg.name kwparams[name] = [called.args.kw_defaults[i], False] @@ -617,7 +614,7 @@ accessed. Python regular expressions are accepted.'} # slice or instances with __index__. parent_type = helpers.safe_infer(node.parent.value) - if not isinstance(parent_type, (astroid.Class, astroid.Instance)): + if not isinstance(parent_type, (astroid.ClassDef, astroid.Instance)): return # Determine what method on the parent this index will use @@ -640,10 +637,10 @@ accessed. Python regular expressions are accepted.'} if methods is astroid.YES: return itemmethod = methods[0] - except (astroid.NotFoundError, IndexError): + except (exceptions.NotFoundError, IndexError): return - if not isinstance(itemmethod, astroid.Function): + if not isinstance(itemmethod, astroid.FunctionDef): return if itemmethod.root().name != BUILTINS: return @@ -673,7 +670,7 @@ accessed. Python regular expressions are accepted.'} try: index_type.getattr('__index__') return - except astroid.NotFoundError: + except exceptions.NotFoundError: pass # Anything else is an error @@ -704,13 +701,12 @@ accessed. Python regular expressions are accepted.'} try: index_type.getattr('__index__') return - except astroid.NotFoundError: + except exceptions.NotFoundError: pass # Anything else is an error self.add_message('invalid-slice-index', node=node) - @check_messages('not-context-manager') def visit_with(self, node): for ctx_mgr, _ in node.items: @@ -736,7 +732,7 @@ accessed. Python regular expressions are accepted.'} # of self explaining tests. for path in six.moves.filter(None, _unflatten(context.path)): scope = path.scope() - if not isinstance(scope, astroid.Function): + if not isinstance(scope, astroid.FunctionDef): continue if decorated_with(scope, ['contextlib.contextmanager']): break @@ -747,7 +743,7 @@ accessed. Python regular expressions are accepted.'} try: infered.getattr('__enter__') infered.getattr('__exit__') - except astroid.NotFoundError: + except exceptions.NotFoundError: if isinstance(infered, astroid.Instance): # If we do not know the bases of this class, # just skip it. diff --git a/pylint/checkers/utils.py b/pylint/checkers/utils.py index b091ad3..767bba8 100644 --- a/pylint/checkers/utils.py +++ b/pylint/checkers/utils.py @@ -29,7 +29,8 @@ from astroid import scoped_nodes from six.moves import map, builtins # pylint: disable=redefined-builtin BUILTINS_NAME = builtins.__name__ -COMP_NODE_TYPES = astroid.ListComp, astroid.SetComp, astroid.DictComp, astroid.GenExpr +COMP_NODE_TYPES = (astroid.ListComp, astroid.SetComp, + astroid.DictComp, astroid.GeneratorExp) PY3K = sys.version_info[0] == 3 if not PY3K: @@ -118,15 +119,15 @@ def clobber_in_except(node): Returns (True, args for W0623) if assignment clobbers an existing variable, (False, None) otherwise. """ - if isinstance(node, astroid.AssAttr): + if isinstance(node, astroid.AssignAttr): return (True, (node.attrname, 'object %r' % (node.expr.as_string(),))) - elif isinstance(node, astroid.AssName): + elif isinstance(node, astroid.AssignName): name = node.name if is_builtin(name): return (True, (name, 'builtins')) else: stmts = node.lookup(name)[1] - if (stmts and not isinstance(stmts[0].ass_type(), + if (stmts and not isinstance(stmts[0].assign_type(), (astroid.Assign, astroid.AugAssign, astroid.ExceptHandler))): return (True, (name, 'outer scope (line %s)' % stmts[0].fromlineno)) @@ -176,11 +177,11 @@ def is_defined_before(var_node): _node = var_node.parent while _node: if isinstance(_node, COMP_NODE_TYPES): - for ass_node in _node.nodes_of_class(astroid.AssName): + for ass_node in _node.nodes_of_class(astroid.AssignName): if ass_node.name == varname: return True elif isinstance(_node, astroid.For): - for ass_node in _node.target.nodes_of_class(astroid.AssName): + for ass_node in _node.target.nodes_of_class(astroid.AssignName): if ass_node.name == varname: return True elif isinstance(_node, astroid.With): @@ -188,10 +189,10 @@ def is_defined_before(var_node): if expr.parent_of(var_node): break if (ids and - isinstance(ids, astroid.AssName) and + isinstance(ids, astroid.AssignName) and ids.name == varname): return True - elif isinstance(_node, (astroid.Lambda, astroid.Function)): + elif isinstance(_node, (astroid.Lambda, astroid.FunctionDef)): if _node.args.is_argument(varname): # If the name is found inside a default value # of a function, then let the search continue @@ -208,7 +209,7 @@ def is_defined_before(var_node): return True break elif isinstance(_node, astroid.ExceptHandler): - if isinstance(_node.name, astroid.AssName): + if isinstance(_node.name, astroid.AssignName): ass_node = _node.name if ass_node.name == varname: return True @@ -218,10 +219,10 @@ def is_defined_before(var_node): _node = stmt.previous_sibling() lineno = stmt.fromlineno while _node and _node.fromlineno == lineno: - for ass_node in _node.nodes_of_class(astroid.AssName): + for ass_node in _node.nodes_of_class(astroid.AssignName): if ass_node.name == varname: return True - for imp_node in _node.nodes_of_class((astroid.From, astroid.Import)): + for imp_node in _node.nodes_of_class((astroid.ImportFrom, astroid.Import)): if varname in [name[1] or name[0] for name in imp_node.names]: return True _node = _node.previous_sibling() @@ -232,7 +233,7 @@ def is_func_default(node): value """ parent = node.scope() - if isinstance(parent, astroid.Function): + if isinstance(parent, astroid.FunctionDef): for default_node in parent.args.defaults: for default_name_node in default_node.nodes_of_class(astroid.Name): if default_name_node is node: @@ -269,7 +270,7 @@ def is_ancestor_name(frame, node): def assign_parent(node): """return the higher parent which is not an AssName, Tuple or List node """ - while node and isinstance(node, (astroid.AssName, + while node and isinstance(node, (astroid.AssignName, astroid.Tuple, astroid.List)): node = node.parent @@ -279,7 +280,7 @@ def assign_parent(node): def overrides_a_method(class_node, name): """return True if <name> is a method overridden from an ancestor""" for ancestor in class_node.ancestors(): - if name in ancestor and isinstance(ancestor[name], astroid.Function): + if name in ancestor and isinstance(ancestor[name], astroid.FunctionDef): return True return False @@ -385,7 +386,7 @@ def node_frame_class(node): """ klass = node.frame() - while klass is not None and not isinstance(klass, astroid.Class): + while klass is not None and not isinstance(klass, astroid.ClassDef): if klass.parent is None: klass = None else: @@ -471,7 +472,7 @@ def decorated_with_property(node): continue try: for infered in decorator.infer(): - if isinstance(infered, astroid.Class): + if isinstance(infered, astroid.ClassDef): if (infered.root().name == BUILTINS_NAME and infered.name == 'property'): return True @@ -520,14 +521,14 @@ def unimplemented_abstract_methods(node, is_abstract_cb=None): for ancestor in mro: for obj in ancestor.values(): infered = obj - if isinstance(obj, astroid.AssName): + if isinstance(obj, astroid.AssignName): infered = safe_infer(obj) if not infered: continue - if not isinstance(infered, astroid.Function): + if not isinstance(infered, astroid.FunctionDef): if obj.name in visited: del visited[obj.name] - if isinstance(infered, astroid.Function): + if isinstance(infered, astroid.FunctionDef): # It's critical to use the original name, # since after inferring, an object can be something # else than expected, as in the case of the diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py index fe69d91..51ff584 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -21,7 +21,6 @@ import re from copy import copy import astroid -from astroid import are_exclusive, builtin_lookup from astroid import modutils from pylint.interfaces import IAstroidChecker, INFERENCE, INFERENCE_FAILURE, HIGH @@ -47,7 +46,7 @@ def _is_from_future_import(stmt, name): return for local_node in module.locals.get(name, []): - if (isinstance(local_node, astroid.From) + if (isinstance(local_node, astroid.ImportFrom) and local_node.modname == FUTURE): return True @@ -69,7 +68,7 @@ def overridden_method(klass, name): # We have found an ancestor defining <name> but it's not in the local # dictionary. This may happen with astroid built from living objects. return None - if isinstance(meth_node, astroid.Function): + if isinstance(meth_node, astroid.FunctionDef): return meth_node return None @@ -110,7 +109,7 @@ def _detect_global_scope(node, frame, defframe): scope = frame.parent.scope() if defframe and defframe.parent: def_scope = defframe.parent.scope() - if isinstance(frame, astroid.Function): + if isinstance(frame, astroid.FunctionDef): # If the parent of the current node is a # function, then it can be under its scope # (defined in, which doesn't concern us) or @@ -118,9 +117,9 @@ def _detect_global_scope(node, frame, defframe): # for annotations of function arguments, they'll have # their parent the Arguments node. if not isinstance(node.parent, - (astroid.Function, astroid.Arguments)): + (astroid.FunctionDef, astroid.Arguments)): return False - elif any(not isinstance(f, (astroid.Class, astroid.Module)) + elif any(not isinstance(f, (astroid.ClassDef, astroid.Module)) for f in (frame, defframe)): # Not interested in other frames, since they are already # not in a global scope. @@ -133,7 +132,7 @@ def _detect_global_scope(node, frame, defframe): # share a global scope. parent_scope = s while parent_scope: - if not isinstance(parent_scope, (astroid.Class, astroid.Module)): + if not isinstance(parent_scope, (astroid.ClassDef, astroid.Module)): break_scopes.append(parent_scope) break if parent_scope.parent: @@ -161,12 +160,12 @@ def _fix_dot_imports(not_consumed): # TODO: this should be improved in issue astroid #46 names = {} for name, stmts in six.iteritems(not_consumed): - if any(isinstance(stmt, astroid.AssName) - and isinstance(stmt.ass_type(), astroid.AugAssign) + if any(isinstance(stmt, astroid.AssignName) + and isinstance(stmt.assign_type(), astroid.AugAssign) for stmt in stmts): continue for stmt in stmts: - if not isinstance(stmt, (astroid.From, astroid.Import)): + if not isinstance(stmt, (astroid.ImportFrom, astroid.Import)): continue for imports in stmt.names: second_name = None @@ -190,7 +189,7 @@ def _find_frame_imports(name, frame): *name*. Such imports can be considered assignments. Returns True if an import for the given name was found. """ - imports = frame.nodes_of_class((astroid.Import, astroid.From)) + imports = frame.nodes_of_class((astroid.Import, astroid.ImportFrom)) for import_node in imports: for import_name, import_alias in import_node.names: # If the import uses an alias, check only that. @@ -421,9 +420,9 @@ builtins. Remember that you should avoid to define new builtins when possible.' checked.add(real_name) if (isinstance(stmt, astroid.Import) or - (isinstance(stmt, astroid.From) and + (isinstance(stmt, astroid.ImportFrom) and not stmt.modname)): - if (isinstance(stmt, astroid.From) and + if (isinstance(stmt, astroid.ImportFrom) and SPECIAL_OBJ.search(imported_name)): # Filter special objects (__doc__, __all__) etc., # because they can be imported for exporting. @@ -433,7 +432,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' else: msg = "%s imported as %s" % (imported_name, as_name) self.add_message('unused-import', args=msg, node=stmt) - elif (isinstance(stmt, astroid.From) + elif (isinstance(stmt, astroid.ImportFrom) and stmt.modname != FUTURE): if SPECIAL_OBJ.search(imported_name): @@ -526,7 +525,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' continue if name in globs and not isinstance(stmt, astroid.Global): definition = globs[name][0] - if (isinstance(definition, astroid.From) + if (isinstance(definition, astroid.ImportFrom) and definition.modname == FUTURE): # It is a __future__ directive, not a symbol. continue @@ -554,7 +553,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' klass = node.parent.frame() if is_method and node.is_abstract(): return - if is_method and isinstance(klass, astroid.Class): + if is_method and isinstance(klass, astroid.ClassDef): confidence = INFERENCE if has_known_bases(klass) else INFERENCE_FAILURE else: confidence = HIGH @@ -577,7 +576,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' stmt = stmts[0] if isinstance(stmt, astroid.Global): continue - if isinstance(stmt, (astroid.Import, astroid.From)): + if isinstance(stmt, (astroid.Import, astroid.ImportFrom)): # Detect imports, assigned to global statements. if global_names: skip = False @@ -620,8 +619,9 @@ builtins. Remember that you should avoid to define new builtins when possible.' continue self.add_message('unused-variable', args=name, node=stmt) - @check_messages('global-variable-undefined', 'global-variable-not-assigned', 'global-statement', - 'global-at-module-level', 'redefined-builtin') + @check_messages('global-variable-undefined', 'global-variable-not-assigned', + 'global-statement', 'global-at-module-level', + 'redefined-builtin') def visit_global(self, node): """check names imported exists in the global scope""" frame = node.frame() @@ -667,11 +667,11 @@ builtins. Remember that you should avoid to define new builtins when possible.' def _check_late_binding_closure(self, node, assignment_node): def _is_direct_lambda_call(): - return (isinstance(node_scope.parent, astroid.CallFunc) + return (isinstance(node_scope.parent, astroid.Call) and node_scope.parent.func is node_scope) node_scope = node.scope() - if not isinstance(node_scope, (astroid.Lambda, astroid.Function)): + if not isinstance(node_scope, (astroid.Lambda, astroid.FunctionDef)): return if isinstance(node.parent, astroid.Arguments): return @@ -723,9 +723,10 @@ builtins. Remember that you should avoid to define new builtins when possible.' _astmts.append(stmt) astmts = _astmts if len(astmts) == 1: - ass = astmts[0].ass_type() - if isinstance(ass, (astroid.For, astroid.Comprehension, astroid.GenExpr)) \ - and not ass.statement() is node.statement(): + ass = astmts[0].assign_type() + if (isinstance(ass, (astroid.For, astroid.Comprehension, + astroid.GeneratorExp)) + and not ass.statement() is node.statement()): self.add_message('undefined-loop-variable', args=name, node=node) @check_messages('redefine-in-handler') @@ -736,7 +737,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' self.add_message('redefine-in-handler', args=args, node=name) def visit_assname(self, node): - if isinstance(node.ass_type(), astroid.AugAssign): + if isinstance(node.assign_type(), astroid.AugAssign): self.visit_name(node) def visit_delname(self, node): @@ -745,7 +746,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' @staticmethod def _defined_in_function_definition(node, frame): in_annotation_or_default = False - if (isinstance(frame, astroid.Function) and + if (isinstance(frame, astroid.FunctionDef) and node.statement() is frame): in_annotation_or_default = ( ( @@ -781,7 +782,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' elif defframe.parent is None: # we are at the module level, check the name is not # defined in builtins - if name in defframe.scope_attrs or builtin_lookup(name)[1]: + if name in defframe.scope_attrs or astroid.builtin_lookup(name)[1]: maybee0601 = False else: # we are in a local scope, check the name is not @@ -796,7 +797,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' for child in defframe.get_children()) if (base_scope_type == 'lambda' and - isinstance(frame, astroid.Class) + isinstance(frame, astroid.ClassDef) and name in frame.locals): # This rule verifies that if the definition node of the @@ -813,8 +814,8 @@ builtins. Remember that you should avoid to define new builtins when possible.' maybee0601 = not (isinstance(defnode, astroid.Arguments) and node in defnode.defaults and frame.locals[name][0].fromlineno < defstmt.fromlineno) - elif (isinstance(defframe, astroid.Class) and - isinstance(frame, astroid.Function)): + elif (isinstance(defframe, astroid.ClassDef) and + isinstance(frame, astroid.FunctionDef)): # Special rule for function return annotations, # which uses the same name as the class where # the function lives. @@ -859,7 +860,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' frame_locals = frame.parent.scope().locals else: frame_locals = frame.locals - return not ((isinstance(frame, astroid.Class) or + return not ((isinstance(frame, astroid.ClassDef) or in_annotation_or_default) and name in frame_locals) @@ -918,7 +919,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' # The class reuses itself in the class scope. recursive_klass = (frame is defframe and defframe.parent_of(node) and - isinstance(defframe, astroid.Class) and + isinstance(defframe, astroid.ClassDef) and node.name == defframe.name) maybee0601, annotation_return = self._is_variable_violation( @@ -928,14 +929,14 @@ builtins. Remember that you should avoid to define new builtins when possible.' if (maybee0601 and not is_defined_before(node) - and not are_exclusive(stmt, defstmt, ('NameError', - 'Exception', - 'BaseException'))): - + and not astroid.are_exclusive(stmt, defstmt, ('NameError', + 'Exception', + 'BaseException'))): + # Used and defined in the same place, e.g `x += 1` and `del x` defined_by_stmt = ( defstmt is stmt - and isinstance(node, (astroid.DelName, astroid.AssName)) + and isinstance(node, (astroid.DelName, astroid.AssignName)) ) if (recursive_klass @@ -954,7 +955,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' # class A: # x = lambda attr: f + attr # f = 42 - if isinstance(frame, astroid.Class) and name in frame.locals: + if isinstance(frame, astroid.ClassDef) and name in frame.locals: if isinstance(node.parent, astroid.Arguments): # Doing the following is fine: # class A: @@ -1133,7 +1134,7 @@ class VariablesChecker3k(VariablesChecker): module_imports = self._to_consume[0][1] consumed = {} - for klass in node.nodes_of_class(astroid.Class): + for klass in node.nodes_of_class(astroid.ClassDef): found = metaclass = name = None if not klass._metaclass: # Skip if this class doesn't use @@ -1159,7 +1160,7 @@ class VariablesChecker3k(VariablesChecker): name = None if isinstance(klass._metaclass, astroid.Name): name = klass._metaclass.name - elif isinstance(klass._metaclass, astroid.Getattr): + elif isinstance(klass._metaclass, astroid.Attribute): name = klass._metaclass.as_string() if name is not None: diff --git a/pylint/pyreverse/diadefslib.py b/pylint/pyreverse/diadefslib.py index 0ef1465..6c2cb3c 100644 --- a/pylint/pyreverse/diadefslib.py +++ b/pylint/pyreverse/diadefslib.py @@ -104,7 +104,7 @@ class DiaDefGenerator(object): for ass_node in ass_nodes: if isinstance(ass_node, astroid.Instance): ass_node = ass_node._proxied - if not (isinstance(ass_node, astroid.Class) + if not (isinstance(ass_node, astroid.ClassDef) and self.show_node(ass_node)): continue yield ass_node @@ -163,7 +163,7 @@ class DefaultDiadefGenerator(LocalsVisitor, DiaDefGenerator): self.linker.visit(node) self.pkgdiagram.add_object(node.name, node) - def visit_class(self, node): + def visit_classdef(self, node): """visit an astroid.Class node add this class to the class diagram definition @@ -171,7 +171,7 @@ class DefaultDiadefGenerator(LocalsVisitor, DiaDefGenerator): anc_level, ass_level = self._get_levels() self.extract_classes(node, anc_level, ass_level) - def visit_from(self, node): + def visit_importfrom(self, node): """visit astroid.From and catch modules for package diagram """ if self.pkgdiagram: diff --git a/pylint/pyreverse/diagrams.py b/pylint/pyreverse/diagrams.py index f0d7a92..dfc03f2 100644 --- a/pylint/pyreverse/diagrams.py +++ b/pylint/pyreverse/diagrams.py @@ -91,7 +91,7 @@ class ClassDiagram(Figure, FilterMixIn): """return visible methods""" methods = [ m for m in node.values() - if isinstance(m, astroid.Function) and self.show_attr(m.name) + if isinstance(m, astroid.FunctionDef) and self.show_attr(m.name) ] return sorted(methods, key=lambda n: n.name) @@ -109,7 +109,7 @@ class ClassDiagram(Figure, FilterMixIn): for ass_node in nodes: if isinstance(ass_node, astroid.Instance): ass_node = ass_node._proxied - if isinstance(ass_node, astroid.Class) \ + if isinstance(ass_node, astroid.ClassDef) \ and hasattr(ass_node, "name") and not self.has_node(ass_node): if ass_node.name not in names: ass_name = ass_node.name @@ -133,7 +133,7 @@ class ClassDiagram(Figure, FilterMixIn): def classes(self): """return all class nodes in the diagram""" - return [o for o in self.objects if isinstance(o.node, astroid.Class)] + return [o for o in self.objects if isinstance(o.node, astroid.ClassDef)] def classe(self, name): """return a class by its name, raise KeyError if not found diff --git a/pylint/pyreverse/inspector.py b/pylint/pyreverse/inspector.py index b916008..b9712a7 100644 --- a/pylint/pyreverse/inspector.py +++ b/pylint/pyreverse/inspector.py @@ -157,7 +157,7 @@ class Linker(IdGeneratorMixIn, utils.LocalsVisitor): if self.tag: node.uid = self.generate_id() - def visit_class(self, node): + def visit_classdef(self, node): """visit an astroid.Class node * set the locals_type and instance_attrs_type mappings @@ -185,7 +185,7 @@ class Linker(IdGeneratorMixIn, utils.LocalsVisitor): except astroid.InferenceError: node.implements = () - def visit_function(self, node): + def visit_functiondef(self, node): """visit an astroid.Function node * set the locals_type mapping @@ -199,10 +199,10 @@ class Linker(IdGeneratorMixIn, utils.LocalsVisitor): link_project = visit_project link_module = visit_module - link_class = visit_class - link_function = visit_function + link_class = visit_classdef + link_function = visit_functiondef - def visit_assname(self, node): + def visit_assignname(self, node): """visit an astroid.AssName node handle locals_type @@ -223,10 +223,10 @@ class Linker(IdGeneratorMixIn, utils.LocalsVisitor): # If the frame doesn't have a locals_type yet, # it means it wasn't yet visited. Visit it now # to add what's missing from it. - if isinstance(frame, astroid.Class): - self.visit_class(frame) - elif isinstance(frame, astroid.Function): - self.visit_function(frame) + if isinstance(frame, astroid.ClassDef): + self.visit_classdef(frame) + elif isinstance(frame, astroid.FunctionDef): + self.visit_functiondef(frame) else: self.visit_module(frame) @@ -259,7 +259,7 @@ class Linker(IdGeneratorMixIn, utils.LocalsVisitor): relative = modutils.is_relative(name[0], context_file) self._imported_module(node, name[0], relative) - def visit_from(self, node): + def visit_importfrom(self, node): """visit an astroid.From node resolve module dependencies diff --git a/pylint/test/extensions/test_check_docs.py b/pylint/test/extensions/test_check_docs.py index 02b5dbf..07afb3e 100644 --- a/pylint/test/extensions/test_check_docs.py +++ b/pylint/test/extensions/test_check_docs.py @@ -5,8 +5,8 @@ from __future__ import division, print_function, absolute_import import unittest +import astroid from astroid import test_utils -import astroid.scoped_nodes from pylint.testutils import CheckerTestCase, Message, set_config from pylint.extensions.check_docs import ParamDocChecker, space_indentation @@ -155,7 +155,7 @@ class ParamDocCheckerTest(CheckerTestCase): :type node: :class:`astroid.scoped_nodes.Class` """ for body_item in node.body: - if (isinstance(body_item, astroid.scoped_nodes.Function) + if (isinstance(body_item, astroid.FunctionDef) and hasattr(body_item, 'name')): self.checker.visit_function(body_item) diff --git a/pylint/test/unittest_pyreverse_diadefs.py b/pylint/test/unittest_pyreverse_diadefs.py index 511ccea..0df6ac4 100644 --- a/pylint/test/unittest_pyreverse_diadefs.py +++ b/pylint/test/unittest_pyreverse_diadefs.py @@ -35,7 +35,7 @@ HANDLER = DiadefsHandler(Config()) def _process_classes(classes): """extract class names of a list""" - return sorted([(isinstance(c.node, astroid.Class), c.title) for c in classes]) + return sorted([(isinstance(c.node, astroid.ClassDef), c.title) for c in classes]) def _process_relations(relations): """extract relation indices from a relation list""" diff --git a/pylint/test/unittest_pyreverse_inspector.py b/pylint/test/unittest_pyreverse_inspector.py index 18823b5..f709fe6 100644 --- a/pylint/test/unittest_pyreverse_inspector.py +++ b/pylint/test/unittest_pyreverse_inspector.py @@ -46,7 +46,7 @@ class LinkerTest(unittest.TestCase): klass = self.project.get_module('data.clientmodule_test')['Ancestor'] self.assertTrue(hasattr(klass, 'implements')) self.assertEqual(len(klass.implements), 1) - self.assertTrue(isinstance(klass.implements[0], nodes.Class)) + self.assertTrue(isinstance(klass.implements[0], nodes.ClassDef)) self.assertEqual(klass.implements[0].name, "Interface") klass = self.project.get_module('data.clientmodule_test')['Specialization'] self.assertTrue(hasattr(klass, 'implements')) diff --git a/pylint/utils.py b/pylint/utils.py index 236f7c8..92d4fca 100644 --- a/pylint/utils.py +++ b/pylint/utils.py @@ -66,6 +66,20 @@ MSG_TYPES_STATUS = { 'F' : 1 } +DEPRECATED_ALIASES = { + # New name, deprecated name. + 'repr': 'backquote', + 'expr': 'discard', + 'assignname': 'assname', + 'assignattr': 'assattr', + 'attribute': 'getattr', + 'call': 'callfunc', + 'importfrom': 'from', + 'classdef': 'class', + 'functiondef': 'function', + 'generatorexp': 'genexpr', +} + _MSG_ORDER = 'EWRCIF' MSG_STATE_SCOPE_CONFIG = 0 MSG_STATE_SCOPE_MODULE = 1 @@ -540,7 +554,8 @@ class FileState(object): # # this is necessary to disable locally messages applying to class / # function using their fromlineno - if isinstance(node, (nodes.Module, nodes.Class, nodes.Function)) and node.body: + if (isinstance(node, (nodes.Module, nodes.ClassDef, nodes.FunctionDef)) + and node.body): firstchildlineno = node.body[0].fromlineno else: firstchildlineno = last @@ -877,15 +892,33 @@ class PyLintASTWalker(object): its children, then leave events. """ cid = astroid.__class__.__name__.lower() + + # Detect if the node is a new name for a deprecated alias. + # In this case, favour the methods for the deprecated + # alias if any, in order to maintain backwards + # compatibility. If both of them are present, + # only the old ones will be called. + old_cid = DEPRECATED_ALIASES.get(cid) + visit_events = () + leave_events = () + + if old_cid: + visit_events = self.visit_events.get(old_cid) + leave_events = self.leave_events.get(old_cid) + if not visit_events: + visit_events = self.visit_events.get(cid) + if not leave_events: + leave_events = self.leave_events.get(cid) + if astroid.is_statement: self.nbstatements += 1 # generate events for this node on each checker - for cb in self.visit_events.get(cid, ()): + for cb in visit_events or (): cb(astroid) # recurse on children - for child in astroid.get_children(): + for child in astroid.get_children(): self.walk(child) - for cb in self.leave_events.get(cid, ()): + for cb in leave_events or (): cb(astroid) |