diff --git a/Lib/inspect.py b/Lib/inspect.py index c52469e63861a2..f726e2bafb0889 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -938,6 +938,8 @@ def getmodule(object, _filename=None): return sys.modules.get(modulesbyfile[_filename]) # Try the cache again with the absolute file name try: + if _filename is None: + _filename = getfile(object) file = getabsfile(object, _filename) except (TypeError, FileNotFoundError): return None diff --git a/Lib/test/test_zipimport_support.py b/Lib/test/test_zipimport_support.py index 2b28f46149b4ff..3c71e42072b85f 100644 --- a/Lib/test/test_zipimport_support.py +++ b/Lib/test/test_zipimport_support.py @@ -3,6 +3,7 @@ # The tests are centralised in this fashion to make it easy to drop them # if a platform doesn't support zipimport import test.support +import importlib import os import os.path import sys @@ -96,6 +97,35 @@ def test_inspect_getsource_issue4223(self): finally: del sys.modules["zip_pkg"] + def test_inspect_fresh_namespace_uses_module_loader(self): + # gh-92041: a frame exec'd in a plain namespace resolves to the + # zipimported module owning its filename, so getsource() can use + # the module's loader. + test_src = textwrap.dedent("""\ + import inspect + + def capture(): + return inspect.currentframe() + + frame = capture() + """) + with os_helper.temp_dir() as d: + script_name = make_script(d, "zipped_mod", test_src) + zip_name, _ = make_zip_script(d, "test_zip", script_name) + os.remove(script_name) + sys.path.insert(0, zip_name) + module = importlib.import_module("zipped_mod") + try: + namespace = {} + exec(compile(test_src, module.__file__, "exec"), namespace) + frame = namespace["frame"] + self.assertIs(inspect.getmodule(frame), module) + self.assertEqual(inspect.getsource(frame), + "def capture():\n" + " return inspect.currentframe()\n") + finally: + del sys.modules["zipped_mod"] + def test_doctest_issue4197(self): # To avoid having to keep two copies of the doctest module's # unit tests in sync, this test works by taking the source of diff --git a/Misc/NEWS.d/next/Library/2026-08-30-12-00-00.gh-issue-92041.nRcsQe.rst b/Misc/NEWS.d/next/Library/2026-08-30-12-00-00.gh-issue-92041.nRcsQe.rst new file mode 100644 index 00000000000000..d3b6af46d55527 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-08-30-12-00-00.gh-issue-92041.nRcsQe.rst @@ -0,0 +1,2 @@ +Speed up :func:`inspect.getmodule` for objects resolved by filename, such +as frames, tracebacks and code objects.