FastAPI-fastkit 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fastapi_fastkit/__init__.py +10 -0
- fastapi_fastkit/__main__.py +8 -0
- fastapi_fastkit/backend.py +112 -0
- fastapi_fastkit/cli.py +432 -0
- fastapi_fastkit/core/__init__.py +0 -0
- fastapi_fastkit/core/exceptions.py +27 -0
- fastapi_fastkit/core/settings.py +107 -0
- fastapi_fastkit/fastapi_project_template/PROJECT_README_TEMPLATE.md +66 -0
- fastapi_fastkit/fastapi_project_template/README.md +20 -0
- fastapi_fastkit/fastapi_project_template/__init__.py +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/.env.test-tpl +3 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/.gitignore-tpl +191 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/README.md-tpl +17 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/main.py-tpl +21 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/requirements.txt-tpl +47 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/script/run-server.sh-tpl +2 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/script/run-test.sh-tpl +2 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/setup.cfg-tpl +13 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/setup.py-tpl +35 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/.DS_Store +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/__init__.py-tpl +88 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/core/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/core/settings.py-tpl +96 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/crud/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/crud/_base.py-tpl +92 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/crud/user.py-tpl +44 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/helper/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/helper/exceptions.py-tpl +94 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/helper/global_data.py-tpl +33 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/helper/logging.py-tpl +25 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/helper/pagination.py-tpl +71 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/mocks/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/mocks/mock_users.json-tpl +17 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/router/__init__.py-tpl +48 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/router/user.py-tpl +126 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/schemas/__init__.py-tpl +48 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/schemas/user.py-tpl +81 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/templates/index.html-tpl +27 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/utils/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/src/utils/documents.py-tpl +20 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/test/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/test/conftest.py-tpl +22 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/test/routes/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-default/test/routes/test_user.py-tpl +112 -0
- fastapi_fastkit/fastapi_project_template/fastapi-dockerized/__init__.py-tpl +0 -0
- fastapi_fastkit/fastapi_project_template/fastapi-psql-orm/__init__.py-tpl +0 -0
- fastapi_fastkit/py.typed +0 -0
- fastapi_fastkit/utils/__init__.py +0 -0
- fastapi_fastkit/utils/inspector.py +15 -0
- fastapi_fastkit/utils/logging.py +33 -0
- fastapi_fastkit/utils/transducer.py +70 -0
- fastapi_fastkit-0.1.0.dist-info/METADATA +46 -0
- fastapi_fastkit-0.1.0.dist-info/RECORD +56 -0
- fastapi_fastkit-0.1.0.dist-info/WHEEL +4 -0
- fastapi_fastkit-0.1.0.dist-info/entry_points.txt +5 -0
- fastapi_fastkit-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: FastAPI template project README format
|
|
3
|
+
about: Project description for users
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
# {FASTAPI TEMPLATE PROJECT NAME}
|
|
7
|
+
|
|
8
|
+
> add FastAPI template project description below
|
|
9
|
+
|
|
10
|
+
(Write here)
|
|
11
|
+
|
|
12
|
+
## Stack
|
|
13
|
+
|
|
14
|
+
> fill out application's stack below
|
|
15
|
+
|
|
16
|
+
- (Write here)
|
|
17
|
+
- FastAPI {version}
|
|
18
|
+
- Python {version}
|
|
19
|
+
- etc...
|
|
20
|
+
|
|
21
|
+
## Project Tree
|
|
22
|
+
|
|
23
|
+
> fill out project source tree below
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
.
|
|
27
|
+
├── README.md
|
|
28
|
+
├── pdm.lock
|
|
29
|
+
├── pyproject.toml
|
|
30
|
+
├── scripts
|
|
31
|
+
│ └── run-server.sh
|
|
32
|
+
├── src
|
|
33
|
+
│ └── sources...
|
|
34
|
+
└── tests
|
|
35
|
+
├── __init__.py
|
|
36
|
+
├── testcases...
|
|
37
|
+
└── conftest.py
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Environment settings
|
|
41
|
+
|
|
42
|
+
> fill out how to setup this project in local below
|
|
43
|
+
|
|
44
|
+
(Write here)
|
|
45
|
+
|
|
46
|
+
## {Other Information ...}
|
|
47
|
+
|
|
48
|
+
> fill out other important information about this project below
|
|
49
|
+
|
|
50
|
+
(Write here)
|
|
51
|
+
|
|
52
|
+
# Origin of this project
|
|
53
|
+
|
|
54
|
+
The source of this project was created based on the template of the [FastAPI-fastkit](https://github.com/bnbong/FastAPI-fastkit) project.
|
|
55
|
+
|
|
56
|
+
The `FastAPI-fastkit` project is an open-source project that allows users who are new to Python and FastAPI to quickly set up a FastAPI-based application development environment in a framework-like format.
|
|
57
|
+
|
|
58
|
+
Thank you for your interest in and use of our software.
|
|
59
|
+
|
|
60
|
+
### Template information
|
|
61
|
+
|
|
62
|
+
> fill out template project author information below (do not modify opensource owner information)
|
|
63
|
+
> information of creator must include `Email` address
|
|
64
|
+
|
|
65
|
+
- Template creator : {fill here}
|
|
66
|
+
- FastAPI-fastkit project owner : [bnbong](mailto:bbbong9@gmail.com)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# About fastapi project templates
|
|
2
|
+
|
|
3
|
+
Each fastapi demo project in this folder is pasted to the user's local folder with the FastAPI-fastkit replication as the source code is.
|
|
4
|
+
|
|
5
|
+
For those with experience in developing Django, it is easy to understand that it performs a similar operation to the `$ django-admin start project mysite` cli-operation.
|
|
6
|
+
|
|
7
|
+
All source codes in demo projects must consist of **`.py-tpl`**, _not_ .py.
|
|
8
|
+
|
|
9
|
+
## Base structure of FastAPI template project
|
|
10
|
+
|
|
11
|
+
(manual will be added later)
|
|
12
|
+
(TODO : add description about -> include "FastAPI-fastkit" in setup.py)
|
|
13
|
+
|
|
14
|
+
## Adding new FastAPI-based template project
|
|
15
|
+
|
|
16
|
+
Before adding new FastAPI-based template project here, I strongly recommend that you read the
|
|
17
|
+
[SECURITY.md](../SECURITY.md) and [CODE_OF_CONDUCT.md](../CODE_OF_CONDUCT.md) files to understand
|
|
18
|
+
the direction of this project and the precautions for cooperation.
|
|
19
|
+
|
|
20
|
+
(outlink to CONTRIBUTING.md will be included & manual will be added later)
|
|
File without changes
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
### venv template
|
|
2
|
+
# Virtualenv
|
|
3
|
+
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
|
|
4
|
+
.Python
|
|
5
|
+
[Bb]in
|
|
6
|
+
[Ii]nclude
|
|
7
|
+
[Ll]ib
|
|
8
|
+
[Ll]ib64
|
|
9
|
+
[Ll]ocal
|
|
10
|
+
[Ss]cripts
|
|
11
|
+
pyvenv.cfg
|
|
12
|
+
.venv
|
|
13
|
+
pip-selfcheck.json
|
|
14
|
+
|
|
15
|
+
### dotenv template
|
|
16
|
+
.env
|
|
17
|
+
|
|
18
|
+
### VirtualEnv template
|
|
19
|
+
# Virtualenv
|
|
20
|
+
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
|
|
21
|
+
.Python
|
|
22
|
+
[Bb]in
|
|
23
|
+
[Ii]nclude
|
|
24
|
+
[Ll]ib
|
|
25
|
+
[Ll]ib64
|
|
26
|
+
[Ll]ocal
|
|
27
|
+
pyvenv.cfg
|
|
28
|
+
.venv
|
|
29
|
+
pip-selfcheck.json
|
|
30
|
+
|
|
31
|
+
### Python template
|
|
32
|
+
# Byte-compiled / optimized / DLL files
|
|
33
|
+
__pycache__/
|
|
34
|
+
*.py[cod]
|
|
35
|
+
*$py.class
|
|
36
|
+
|
|
37
|
+
# C extensions
|
|
38
|
+
*.so
|
|
39
|
+
|
|
40
|
+
# Distribution / packaging
|
|
41
|
+
.Python
|
|
42
|
+
build/
|
|
43
|
+
develop-eggs/
|
|
44
|
+
dist/
|
|
45
|
+
downloads/
|
|
46
|
+
eggs/
|
|
47
|
+
.eggs/
|
|
48
|
+
lib/
|
|
49
|
+
lib64/
|
|
50
|
+
parts/
|
|
51
|
+
sdist/
|
|
52
|
+
var/
|
|
53
|
+
wheels/
|
|
54
|
+
share/python-wheels/
|
|
55
|
+
*.egg-info/
|
|
56
|
+
.installed.cfg
|
|
57
|
+
*.egg
|
|
58
|
+
MANIFEST
|
|
59
|
+
|
|
60
|
+
# PyInstaller
|
|
61
|
+
# Usually these files are written by a python script from a template
|
|
62
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
63
|
+
*.manifest
|
|
64
|
+
*.spec
|
|
65
|
+
|
|
66
|
+
# Installer logs
|
|
67
|
+
pip-log.txt
|
|
68
|
+
pip-delete-this-directory.txt
|
|
69
|
+
|
|
70
|
+
# Unit test / coverage reports
|
|
71
|
+
htmlcov/
|
|
72
|
+
.tox/
|
|
73
|
+
.nox/
|
|
74
|
+
.coverage
|
|
75
|
+
.coverage.*
|
|
76
|
+
.cache
|
|
77
|
+
nosetests.xml
|
|
78
|
+
coverage.xml
|
|
79
|
+
*.cover
|
|
80
|
+
*.py,cover
|
|
81
|
+
.hypothesis/
|
|
82
|
+
.pytest_cache/
|
|
83
|
+
cover/
|
|
84
|
+
|
|
85
|
+
# Translations
|
|
86
|
+
*.mo
|
|
87
|
+
*.pot
|
|
88
|
+
|
|
89
|
+
# Django stuff:
|
|
90
|
+
*.log
|
|
91
|
+
local_settings.py
|
|
92
|
+
db.sqlite3
|
|
93
|
+
db.sqlite3-journal
|
|
94
|
+
|
|
95
|
+
# Flask stuff:
|
|
96
|
+
instance/
|
|
97
|
+
.webassets-cache
|
|
98
|
+
|
|
99
|
+
# Scrapy stuff:
|
|
100
|
+
.scrapy
|
|
101
|
+
|
|
102
|
+
# Sphinx documentation
|
|
103
|
+
docs/_build/
|
|
104
|
+
|
|
105
|
+
# PyBuilder
|
|
106
|
+
.pybuilder/
|
|
107
|
+
target/
|
|
108
|
+
|
|
109
|
+
# Jupyter Notebook
|
|
110
|
+
.ipynb_checkpoints
|
|
111
|
+
|
|
112
|
+
# IPython
|
|
113
|
+
profile_default/
|
|
114
|
+
ipython_config.py
|
|
115
|
+
|
|
116
|
+
# pyenv
|
|
117
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
118
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
119
|
+
# .python-version
|
|
120
|
+
|
|
121
|
+
# pipenv
|
|
122
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
123
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
124
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
125
|
+
# install all needed dependencies.
|
|
126
|
+
#Pipfile.lock
|
|
127
|
+
|
|
128
|
+
# poetry
|
|
129
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
130
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
131
|
+
# commonly ignored for libraries.
|
|
132
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
133
|
+
# poetry.lock
|
|
134
|
+
|
|
135
|
+
# pdm
|
|
136
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
137
|
+
#pdm.lock
|
|
138
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
139
|
+
# in version control.
|
|
140
|
+
# https://pdm.fming.dev/#use-with-ide
|
|
141
|
+
.pdm.toml
|
|
142
|
+
|
|
143
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
144
|
+
__pypackages__/
|
|
145
|
+
|
|
146
|
+
# Celery stuff
|
|
147
|
+
celerybeat-schedule
|
|
148
|
+
celerybeat.pid
|
|
149
|
+
|
|
150
|
+
# SageMath parsed files
|
|
151
|
+
*.sage.py
|
|
152
|
+
|
|
153
|
+
# Environments
|
|
154
|
+
.env
|
|
155
|
+
.venv
|
|
156
|
+
env/
|
|
157
|
+
venv/
|
|
158
|
+
ENV/
|
|
159
|
+
env.bak/
|
|
160
|
+
venv.bak/
|
|
161
|
+
|
|
162
|
+
# Spyder project settings
|
|
163
|
+
.spyderproject
|
|
164
|
+
.spyproject
|
|
165
|
+
|
|
166
|
+
# Rope project settings
|
|
167
|
+
.ropeproject
|
|
168
|
+
|
|
169
|
+
# mkdocs documentation
|
|
170
|
+
/site
|
|
171
|
+
|
|
172
|
+
# mypy
|
|
173
|
+
.mypy_cache/
|
|
174
|
+
.dmypy.json
|
|
175
|
+
dmypy.json
|
|
176
|
+
|
|
177
|
+
# Pyre type checker
|
|
178
|
+
.pyre/
|
|
179
|
+
|
|
180
|
+
# pytype static type analyzer
|
|
181
|
+
.pytype/
|
|
182
|
+
|
|
183
|
+
# Cython debug symbols
|
|
184
|
+
cython_debug/
|
|
185
|
+
|
|
186
|
+
# PyCharm
|
|
187
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
188
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
189
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
190
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
191
|
+
.idea/
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Simple FastAPI Project
|
|
2
|
+
|
|
3
|
+
This is a test project using FastAPI. It is a RESTful API server with user management functionality.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- User Creation, Read, Update, Delete (CRUD) functionality
|
|
8
|
+
- Automatic OpenAPI documentation generation (Swagger UI, ReDoc)
|
|
9
|
+
- Custom exception handling
|
|
10
|
+
- Test environment with mock data
|
|
11
|
+
|
|
12
|
+
## Stack
|
|
13
|
+
|
|
14
|
+
- Python 3.11+
|
|
15
|
+
- FastAPI 0.111.1
|
|
16
|
+
- Pydantic 2.8.2
|
|
17
|
+
- pytest 8.2.2
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# --------------------------------------------------------------------------
|
|
2
|
+
# Application's main routine
|
|
3
|
+
# --------------------------------------------------------------------------
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import uvicorn
|
|
7
|
+
|
|
8
|
+
from src import create_app, init_logger
|
|
9
|
+
from src.core.settings import settings
|
|
10
|
+
|
|
11
|
+
init_logger(settings)
|
|
12
|
+
|
|
13
|
+
app = create_app(settings, app_title, app_description)
|
|
14
|
+
|
|
15
|
+
if __name__ == "__main__":
|
|
16
|
+
uvicorn.run(
|
|
17
|
+
"main:app",
|
|
18
|
+
host=settings.SERVER_DOMAIN,
|
|
19
|
+
port=settings.SERVER_PORT,
|
|
20
|
+
reload=True,
|
|
21
|
+
)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
annotated-types==0.7.0
|
|
2
|
+
anyio==4.4.0
|
|
3
|
+
black==24.4.2
|
|
4
|
+
certifi==2024.7.4
|
|
5
|
+
click==8.1.7
|
|
6
|
+
dnspython==2.6.1
|
|
7
|
+
email_validator==2.2.0
|
|
8
|
+
fastapi==0.111.1
|
|
9
|
+
fastapi-cli==0.0.4
|
|
10
|
+
h11==0.14.0
|
|
11
|
+
httpcore==1.0.5
|
|
12
|
+
httptools==0.6.1
|
|
13
|
+
httpx==0.27.0
|
|
14
|
+
idna==3.7
|
|
15
|
+
iniconfig==2.0.0
|
|
16
|
+
Jinja2==3.1.4
|
|
17
|
+
markdown-it-py==3.0.0
|
|
18
|
+
MarkupSafe==2.1.5
|
|
19
|
+
mdurl==0.1.2
|
|
20
|
+
mypy-extensions==1.0.0
|
|
21
|
+
packaging==24.1
|
|
22
|
+
pathspec==0.12.1
|
|
23
|
+
platformdirs==4.2.2
|
|
24
|
+
pluggy==1.5.0
|
|
25
|
+
pydantic==2.8.2
|
|
26
|
+
pydantic-settings==2.3.4
|
|
27
|
+
pydantic_core==2.20.1
|
|
28
|
+
Pygments==2.18.0
|
|
29
|
+
pytest==8.2.2
|
|
30
|
+
pytest-asyncio==0.23.8
|
|
31
|
+
pytest-timeout==2.3.1
|
|
32
|
+
python-dotenv==1.0.1
|
|
33
|
+
python-multipart==0.0.9
|
|
34
|
+
PyYAML==6.0.1
|
|
35
|
+
rich==13.7.1
|
|
36
|
+
setuptools-scm==8.1.0
|
|
37
|
+
shellingham==1.5.4
|
|
38
|
+
sniffio==1.3.1
|
|
39
|
+
starlette==0.37.2
|
|
40
|
+
typer==0.12.3
|
|
41
|
+
typing_extensions==4.12.2
|
|
42
|
+
uvicorn==0.30.1
|
|
43
|
+
uvloop==0.19.0
|
|
44
|
+
watchfiles==0.22.0
|
|
45
|
+
websockets==12.0
|
|
46
|
+
SQLAlchemy==2.0.36
|
|
47
|
+
sqlmodel==0.0.22
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# --------------------------------------------------------------------------
|
|
2
|
+
# module description here
|
|
3
|
+
# --------------------------------------------------------------------------
|
|
4
|
+
from setuptools import setup, find_packages
|
|
5
|
+
|
|
6
|
+
install_requires = [
|
|
7
|
+
# Main Application Dependencies
|
|
8
|
+
"fastapi==0.111.1",
|
|
9
|
+
"uvicorn==0.30.1",
|
|
10
|
+
"httpx==0.27.0",
|
|
11
|
+
"jinja2==3.1.2",
|
|
12
|
+
# ORM Dependencies
|
|
13
|
+
"pydantic==2.8.2",
|
|
14
|
+
"pydantic_core==2.20.1",
|
|
15
|
+
"pydantic-settings==2.3.4",
|
|
16
|
+
# Utility Dependencies
|
|
17
|
+
"starlette==0.37.2",
|
|
18
|
+
"typing_extensions==4.12.2",
|
|
19
|
+
"watchfiles==0.22.0",
|
|
20
|
+
"pytest==8.2.2",
|
|
21
|
+
"pytest-asyncio==0.23.8",
|
|
22
|
+
"FastAPI-fastkit",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
# IDE will watch this setup config through your project src, and help you to set up your environment
|
|
26
|
+
setup(
|
|
27
|
+
name="<project_name>",
|
|
28
|
+
description="<description>",
|
|
29
|
+
author="<author>",
|
|
30
|
+
author_email=f"<author_email>",
|
|
31
|
+
packages=find_packages(where="src"),
|
|
32
|
+
use_scm_version=True,
|
|
33
|
+
requires=["python (>=3.11)"],
|
|
34
|
+
install_requires=install_requires,
|
|
35
|
+
)
|
|
Binary file
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# --------------------------------------------------------------------------
|
|
2
|
+
# The module creates FastAPI Application.
|
|
3
|
+
# --------------------------------------------------------------------------
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
|
|
8
|
+
from fastapi import FastAPI, Request
|
|
9
|
+
from fastapi.responses import JSONResponse, RedirectResponse
|
|
10
|
+
from starlette.middleware.cors import CORSMiddleware
|
|
11
|
+
from contextlib import asynccontextmanager
|
|
12
|
+
from setuptools_scm import get_version
|
|
13
|
+
|
|
14
|
+
from src.core.settings import settings
|
|
15
|
+
from src.helper.exceptions import InternalException
|
|
16
|
+
from src.helper.logging import init_logger as _init_logger
|
|
17
|
+
from src.helper.global_data import initialize_mock_data
|
|
18
|
+
from src.router import router
|
|
19
|
+
from src.core.settings import AppSettings
|
|
20
|
+
from src.utils.documents import add_description_at_api_tags
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
__version__ = get_version(
|
|
24
|
+
root="../", relative_to=__file__
|
|
25
|
+
) # git version (dev version)
|
|
26
|
+
except LookupError:
|
|
27
|
+
__version__ = "1.0.0" # production version
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
logger = logging.getLogger(__name__)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def init_logger(app_settings: AppSettings) -> None:
|
|
34
|
+
_init_logger(f"fastapi-backend@{__version__}", app_settings)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
@asynccontextmanager
|
|
38
|
+
async def lifespan(app: FastAPI):
|
|
39
|
+
try:
|
|
40
|
+
logger.info("Application startup")
|
|
41
|
+
|
|
42
|
+
logger.info("Init mock data at memory") # you can put mocking data
|
|
43
|
+
# in your main FastAPI coroutine memory space.
|
|
44
|
+
initialize_mock_data()
|
|
45
|
+
yield
|
|
46
|
+
finally:
|
|
47
|
+
logger.info("Application shutdown")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def create_app(app_settings: AppSettings, app_title: str, app_description: str) -> FastAPI:
|
|
51
|
+
app = FastAPI(
|
|
52
|
+
title=f"{app_title}",
|
|
53
|
+
description=f"{app_description}",
|
|
54
|
+
version=__version__,
|
|
55
|
+
lifespan=lifespan,
|
|
56
|
+
openapi_url="/openapi.json",
|
|
57
|
+
redoc_url="/redoc",
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Apply Middlewares
|
|
61
|
+
if settings.BACKEND_CORS_ORIGINS:
|
|
62
|
+
app.add_middleware(
|
|
63
|
+
CORSMiddleware,
|
|
64
|
+
allow_origins=[
|
|
65
|
+
str(origin).strip("/") for origin in settings.BACKEND_CORS_ORIGINS
|
|
66
|
+
],
|
|
67
|
+
allow_credentials=True,
|
|
68
|
+
allow_methods=["*"],
|
|
69
|
+
allow_headers=["*"],
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
# Apply Custom Exception Handler
|
|
73
|
+
@app.exception_handler(InternalException)
|
|
74
|
+
async def internal_exception_handler(request: Request, exc: InternalException):
|
|
75
|
+
return JSONResponse(
|
|
76
|
+
status_code=exc.status,
|
|
77
|
+
content=exc.to_response(path=str(request.url)).model_dump(),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
@app.get("/", include_in_schema=False)
|
|
81
|
+
async def root(request: Request):
|
|
82
|
+
return RedirectResponse(url="/v1/")
|
|
83
|
+
|
|
84
|
+
app.include_router(router)
|
|
85
|
+
|
|
86
|
+
add_description_at_api_tags(app)
|
|
87
|
+
|
|
88
|
+
return app
|
|
File without changes
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# --------------------------------------------------------------------------
|
|
2
|
+
# The module configures Backend Application's settings.
|
|
3
|
+
#
|
|
4
|
+
# This module looks up two .env files below:
|
|
5
|
+
# - production environment: .env file
|
|
6
|
+
# - test environment: .env.test
|
|
7
|
+
# --------------------------------------------------------------------------
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import warnings
|
|
11
|
+
|
|
12
|
+
from typing import Any, Optional, Annotated, Literal
|
|
13
|
+
from typing_extensions import Self
|
|
14
|
+
|
|
15
|
+
from pydantic import (
|
|
16
|
+
Field,
|
|
17
|
+
AnyUrl,
|
|
18
|
+
BeforeValidator,
|
|
19
|
+
model_validator,
|
|
20
|
+
)
|
|
21
|
+
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def parse_cors(v: Any) -> list[str] | str:
|
|
25
|
+
if isinstance(v, str) and not v.startswith("["):
|
|
26
|
+
return [i.strip() for i in v.split(",")]
|
|
27
|
+
elif isinstance(v, list | str):
|
|
28
|
+
return v
|
|
29
|
+
raise ValueError(v)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class AppSettings(BaseSettings):
|
|
33
|
+
model_config = SettingsConfigDict(env_file=".env")
|
|
34
|
+
|
|
35
|
+
# Application general configuration
|
|
36
|
+
LOGGING_DEBUG_LEVEL: bool = Field(
|
|
37
|
+
default=True,
|
|
38
|
+
description="True: DEBUG mode, False:: INFO mode",
|
|
39
|
+
)
|
|
40
|
+
LOG_FILE_PATH: str = Field(
|
|
41
|
+
default="../../logs/app.log",
|
|
42
|
+
description="Log file path",
|
|
43
|
+
)
|
|
44
|
+
DEBUG_ALLOW_CORS_ALL_ORIGIN: bool = Field(
|
|
45
|
+
default=True,
|
|
46
|
+
description="If True, allow origins for CORS requests.",
|
|
47
|
+
)
|
|
48
|
+
DEBUG_ALLOW_NON_CERTIFICATED_USER_GET_TOKEN: bool = Field(
|
|
49
|
+
default=True,
|
|
50
|
+
description="If True, allow non-cerficiated users to get ESP token.",
|
|
51
|
+
)
|
|
52
|
+
BACKEND_CORS_ORIGINS: Annotated[list[AnyUrl] | str, BeforeValidator(parse_cors)] = (
|
|
53
|
+
[]
|
|
54
|
+
)
|
|
55
|
+
THREAD_POOL_SIZE: Optional[int] = Field(
|
|
56
|
+
default=10,
|
|
57
|
+
description="Change the server's thread pool size to handle non-async function",
|
|
58
|
+
)
|
|
59
|
+
ENVIRONMENT: Literal["local", "staging", "production"] = "local"
|
|
60
|
+
SERVER_DOMAIN: str = Field(
|
|
61
|
+
default="localhost",
|
|
62
|
+
description="Domain of server",
|
|
63
|
+
)
|
|
64
|
+
SERVER_PORT: int = Field(
|
|
65
|
+
default=9080,
|
|
66
|
+
description="Server's port",
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# Application security configuration
|
|
70
|
+
SECRET_KEY: str = Field(
|
|
71
|
+
default="example_secret_key_WoW",
|
|
72
|
+
description="Secret key to be used for issuing HMAC tokens.",
|
|
73
|
+
)
|
|
74
|
+
HASH_ALGORITHM: str = Field(default="HS256", description="Algorithm for Hashing") # for JWT utility
|
|
75
|
+
# 60 minutes * 24 hours * 8 days = 8 days
|
|
76
|
+
ACCESS_TOKEN_EXPIRE_MINUTES: int = 60 * 24 * 8 # for JWT utility
|
|
77
|
+
|
|
78
|
+
def _check_default_secret(self, var_name: str, value: str | None) -> None:
|
|
79
|
+
if value == "example_secret_key_WoW":
|
|
80
|
+
message = (
|
|
81
|
+
f'The value of {var_name} is "example_secret_key_WoW", '
|
|
82
|
+
"for security, please change it, at least for deployments."
|
|
83
|
+
)
|
|
84
|
+
if self.ENVIRONMENT == "local":
|
|
85
|
+
warnings.warn(message, stacklevel=1)
|
|
86
|
+
else:
|
|
87
|
+
raise ValueError(message)
|
|
88
|
+
|
|
89
|
+
@model_validator(mode="after")
|
|
90
|
+
def _enforce_non_default_secrets(self) -> Self:
|
|
91
|
+
self._check_default_secret("SECRET_KEY", self.SECRET_KEY)
|
|
92
|
+
|
|
93
|
+
return self
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
settings = AppSettings()
|
|
File without changes
|