Summary
When lightkube and lightkube-models are installed into different directories on sys.path (common with Bazel rules_python, PEX/zipapp, layered containers, or custom PYTHONPATH setups), imports inside lightkube that rely on lightkube.models fail with: ModuleNotFoundError: No module named 'lightkube.models'
How to reproduce
# Create fresh venv
python3 -m venv lk-venv
. lk-venv/bin/activate
# Install the two packages into SEPARATE directories (simulates Bazel/rules_python layout)
mkdir -p lk-repro/a lk-repro/b
pip install --target lk-repro/a 'lightkube==0.17.2'
rm -rf lk-repro/a/lightkube/{models,resources} # Remove lightkube-models from the first directory to simulate split-layout
pip install --target lk-repro/b 'lightkube-models==1.31.1.8'
# Reproduce the failure: lightkube can't see models from the other root
PYTHONPATH=lk-repro/a:lk-repro/b python -c "import lightkube"
# Observe ModuleNotFoundError: No module named 'lightkube.models'
Root cause
lightkube and lightkube-models both provide modules under the same top-level package name lightkube/.
- The
lightkube/__init__.py in the lightkube wheel prevents implicit namespace package behavior, so Python does not merge the lightkube package tree across multiple directories.
- Thus,
lightkube.__path__ points only to the first directory containing lightkube, and subpackages from the other wheel (e.g., lightkube.models, lightkube.resources) are invisible.
Proposed fix (backward-compatible, minimal)
Make lightkube a pkgutil-style namespace package by extending its package path in lightkube/__init__.py. This preserves the existing public API re-exports and works even when wheels are installed to different directories.
Add these two lines at the very top of lightkube/__init__.py:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
Why this works:
pkgutil.extend_path tells Python to treat lightkube as a namespace spanning all lightkube/ directories on sys.path.
- It’s compatible with current packaging and does not require removing
__init__.py or altering the public API.
Alternatives
- PEP 420 implicit namespace package: remove
lightkube/__init__.py. Not great here because lightkube/__init__.py re-exports the public API; removing it would be a breaking change or require moving those symbols.
- Runtime workaround in user code (not ideal): mutate
lightkube.__path__ or add a custom MetaPathFinder before importing lightkube to merge paths. This is what some users do under Bazel, but it’s brittle and belongs in the package.
Affected versions
- lightkube: 0.17.2 (and likely earlier)
- lightkube-models: 1.31.x
- Python: 3.12 (also reproducible on 3.10–3.11)
Summary
When
lightkubeandlightkube-modelsare installed into different directories onsys.path(common with Bazel rules_python, PEX/zipapp, layered containers, or custom PYTHONPATH setups), imports insidelightkubethat rely onlightkube.modelsfail with:ModuleNotFoundError: No module named 'lightkube.models'How to reproduce
Root cause
lightkubeandlightkube-modelsboth provide modules under the same top-level package namelightkube/.lightkube/__init__.pyin thelightkubewheel prevents implicit namespace package behavior, so Python does not merge thelightkubepackage tree across multiple directories.lightkube.__path__points only to the first directory containinglightkube, and subpackages from the other wheel (e.g.,lightkube.models,lightkube.resources) are invisible.Proposed fix (backward-compatible, minimal)
Make
lightkubea pkgutil-style namespace package by extending its package path inlightkube/__init__.py. This preserves the existing public API re-exports and works even when wheels are installed to different directories.Add these two lines at the very top of
lightkube/__init__.py:Why this works:
pkgutil.extend_pathtells Python to treatlightkubeas a namespace spanning alllightkube/directories onsys.path.__init__.pyor altering the public API.Alternatives
lightkube/__init__.py. Not great here becauselightkube/__init__.pyre-exports the public API; removing it would be a breaking change or require moving those symbols.lightkube.__path__or add a customMetaPathFinderbefore importinglightkubeto merge paths. This is what some users do under Bazel, but it’s brittle and belongs in the package.Affected versions