From 6aefe5f8784208e23983224b5211a4b92d750158 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Feb 2026 17:37:26 +0000 Subject: [PATCH 1/2] Initial plan From d14327bfb9bfba75a6a0a1b53d4464072883b9e7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 23 Feb 2026 17:49:24 +0000 Subject: [PATCH 2/2] 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> --- .../_vendored/pydevd/pydevd_file_utils.py | 17 +++++----- .../tests_python/test_convert_utilities.py | 31 +++++++++++++++++++ 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/debugpy/_vendored/pydevd/pydevd_file_utils.py b/src/debugpy/_vendored/pydevd/pydevd_file_utils.py index 7ca383444..b16178e9f 100644 --- a/src/debugpy/_vendored/pydevd/pydevd_file_utils.py +++ b/src/debugpy/_vendored/pydevd/pydevd_file_utils.py @@ -966,17 +966,14 @@ def get_abs_path_real_path_and_base_from_frame(frame, NORM_PATHS_AND_BASE_CONTAI def get_fullname(mod_name): - import pkgutil - try: - loader = pkgutil.get_loader(mod_name) - except: - return None - if loader is not None: - for attr in ("get_filename", "_get_filename"): - meth = getattr(loader, attr, None) - if meth is not None: - return meth(mod_name) + import importlib.util + + spec = importlib.util.find_spec(mod_name) + if spec is not None and spec.origin is not None and spec.has_location: + return spec.origin + except (ImportError, ModuleNotFoundError, ValueError): + pass return None diff --git a/src/debugpy/_vendored/pydevd/tests_python/test_convert_utilities.py b/src/debugpy/_vendored/pydevd/tests_python/test_convert_utilities.py index fd640ab84..97248b6c7 100644 --- a/src/debugpy/_vendored/pydevd/tests_python/test_convert_utilities.py +++ b/src/debugpy/_vendored/pydevd/tests_python/test_convert_utilities.py @@ -560,3 +560,34 @@ def test_mapping_conflict_to_server(): {"remoteRoot": "/var/home/p3", "localRoot": "/opt/v2/path"}, {"remoteRoot": "/var/home/p4", "localRoot": "/opt/v2/pathsomething"}, ] + + +def test_get_fullname(tmp_path): + """Test that get_fullname correctly resolves module names to file paths. + + This is a regression test for the fix that replaced pkgutil.get_loader + (removed in Python 3.14) with importlib.util.find_spec. + """ + from pydevd_file_utils import get_fullname + + # Create a temporary module file + mod_file = tmp_path / "my_test_mod.py" + mod_file.write_text("x = 1\n") + + # Add tmp_path to sys.path so the module can be found + sys.path.insert(0, str(tmp_path)) + try: + result = get_fullname("my_test_mod") + assert result is not None + assert result.endswith("my_test_mod.py") + + # Non-existent module should return None + result = get_fullname("nonexistent_module_xyz_12345") + assert result is None + + # A stdlib package with __init__.py should be found + result = get_fullname("json") + assert result is not None + assert result.endswith("__init__.py") + finally: + sys.path.remove(str(tmp_path))