Skip to content

Commit bc6fe51

Browse files
Copilotrchiodo
andauthored
Replace removed pkgutil.get_loader with importlib.util.find_spec in get_fullname (#1998)
* Initial plan * Fix get_fullname to use importlib.util.find_spec instead of removed pkgutil.get_loader pkgutil.get_loader() was removed in Python 3.14, causing subprocess module execution to fail with "No module named" when subProcess: true. Replace with importlib.util.find_spec() which is the recommended replacement and works across all supported Python versions. Co-authored-by: rchiodo <19672699+rchiodo@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: rchiodo <19672699+rchiodo@users.noreply.github.com>
1 parent 7ac3d1f commit bc6fe51

File tree

2 files changed

+38
-10
lines changed

2 files changed

+38
-10
lines changed

src/debugpy/_vendored/pydevd/pydevd_file_utils.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -966,17 +966,14 @@ def get_abs_path_real_path_and_base_from_frame(frame, NORM_PATHS_AND_BASE_CONTAI
966966

967967

968968
def get_fullname(mod_name):
969-
import pkgutil
970-
971969
try:
972-
loader = pkgutil.get_loader(mod_name)
973-
except:
974-
return None
975-
if loader is not None:
976-
for attr in ("get_filename", "_get_filename"):
977-
meth = getattr(loader, attr, None)
978-
if meth is not None:
979-
return meth(mod_name)
970+
import importlib.util
971+
972+
spec = importlib.util.find_spec(mod_name)
973+
if spec is not None and spec.origin is not None and spec.has_location:
974+
return spec.origin
975+
except (ImportError, ModuleNotFoundError, ValueError):
976+
pass
980977
return None
981978

982979

src/debugpy/_vendored/pydevd/tests_python/test_convert_utilities.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,3 +560,34 @@ def test_mapping_conflict_to_server():
560560
{"remoteRoot": "/var/home/p3", "localRoot": "/opt/v2/path"},
561561
{"remoteRoot": "/var/home/p4", "localRoot": "/opt/v2/pathsomething"},
562562
]
563+
564+
565+
def test_get_fullname(tmp_path):
566+
"""Test that get_fullname correctly resolves module names to file paths.
567+
568+
This is a regression test for the fix that replaced pkgutil.get_loader
569+
(removed in Python 3.14) with importlib.util.find_spec.
570+
"""
571+
from pydevd_file_utils import get_fullname
572+
573+
# Create a temporary module file
574+
mod_file = tmp_path / "my_test_mod.py"
575+
mod_file.write_text("x = 1\n")
576+
577+
# Add tmp_path to sys.path so the module can be found
578+
sys.path.insert(0, str(tmp_path))
579+
try:
580+
result = get_fullname("my_test_mod")
581+
assert result is not None
582+
assert result.endswith("my_test_mod.py")
583+
584+
# Non-existent module should return None
585+
result = get_fullname("nonexistent_module_xyz_12345")
586+
assert result is None
587+
588+
# A stdlib package with __init__.py should be found
589+
result = get_fullname("json")
590+
assert result is not None
591+
assert result.endswith("__init__.py")
592+
finally:
593+
sys.path.remove(str(tmp_path))

0 commit comments

Comments
 (0)