This project aims to provide a pre-configured python API server template based on the Flask python framework.
Table of Contents |
---|
Quickstart Guide |
The Hitchhicker's Guide to api_boilerplate |
Developer Guide |
- Ensure that you have docker installed on your system.
- Clone this repository using
git clone https://github.com/freelancer/esapyi.git
- (Optional) Pick a new name for your project and run
./project_rename.sh "my_project_name"
- Start the python server using
./run.sh dev
This section will take you through the following
- Project Structure
- Writing versioned APIs (TODO)
api_boilerplate ├── app.py ├── config │ ├── __init__.py │ ├── local_development.py │ ├── prod.py │ └── testing.py ├── exceptions ├── handlers ├── healthcheck ├── models ├── utils └── v1 ├── exceptions ├── handlers ├── input_schemas.py ├── output_schemas.py
This section goes through the various tools and procedures a developer would need when developing using this setup.
Contents
- Commands Quickstart: Getting the most out of the utility scripts
- Linting: The linter setup and now to customize it
- Testing: Getting the most out of the test setup
- Database Migrations: How to track and alter the database schema
- Production Deployment: The ideal way of running the production server
All of the common development tasks that need to be performed are done through the run.sh
script located at the root of the project.
run.sh
has the following commands
run.sh dev
- start the local db and python development server at port 8080run.sh prod
- start the local db and the production uWSGI python server at port 8080run.sh lint
- lint the entire projectrun.sh test
- run the entire test suite for the projectrun.sh check
- run the lint and test command in successionrun.sh dev db
- spin up and connect to the local dev databaserun.sh alembic
- proxy to the alembic cli
This project uses 2 main linting programs
If you want to customize the lint configuration, modify the following files
- pyproject.toml - to customize the mypy setup
- pyproject.toml - to customize the ruff setup
This project uses the pytest framework for writing and maintaining unit tests.
- In order to configure pytest, use the pytest.ini file
The unit tests also spin up a dockerized MySQL database. Every run.sh test
call will kill and re-create the database to ensure tests are running in a fresh environment.
There are 3 base test classes which you should extend when writing tests.
- BaseTestCase
- An empty class that extends unittest.TestCase
- AppContextTestCase
- A class makes a flask test client available at
self.client
- A class makes a flask test client available at
- DbContextTestCase
- Waits for the database to become available if it's not
- Re-sets the database after every test using alembic.
This project uses alembic as a database migrations tool. This tool essentially acts as a version control for your database schema. Any changes that need to be made should be tracked and done through alembic.
Example: Adding a new column
Say we want to add a new column to our users table - first_name
.
To do so, follow these steps
- Modify the user model and add the first_name column
first_name = Column(Text, nullable=False)
- Run the alembic command to autogenerate a revision
- This command creates a new file under the migrations/versions folder which contains code to create this new column in the db
./run.sh alembic revision --autogenerate -m"add_fname_to_user"
- Run the alembic command to upgrade the database
./run.sh alembic upgrade head
- That's it! The user table in the local docker database now has a first_name column. Remember to commit the generated migration file to git.
It is recommended that you deploy this API as a docker container on your production server. In order to help build this container there is a production ready dockerfile provided.
In production, the python app is run using uWSGI. The configuration for this uWSGI server is in uwsgi_prod_app_config.ini.