diff -r df79735b21c1 Lib/importlib/_bootstrap.py --- a/Lib/importlib/_bootstrap.py Fri Jul 05 01:39:49 2013 +0200 +++ b/Lib/importlib/_bootstrap.py Fri Jul 05 23:50:19 2013 +0200 @@ -471,16 +471,16 @@ """ 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:] + source_path = bytecode_path[:-1] - return source_path if _path_isfile(source_stats) else bytecode_path + return source_path if _path_isfile(source_path) else bytecode_path def _verbose_message(message, *args, verbosity=1): diff -r df79735b21c1 Lib/test/test_import.py --- a/Lib/test/test_import.py Fri Jul 05 01:39:49 2013 +0200 +++ b/Lib/test/test_import.py Fri Jul 05 23:50:19 2013 +0200 @@ -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,34 @@ self.assertIs(imp.new_module, mod.new_module) +@cpython_only +class GetSourcefileTests(unittest.TestCase): + + def test_get_sourcefile(self): + # Given a valid bytecode path, return the path to the corresponding + # source file if it exists. _bootstrap._path_isfile is mocked to avoid + # using actual .pyc and .py files for testing + 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 +1058,7 @@ run_unittest(ImportTests, PycacheTests, FilePermissionTests, PycRewritingTests, PathsTests, RelativeImportTests, OverridingImportBuiltinTests, - ImportlibBootstrapTests, + ImportlibBootstrapTests, GetSourcefileTests, TestSymbolicallyLinkedPackage, ImportTracebackTests)