Commit 265956d
authored
Fix pip module package building (#421)
Status: Ready
The v1.0.0 release on PyPI is missing all submodules (wave, tidal,
dolfyn, etc.) when installed via pip and downstream via conda.
## Reproduction
```bash
pip install "mhkit[all]"
```
```bash
python
Python 3.11.12 (main, Apr 8 2025, 14:15:29) [Clang 15.0.0 (clang-1500.1.0.2.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import mhkit
>>> mhkit.__version__
'v1.0.0'
>>> from mhkit import river
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: cannot import name 'river' from 'mhkit' (/opt/homebrew/lib/python3.11/site-packages/mhkit/__init__.py)
```
### Installed Package Contents
Inspecting the installed package shows two files (run `python -m site`
to find `site-packages`
path):
```bash
ls /opt/homebrew/lib/python3.11/site-packages/mhkit
__init__.py __pycache__ warnings.py
```
All submodules (wave, river, tidal, dolfyn, power, loads, mooring,
acoustics, qc, utils) are missing.
### Reproduction
Running the same build command used by GitHub Actions:
```bash
python -m build --wheel --outdir dist/ .
```
- `python -m build`: Runs Python's `build` module (PEP 517 build
frontend) to build the package
- `--wheel`: Build only a wheel distribution (skips source distribution)
- `--outdir dist/`: Output directory for built files
- `.`: Build the package in the current directory (where
`pyproject.toml` is)
Build output shows two files being copied:
```
running build_py
creating build/lib/mhkit
copying mhkit/warnings.py -> build/lib/mhkit
copying mhkit/__init__.py -> build/lib/mhkit
```
Wheel contents:
```
adding 'mhkit/__init__.py'
adding 'mhkit/warnings.py'
```
## Probable Root Cause
In `pyproject.toml`, this configuration tells setuptools to only include
the top-level `mhkit` package, not any subpackages per:
https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html#setuptools-specific-configuration
```toml
[tool.setuptools]
packages = ["mhkit"]
```
## Proposed Fix
Replace the explicit package list with automatic package discovery using
setuptools' `find` directive.
[Setuptools Package Discovery
Documentation](https://setuptools.pypa.io/en/latest/userguide/package_discovery.html#finding-simple-packages)
```toml
[tool.setuptools.packages.find]
where = ["."]
include = ["mhkit*"]
[tool.setuptools]
zip-safe = false
include-package-data = true
```
What this does (from setuptools docs):
- `where = ["."]`: Search for packages starting from the root directory
- `include = ["mhkit*"]`: Only include packages that match the pattern
`mhkit*` (this includes `mhkit`, `mhkit.wave`, `mhkit.river`, etc.)
- Setuptools will automatically discover all directories containing
`__init__.py` files
This will automatically discover and include:
- `mhkit`
- `mhkit.wave`
- `mhkit.river`
- `mhkit.tidal`
- `mhkit.dolfyn`
- `mhkit.dolfyn.adp`
- `mhkit.dolfyn.adv`
- `mhkit.dolfyn.io`
- `mhkit.dolfyn.rotate`
- `mhkit.dolfyn.tools`
- `mhkit.power`
- `mhkit.loads`
- `mhkit.loads.extreme`
- `mhkit.mooring`
- `mhkit.acoustics`
- `mhkit.qc`
- `mhkit.utils`
- `mhkit.wave.io`
- `mhkit.wave.io.hindcast`
- `mhkit.tidal.io`
- `mhkit.river.io`
- `mhkit.tests.*`
### Verification of Fix
```bash
python -m build --sdist --wheel --outdir dist/ .
unzip -l dist/mhkit-*.whl | grep "mhkit/" | grep "__init__.py"
```
- `python -m build`: Runs Python's `build` module to build the package
- `--sdist`: Build a source distribution (`.tar.gz` file) - a compressed
archive of source code
- `--wheel`: Build a wheel (`.whl` file) - a pre-built distribution that
pip installs directly
- Can be unzipped and inspected: `unzip -l
dist/mhkit-1.0.0-py3-none-any.whl | grep "mhkit/" | grep "__init__.py"`
Why build both formats?
- Wheel: This is what `pip install mhkit` downloads and installs. The
bug affects this format.
- Source distribution: Backup format for systems that can't use wheels.
Always includes all source files.
- Current GitHub Actions builds both, so this matches the actual release
process.
References:
- [Python Packaging: Source
Distribution](https://packaging.python.org/en/latest/specifications/source-distribution-format/)
- [Python Packaging:
Wheel](https://packaging.python.org/en/latest/specifications/binary-distribution-format/)
Contents of newly build wheel:
```bash
unzip -l dist/mhkit-1.0.0-py3-none-any.whl | grep "mhkit/" | grep "__init__.py"
1556 10-02-2025 16:10 mhkit/__init__.py
1156 10-02-2025 16:10 mhkit/acoustics/__init__.py
493 05-08-2024 16:38 mhkit/dolfyn/__init__.py
18 05-08-2024 16:38 mhkit/dolfyn/adp/__init__.py
18 05-08-2024 16:38 mhkit/dolfyn/adv/__init__.py
362 04-24-2024 16:42 mhkit/dolfyn/io/__init__.py
227 04-24-2024 16:42 mhkit/dolfyn/rotate/__init__.py
71 04-24-2024 16:42 mhkit/dolfyn/tools/__init__.py
493 10-02-2025 16:10 mhkit/loads/__init__.py
974 10-02-2025 16:10 mhkit/loads/extreme/__init__.py
84 04-24-2024 16:42 mhkit/mooring/__init__.py
94 05-08-2024 16:38 mhkit/power/__init__.py
145 05-08-2024 16:38 mhkit/qc/__init__.py
223 10-02-2025 16:10 mhkit/river/__init__.py
161 10-02-2025 16:10 mhkit/river/io/__init__.py
284 10-02-2025 16:10 mhkit/tidal/__init__.py
157 05-08-2024 16:38 mhkit/wave/__init__.py
```
5. Installed and tested the fixed wheel:
```bash
pip uninstall mhkit
pip install dist/mhkit-1.0.0-py3-none-any.whl
```
6. Verified imports work:
```bash
In [1]: import mhkit
In [2]: mhkit.__version__
Out[2]: 'v1.0.0'
In [3]: from mhkit import river
In [4]: river.performance.circular(30)
Out[4]: (30, 706.8583470577034)
```
## Preventing Future Issues
To prevent this issue from happening again, this adds two GH actions
changes in `.github/workflows/main.yml`
and `.github/workflows/pypi.yml, `to verify the built wheel includes all
submodules and run the
tests against the installed wheel.1 parent f4a1e8d commit 265956d
File tree
4 files changed
+77
-2
lines changed- .github/workflows
- mhkit
4 files changed
+77
-2
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
390 | 390 | | |
391 | 391 | | |
392 | 392 | | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
393 | 449 | | |
394 | 450 | | |
395 | 451 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
30 | 35 | | |
31 | 36 | | |
32 | 37 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
14 | | - | |
| 14 | + | |
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
126 | 126 | | |
127 | 127 | | |
128 | 128 | | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
129 | 144 | | |
130 | | - | |
131 | 145 | | |
132 | 146 | | |
133 | 147 | | |
| |||
0 commit comments