Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump pillow from 9.5.0 to 10.3.0 #23

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
custom: https://wu-clan.github.io/sponsor/
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
__pycache__/
.idea/
.env
.venv/
venv/
backend/app/log/
backend/app/migrations/
.ruff_cache/
.pdm-python
30 changes: 30 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: check-added-large-files
- id: end-of-file-fixer
- id: check-yaml
- id: check-toml

- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.4.5
hooks:
- id: ruff
args:
- '--config'
- '.ruff.toml'
- '--fix'
- '--unsafe-fixes'
- id: ruff-format

- repo: https://github.com/pdm-project/pdm
rev: 2.12.4
hooks:
- id: pdm-export
args:
- '-o'
- 'requirements.txt'
- '--without-hashes'
files: ^pdm.lock$
- id: pdm-lock-check
31 changes: 31 additions & 0 deletions .ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
line-length = 120
target-version = "py310"
cache-dir = "./.ruff_cache"

[lint]
select = [
"E",
"F",
"I",
"W505",
"PT018",
"SIM101",
"SIM114",
"PGH004",
"PLE1142",
"RUF100",
"F404",
"TCH",
"UP007"
]

[lint.isort]
lines-between-types = 1

[lint.per-file-ignores]
"backend/app/api/v1/*.py" = ["TCH"]
"backend/app/models/*.py" = ["TCH003"]
"backend/app/**/__init__.py" = ["F401"]

[format]
quote-style = "single"
23 changes: 23 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM python:3.10-slim

WORKDIR /ftm

COPY . .

RUN sed -i s@/deb.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list \
&& sed -i s@/security.debian.org/@/mirrors.aliyun.com/@g /etc/apt/sources.list

RUN apt-get update \
&& apt-get install -y --no-install-recommends gcc python3-dev \
&& rm -rf /var/lib/apt/lists/*

RUN pip install --upgrade pip -i https://mirrors.aliyun.com/pypi/simple \
&& pip install --no-cache-dir -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple

ENV TZ = Asia/Shanghai

RUN mkdir -p /var/log/fastapi_server

EXPOSE 8001

CMD ["uvicorn", "backend.app.main:app", "--host", "127.0.0.1", "--port", "8000"]
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2022 xiaowu

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
36 changes: 0 additions & 36 deletions README.en.md

This file was deleted.

109 changes: 84 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,96 @@
# FastAutoTest
# FastAPI Tortoise Architecture

#### 介绍
基于 fastapi + tortoise + mysql8 自动化接口测试平台
作为 FastAPI 框架的一个基础项目,基于 python3.10 开发

#### 软件架构
软件架构说明
## 特征

- [x] FastAPI > 0.100.0
- [x] Async design
- [x] Restful API
- [x] Tortoise-orm > 0.20.0
- [x] Pydantic 2.0
- [x] Docker
- [ ] ......

#### 安装教程
## 使用

1. xxxx
2. xxxx
3. xxxx
> [!WARNING]
> 此过程请格外注意端口占用情况, 特别是 8000, 3306, 6379...

#### 使用说明
### 1: 传统

1. xxxx
2. xxxx
3. xxxx
1. 安装依赖项

#### 参与贡献
```shell
pip install -r requirements.txt
```

1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
2. 创建一个数据库 `ftm`, 选择 utf8mb4 编码
3. 安装启动 redis
4. 在 `backend/app/` 目录下创建一个 `.env` 文件

```shell
cd backend/app/
touch .env
```

#### 特技
5. 复制 `.env.example` 到 `.env`

1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
```shell
cp .env.example .env
```

6. 数据库迁移

```shell
cd backend/app

# 初始化配置
aerich init -t migration.TORTOISE_ORM

# 初始化数据库,生成迁移文件
aerich init-db

# 执行迁移
aerich upgrade

# 当更新数据库 model 后,执行下面两个命令进行迁移
aerich migrate
aerich upgrade
```

7. 执行 backend/app/main.py 文件启动服务
8. 浏览器访问: http://127.0.0.1:8000/api/v1/docs

---

### 2: docker

1. 进入 `docker-compose.yml` 文件所在目录,创建环境变量文件 `.env`

```shell
dcd deploy/docker-compose/

cp .env.server ../../backend/app/.env
```

2. 执行一键启动命令

```shell
docker-compose up -d --build
```

3. 等待命令自动完成
4. 浏览器访问:http://127.0.0.1:8000/api/v1/docs

## 互动

[WeChat / QQ](https://github.com/wu-clan)

## 赞助

如果此项目能够帮助到你,你可以赞助作者一些咖啡豆表示鼓励:[:coffee: Sponsor :coffee:](https://wu-clan.github.io/sponsor/)

## 许可证

本项目根据 MIT 许可证的条款进行许可
14 changes: 14 additions & 0 deletions backend/app/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Env: dev、pro
ENVIRONMENT='dev'
# MySQL
DB_HOST='127.0.0.1'
DB_PORT=3306
DB_USER='root'
DB_PASSWORD='123456'
# Redis
REDIS_HOST='127.0.0.1'
REDIS_PORT=6379
REDIS_PASSWORD=''
REDIS_DATABASE=0
# Token
TOKEN_SECRET_KEY='1VkVF75nsNABBjK_7-qz7GtzNy3AMvktc9TCPwKczCk'
2 changes: 2 additions & 0 deletions backend/app/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
2 changes: 2 additions & 0 deletions backend/app/api/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
13 changes: 13 additions & 0 deletions backend/app/api/routers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from fastapi import APIRouter

from backend.app.api.v1.auth import router as auth_router
from backend.app.api.v1.user import router as user_router
from backend.app.core.conf import settings

v1 = APIRouter(prefix=settings.API_V1_STR)

v1.include_router(auth_router, prefix='/auth', tags=['认证'])

v1.include_router(user_router, prefix='/users', tags=['用户'])
2 changes: 2 additions & 0 deletions backend/app/api/v1/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
11 changes: 11 additions & 0 deletions backend/app/api/v1/auth/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from fastapi import APIRouter

from backend.app.api.v1.auth.auth import router as auth_router
from backend.app.api.v1.auth.captcha import router as captcha_router

router = APIRouter()

router.include_router(auth_router)
router.include_router(captcha_router)
35 changes: 35 additions & 0 deletions backend/app/api/v1/auth/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from fastapi import APIRouter, Depends, Request
from fastapi.security import OAuth2PasswordRequestForm

from backend.app.common.jwt import DependsJwtUser
from backend.app.common.response.response_schema import response_base
from backend.app.schemas.token import Token
from backend.app.schemas.user import Auth, Auth2
from backend.app.services.user_service import UserService

router = APIRouter()


@router.post('/swagger_login', summary='swagger 表单登录', description='form 格式登录,仅用于 swagger 文档调试接口')
async def login1(form_data: OAuth2PasswordRequestForm = Depends()) -> Token:
token, user = await UserService.login_swagger(form_data)
return Token(access_token=token, user=user)


@router.post('/login', summary='json登录')
async def login2(obj: Auth) -> Token:
token, user = await UserService.login_json(obj)
return Token(access_token=token, user=user)


@router.post('/captcha_login', summary='验证码登录')
async def login3(request: Request, obj: Auth2) -> Token:
token, user = await UserService.login_captcha(obj=obj, request=request)
return Token(access_token=token, user=user)


@router.post('/logout', summary='登出', dependencies=[DependsJwtUser])
async def user_logout():
return await response_base.response_200()
22 changes: 22 additions & 0 deletions backend/app/api/v1/auth/captcha.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from fast_captcha import img_captcha
from fastapi import APIRouter, Depends, Request
from fastapi_limiter.depends import RateLimiter
from starlette.concurrency import run_in_threadpool
from starlette.responses import StreamingResponse

from backend.app.common.redis import redis_client
from backend.app.core.conf import settings
from backend.app.utils.generate_string import get_uuid4_str

router = APIRouter()


@router.get('/captcha', summary='获取验证码', dependencies=[Depends(RateLimiter(times=5, seconds=10))])
async def get_captcha(request: Request):
img, code = await run_in_threadpool(img_captcha)
uuid = get_uuid4_str()
request.app.state.captcha_uuid = uuid
await redis_client.set(uuid, code, settings.CAPTCHA_EXPIRATION_TIME)
return StreamingResponse(content=img, media_type='image/jpeg')
Loading