From 1b460fcddc420ce791f7f7bb33b260826034f3c9 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Filipe=20La=C3=ADns?= Date: Tue, 9 Dec 2025 15:50:50 +0000 Subject: [PATCH] gh-84530: fix namespace package support in modulefinder (#29196) MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * bpo-40350: fix namespace package support in modulefinder Signed-off-by: Filipe Laíns * consider that namespace package specs might have the loader set Signed-off-by: Filipe Laíns * Revert "consider that namespace package specs might have the loader set" This reverts commit 23fb4e0de38466217e932115143db1a9584e35da. Signed-off-by: Filipe Laíns * Fix load_module and load_package to handle namespace packages Signed-off-by: Filipe Laíns * Drop _NAMESPACE constant Signed-off-by: Filipe Laíns * Drop importlib changes Signed-off-by: Filipe Laíns * Update NamespacePath check Signed-off-by: Filipe Laíns * Mixed some Signed-off-by: Filipe Laíns --------- Signed-off-by: Filipe Laíns --- Lib/modulefinder.py | 12 +++++++++++- Lib/test/test_modulefinder.py | 15 +++++++++++++++ .../2021-10-23-22-12-13.bpo-40350.t0dQMY.rst | 1 + 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2021-10-23-22-12-13.bpo-40350.t0dQMY.rst diff --git a/Lib/modulefinder.py b/Lib/modulefinder.py index 7fb19a5c5d18..b8dccc2dd33a 100644 --- a/Lib/modulefinder.py +++ b/Lib/modulefinder.py @@ -66,7 +66,12 @@ def _find_module(name, path=None): file_path = spec.origin - if spec.loader.is_package(name): + # On namespace packages, spec.loader might be None, but + # spec.submodule_search_locations should always be set — check it instead. + if isinstance(spec.submodule_search_locations, importlib.machinery.NamespacePath): + return None, spec.submodule_search_locations, ("", "", _PKG_DIRECTORY) + + if spec.loader.is_package(name): # non-namespace package return None, os.path.dirname(file_path), ("", "", _PKG_DIRECTORY) if isinstance(spec.loader, importlib.machinery.SourceFileLoader): @@ -453,6 +458,11 @@ class ModuleFinder: if newname: fqname = newname m = self.add_module(fqname) + + if isinstance(pathname, importlib.machinery.NamespacePath): + m.__path__ = pathname + return m + m.__file__ = pathname m.__path__ = [pathname] diff --git a/Lib/test/test_modulefinder.py b/Lib/test/test_modulefinder.py index b64e684f8059..703bfbf94d7b 100644 --- a/Lib/test/test_modulefinder.py +++ b/Lib/test/test_modulefinder.py @@ -76,6 +76,18 @@ a/c.py from sys import version_info """] +namespace_package_test = [ + "module", + ["a", "module"], + ["a.c", "blahblah"], [], + """\ +module.py + import a + import a.c + import blahblah +a/b.py +"""] + absolute_import_test = [ "a.module", ["a", "a.module", @@ -353,6 +365,9 @@ class ModuleFinderTest(unittest.TestCase): def test_package(self): self._do_test(package_test) + def test_namespace_package(self): + self._do_test(namespace_package_test) + def test_maybe(self): self._do_test(maybe_test) diff --git a/Misc/NEWS.d/next/Library/2021-10-23-22-12-13.bpo-40350.t0dQMY.rst b/Misc/NEWS.d/next/Library/2021-10-23-22-12-13.bpo-40350.t0dQMY.rst new file mode 100644 index 000000000000..a5236cc57a02 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-10-23-22-12-13.bpo-40350.t0dQMY.rst @@ -0,0 +1 @@ +Fix support for namespace packages in :mod:`modulefinder`. -- 2.47.3