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
|
@ -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 random
|
|||
import stat
|
||||
import sys
|
||||
import unittest
|
||||
import unittest.mock as mock
|
||||
import textwrap
|
||||
import errno
|
||||
import shutil
|
||||
|
@ -864,6 +866,40 @@ class ImportlibBootstrapTests(unittest.TestCase):
|
|||
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…
Reference in New Issue