-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17 from Parallel-NetCDF/developer_notes
add developer notes
- Loading branch information
Showing
1 changed file
with
358 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,358 @@ | ||
## Notes for PnetCDF-Python developers | ||
|
||
This file contains instructions for PnetCDF-Python developers. | ||
Users of PnetCDF-Python please refer to the | ||
[PnetCDF-Python User Guide](https://pnetcdf-python.readthedocs.io/en/latest/). | ||
|
||
* [Making A New Release](#making-a-new-release) | ||
* [Library Packaging And Publishing](#library-packaging-and-publishing) | ||
* [Library installation](#library-installation) | ||
* [User Guide](user-guide) | ||
|
||
--- | ||
### Making A New Release | ||
|
||
Below is a list of tasks to be done immediately before making a new release | ||
(must run in the following order). | ||
|
||
1. Update the release version string | ||
* Edit file [src/pnetcdf/__init__.py](src/pnetcdf/__init__.py) and update | ||
the following string to the new version number. | ||
``` | ||
__version__ = "1.0.0" | ||
``` | ||
<ul> | ||
<li> <details> | ||
<summary>GNU guideline for updating version numbers(click to expand)</summary> | ||
<li> For libtool Application Binary Versioning (ABI) versioning rules see: | ||
http://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info | ||
</li> | ||
<li> Update the version information only immediately before a public release. | ||
</li> | ||
<li> Quote from the GNU guide: Here are a set of rules to help you update | ||
your library version information: | ||
<ul> | ||
<li> Start with version information of '0:0:0' for each libtool library. | ||
</li> | ||
<li> Update the version information only immediately before a public | ||
release of your software. More frequent updates are unnecessary, and | ||
only guarantee that the current interface number gets larger faster. | ||
</li> | ||
<li> If the library source code has changed at all since the last update, | ||
then increment revision ('c:r:a' becomes 'c:r+1:a'). | ||
</li> | ||
<li> If any interfaces have been added, removed, or changed since the last | ||
update, increment current, and set revision to 0. | ||
</li> | ||
<li> If any interfaces have been added since the last public release, then | ||
increment age. | ||
</li> | ||
<li> If any interfaces have been removed or changed since the last public | ||
release, then set age to 0. | ||
</li> | ||
</li> | ||
<ul> | ||
</details></li> | ||
</ul> | ||
2. Update release note | ||
* Edit file [./RELEASE_NOTES.md](./RELEASE_NOTES.md) to include notes about | ||
new features and other noticeable changes. | ||
* Edit and update the release date. | ||
3. Commit all changes to github repo | ||
* Run command below to upload changes to github.com. | ||
``` | ||
git push upstream main | ||
``` | ||
4. Create a tag and push it to the github repo | ||
* Run commands below to do so. Replace the proper version string. | ||
``` | ||
git tag -a pnetcdf-python.1.0.0 -m "PnetCDF-Python package version 1.0.0" | ||
git push upstream pnetcdf-python.1.0.0 | ||
``` | ||
5. Create a new release from the tag on github.com. | ||
* Visit PnetCDF-Python github repo's | ||
[tags](https://github.com/Parallel-NetCDF/PnetCDF-Python/tags) | ||
* Click the name of tag just pushed. | ||
* Click "Create release from tag". | ||
* Fill in "Release title" | ||
* Fill in "Description field" | ||
* Optionally, click "Set as a pre-release", if this is a pre-release. | ||
* Optionally, click "Generate release notes", which will add a list of all | ||
PRs and new contributors into the Description field.. | ||
* Click "Save draft" to save the changes. It can be modified later. | ||
* See all options from [github docs](https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes) | ||
6. If a new commit were added or pushed to the main branch after a draft | ||
release was created, make sure the local main branch is up-to-date and then | ||
run commands below to force-update the tag on both local and remote. | ||
``` | ||
git tag -fa pnetcdf-python.1.0.0 | ||
git push -f --tags | ||
``` | ||
--- | ||
### Library Packaging And Publishing | ||
* Currently, pip-install via build distribution is disabled. No wheel files | ||
are uploaded to PyPI. Lastest PnetCDF-Python package on PyPI can be found | ||
in: https://pypi.org/project/pnetcdf/ | ||
* Packaging: build source distribution and wheel distribution on a local | ||
machine by following these steps. | ||
1. Install PnetCDF-C library | ||
2. Make sure a python virtual env is created and all python dependencies are | ||
installed as the developer installation. | ||
``` | ||
cd $HOME | ||
python -m venv tmp_env | ||
source $HOME/tmp_env/bin/activate | ||
pip install --upgrade pip setuptools wheel packaging | ||
pip install numpy Cython | ||
CC=/path/to/mpicc pip install mpi4py | ||
``` | ||
3. Download the release tarball of PnetCDF-Python. For example, use commands | ||
as shown below. | ||
``` | ||
wget https://github.com/Parallel-NetCDF/PnetCDF-Python/archive/refs/tags/pnetcdf-python.1.0.0.tar.gz | ||
tar -xfv pnetcdf-python.1.0.0.tar.gz | ||
cd PnetCDF-Python | ||
python3 -m pip install --upgrade build twine | ||
``` | ||
4. Build the package and generate distribution. | ||
``` | ||
CC=/path/to/mpicc PNETCDF_DIR=/path/to/pnetcdf/dir python3 -m build | ||
``` | ||
A successful run of this command will generate 2 new files: | ||
+ `dist/pnetcdf-x.x.x.tar.gz` and | ||
+ `dist/pnetcdf-x.x.x-cp39-cp39-linux_x86_64.whl` | ||
5. Leave the python environment, tmp_env, by running command | ||
``` | ||
deactivate | ||
``` | ||
* Test distribution | ||
1. For testing purpose, we must publish the package built above on | ||
[TestPyPI](https://packaging.python.org/en/latest/guides/using-testpypi), | ||
by only uploading source distribution archive, since the wheel file | ||
(dist/pnetcdf-x.x.x*.whl) works exclusively for your own system and python | ||
version and is not useful for the users. | ||
2. Create TestPyPI account. | ||
* Optionally, update file `$HOME/.pypirc` on local machine to skip | ||
the log-in credentials | ||
3. Publish source distribution on TestPyPI: | ||
``` | ||
python3 -m twine upload --repository testpypi dist/pnetcdf-x.x.x.tar.gz | ||
``` | ||
The command will first check if the same name and version number have | ||
already existed. The command will error out if the same names have been | ||
found. After uploading, open your browser, go to https://test.pypi.org | ||
and search for package name: `pnetcdf` to verify. | ||
4. Next, test the uploaded distribution on a local machine | ||
* Create a new empty folder. E.g. | ||
``` | ||
mkdir pypi_test | ||
cd pypi_test | ||
``` | ||
* Make sure PnetCDF-C and mpich are installed. | ||
* Create and activate a new vanilla python env for testing. | ||
* This env shouldn't be the same env used in developer install, i.e. the | ||
environment does not contain any pre-installed PnetCDF-Python library | ||
``` | ||
python -m venv test_env | ||
source test_env/bin/activate | ||
``` | ||
* Do a quick install via the distribution on TestPyPI (no python | ||
dependencies required). Note that `-i` redirects pip-install to search | ||
PnetCDF-Python in testpypi index and `--extra-index-url` redirects | ||
pip-install to search dependency libraries (e.g. numpy) in official | ||
pypi index. | ||
``` | ||
CC=/path/to/mpicc PNETCDF_DIR=/path/to/pnetcdf/dir \ | ||
pip install -i https://test.pypi.org/simple/ \ | ||
--extra-index-url https://pypi.org/simple pnetcdf==x.x.x | ||
``` | ||
This command will download the package from testpypi and install | ||
PnetCDF-Python library in the current env. | ||
5. Run PnetCDF-Python test programs. For example, using test programs | ||
available in folder `test` of PnetCD-Python package. | ||
``` | ||
wget https://github.com/Parallel-NetCDF/PnetCDF-Python/archive/refs/tags/pnetcdf-python.1.0.0.tar.gz | ||
tar -xfv pnetcdf.1.0.0.tar.gz | ||
cd PnetCDF-Python | ||
cd test | ||
make check | ||
make ptests | ||
``` | ||
Test programs available in folder `examples`, which requires pytorch. | ||
``` | ||
cd ../examples | ||
pip install torch torchvision | ||
make check | ||
make ptests | ||
``` | ||
Leave the python environment, test_env, by running command | ||
``` | ||
deactivate | ||
``` | ||
* Publish official release on PyPI | ||
1. Official releases are published on [PyPI](https://pypi.org/) | ||
2. WARNING: after upload to pypi, one cannot overwrite or change the | ||
published package on pypi! | ||
3. Create PyPI account and update `.pypirc` per instructions above. | ||
4. Publish source distribution on PyPI | ||
``` | ||
python3 -m twine upload dist/pnetcdf-x.x.x.tar.gz | ||
``` | ||
5. For testing, just create a new virtual env and quick install (using | ||
default PyPI index) without source code repo. | ||
``` | ||
CC=/path/to/mpicc PNETCDF_DIR=/path/to/pnetcdf/dir pip install pnetcdf | ||
``` | ||
6. To verify the official published verion, open the browser and go to | ||
https://pypi.org/project/pnetcdf/ to check the latest release. | ||
--- | ||
### Library installation | ||
* Quick install | ||
* `MANIFEST.in` controls files to be included in source distribution | ||
(sdist), which will be eventually uploaded to PyPI if we enables quick | ||
install in the future. After modifications to `MANIFEST.IN` file, here are | ||
steps to check if the files included are valid to build the library. | ||
1. Make sure pnetcdf.egg-info folder is deleted. Otherwise it will first | ||
cache previous versions of `MANIFEST.IN` requirement. This can be done | ||
by running command below at the root folder. | ||
``` | ||
make build-clean | ||
``` | ||
2. Build the source distribution | ||
``` | ||
CC=/path/to/mpicc PNETCDF_DIR=/path/to/pnetcdf/dir \ | ||
python setup.py sdist | ||
``` | ||
3. Check source distribution content if the list matches `MANIFEST.IN` | ||
``` | ||
tar -tzf dist/package-<version>.tar.gz | ||
``` | ||
4. Install the library from sdist | ||
``` | ||
CC=/path/to/mpicc PNETCDF_DIR=/path/to/pnetcdf/dir \ | ||
pip install dist/package-<version>.tar.gz | ||
``` | ||
5. Check installation by testing programs in folders test and examples | ||
* Additional notes about quick install | ||
1. Source distribution(.tar.gz) | ||
* Pip-install command’s second go-to option if no matching build | ||
distribution is found on PyPI. It will build its own wheel file for | ||
the current system. For python libs with C-extension (like | ||
PnetCDF-Python netcdf4-python, h5py), wheel installation require | ||
their C bindings. | ||
* Invariant to platforms/versions, usually each version of python | ||
library has one single source distribution. | ||
2. Build distribution (.whl) | ||
* Pip-install command’s first go-to option by default. For python libs | ||
with C-extension (like PnetCDF-Python netcdf4-python, h5py), wheel | ||
installation does not require their C bindings. | ||
* Wheels are platform-specific and python-version specific. Different | ||
system used for building and uploading will generate different | ||
versions of wheel files on PyPI. To cover most mainstream python | ||
versions and operating systems, python libraries (like | ||
[numpy 1.25](https://pypi.org/project/numpy/#files)) has 20+ wheels | ||
files to cover most mainstream systems (e.g. Linux (x86_64), MacOS | ||
(x86_64), and Windows (32-bit and 64-bit)) and recent python versions. | ||
* General procedures of building and uploading python library wheels | ||
(build distributions) for MacOS and Linux systems | ||
+ Python libs with C-extension (like PnetCDF-Python, netcdf4-python, | ||
h5py) requires shared object (.so in Linux and .dylibs in mac) | ||
files collected from C software installation. When making python | ||
library wheels (build distribution), an extra post-processing step | ||
(Delocate tool for Mac, auditwheel Tool in linux) is usually | ||
performed to copy and store these files in the python package to | ||
remove these dependencies. That’s why the user’s pip install with | ||
build distribution does not require a C installation as a | ||
prerequisite. | ||
+ For MacOS wheels (such as | ||
netCDF4-1.6.4-cp311-cp311-macosx_10_9_x86_64.whl) do the | ||
followings. | ||
1. Build the package to create the wheel, | ||
2. Use Delocate tool to fix wheels | ||
3. Upload to PyPI. | ||
+ For Linux wheels, do the followings. | ||
1. Pull manylinux docker image | ||
2. Build the package to create the wheel in this container | ||
3. Use auditwheel Tool to fix wheels | ||
4. Upload to PyPI. | ||
+ For some python libraries (numpy, netCDF4), a | ||
[dedicated github repo](https://github.com/MacPython/netcdf4-python-wheels) | ||
is used to automate building wheels for every release. | ||
* Developer install on a local machine | ||
* Developer installation is mainly managed by files `setup.py` and | ||
`pyproject.toml`. The former is the core file to build the package | ||
and the latter manages dependencies required by `pip install` command. | ||
* Command below builds and installs the python library based on the current | ||
python environment. | ||
``` | ||
python setup.py install | ||
``` | ||
The command will error out if any dependency (e.g. mpi4py) is missing. | ||
This command will soon be deprecated and is not recommended for modern | ||
python library installation. | ||
* Command below works as a wrapper command for the above but does further | ||
to automatically handle and install any dependencies listed in file | ||
`pyproject.toml`. Need to pay special attention to the dependencies | ||
listed in the filed of `requires` under `[build-system]` and | ||
`dependencies`. | ||
``` | ||
pip install . | ||
``` | ||
+ Field `dependencies` in file `pyproject.toml` defines python libraries | ||
required for running the project and will first check if requirement | ||
already satisfied in current environment before installing the latest | ||
qualified version of the library. | ||
+ Field `requires` in file `pyproject.toml` defines libraries required | ||
for building the project. Command `pip install` by default creates and | ||
uses isolated building env for building stage which completely ignores | ||
current user env. For example, if user already installed mpi4py==3.1.6, | ||
setting this field to "mpi4py>=3.1.4" will automatically install a | ||
mpi4py 4.0.0 in the building env and thereafter use syntax from 4.0.0 | ||
to build PnetCDF-Python This causes version mismatch issues between | ||
building and running envs when numpy 2.0 and mpi4py 4.0.0 are released. | ||
To address this issue, use command below. | ||
``` | ||
pip install --no-build-isolation -e . | ||
``` | ||
--- | ||
### User Guide | ||
Note on configuring Read-the-Docs tool for generating PnetCDF-Python user guide. | ||
* Read the Docs settings | ||
+ User guide is automatically generated when new commits are pushed to the | ||
main branch and a new PR is created. Modify this in Read the Docs dashboard | ||
if needed. | ||
* Doc files | ||
+ `.readthedocs.yaml` -- is a script file controls commands that run before | ||
installation of PnetCDF-Python (under `pre-install:`) and installation | ||
(under `python:`) | ||
+ `/docs/requirements.txt` -- lists all Python dependencies required for doc | ||
generation, including `sphinx` | ||
* Important environment variables | ||
+ User guide generation requires environment variables set by Read the Docs | ||
dashboard (`Admin` -> `Environment Variables`). Delete and add a new | ||
variable to modify (remember to select `Expose this environment variable in | ||
PR builds` if PR auto-build is enabled) | ||
+ Current environment variables set (only effective solution found to set env | ||
variable at installation): | ||
* `CC`: mpicc.mpich | ||
* `PNETCDF_DIR`: /home/docs/checkouts/readthedocs.org/user_builds/pnetcdf-python/checkouts/latest/_readthedocs/PnetCDF | ||
* `PNETCDF_VER`: 1.14.0 | ||