From 373fd085eeeddac9fecf08d76cc24db076592126 Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Tue, 31 May 2022 11:57:20 -0400 Subject: [PATCH 1/2] More conservative interpretation of `PathFinder.find_spec()` failures --- astroid/interpreter/_import/util.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/astroid/interpreter/_import/util.py b/astroid/interpreter/_import/util.py index 5db1702d5a..ab3aa652fb 100644 --- a/astroid/interpreter/_import/util.py +++ b/astroid/interpreter/_import/util.py @@ -34,8 +34,17 @@ def is_namespace(modname: str) -> bool: working_modname, path=last_submodule_search_locations ) except ValueError: - # Assume it's a .pth file, unless it's __main__ - return modname != "__main__" + if modname == "__main__": + return False + try: + # .pth files will be on sys.modules + return sys.modules[modname].__spec__ is None + except KeyError: + return False + except AttributeError: + # Workaround for "py" module + # https://github.com/pytest-dev/apipkg/issues/13 + return False except KeyError: # Intermediate steps might raise KeyErrors # https://github.com/python/cpython/issues/93334 From 6a2d85d236f746c6ed7c706c8390431accb64d8e Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Tue, 31 May 2022 13:05:36 -0400 Subject: [PATCH 2/2] Add test --- tests/unittest_manager.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/unittest_manager.py b/tests/unittest_manager.py index e9a1957e44..9cf02aff86 100644 --- a/tests/unittest_manager.py +++ b/tests/unittest_manager.py @@ -129,6 +129,15 @@ def test_module_is_not_namespace(self) -> None: self.assertFalse(util.is_namespace("tests.testdata.python3.data.all")) self.assertFalse(util.is_namespace("__main__")) + def test_module_unexpectedly_missing_spec(self) -> None: + astroid_module = sys.modules["astroid"] + original_spec = astroid_module.__spec__ + del astroid_module.__spec__ + try: + self.assertFalse(util.is_namespace("astroid")) + finally: + astroid_module.__spec__ = original_spec + def test_implicit_namespace_package(self) -> None: data_dir = os.path.dirname(resources.find("data/namespace_pep_420")) contribute = os.path.join(data_dir, "contribute_to_namespace")