Skip to content
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

BUG: empty __spec__.submodule_search_locations and __path__ values for editable packages #562

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion mesonpy/_editable.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,13 @@ def build_module_spec(cls: type, name: str, path: str, tree: Optional[Node]) ->
spec = importlib.machinery.ModuleSpec(name, loader, origin=path)
spec.has_location = True
if loader.is_package(name):
spec.submodule_search_locations = []
spec.submodule_search_locations = [os.path.dirname(path)]
if tree is not None:
for submodule_node in tree.values():
if isinstance(submodule_node, str):
parent_folder = os.path.dirname(submodule_node)
if parent_folder not in spec.submodule_search_locations:
spec.submodule_search_locations.append(parent_folder)
return spec


Expand Down
44 changes: 43 additions & 1 deletion tests/test_editable.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import os
import pathlib
import pkgutil
import sys

import pytest
Expand Down Expand Up @@ -86,10 +87,23 @@ def test_mesonpy_meta_finder(package_complex, tmp_path):
# verify that we can import the modules
import complex
assert complex.__spec__.origin == os.fspath(package_complex / 'complex/__init__.py')
assert complex.__file__ == os.fspath(package_complex / 'complex/__init__.py')
assert complex.__spec__.submodule_search_locations == [
os.fspath(package_complex / 'complex'),
str(tmp_path),
]
assert complex.__file__ == complex.__spec__.origin
assert complex.__path__ == complex.__spec__.submodule_search_locations
import complex.test
assert complex.test.__spec__.origin == os.fspath(tmp_path / f'test{EXT_SUFFIX}')
assert complex.test.__file__ == complex.test.__spec__.origin
assert complex.test.__spec__.submodule_search_locations is None
assert not hasattr(complex.test, '__path__')
assert complex.test.answer() == 42
import complex.more
assert complex.more.__spec__.origin == os.fspath(package_complex / 'complex/more/__init__.py')
assert complex.more.__spec__.submodule_search_locations == [os.fspath(package_complex / 'complex/more')]
assert complex.more.__file__ == complex.more.__spec__.origin
assert complex.more.__path__ == complex.more.__spec__.submodule_search_locations
import complex.namespace.foo
assert complex.namespace.foo.__spec__.origin == os.fspath(package_complex / 'complex/namespace/foo.py')
assert complex.namespace.foo.foo() == 'foo'
Expand All @@ -98,6 +112,34 @@ def test_mesonpy_meta_finder(package_complex, tmp_path):
del sys.meta_path[0]


def test_walk_packages(package_complex, tmp_path):
# build a package in a temporary directory
mesonpy.Project(package_complex, tmp_path)

# point the meta finder to the build directory
finder = _editable.MesonpyMetaFinder({'complex'}, os.fspath(tmp_path), ['ninja'])

try:
# install the finder in the meta path
sys.meta_path.insert(0, finder)

import complex

module_names = sorted(
module_info.name
for module_info in pkgutil.walk_packages(complex.__path__, prefix='complex.')
)
assert module_names == [
'complex.more',
'complex.test',
# XXX: should namespace packages be discovered by walk_packages?
]

finally:
# remove finder from the meta path
del sys.meta_path[0]


def test_mesonpy_traversable():
tree = _editable.Node()
tree[('package', '__init__.py')] = '/tmp/src/package/__init__.py'
Expand Down