-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
package __path__
is an empty list
#557
Comments
It is my understanding that the Editable installs as implemented by meson-python use a customized module loader to load the module code from the source directory and the build directory, as needed. A consequence of this, is that we need to make the |
Agreed. For the record, I haven't encountered any issues when switching to |
Thanks for your answer, it seems like a side-effect of this is that This is a mild annoyance since we are using |
Please refer to the documentation of
The fact that the custom loader exposes an empty Looking at this a tiny bit more in depth, the interface of |
OK thanks for your pointers, I'll try to look into it a bit more. I have to admit I am not familiar at all with this kind of subtle import machinery. |
I'll note that this usage of It'd be better to avoid |
OK weird, just to make 100% sure, can you confirm that If that's the case, there may be something that is |
Eh oh, good catch. The test is silently passing, but it is an empty list and hence the test does not work as intended in editable mode:
|
OK so at least this is not scikit-learn specific 😌 |
Thanks for the feedback @dnicolodi. After a bit of trial and error, here is the only way I could get to write an alternative to from pathlib import Path
from importlib.util import find_spec
from pkgutil import iter_modules
# Alternative to sklearn.__path__ that does not rely on sklearn.__file__:
def get_package_path(package):
spec = find_spec(package)
if spec is None:
raise ImportError(f"No module named {package!r}")
return [Path(spec.origin).parent]
print(f"{get_package_path('sklearn') = }")
# Alternative to pkgutil.walk_packages that does not rely on pkg.__path__:
def walk_packages(path=None, prefix='', onerror=None):
"""Yields ModuleInfo for all modules recursively
on path, or, if path is None, all accessible modules.
'path' should be either None or a list of paths to look for
modules in.
'prefix' is a string to output on the front of every module name
on output.
Note that this function must import all *packages* (NOT all
modules!) on the given path, in order to access the __path__
attribute to find submodules.
'onerror' is a function which gets called with one argument (the
name of the package which was being imported) if any exception
occurs while trying to import a package. If no onerror function is
supplied, ImportErrors are caught and ignored, while all other
exceptions are propagated, terminating the search.
Examples:
# list all modules python can access
walk_packages()
# list all submodules of ctypes
walk_packages(ctypes.__path__, ctypes.__name__+'.')
"""
def seen(p, m={}):
if p in m:
return True
m[p] = True
for info in iter_modules(path, prefix):
yield info
if info.ispkg:
try:
__import__(info.name)
except ImportError:
if onerror is not None:
onerror(info.name)
except Exception:
if onerror is not None:
onerror(info.name)
else:
raise
else:
path = get_package_path(info.name)
# don't traverse path items we've seen before
path = [p for p in path if not seen(p)]
yield from walk_packages(path, info.name+'.', onerror)
for info in walk_packages(get_package_path('sklearn'), 'sklearn.'):
print(info.name) The It seems to fix the problem for scikit-learn when installed in meson-python editable mode, but it's a shame not to be able to use the standard Shall this be considered a bug in |
This solves the problem of empty __path__ attributes for packages imported from an editable install. Fixes mesonbuild#557.
By reading more about import machinery in CPython and the source code of mesonpy, I think this is just a missing feature in mesonpy's custom module finder for editable install and the fix is quite straightforward, see #562. |
The implementation of |
Set the __path__ module attribute to a placeholder path. Because how editable installs are implemented, this cannot correspond to the filesystem path for the package. And add a sys.path_hook that recognizes this paths and returns a path loader that implements iter_modules(). This allows pkgutil.iter_packages() to work properly. Fixes mesonbuild#557.
Set the __path__ module attribute to a placeholder path. Because how editable installs are implemented, this cannot correspond to the filesystem path for the package. And add a sys.path_hook that recognizes this paths and returns a path loader that implements iter_modules(). This allows pkgutil.iter_packages() to work properly. Fixes mesonbuild#557.
Set the __path__ module attribute to a placeholder path. Because how editable installs are implemented, this cannot correspond to the filesystem path for the package. And add a sys.path_hook that recognizes this paths and returns a path loader that implements iter_modules(). This allows pkgutil.iter_packages() to work properly. Fixes mesonbuild#557.
Set the __path__ module attribute to a placeholder path. Because how editable installs are implemented, this cannot correspond to the filesystem path for the package. And add a sys.path_hook that recognizes this paths and returns a path loader that implements iter_modules(). This allows pkgutil.iter_packages() to work properly. Fixes mesonbuild#557.
Set the __path__ module attribute to a placeholder path. Because how editable installs are implemented, this cannot correspond to the filesystem path for the package. And add a sys.path_hook that recognizes this paths and returns a path loader that implements iter_modules(). This allows pkgutil.iter_packages() to work properly. Fixes mesonbuild#557.
Set the __path__ module attribute to a placeholder path. Because how editable installs are implemented, this cannot correspond to the filesystem path for the package. And add a sys.path_hook that recognizes this paths and returns a path loader that implements iter_modules(). This allows pkgutil.iter_packages() to work properly. Fixes mesonbuild#557.
Set the __path__ module attribute to a placeholder path. Because how editable installs are implemented, this cannot correspond to the filesystem path for the package. And add a sys.path_hook that recognizes this paths and returns a path loader that implements iter_modules(). This allows pkgutil.iter_packages() to work properly. Fixes mesonbuild#557.
Set the __path__ module attribute to a placeholder path. Because how editable installs are implemented, this cannot correspond to the filesystem path for the package. And add a sys.path_hook that recognizes this paths and returns a path loader that implements iter_modules(). This allows pkgutil.iter_packages() to work properly. Fixes mesonbuild#557.
Set the __path__ module attribute to a placeholder path. Because how editable installs are implemented, this cannot correspond to the filesystem path for the package. And add a sys.path_hook that recognizes this paths and returns a path loader that implements iter_modules(). This allows pkgutil.iter_packages() to work properly. Fixes mesonbuild#557.
Set the __path__ module attribute to a placeholder path. Because how editable installs are implemented, this cannot correspond to the filesystem path for the package. And add a sys.path_hook that recognizes this paths and returns a path loader that implements iter_modules(). This allows pkgutil.iter_packages() to work properly. Fixes mesonbuild#557, mesonbuild#568.
Set the __path__ module attribute to a placeholder path. Because how editable installs are implemented, this cannot correspond to the filesystem path for the package. And add a sys.path_hook that recognizes this paths and returns a path loader that implements iter_modules(). This allows pkgutil.iter_packages() to work properly. Fixes mesonbuild#557. Fixes mesonbuild#568.
Set the __path__ module attribute to a placeholder path. Because how editable installs are implemented, this cannot correspond to the filesystem path for the package. And add a sys.path_hook that recognizes this paths and returns a path loader that implements iter_modules(). This allows pkgutil.iter_packages() to work properly. Fixes mesonbuild#557. Fixes mesonbuild#568.
Set the __path__ module attribute to a placeholder path. Because how editable installs are implemented, this cannot correspond to the filesystem path for the package. And add a sys.path_hook that recognizes this paths and returns a path loader that implements iter_modules(). This allows pkgutil.iter_packages() to work properly. Fixes mesonbuild#557. Fixes mesonbuild#568.
Set the __path__ module attribute to a placeholder path. Because how editable installs are implemented, this cannot correspond to the filesystem path for the package. And add a sys.path_hook that recognizes this paths and returns a path loader that implements iter_modules(). This allows pkgutil.iter_packages() to work properly. Fixes #557. Fixes #568.
I noticed this when working on moving scikit-learn to Meson. I tried with numpy and get the same result so I am guessing this is not something due to our particular setup?
With editable install (
pip install -e . --no-build-isolation
)When I use normal install (
pip install . --no-build-isolation
), I get something like this:This is not a huge issue since we were able to use
__file__
for our needs, but I thought I would open an issue anyway.The text was updated successfully, but these errors were encountered: