Skip to content

Commit

Permalink
improve is_namespace check
Browse files Browse the repository at this point in the history
See https://stackoverflow.com/a/42962529.

Let's take the following contents as an example:
```python
import celery.result

```

From pylint-dev#1777, astroid started to use `processed_components` for
namespace check. In the above case, the `modname` is `celery.result`,
it first checks for `celery` and then `celery.result`.
Before that PR, it'd always check for `celery.result`.

But if you have imported it as `celery.result`,
`sys.modules["celery"].__spec__` is going to be `None`, and hence
the function will return True, and but below where we try to load
get `submodule_path`/`__path__` for `celery.result` will fail as
it is not a package.

See https://github.com/PyCQA/astroid/blob/056d8e5fab7a167f73115d524ab92170b3ed5f9f/astroid/interpreter/_import/spec.py#L205-L207

---

The `celery.result` gets imported for me when pylint-pytest plugin tries
to load fixtures, but this could happen anytime if any plugin imports
packages. In that case, `find_spec("celery")` will raise ValueError
since it's already in `sys.modules` and does not have a spec.

I still think there's a bug for the
`ExplicitNamespacePackageFinder.find_module` for namespace packages,
since `modname` might be `namespace.package.module` but since
`is_namespace` package goes through components, the successive
`sys.modules[modname].__path__` may raise error, since modname
could be not a package in a namespaced package. But I am not quite sure
about that."
  • Loading branch information
skshetry committed Sep 21, 2022
1 parent 849d043 commit 69c5660
Showing 1 changed file with 4 additions and 1 deletion.
5 changes: 4 additions & 1 deletion astroid/interpreter/_import/util.py
Expand Up @@ -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:
Expand Down

0 comments on commit 69c5660

Please sign in to comment.