diff options
Diffstat (limited to 'pylint/checkers')
-rw-r--r-- | pylint/checkers/imports.py | 61 | ||||
-rw-r--r-- | pylint/checkers/newstyle.py | 14 | ||||
-rw-r--r-- | pylint/checkers/stdlib.py | 12 | ||||
-rw-r--r-- | pylint/checkers/typecheck.py | 20 | ||||
-rw-r--r-- | pylint/checkers/variables.py | 4 |
5 files changed, 70 insertions, 41 deletions
diff --git a/pylint/checkers/imports.py b/pylint/checkers/imports.py index 0e16d18..2d37461 100644 --- a/pylint/checkers/imports.py +++ b/pylint/checkers/imports.py @@ -88,6 +88,14 @@ def _get_first_import(node, context, name, base, level): if found and not are_exclusive(first, node): return first + +def _ignore_import_failure(node, modname, ignored_modules): + for submodule in _qualified_names(modname): + if submodule in ignored_modules: + return True + + return node_ignores_exception(node, ImportError) + # utilities to represents import dependencies as tree and dot graph ########### def _make_tree_defs(mod_files_list): @@ -161,6 +169,10 @@ MSGS = { 'import-error', 'Used when pylint has been unable to import a module.', {'old_names': [('F0401', 'import-error')]}), + 'E0402': ('Attempted relative import beyond top-level package', + 'relative-beyond-top-level', + 'Used when a relative import tries to access too many levels ' + 'in the current package.'), 'R0401': ('Cyclic import (%s)', 'cyclic-import', 'Used when a cyclic import between two or more modules is \ @@ -298,7 +310,7 @@ given file (report RP0402 must not be disabled)'} for name in names: self._check_deprecated_module(node, name) - importedmodnode = self.get_imported_module(node, name) + importedmodnode = self._get_imported_module(node, name) if isinstance(node.scope(), astroid.Module): self._check_position(node) self._record_import(node, importedmodnode) @@ -320,7 +332,7 @@ given file (report RP0402 must not be disabled)'} self._check_reimport(node, basename=basename, level=node.level) modnode = node.root() - importedmodnode = self.get_imported_module(node, basename) + importedmodnode = self._get_imported_module(node, basename) if isinstance(node.scope(), astroid.Module): self._check_position(node) self._record_import(node, importedmodnode) @@ -369,9 +381,24 @@ given file (report RP0402 must not be disabled)'} = visit_ifexp = visit_comprehension = visit_if def visit_functiondef(self, node): - # if it is the first non import instruction of the module, record it - if not self._first_non_import_node: - self._first_non_import_node = node + # If it is the first non import instruction of the module, record it. + if self._first_non_import_node: + return + + # Check if the node belongs to an `If` or a `Try` block. If they + # contain imports, skip recording this node. + if not isinstance(node.parent.scope(), astroid.Module): + return + + root = node + while not isinstance(root.parent, astroid.Module): + root = root.parent + + if isinstance(root, (astroid.If, astroid.TryFinally, astroid.TryExcept)): + if any(root.nodes_of_class((astroid.Import, astroid.ImportFrom))): + return + + self._first_non_import_node = node visit_classdef = visit_for = visit_while = visit_functiondef @@ -458,22 +485,22 @@ given file (report RP0402 must not be disabled)'} '"%s"' % local_imports[0][0].as_string())) return std_imports, extern_imports, local_imports - def get_imported_module(self, importnode, modname): + def _get_imported_module(self, importnode, modname): try: return importnode.do_import_module(modname) - except astroid.InferenceError as ex: - dotted_modname = _get_import_name(importnode, modname) - if str(ex) != modname: - args = '%r (%s)' % (dotted_modname, ex) - else: - args = repr(dotted_modname) + except astroid.TooManyLevelsError: + if _ignore_import_failure(importnode, modname, self._ignored_modules): + return None + + self.add_message('relative-beyond-top-level', node=importnode) - for submodule in _qualified_names(modname): - if submodule in self._ignored_modules: - return None + except astroid.AstroidBuildingException as exc: + if _ignore_import_failure(importnode, modname, self._ignored_modules): + return None - if not node_ignores_exception(importnode, ImportError): - self.add_message("import-error", args=args, node=importnode) + dotted_modname = _get_import_name(importnode, modname) + self.add_message('import-error', args=repr(dotted_modname), + node=importnode) def _check_relative_import(self, modnode, importnode, importedmodnode, importedasname): diff --git a/pylint/checkers/newstyle.py b/pylint/checkers/newstyle.py index 489c22f..5cc8f13 100644 --- a/pylint/checkers/newstyle.py +++ b/pylint/checkers/newstyle.py @@ -128,12 +128,10 @@ class NewStyleConflictChecker(BaseChecker): isinstance(call.func, astroid.Name) and call.func.name == 'super'): continue - confidence = (INFERENCE if has_known_bases(klass) - else INFERENCE_FAILURE) - if not klass.newstyle: + + if not klass.newstyle and has_known_bases(klass): # super should not be used on an old style class - self.add_message('super-on-old-class', node=node, - confidence=confidence) + self.add_message('super-on-old-class', node=node) else: # super first arg should be the class if not call.args and sys.version_info[0] == 3: @@ -147,8 +145,7 @@ class NewStyleConflictChecker(BaseChecker): continue if supcls is None: - self.add_message('missing-super-argument', node=call, - confidence=confidence) + self.add_message('missing-super-argument', node=call) continue if klass is not supcls: @@ -162,8 +159,7 @@ class NewStyleConflictChecker(BaseChecker): if hasattr(call.args[0], 'name'): name = call.args[0].name if name is not None: - self.add_message('bad-super-call', node=call, args=(name, ), - confidence=confidence) + self.add_message('bad-super-call', node=call, args=(name, )) def register(linter): diff --git a/pylint/checkers/stdlib.py b/pylint/checkers/stdlib.py index afb4541..0ec3d6c 100644 --- a/pylint/checkers/stdlib.py +++ b/pylint/checkers/stdlib.py @@ -211,7 +211,7 @@ class StdlibChecker(BaseChecker): for value in node.values: self._check_datetime(value) - def _check_deprecated_method(self, node, infer): + def _check_deprecated_method(self, node, inferred): py_vers = sys.version_info[0] if isinstance(node.func, astroid.Attribute): @@ -222,7 +222,14 @@ class StdlibChecker(BaseChecker): # Not interested in other nodes. return - qname = infer.qname() + # Reject nodes which aren't of interest to us. + acceptable_nodes = (astroid.BoundMethod, + astroid.UnboundMethod, + astroid.FunctionDef) + if not isinstance(inferred, acceptable_nodes): + return + + qname = inferred.qname() if qname in self.deprecated[0]: self.add_message('deprecated-method', node=node, args=(func_name, )) @@ -233,7 +240,6 @@ class StdlibChecker(BaseChecker): args=(func_name, )) break - def _check_redundant_assert(self, node, infer): if (isinstance(infer, astroid.BoundMethod) and node.args and isinstance(node.args[0], astroid.Const) and diff --git a/pylint/checkers/typecheck.py b/pylint/checkers/typecheck.py index 46535d2..076f21a 100644 --- a/pylint/checkers/typecheck.py +++ b/pylint/checkers/typecheck.py @@ -317,7 +317,15 @@ accessed. Python regular expressions are accepted.'} def open(self): # do this in open since config not fully initialized in __init__ - self.generated_members = list(self.config.generated_members) + # generated_members may contain regular expressions + # (surrounded by quote `"` and followed by a comma `,`) + # REQUEST,aq_parent,"[a-zA-Z]+_set{1,2}"' => + # ('REQUEST', 'aq_parent', '[a-zA-Z]+_set{1,2}') + if isinstance(self.config.generated_members, str): + gen = shlex.shlex(self.config.generated_members) + gen.whitespace += ',' + gen.wordchars += '[]-+' + self.config.generated_members = tuple(tok.strip('"') for tok in gen) def visit_assignattr(self, node): if isinstance(node.assign_type(), astroid.AugAssign): @@ -335,19 +343,11 @@ accessed. Python regular expressions are accepted.'} function/method, super call and metaclasses are ignored """ - # generated_members may contain regular expressions - # (surrounded by quote `"` and followed by a comma `,`) - # REQUEST,aq_parent,"[a-zA-Z]+_set{1,2}"' => - # ('REQUEST', 'aq_parent', '[a-zA-Z]+_set{1,2}') - if isinstance(self.config.generated_members, str): - gen = shlex.shlex(self.config.generated_members) - gen.whitespace += ',' - gen.wordchars += '[]-+' - self.config.generated_members = tuple(tok.strip('"') for tok in gen) for pattern in self.config.generated_members: # attribute is marked as generated, stop here if re.match(pattern, node.attrname): return + try: infered = list(node.expr.infer()) except exceptions.InferenceError: diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py index 7629a7b..b7a114d 100644 --- a/pylint/checkers/variables.py +++ b/pylint/checkers/variables.py @@ -44,7 +44,7 @@ def _is_from_future_import(stmt, name): """Check if the name is a future import from another module.""" try: module = stmt.do_import_module(stmt.modname) - except astroid.InferenceError: + except astroid.AstroidBuildingException: return for local_node in module.locals.get(name, []): @@ -1014,7 +1014,7 @@ builtins. Remember that you should avoid to define new builtins when possible.' name_parts = node.modname.split('.') try: module = node.do_import_module(name_parts[0]) - except Exception: + except astroid.AstroidBuildingException: return module = self._check_module_attrs(node, module, name_parts[1:]) if not module: |