summaryrefslogtreecommitdiff
path: root/pylint/checkers/imports.py
diff options
context:
space:
mode:
authorClaudiu Popa <pcmanticore@gmail.com>2015-12-06 18:41:34 +0200
committerClaudiu Popa <pcmanticore@gmail.com>2015-12-06 18:41:34 +0200
commitb7f934de0d5ded5a120685d92ae07c2eb54b9ff1 (patch)
treed5ae59bdcf3d8099f907fe854c9ee315bdfa9281 /pylint/checkers/imports.py
parentb700c2f8a0e6b8d61c3abea8d41438f66cd55025 (diff)
downloadpylint-b7f934de0d5ded5a120685d92ae07c2eb54b9ff1.tar.gz
Added a new error, 'relative-beyond-top-level'.
This is emitted when a relative import was attempted beyond the top level package. For instance, if a package has X levels, trying to climb X + n levels with a relative import, as in `from ..stuff import Stuff`, will result in an error. Closes issue #588.
Diffstat (limited to 'pylint/checkers/imports.py')
-rw-r--r--pylint/checkers/imports.py26
1 files changed, 20 insertions, 6 deletions
diff --git a/pylint/checkers/imports.py b/pylint/checkers/imports.py
index 5863130..2fdcc85 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 \
@@ -461,16 +473,18 @@ given file (report RP0402 must not be disabled)'}
def _get_imported_module(self, importnode, modname):
try:
return importnode.do_import_module(modname)
- except astroid.AstroidBuildingException as exc:
- for submodule in _qualified_names(modname):
- if submodule in self._ignored_modules:
- return None
+ except astroid.TooManyLevelsError:
+ if _ignore_import_failure(importnode, modname, self._ignored_modules):
+ return None
+
+ self.add_message('relative-beyond-top-level', node=importnode)
- if node_ignores_exception(importnode, ImportError):
+ except astroid.AstroidBuildingException as exc:
+ if _ignore_import_failure(importnode, modname, self._ignored_modules):
return None
dotted_modname = _get_import_name(importnode, modname)
- self.add_message("import-error", args=repr(dotted_modname),
+ self.add_message('import-error', args=repr(dotted_modname),
node=importnode)
def _check_relative_import(self, modnode, importnode, importedmodnode,