diff --git a/ChangeLog b/ChangeLog index fad64dc07..15b5d5172 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,10 @@ Release date: TBA Refs PyCQA/pylint#3941 +* Improve detection of namespace packages for the modules with ``__spec__`` set to None. + + Closes PyCQA/pylint#7488. + What's New in astroid 2.12.11? ============================== diff --git a/astroid/interpreter/_import/util.py b/astroid/interpreter/_import/util.py index c9466999a..b5b089331 100644 --- a/astroid/interpreter/_import/util.py +++ b/astroid/interpreter/_import/util.py @@ -52,8 +52,11 @@ def is_namespace(modname: str) -> bool: # Check first fragment of modname, e.g. "astroid", not "astroid.interpreter" # because of cffi's behavior # See: https://github.com/PyCQA/astroid/issues/1776 + mod = sys.modules[processed_components[0]] return ( - sys.modules[processed_components[0]].__spec__ is None + mod.__spec__ is None + and getattr(mod, "__file__", None) is None + and hasattr(mod, "__path__") and not IS_PYPY ) except KeyError: diff --git a/tests/unittest_manager.py b/tests/unittest_manager.py index 6c13da787..5a4e943e1 100644 --- a/tests/unittest_manager.py +++ b/tests/unittest_manager.py @@ -144,6 +144,15 @@ def test_module_unexpectedly_missing_spec(self) -> None: finally: astroid_module.__spec__ = original_spec + def test_module_unexpectedly_spec_is_none(self) -> None: + astroid_module = sys.modules["astroid"] + original_spec = astroid_module.__spec__ + astroid_module.__spec__ = None + 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")