Python Package for PyPI
src-layout package with pyproject.toml (hatchling), a console script, `python -m build` and `twine upload` to TestPyPI then PyPI.
10 steps
Shown with defaults: npm, pip, Node LTS, Python 3.12 and the template's default add-ons.
1. Check Python 3.12
runtimeMake sure Python 3 is installed. Python 3.12 is recommended for this stack.
bashpython3 --version- Expected result
- Prints Python 3.x.
- Verify
- python3 -c "import sys; assert sys.version_info >= (3, 9); print(sys.version)"
- OS notes
- Install from python.org, `brew install python@3.12` (macOS), `sudo apt install python3 python3-venv` (Debian/Ubuntu), or `pyenv install 3.12`. On Windows the `py` launcher comes with the python.org installer.
2. Create the project folder
templateCreate an empty folder for the project and move into it. All following commands run inside it.
bashmkdir nvx-hello-pycd nvx-hello-py- Expected result
- You are inside ./nvx-hello-py
- Verify
- pwd
3. Create and activate a virtual environment
templateA virtual environment (.venv) keeps this project's Python packages isolated from the system Python.
bashpython3 -m venv .venvsource .venv/bin/activate- Expected result
- Your prompt shows (.venv) and `python` points inside .venv.
- Verify
- python -c "import sys; print(sys.prefix)"
- OS notes
- Debian/Ubuntu may need: sudo apt install python3-venv. On Windows, if activation is blocked run: Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
4. Create pyproject.toml and the package
templatepyproject.toml holds metadata and the build backend. The src/ layout prevents importing the un-installed folder by accident.
Files written by this step: pyproject.toml, README.md, src/nvx_hello_py/__init__.py, src/nvx_hello_py/cli.py
pyproject.toml[build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "nvx-hello-py" version = "0.1.0" description = "A small Python package created with NVX Stack Builder" readme = "README.md" requires-python = ">=3.9" license = "MIT" authors = [{ name = "Your Name", email = "you@example.com" }] dependencies = [] classifiers = [ "Programming Language :: Python :: 3", "Operating System :: OS Independent", ] [project.scripts] nvx-hello-py = "nvx_hello_py.cli:main" [tool.hatch.build.targets.wheel] packages = ["src/nvx_hello_py"]README.md# nvx-hello-py pip install nvx-hello-py nvx-hello-py --name NVXsrc/nvx_hello_py/__init__.py"""nvx-hello-py - created with NVX Stack Builder.""" __version__ = "0.1.0" def greet(name: str = "world") -> str: return f"Hello, {name}!"src/nvx_hello_py/cli.pyimport argparse from . import __version__, greet def main() -> None: parser = argparse.ArgumentParser(prog="nvx-hello-py") parser.add_argument("--name", default="world") parser.add_argument("--version", action="version", version=__version__) args = parser.parse_args() print(greet(args.name)) if __name__ == "__main__": main()- Expected result
- pyproject.toml and src/nvx_hello_py/ exist.
5. Install build and twine
templatebuild creates the sdist and wheel; twine checks and uploads them.
bashpython -m pip install --upgrade build twine- Expected result
- python -m build --version works.
- Verify
- python -m twine --version
6. Install in editable mode and try it
template-e links the source so code changes apply without reinstalling.
bashpython -m pip install -e .- Expected result
- `nvx-hello-py --name NVX` prints Hello, NVX!
- Verify
- nvx-hello-py --name NVX
7. Build the distributions
templateCreates dist/*.tar.gz (sdist) and dist/*.whl (wheel), then validates metadata.
bashpython -m buildpython -m twine check dist/*- Expected result
- twine check reports PASSED for both files.
- Verify
- ls dist
8. Add tests with pytest
add-onpytest discovers test_*.py files automatically.
bashpython -m pip install pytestFiles written by this step: tests/test_sanity.py
tests/test_sanity.pydef test_sanity(): assert 1 + 1 == 2- Expected result
- 1 passed.
- Verify
- python -m pytest -q
9. Upload to TestPyPI first
templatepublish · manualCreate an API token at test.pypi.org. Username is __token__ and the password is the token. Rehearse here before the real index.
bashpython -m twine upload --repository testpypi dist/*- Expected result
- https://test.pypi.org/project/nvx-hello-py/ exists.
- Verify
- python -m pip install --index-url https://test.pypi.org/simple/ --no-deps nvx-hello-py
10. Publish to PyPI
templatepublish · manualSame command without --repository uploads to pypi.org. Versions cannot be re-used — bump version in pyproject.toml for each release.
bashpython -m twine upload dist/*- Expected result
- Anyone can `pip install nvx-hello-py`.
- Verify
- python -m pip index versions nvx-hello-py