Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a53cca3

Browse files
committed
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.
1 parent 2a99d5d commit a53cca3

5 files changed

Lines changed: 3415 additions & 3376 deletions

File tree

Lib/importlib/_bootstrap.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -471,16 +471,14 @@ def _get_sourcefile(bytecode_path):
471471
"""
472472
if len(bytecode_path) == 0:
473473
return None
474-
rest, _, extension = bytecode_path.rparition('.')
475-
if not rest or extension.lower()[-3:-1] != '.py':
474+
rest, _, extension = bytecode_path.rpartition('.')
475+
if not rest or extension.lower()[-3:-1] != 'py':
476476
return bytecode_path
477-
478477
try:
479478
source_path = source_from_cache(bytecode_path)
480479
except (NotImplementedError, ValueError):
481-
source_path = bytcode_path[-1:]
482-
483-
return source_path if _path_isfile(source_stats) else bytecode_path
480+
source_path = bytecode_path[:-1]
481+
return source_path if _path_isfile(source_path) else bytecode_path
484482

485483

486484
def _verbose_message(message, *args, verbosity=1):

Lib/test/test_import.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# We import importlib *ASAP* in order to test #15386
22
import importlib
3+
from importlib._bootstrap import _get_sourcefile
34
import builtins
45
import imp
56
from test.test_importlib.import_ import util as importlib_util
@@ -11,6 +12,7 @@
1112
import stat
1213
import sys
1314
import unittest
15+
import unittest.mock as mock
1416
import textwrap
1517
import errno
1618
import shutil
@@ -864,6 +866,40 @@ def test_there_can_be_only_one(self):
864866
self.assertIs(imp.new_module, mod.new_module)
865867

866868

869+
@cpython_only
870+
class GetSourcefileTests(unittest.TestCase):
871+
872+
"""Test importlib._bootstrap._get_sourcefile() as used by the C API.
873+
874+
Because of the peculiarities of the need of this function, the tests are
875+
knowingly whitebox tests.
876+
877+
"""
878+
879+
def test_get_sourcefile(self):
880+
# Given a valid bytecode path, return the path to the corresponding
881+
# source file if it exists.
882+
with mock.patch('importlib._bootstrap._path_isfile') as _path_isfile:
883+
_path_isfile.return_value = True;
884+
path = TESTFN + '.pyc'
885+
expect = TESTFN + '.py'
886+
self.assertEqual(_get_sourcefile(path), expect)
887+
888+
def test_get_sourcefile_no_source(self):
889+
# Given a valid bytecode path without a corresponding source path,
890+
# return the original bytecode path.
891+
with mock.patch('importlib._bootstrap._path_isfile') as _path_isfile:
892+
_path_isfile.return_value = False;
893+
path = TESTFN + '.pyc'
894+
self.assertEqual(_get_sourcefile(path), path)
895+
896+
def test_get_sourcefile_bad_ext(self):
897+
# Given a path with an invalid bytecode extension, return the
898+
# bytecode path passed as the argument.
899+
path = TESTFN + '.bad_ext'
900+
self.assertEqual(_get_sourcefile(path), path)
901+
902+
867903
class ImportTracebackTests(unittest.TestCase):
868904

869905
def setUp(self):
@@ -1028,7 +1064,7 @@ def test_main(verbose=None):
10281064
run_unittest(ImportTests, PycacheTests, FilePermissionTests,
10291065
PycRewritingTests, PathsTests, RelativeImportTests,
10301066
OverridingImportBuiltinTests,
1031-
ImportlibBootstrapTests,
1067+
ImportlibBootstrapTests, GetSourcefileTests,
10321068
TestSymbolicallyLinkedPackage,
10331069
ImportTracebackTests)
10341070

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,7 @@ Laura Matson
788788
Graham Matthews
789789
Dieter Maurer
790790
Daniel May
791+
Madison May
791792
Arnaud Mazin
792793
Rebecca McCreary
793794
Kirk McDonald

Misc/NEWS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,12 @@ Library
130130
- Issue #18113: Fixed a refcount leak in the curses.panel module's
131131
set_userptr() method. Reported by Atsuo Ishimoto.
132132

133+
C API
134+
-----
135+
136+
- Issue #18351: Fix various issues with a helper function in importlib used
137+
by PyImport_ExecCodeModuleWithPathnames() (and thus by extension PyImport_ExecCodeModule() and PyImport_ExecCodeModuleEx()).
138+
133139
IDLE
134140
----
135141

0 commit comments

Comments
 (0)