Asif Rahman

Python project setup

2022-03-08

All my Python projects are setup in the same way - as a Python package with a Makefile. This is a template for that setup.

.
├── Makefile
├── setup.py
├── myproject
│   ├── __init__.py

The setup.py file defines the requirements for the package, and the Makefile defines the commands to run.

The setup creates a virtual environment in .venv directory, installs the package in editable mode, and installs the development dependencies. Editable installs are useful when developing a package, as changes to the code are immediately available without having to reinstall the package. If you add a new dependency to the setup.py file, you will need to run make setup again to install it.

Here is an example setup.py file:

from setuptools import setup

VERSION = "0.1.0"

setup(
    # package name, which can be different from project, this is the name used
    # when installing the package with pip, e.g. pip install mypackage
    name="mypackage",
    version=VERSION,
    maintainer="",
    maintainer_email="",
    description="",
    license="",
    python_requires=">=3.10",
    # static files to include in the package
    package_data={
        "myproject": [
            "var/*",
        ]
    },
    # command line entry points
    entry_points={
        "console_scripts": [
            "myproject = myproject.__main__:main",
        ]
    },
    # fol
    packages=["myproject"],
    install_requires=[
        "pip",
        "pyarrow==13.0.0",
        "polars==0.18.15",
        "awscli==1.29.38",
        "boto3==1.28.38",
        "botocore==1.31.38",
        "python-dotenv==1.0.0",
        "uvicorn==0.24.0.post1",
        "requests==2.31.0",
    ],
    extras_require={
        "dev": [
            "ruff",
            "ipykernel",
            "pytest",
        ]
    },
    include_package_data=True,
    zip_safe=False,
    classifiers=[
        "Intended Audience :: Science/Research",
        "Programming Language :: Python :: 3.10",
        "Operating System :: OS Independent",
    ],
    keywords="python",
)

The Makefile looks like this:

help: ## Show this help
  @echo "\nSpecify a command. The choices are:\n"
  @grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "  \033[0;36m%-12s\033[m %s\n", $$1, $$2}'
  @echo ""
.PHONY: help

clean:  ## Clean
  rm -rf ./.venv
  rm -rf ./dist
  rm -rf ./mypackage.egg-info
  rm -rf ./mypackage/__pycache__
  rm -rf ./myproject/*.so
  rm -rf ./myproject/__pycache__/
.PHONY: clean

setup:  ## Editable install
  test -d .venv || python3 -m venv .venv
  . .venv/bin/activate; \
  python -m pip install --upgrade -i https://pypi.example.com/simple/ -e .[dev]
.PHONY: setup

server:  ## Start local server
  uvicorn myproject.app:app --reload --workers=1 --reload-include="./myproject*"
.PHONY: server

Running make or make help will show the available commands:

Specify a command. The choices are:

  help         Show this help
  setup        Editable install
  server       Start local server