mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	Add importlib.util.resolve_name().
This commit is contained in:
		
							parent
							
								
									61009468c5
								
							
						
					
					
						commit
						d200bf534b
					
				
					 4 changed files with 73 additions and 1 deletions
				
			
		|  | @ -737,6 +737,22 @@ find and load modules. | ||||||
| This module contains the various objects that help in the construction of | This module contains the various objects that help in the construction of | ||||||
| an :term:`importer`. | 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 | .. decorator:: module_for_loader | ||||||
| 
 | 
 | ||||||
|     A :term:`decorator` for a :term:`loader` method, |     A :term:`decorator` for a :term:`loader` method, | ||||||
|  |  | ||||||
|  | @ -161,9 +161,47 @@ def fxn(module): pass | ||||||
|         self.assertEqual(wrapped.__name__, fxn.__name__) |         self.assertEqual(wrapped.__name__, fxn.__name__) | ||||||
|         self.assertEqual(wrapped.__qualname__, fxn.__qualname__) |         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(): | def test_main(): | ||||||
|     from test import support |     from test import support | ||||||
|     support.run_unittest(ModuleForLoaderTests, SetPackageTests) |     support.run_unittest( | ||||||
|  |             ModuleForLoaderTests, | ||||||
|  |             SetPackageTests, | ||||||
|  |             ResolveNameTests | ||||||
|  |         ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|  |  | ||||||
|  | @ -3,3 +3,19 @@ | ||||||
| from ._bootstrap import module_for_loader | from ._bootstrap import module_for_loader | ||||||
| from ._bootstrap import set_loader | from ._bootstrap import set_loader | ||||||
| from ._bootstrap import set_package | 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) | ||||||
|  |  | ||||||
|  | @ -23,6 +23,8 @@ Core and Builtins | ||||||
| Library | Library | ||||||
| ------- | ------- | ||||||
| 
 | 
 | ||||||
|  | - Add importlib.util.resolve_name(). | ||||||
|  | 
 | ||||||
| - Issue #14366: Support lzma compression in zip files. | - Issue #14366: Support lzma compression in zip files. | ||||||
|   Patch by Serhiy Storchaka. |   Patch by Serhiy Storchaka. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Brett Cannon
						Brett Cannon