diff options
author | Claudiu Popa <pcmanticore@gmail.com> | 2015-12-06 18:00:01 +0200 |
---|---|---|
committer | Claudiu Popa <pcmanticore@gmail.com> | 2015-12-06 18:00:01 +0200 |
commit | f77f5e36632bf6ea76d044bf14a132ff6e22dbfb (patch) | |
tree | f6a34d4946bb7c8f6052b9071dc9ba9930aecd79 | |
parent | 853726a295a8b4000bbb7ff9032cd1573e5ddf6c (diff) | |
download | astroid-git-f77f5e36632bf6ea76d044bf14a132ff6e22dbfb.tar.gz |
relative_to_absolute_name will now raise TooManyLevelsError when a relative import is trying to access something beyond the top-level package.
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | astroid/exceptions.py | 15 | ||||
-rw-r--r-- | astroid/tests/unittest_scoped_nodes.py | 13 | ||||
-rw-r--r-- | astroid/tree/scoped_nodes.py | 4 |
4 files changed, 35 insertions, 0 deletions
@@ -2,6 +2,9 @@ Change log for the astroid package (used to be astng) ===================================================== -- + * relative_to_absolute_name or methods calling it will now raise + TooManyLevelsError when a relative import was trying to + access something beyond the top-level package. * AstroidBuildingException is now AstroidBuildingError. The first name will exist until astroid 2.0. diff --git a/astroid/exceptions.py b/astroid/exceptions.py index 9d57058c..21e9b61f 100644 --- a/astroid/exceptions.py +++ b/astroid/exceptions.py @@ -58,6 +58,21 @@ class AstroidImportError(AstroidBuildingError): """Exception class used when a module can't be imported by astroid.""" +class TooManyLevelsError(AstroidImportError): + """Exception class which is raised when a relative import was beyond the top-level. + + Standard attributes: + level: The level which was attempted. + name: the name of the module on which the relative import was attempted. + """ + level = None + name = None + + def __init__(self, message='Relative import with too many levels ' + '({level}) for module {name!r}', **kws): + super(TooManyLevelsError, self).__init__(message, **kws) + + class AstroidSyntaxError(AstroidBuildingError): """Exception class used when a module can't be parsed.""" diff --git a/astroid/tests/unittest_scoped_nodes.py b/astroid/tests/unittest_scoped_nodes.py index b66e83d5..8467099c 100644 --- a/astroid/tests/unittest_scoped_nodes.py +++ b/astroid/tests/unittest_scoped_nodes.py @@ -35,6 +35,7 @@ from astroid.exceptions import ( InferenceError, AttributeInferenceError, NoDefault, ResolveError, MroError, InconsistentMroError, DuplicateBasesError, + TooManyLevelsError, ) from astroid.interpreter.objects import ( Instance, BoundMethod, UnboundMethod, Generator @@ -165,6 +166,18 @@ class ModuleNodeTest(ModuleLoader, unittest.TestCase): modname = mod.relative_to_absolute_name('', 1) self.assertEqual(modname, 'very.multi') + def test_relative_to_absolute_name_beyond_top_level(self): + mod = nodes.Module('a.b.c', '') + mod.package = True + for level in (5, 4): + with self.assertRaises(TooManyLevelsError) as cm: + mod.relative_to_absolute_name('test', level) + + expected = ("Relative import with too many levels " + "({level}) for module {name!r}".format( + level=level - 1, name=mod.name)) + self.assertEqual(expected, str(cm.exception)) + def test_import_1(self): data = '''from . import subpackage''' sys.path.insert(0, resources.find('data')) diff --git a/astroid/tree/scoped_nodes.py b/astroid/tree/scoped_nodes.py index 6aa5948c..ae8da65f 100644 --- a/astroid/tree/scoped_nodes.py +++ b/astroid/tree/scoped_nodes.py @@ -541,6 +541,10 @@ class Module(LocalsDictNodeNG): if level: if self.package: level = level - 1 + if level and self.name.count('.') < level: + raise exceptions.TooManyLevelsError( + level=level, name=self.name) + package_name = self.name.rsplit('.', level)[0] elif self.package: package_name = self.name |