Skip to content

Commit c19017a

Browse files
authored
Merge pull request #13 from leosussan/leo/pre-commit
Pre-Commit
2 parents 0cb613a + ba68eb4 commit c19017a

File tree

16 files changed

+276
-41
lines changed

16 files changed

+276
-41
lines changed

.flake8

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[flake8]
2+
ignore = E203, E266, E501, W503, F403, F401
3+
max-line-length = 79
4+
max-complexity = 18
5+
select = B,C,E,F,W,T4,B9
6+
per-file-ignores =
7+
app/models/orm/migrations/env.py:E402
8+
app/main.py:E402
9+
app/worker.py:E402

.pre-commit-config.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
repos:
2+
- repo: https://github.com/asottile/seed-isort-config
3+
rev: v2.1.1
4+
hooks:
5+
- id: seed-isort-config
6+
args: [--application-directories, "./app:./"]
7+
- repo: https://github.com/pre-commit/mirrors-isort
8+
rev: v4.3.21
9+
hooks:
10+
- id: isort
11+
additional_dependencies: ["toml"]
12+
- repo: https://github.com/ambv/black
13+
rev: stable
14+
hooks:
15+
- id: black
16+
- repo: https://gitlab.com/pycqa/flake8
17+
rev: 3.7.9
18+
hooks:
19+
- id: flake8
20+
additional_dependencies: [
21+
"git+https://github.com/PyCQA/pyflakes#egg=pyflakes",
22+
"git+https://gitlab.com/PyCQA/pycodestyle#egg=pycodestyle",
23+
]
24+
default_language_version:
25+
python: python3.8

README.md

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,52 @@
11
# fastapi-gino-arq-uvicorn
22
High-performance Async REST API, in Python. FastAPI + GINO + Arq + Uvicorn (powered by Redis & PostgreSQL).
33

4-
## Get Started
5-
### Run Locally
6-
_NOTE: You must have PostgreSQL & Redis running locally._
4+
## Contents
5+
* [Get Started](#get-started)
6+
* [Setup](#setup)
7+
* [Run](#run)
8+
* [Run Locally](#run-locally)
9+
* [Run Locally with Docker-Compose](#run-locally-with-docker-compose)
10+
* [Build Your Application](#build-your-application)
11+
* [Features](#features)
12+
* [Core Dependencies](#core-dependencies)
13+
* [Additional Dependencies](#additional-dependencies)
714

15+
## Get Started
16+
### Setup
817
1. Clone this Repository. `git clone https://github.com/leosussan/fastapi-gino-arq-uvicorn.git`
918
2. Install `Python 3.8` and `poetry`.
10-
* _RECOMMENDED_: use `asdf`, which is like `pyenv` / `nvm` / `gvm` for everything.
11-
* [Install](https://asdf-vm.com/#/core-manage-asdf-vm?id=install-asdf-vm), then run `asdf plugin add python`, `asdf plugin add poetry`, and `asdf install`
12-
3. Run `poetry install` from root.
13-
4. Make a copy of `.dist.env`, rename to `.env`. Fill in PostgreSQL, Redis connection vars.
14-
5. Generate DB Migrations: `alembic revision --autogenerate`. It will be applied when the application starts. You can trigger manually with `alembic upgrade head`.
15-
6. Run:
19+
* Recommended Method: `asdf` - a universal version manager (think `nvm` or `pyenv`)
20+
* Follow [these instructions](https://asdf-vm.com/#/core-manage-asdf-vm?id=install-asdf-vm) to install `asdf`.
21+
* Run the following commands from the project root:
22+
* `asdf plugin add python`
23+
* `asdf plugin add poetry`
24+
* `asdf install` -- will download & configure this project's `Python` + `poetry` setup
25+
* If you have `Python 3.8` and `poetry` installed already, please feel free to skip.
26+
3. Install dependencies (`poetry install`).
27+
4. Activate pre-commit hooks (in `poetry shell`, run `pre-commit install`).
28+
5. Make a copy of `.dist.env`, rename to `.env`. Fill in PostgreSQL, Redis, Sentry (optional) variables.
29+
6. Generate DB Migrations: in `poetry shell`, run `alembic revision --autogenerate`.
30+
* Apply migrations manually with `alembic upgrade head`.
31+
* If using the Dockerfile, migrations are applied at startup.
32+
33+
### Run
34+
35+
#### Run Locally
36+
_NOTE: You must have PostgreSQL & Redis running locally._
37+
38+
1. Make sure PostgreSQL & Redis are running locally.
39+
2. Run:
1640
- FastAPI Application:
1741
* _For Active Development (w/ auto-reload):_ Run locally with `poetry run task app`
1842
* _For Debugging (compatible w/ debuggers, no auto-reload):_ Configure debugger to run `python app/main.py`.
1943
- Background Task Worker:
2044
* _For Active Development:_ Run `poetry run task worker`
2145

22-
### Run Locally with Docker-Compose
23-
1. Clone this Repository. `git clone https://github.com/leosussan/fastapi-gino-arq-uvicorn.git`
24-
2. Generate a DB Migration: `alembic revision --autogenerate`.*
25-
3. Run locally using docker-compose. `poetry run task compose-up`.
26-
* Run `poetry run task compose-down` to spin down, clean up.
46+
#### Run Locally with Docker-Compose.
47+
1. Make sure `Docker` is running locally.
48+
2. Run `poetry run task compose-up`*.
49+
- Run `poetry run task compose-down` to spin down, clean up.
2750

2851
*`app/settings/prestart.sh` will run migrations for you before the app starts.
2952

@@ -53,4 +76,5 @@ _NOTE: You must have PostgreSQL & Redis running locally._
5376
* **Alembic:** Handles database migrations. Compatible with GINO.
5477
* **SQLAlchemy_Utils:** Provides essential handles & datatypes. Compatible with GINO.
5578
* **Sentry:** Open-source, cloud-hosted error + event monitoring.
79+
* **Pre-Commit:** automatic formatting (`black` + `isort`) and linting (`flake8`).
5680
* **Taskipy:** Small, flexible task runner for Poetry.

app/application.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@
22
from gino.ext.starlette import Gino
33
from sentry_sdk import init as initialize_sentry
44
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
5-
from starlette.datastructures import Secret
65
from sqlalchemy.schema import MetaData
6+
from starlette.datastructures import Secret
77

88
from .settings.globals import DATABASE_CONFIG, SENTRY_DSN
99

1010
if isinstance(SENTRY_DSN, Secret) and SENTRY_DSN.__str__() not in ("None", ""):
1111
initialize_sentry(
12-
dsn=SENTRY_DSN.__str__(),
13-
integrations=[SqlalchemyIntegration()]
12+
dsn=SENTRY_DSN.__str__(), integrations=[SqlalchemyIntegration()]
1413
)
1514

1615
app: FastAPI = FastAPI()

app/main.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# isort:skip_file
2+
13
import sys
24

35
sys.path.extend(["./"])

app/models/orm/base.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@
1111
@generic_repr
1212
class Base(db.Model):
1313
__abstract__ = True
14-
created_on = db.Column(db.DateTime, default=datetime.utcnow, server_default=db.func.now())
14+
created_on = db.Column(
15+
db.DateTime, default=datetime.utcnow, server_default=db.func.now()
16+
)
1517
updated_on = db.Column(
16-
db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow, server_default=db.func.now())
18+
db.DateTime,
19+
default=datetime.utcnow,
20+
onupdate=datetime.utcnow,
21+
server_default=db.func.now(),
22+
)
1723
id = db.Column(db.BigInteger, primary_key=True, autoincrement=True)

app/models/orm/migrations/env.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,25 @@
1-
# Native libraries
1+
# isort:skip_file
2+
23
import sys
3-
sys.path.extend(['./'])
4+
5+
sys.path.extend(["./"])
6+
7+
from logging.config import fileConfig
8+
9+
from sqlalchemy import engine_from_config, pool
10+
from alembic import context
11+
12+
from app.settings.globals import ALEMBIC_CONFIG
413

514
######################## --- MODELS FOR MIGRATIONS --- ########################
615
from app.application import db
716
from app.models.orm.user import User
817

918
# To include a model in migrations, add a line here.
19+
# from app.models.orm.person import Person
1020

1121
###############################################################################
1222

13-
# Third party packages
14-
from sqlalchemy import engine_from_config, pool
15-
from alembic import context
16-
from logging.config import fileConfig
17-
18-
# App imports
19-
from app.settings.globals import ALEMBIC_CONFIG
20-
2123
config = context.config
2224
fileConfig(config.config_file_name)
2325
target_metadata = db
@@ -36,7 +38,9 @@ def run_migrations_offline():
3638
3739
"""
3840
context.configure(
39-
url=ALEMBIC_CONFIG.url.__to_string__(hide_password=False), target_metadata=target_metadata, literal_binds=True
41+
url=ALEMBIC_CONFIG.url.__to_string__(hide_password=False),
42+
target_metadata=target_metadata,
43+
literal_binds=True,
4044
)
4145

4246
with context.begin_transaction():
@@ -51,7 +55,11 @@ def run_migrations_online():
5155
5256
"""
5357
connectable = engine_from_config(
54-
{"sqlalchemy.url": ALEMBIC_CONFIG.url.__to_string__(hide_password=False)},
58+
{
59+
"sqlalchemy.url": ALEMBIC_CONFIG.url.__to_string__(
60+
hide_password=False
61+
)
62+
},
5563
prefix="sqlalchemy.",
5664
poolclass=pool.NullPool,
5765
)

app/models/orm/user.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33

44
class User(Base):
5-
__tablename__ = 'users'
5+
__tablename__ = "users"
66
name = db.Column(db.String(255))
77
email = db.Column(db.EmailType)
88
phone_number = db.Column(db.Unicode(20))

app/models/pydantic/base.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
from pydantic import BaseModel
21
from datetime import datetime
32

3+
from pydantic import BaseModel
4+
45

56
class Base(BaseModel):
67
id: int

app/models/pydantic/user.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
from pydantic import EmailStr, BaseModel
21
from typing import Optional
32

3+
from pydantic import BaseModel, EmailStr
4+
45
from .base import Base
56

67

0 commit comments

Comments
 (0)