PackagePython

Python Package for PyPI

src-layout package with pyproject.toml (hatchling), a console script, `python -m build` and `twine upload` to TestPyPI then PyPI.

Open in builder →

10 steps

Shell

Shown with defaults: npm, pip, Node LTS, Python 3.12 and the template's default add-ons.

  1. 1. Check Python 3.12

    runtime

    Make sure Python 3 is installed. Python 3.12 is recommended for this stack.

    bash
    python3 --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. 2. Create the project folder

    template

    Create an empty folder for the project and move into it. All following commands run inside it.

    bash
    mkdir nvx-hello-pycd nvx-hello-py
    Expected result
    You are inside ./nvx-hello-py
    Verify
    pwd
  3. 3. Create and activate a virtual environment

    template

    A virtual environment (.venv) keeps this project's Python packages isolated from the system Python.

    bash
    python3 -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. 4. Create pyproject.toml and the package

    template

    pyproject.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 NVX
    
    src/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.py
    import 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. 5. Install build and twine

    template

    build creates the sdist and wheel; twine checks and uploads them.

    bash
    python -m pip install --upgrade build twine
    Expected result
    python -m build --version works.
    Verify
    python -m twine --version
  6. 6. Install in editable mode and try it

    template

    -e links the source so code changes apply without reinstalling.

    bash
    python -m pip install -e .
    Expected result
    `nvx-hello-py --name NVX` prints Hello, NVX!
    Verify
    nvx-hello-py --name NVX
  7. 7. Build the distributions

    template

    Creates dist/*.tar.gz (sdist) and dist/*.whl (wheel), then validates metadata.

    bash
    python -m buildpython -m twine check dist/*
    Expected result
    twine check reports PASSED for both files.
    Verify
    ls dist
  8. 8. Add tests with pytest

    add-on

    pytest discovers test_*.py files automatically.

    bash
    python -m pip install pytest
    Files written by this step: tests/test_sanity.py
    tests/test_sanity.py
    def test_sanity():
        assert 1 + 1 == 2
    
    Expected result
    1 passed.
    Verify
    python -m pytest -q
  9. 9. Upload to TestPyPI first

    templatepublish · manual

    Create an API token at test.pypi.org. Username is __token__ and the password is the token. Rehearse here before the real index.

    bash
    python -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. 10. Publish to PyPI

    templatepublish · manual

    Same command without --repository uploads to pypi.org. Versions cannot be re-used — bump version in pyproject.toml for each release.

    bash
    python -m twine upload dist/*
    Expected result
    Anyone can `pip install nvx-hello-py`.
    Verify
    python -m pip index versions nvx-hello-py