Skip to content

Bootstrap a deployment-ready Python project ๐Ÿš€

License

Notifications You must be signed in to change notification settings

cepedus/python-app-bootstrap

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

11 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Poetry-FastAPI bootstrap template

Author: cepedus

README version: 2023-06-25

This repository contains the setup, configuration and make targets to develop and deploy the simplest FastAPI app, providing scalable utils to type-check, lint and test your code.

๐Ÿšฆ Requirements

Assuming you have a Unix shell with make and curl

  • This repository works by default with Python 3.11. Details are provided on how to change this on the sections below.
  • A Python 3.11 executable of your choice: install using pyenv, official installers, brew, conda, mamba, etc.

๐Ÿฅพ Want to set up a Poetry-managed replicable environment?

make init

๐Ÿงช Want to test the code and configuration?

make app-ci

โœจ Want to build and run the app?

make app-run

๐Ÿช„ The magic tricks

You're wondering what those 3 commands actually do. The main control over the repo is hosted under make targets that link commonly used utils when developing a Python app:

The package-specific configurations are gathered on a single TOML file (Poetry, mypy, pylint and isort). In particular, we use:

  • Pytorch's mypy-strict.ini rules
  • Minimal disable rules for pylint (no docstring whatsoever => keep your code as clean as possible!)
  • Strict asyncio mode for pytest.

Dissecting Makefile

  • init installs Poetry using the official installer (if not present on your system), creates a project-specific virtual environment and installs the dependencies of your .lock file.
  • app-ci launches pylint, mypy and pytest on your source code.
  • app-run builds and deploys locally your app. The 2 services (app and database) are launched on the same virtual network.
  • clean clears bytecode, poetry/pip caches and Docker cache, dangling images and volumes. Use with caution.

Dissecting .python-version

  • A single entrypoint for changing your build defining, for example, 3.11.3. Works best algonside with pyenv

๐Ÿ‘€ What are the extra files?

Dissecting Dockerfile

It consists of a standard 2-layer image. On the first one we install poetry and on the 2nd one we install our requirements and run the app, passing environment variables individually.

Why a custom entrypoint?

To properly propagate process signals to the container. As the spawned shell to run our app runs on Bash, we spawns a child process to run node, but signals sent to the parent process are not forwarded to the child processes (a more detailed explanation in found here and there).

In order to have a proper signal managmement, we trap and handle SIGINT and SIGTERM: see server/entrypoint.sh.

We explicitly define an internal network in order for the containers of Mongo and our app to work properly.

Dissecting pyproject.toml

Here we centralise all of the relevant configuration for:

  • Poetry
  • Mypy
  • Ruff
  • isort
  • Black
  • Pytest

๐Ÿ’ก Why I did this?

Setting up a replicable environment, creating your Dockerfiles and making sure everything is coherent when developing is, well, not actual development of new features for your app. If some of those preliminary, yet necessary steps fail it can easily take down your deployment or give place to strange dependency bugs, Docker not finding what's supposed to or even security implications in your containers.

In this repo I tried to gather all of these generic building bricks to allow focusing on what's important if you're developing: writing code rather than configurations. If the entrypoint to land on your app is simplified, you can onboard contributors much more easily and your app's "control tower" is abstracted.

Also, with the right building blocks is easier to follow coding good practices and thus maintain your codebase away from spaghettification.

โžก๏ธ What's missing

  • Repository configuration: direct commits to the main branch are forbidden, only possible to do so through PRs.
  • GitHub Actions: workflows to CI check each commit to the main branch and on PRs.