Skip to content

[BUG] PEP 420 namespace packages via package_dir don't work with editable installs #4943

Open
@mgorny

Description

@mgorny

setuptools version

78.1.0

Python version

3.13.3

OS

Gentoo Linux amd64

Additional environment information

No response

Description

I'm trying to port Triton's setup.py to stop using symlinks to cross-link Python packages and use package_dir instead. Unfortunately, it seems that if a package referenced through package_dir does not have a __init__.py (i.e. is effectively a PEP 420 namespace package), it cannot be imported from an editable install.

Expected behavior

All packages being importable from an editable install.

How to Reproduce

mkdir -p python/test third_party/{a,b}
> python/test/__init__.py
> third_party/a/__init__.py
> third_party/a/foo.py
> third_party/b/foo.py
cat > setup.py <<EOF
from setuptools import setup
setup(name="test",
      packages=["test", "test.a", "test.b"],
      package_dir={"": "python",
                   "test.a": "third_party/a",
                   "test.b": "third_party/b"})
EOF
pip install -e .
python -c 'import test.a.foo; import test.b.foo'

Output

$ pip install -e .
Obtaining file:///tmp/repro
  Installing build dependencies ... done
  Checking if build backend supports build_editable ... done
  Getting requirements to build editable ... done
  Preparing editable metadata (pyproject.toml) ... done
Building wheels for collected packages: test
  Building editable for test (pyproject.toml) ... done
  Created wheel for test: filename=test-0.0.0-0.editable-py3-none-any.whl size=2570 sha256=ede19ca9e89c0f19de29833a8d0466abf67ab9b99dd30d04237612a997803cd0
  Stored in directory: /tmp/pip-ephem-wheel-cache-ijmh_p0o/wheels/0e/11/03/c16968b602979cd363b907ce63c485bbbc0baada53c46b3cc5
Successfully built test
Installing collected packages: test
Successfully installed test-0.0.0
$ python -c 'import test.a.foo; import test.b.foo'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
    import test.a.foo; import test.b.foo
                       ^^^^^^^^^^^^^^^^^
ModuleNotFoundError: No module named 'test.b'

Note that wheel has a working file structure, by comparison:

$ unzip -l dist/test-0.0.0-py3-none-any.whl 
Archive:  dist/test-0.0.0-py3-none-any.whl
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  04-11-2025 16:14   test/__init__.py
        0  04-11-2025 16:14   test/a/__init__.py
        0  04-11-2025 16:14   test/a/foo.py
        0  04-11-2025 16:14   test/b/foo.py
       48  04-11-2025 16:15   test-0.0.0.dist-info/METADATA
       91  04-11-2025 16:15   test-0.0.0.dist-info/WHEEL
        5  04-11-2025 16:15   test-0.0.0.dist-info/top_level.txt
      559  04-11-2025 16:15   test-0.0.0.dist-info/RECORD
---------                     -------
      703                     8 files

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions