Skip to content

Commit 3fbfadc

Browse files
committed
gh-92041: Preserve frame filename semantics
1 parent 58703a5 commit 3fbfadc

2 files changed

Lines changed: 56 additions & 1 deletion

File tree

Lib/inspect.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,22 @@ def getmodule(object, _filename=None):
943943
if not isinstance(module_name, str):
944944
return None
945945
module = sys.modules.get(module_name)
946-
if ismodule(module) and module.__dict__ is object_globals:
946+
if not (ismodule(module) and module.__dict__ is object_globals):
947+
return None
948+
module_file = getattr(module, '__file__', None)
949+
if module_file is None:
950+
return None
951+
try:
952+
file = getabsfile(object, _filename)
953+
except (TypeError, FileNotFoundError):
954+
return None
955+
if object.f_code.co_filename == module_file:
956+
return module
957+
try:
958+
module_file = getabsfile(module)
959+
except (TypeError, FileNotFoundError):
960+
return None
961+
if file == module_file or file == os.path.realpath(module_file):
947962
return module
948963
return None
949964

Lib/test/test_inspect/test_inspect.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,46 @@ def exec_namespace(namespace):
871871
finally:
872872
del sys.modules[module_name]
873873

874+
def test_getmodule_registered_exec_frame(self):
875+
def exec_module(module, filename):
876+
module.inspect = inspect
877+
exec(compile(textwrap.dedent("""
878+
frame = inspect.currentframe()
879+
try:
880+
1 / 0
881+
except ZeroDivisionError as error:
882+
traceback = error.__traceback__
883+
"""), filename, "exec"), module.__dict__)
884+
885+
module_name = f"{__name__}.registered"
886+
module = types.ModuleType(module_name)
887+
sys.modules[module_name] = module
888+
try:
889+
with temp_cwd() as cwd:
890+
filename = os.path.join(cwd, "registered.py")
891+
with open(filename, "w"):
892+
pass
893+
module.__file__ = filename
894+
895+
exec_module(module, filename)
896+
self.assertIs(inspect.getmodule(module.frame), module)
897+
self.assertIs(inspect.getmodule(module.traceback), module)
898+
899+
# Globals identity is insufficient when the code came from a
900+
# different origin than the registered module.
901+
exec_module(module, filename + ".other")
902+
self.assertIsNone(inspect.getmodule(module.frame))
903+
self.assertIsNone(inspect.getmodule(module.traceback))
904+
905+
# Preserve the existing result for fileless modules while
906+
# avoiding a scan of sys.modules.
907+
del module.__file__
908+
exec_module(module, "<fileless>")
909+
self.assertIsNone(inspect.getmodule(module.frame))
910+
self.assertIsNone(inspect.getmodule(module.traceback))
911+
finally:
912+
del sys.modules[module_name]
913+
874914
def test_getmodule_file_not_found(self):
875915
# See bpo-45406
876916
def _getabsfile(obj, _filename):

0 commit comments

Comments
 (0)