Add importlib.util.resolve_name().
This commit is contained in:
parent
61009468c5
commit
d200bf534b
|
@ -737,6 +737,22 @@ find and load modules.
|
|||
This module contains the various objects that help in the construction of
|
||||
an :term:`importer`.
|
||||
|
||||
.. function:: resolve_name(name, package)
|
||||
|
||||
Resolve a relative module name to an absolute one.
|
||||
|
||||
If **name** has no leading dots, then **name** is simply returned. This
|
||||
allows for usage such as
|
||||
``importlib.util.resolve_name('sys', __package__)`` without doing a
|
||||
check to see if the **package** argument is needed.
|
||||
|
||||
:exc:`ValueError` is raised if **name** is a relative module name but
|
||||
package is a false value (e.g. ``None`` or the empty string).
|
||||
:exc:`ValueError` is also raised a relative name would escape its containing
|
||||
package (e.g. requesting ``..bacon`` from within the ``spam`` package).
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
.. decorator:: module_for_loader
|
||||
|
||||
A :term:`decorator` for a :term:`loader` method,
|
||||
|
|
|
@ -161,9 +161,47 @@ class SetPackageTests(unittest.TestCase):
|
|||
self.assertEqual(wrapped.__name__, fxn.__name__)
|
||||
self.assertEqual(wrapped.__qualname__, fxn.__qualname__)
|
||||
|
||||
|
||||
class ResolveNameTests(unittest.TestCase):
|
||||
|
||||
"""Tests importlib.util.resolve_name()."""
|
||||
|
||||
def test_absolute(self):
|
||||
# bacon
|
||||
self.assertEqual('bacon', util.resolve_name('bacon', None))
|
||||
|
||||
def test_aboslute_within_package(self):
|
||||
# bacon in spam
|
||||
self.assertEqual('bacon', util.resolve_name('bacon', 'spam'))
|
||||
|
||||
def test_no_package(self):
|
||||
# .bacon in ''
|
||||
with self.assertRaises(ValueError):
|
||||
util.resolve_name('.bacon', '')
|
||||
|
||||
def test_in_package(self):
|
||||
# .bacon in spam
|
||||
self.assertEqual('spam.eggs.bacon',
|
||||
util.resolve_name('.bacon', 'spam.eggs'))
|
||||
|
||||
def test_other_package(self):
|
||||
# ..bacon in spam.bacon
|
||||
self.assertEqual('spam.bacon',
|
||||
util.resolve_name('..bacon', 'spam.eggs'))
|
||||
|
||||
def test_escape(self):
|
||||
# ..bacon in spam
|
||||
with self.assertRaises(ValueError):
|
||||
util.resolve_name('..bacon', 'spam')
|
||||
|
||||
|
||||
def test_main():
|
||||
from test import support
|
||||
support.run_unittest(ModuleForLoaderTests, SetPackageTests)
|
||||
support.run_unittest(
|
||||
ModuleForLoaderTests,
|
||||
SetPackageTests,
|
||||
ResolveNameTests
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -3,3 +3,19 @@
|
|||
from ._bootstrap import module_for_loader
|
||||
from ._bootstrap import set_loader
|
||||
from ._bootstrap import set_package
|
||||
from ._bootstrap import _resolve_name
|
||||
|
||||
|
||||
def resolve_name(name, package):
|
||||
"""Resolve a relative module name to an absolute one."""
|
||||
if not name.startswith('.'):
|
||||
return name
|
||||
elif not package:
|
||||
raise ValueError('{!r} is not a relative name '
|
||||
'(no leading dot)'.format(name))
|
||||
level = 0
|
||||
for character in name:
|
||||
if character != '.':
|
||||
break
|
||||
level += 1
|
||||
return _resolve_name(name[level:], package, level)
|
||||
|
|
Loading…
Reference in New Issue