mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	Issue #18351: Fix various issues with
importlib._bootstrap._get_sourcefile(). Thanks to its only use by the C API, it was never properly tested until now. Thanks to Neal Norwitz for discovering the bug and Madison May for the patch.
This commit is contained in:
		
							parent
							
								
									2a99d5df63
								
							
						
					
					
						commit
						a53cca3fea
					
				
					 5 changed files with 3446 additions and 3407 deletions
				
			
		|  | @ -471,16 +471,14 @@ def _get_sourcefile(bytecode_path): | |||
|     """ | ||||
|     if len(bytecode_path) == 0: | ||||
|         return None | ||||
|     rest, _, extension = bytecode_path.rparition('.') | ||||
|     if not rest or extension.lower()[-3:-1] != '.py': | ||||
|     rest, _, extension = bytecode_path.rpartition('.') | ||||
|     if not rest or extension.lower()[-3:-1] != 'py': | ||||
|         return bytecode_path | ||||
| 
 | ||||
|     try: | ||||
|         source_path = source_from_cache(bytecode_path) | ||||
|     except (NotImplementedError, ValueError): | ||||
|         source_path = bytcode_path[-1:] | ||||
| 
 | ||||
|     return source_path if _path_isfile(source_stats) else bytecode_path | ||||
|         source_path = bytecode_path[:-1] | ||||
|     return source_path if _path_isfile(source_path) else bytecode_path | ||||
| 
 | ||||
| 
 | ||||
| def _verbose_message(message, *args, verbosity=1): | ||||
|  |  | |||
|  | @ -1,5 +1,6 @@ | |||
| # We import importlib *ASAP* in order to test #15386 | ||||
| import importlib | ||||
| from importlib._bootstrap import _get_sourcefile | ||||
| import builtins | ||||
| import imp | ||||
| from test.test_importlib.import_ import util as importlib_util | ||||
|  | @ -11,6 +12,7 @@ | |||
| import stat | ||||
| import sys | ||||
| import unittest | ||||
| import unittest.mock as mock | ||||
| import textwrap | ||||
| import errno | ||||
| import shutil | ||||
|  | @ -864,6 +866,40 @@ def test_there_can_be_only_one(self): | |||
|         self.assertIs(imp.new_module, mod.new_module) | ||||
| 
 | ||||
| 
 | ||||
| @cpython_only | ||||
| class GetSourcefileTests(unittest.TestCase): | ||||
| 
 | ||||
|     """Test importlib._bootstrap._get_sourcefile() as used by the C API. | ||||
| 
 | ||||
|     Because of the peculiarities of the need of this function, the tests are | ||||
|     knowingly whitebox tests. | ||||
| 
 | ||||
|     """ | ||||
| 
 | ||||
|     def test_get_sourcefile(self): | ||||
|         # Given a valid bytecode path, return the path to the corresponding | ||||
|         # source file if it exists. | ||||
|         with mock.patch('importlib._bootstrap._path_isfile') as _path_isfile: | ||||
|             _path_isfile.return_value = True; | ||||
|             path = TESTFN + '.pyc' | ||||
|             expect = TESTFN + '.py' | ||||
|             self.assertEqual(_get_sourcefile(path), expect) | ||||
| 
 | ||||
|     def test_get_sourcefile_no_source(self): | ||||
|         # Given a valid bytecode path without a corresponding source path, | ||||
|         # return the original bytecode path. | ||||
|         with mock.patch('importlib._bootstrap._path_isfile') as _path_isfile: | ||||
|             _path_isfile.return_value = False; | ||||
|             path = TESTFN + '.pyc' | ||||
|             self.assertEqual(_get_sourcefile(path), path) | ||||
| 
 | ||||
|     def test_get_sourcefile_bad_ext(self): | ||||
|         # Given a path with an invalid bytecode extension, return the | ||||
|         # bytecode path passed as the argument. | ||||
|         path = TESTFN + '.bad_ext' | ||||
|         self.assertEqual(_get_sourcefile(path), path) | ||||
| 
 | ||||
| 
 | ||||
| class ImportTracebackTests(unittest.TestCase): | ||||
| 
 | ||||
|     def setUp(self): | ||||
|  | @ -1028,7 +1064,7 @@ def test_main(verbose=None): | |||
|     run_unittest(ImportTests, PycacheTests, FilePermissionTests, | ||||
|                  PycRewritingTests, PathsTests, RelativeImportTests, | ||||
|                  OverridingImportBuiltinTests, | ||||
|                  ImportlibBootstrapTests, | ||||
|                  ImportlibBootstrapTests, GetSourcefileTests, | ||||
|                  TestSymbolicallyLinkedPackage, | ||||
|                  ImportTracebackTests) | ||||
| 
 | ||||
|  |  | |||
|  | @ -788,6 +788,7 @@ Laura Matson | |||
| Graham Matthews | ||||
| Dieter Maurer | ||||
| Daniel May | ||||
| Madison May | ||||
| Arnaud Mazin | ||||
| Rebecca McCreary | ||||
| Kirk McDonald | ||||
|  |  | |||
|  | @ -130,6 +130,12 @@ Library | |||
| - Issue #18113: Fixed a refcount leak in the curses.panel module's | ||||
|   set_userptr() method.  Reported by Atsuo Ishimoto. | ||||
| 
 | ||||
| C API | ||||
| ----- | ||||
| 
 | ||||
| - Issue #18351: Fix various issues with a helper function in importlib used | ||||
|   by PyImport_ExecCodeModuleWithPathnames() (and thus by extension PyImport_ExecCodeModule() and PyImport_ExecCodeModuleEx()). | ||||
| 
 | ||||
| IDLE | ||||
| ---- | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										6798
									
								
								Python/importlib.h
									
										
									
									
									
								
							
							
						
						
									
										6798
									
								
								Python/importlib.h
									
										
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Brett Cannon
						Brett Cannon