fastapi-augment 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_augment/__init__.py +24 -0
- fastapi_augment/common/__init__.py +61 -0
- fastapi_augment/common/constants.py +26 -0
- fastapi_augment/common/exception_handlers.py +178 -0
- fastapi_augment/common/exceptions.py +162 -0
- fastapi_augment/common/utils/__init__.py +5 -0
- fastapi_augment/common/utils/strings.py +175 -0
- fastapi_augment/config/__init__.py +8 -0
- fastapi_augment/config/settings.py +104 -0
- fastapi_augment/db/__init__.py +5 -0
- fastapi_augment/db/sqlalchemy/__init__.py +20 -0
- fastapi_augment/db/sqlalchemy/alembic/__init__.py +5 -0
- fastapi_augment/db/sqlalchemy/alembic/env.py +141 -0
- fastapi_augment/db/sqlalchemy/base.py +9 -0
- fastapi_augment/db/sqlalchemy/crud_base.py +426 -0
- fastapi_augment/db/sqlalchemy/engine.py +238 -0
- fastapi_augment/db/sqlalchemy/migrate.py +356 -0
- fastapi_augment/db/sqlalchemy/mixins/__init__.py +18 -0
- fastapi_augment/db/sqlalchemy/mixins/audit.py +61 -0
- fastapi_augment/db/sqlalchemy/mixins/soft_delete.py +80 -0
- fastapi_augment/db/sqlalchemy/mixins/timestamp.py +48 -0
- fastapi_augment/db/sqlalchemy/model_base.py +47 -0
- fastapi_augment/db/sqlalchemy/session.py +160 -0
- fastapi_augment/factory.py +238 -0
- fastapi_augment/health/__init__.py +34 -0
- fastapi_augment/health/checker.py +101 -0
- fastapi_augment/health/checkers.py +109 -0
- fastapi_augment/health/router.py +87 -0
- fastapi_augment/lifespan.py +450 -0
- fastapi_augment/log/__init__.py +26 -0
- fastapi_augment/log/config.py +201 -0
- fastapi_augment/log/factory.py +32 -0
- fastapi_augment/log/filters.py +23 -0
- fastapi_augment/log/handlers.py +81 -0
- fastapi_augment/middlewares/__init__.py +20 -0
- fastapi_augment/middlewares/base.py +79 -0
- fastapi_augment/middlewares/request_id.py +82 -0
- fastapi_augment/openapi.py +110 -0
- fastapi_augment/py.typed +0 -0
- fastapi_augment/schemas/__init__.py +29 -0
- fastapi_augment/schemas/base.py +32 -0
- fastapi_augment/schemas/pagination.py +46 -0
- fastapi_augment/schemas/request.py +28 -0
- fastapi_augment/schemas/response.py +139 -0
- fastapi_augment/schemas/types.py +11 -0
- fastapi_augment-0.1.0.dist-info/METADATA +654 -0
- fastapi_augment-0.1.0.dist-info/RECORD +50 -0
- fastapi_augment-0.1.0.dist-info/WHEEL +5 -0
- fastapi_augment-0.1.0.dist-info/entry_points.txt +2 -0
- fastapi_augment-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""
|
|
2
|
+
@Author : hangu
|
|
3
|
+
@CreateDate : 2026/9/1
|
|
4
|
+
@Description : 分页响应模型 PageData,对外输出,继承APISchemaBase
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from math import ceil
|
|
9
|
+
from typing import Generic, Sequence
|
|
10
|
+
|
|
11
|
+
from pydantic import Field
|
|
12
|
+
|
|
13
|
+
from .base import SchemaBase
|
|
14
|
+
from .types import T
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class PageData(SchemaBase, Generic[T]):
|
|
18
|
+
"""通用分页返回体"""
|
|
19
|
+
items: Sequence[T] = Field(default_factory=list, description='当前页数据列表')
|
|
20
|
+
page: int = Field(default=1, description='当前页码')
|
|
21
|
+
size: int = Field(default=10, description='每页数量')
|
|
22
|
+
pages: int = Field(default=0, description='总页数')
|
|
23
|
+
total: int = Field(default=0, description='总记录数')
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def build(
|
|
27
|
+
cls,
|
|
28
|
+
items: list[T] | Sequence[T],
|
|
29
|
+
*,
|
|
30
|
+
page: int,
|
|
31
|
+
size: int,
|
|
32
|
+
total: int
|
|
33
|
+
) -> 'PageData[T]':
|
|
34
|
+
"""构建分页对象,自动计算总页数
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
items: 当前页数据列表
|
|
38
|
+
page: 当前页码
|
|
39
|
+
size: 每页数量
|
|
40
|
+
total: 总记录数
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
分页对象
|
|
44
|
+
"""
|
|
45
|
+
pages = ceil(total / size) if size > 0 else 0
|
|
46
|
+
return cls(items=items, page=page, size=size, pages=pages, total=total)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""
|
|
2
|
+
@Author : hangu
|
|
3
|
+
@CreateDate : 2026/9/1
|
|
4
|
+
@Description : 请求参数定义
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from pydantic import Field
|
|
10
|
+
|
|
11
|
+
from .base import SchemaBase
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class PageParams(SchemaBase):
|
|
15
|
+
"""通用分页请求参数"""
|
|
16
|
+
page: int = Field(default=1, description='当前页码', ge=1)
|
|
17
|
+
size: int = Field(default=100, description='每页数量', ge=1, le=1000)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class TimeRangeParams(SchemaBase):
|
|
21
|
+
"""通用时间范围查询参数"""
|
|
22
|
+
start_time: datetime | None = Field(default=None, description='开始时间')
|
|
23
|
+
end_time: datetime | None = Field(default=None, description='结束时间')
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class KeywordParams(SchemaBase):
|
|
27
|
+
"""通用关键字搜索参数"""
|
|
28
|
+
keyword: str | None = Field(default=None, description='搜索关键字', max_length=100)
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"""
|
|
2
|
+
@Author : hangu
|
|
3
|
+
@CreateDate : 2026/9/1
|
|
4
|
+
@Description : 统一API响应模型与工厂函数
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from typing import Generic, overload
|
|
9
|
+
|
|
10
|
+
from pydantic import Field
|
|
11
|
+
|
|
12
|
+
from .base import SchemaBase
|
|
13
|
+
from .types import T, E
|
|
14
|
+
|
|
15
|
+
CODE_SUCCESS = 0
|
|
16
|
+
|
|
17
|
+
# ====================== request_id 默认值 ======================
|
|
18
|
+
def _default_request_id() -> str:
|
|
19
|
+
"""获取当前请求ID,无请求上下文返回空字符串
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
请求ID
|
|
23
|
+
"""
|
|
24
|
+
# 延迟导入,避免循环依赖
|
|
25
|
+
from ..middlewares import get_request_id
|
|
26
|
+
return get_request_id() or ''
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# ====================== API响应模型 ======================
|
|
30
|
+
class APIResponse(SchemaBase, Generic[T, E]):
|
|
31
|
+
"""全局统一返回格式
|
|
32
|
+
|
|
33
|
+
request_id: 自动从 ContextVar 获取当前请求ID;无请求上下文返回空字符串
|
|
34
|
+
"""
|
|
35
|
+
request_id: str = Field(default_factory=_default_request_id, description='请求唯一追踪ID')
|
|
36
|
+
code: int = Field(default=CODE_SUCCESS, description='业务码,0代表成功')
|
|
37
|
+
message: str = Field(default='操作成功', description='提示文案')
|
|
38
|
+
data: T | None = Field(default=None, description='业务主体数据')
|
|
39
|
+
extra: E | None = Field(default=None, description='扩展附加信息')
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# ====================== 工厂函数 overload 重载,优化IDE泛型推导 ======================
|
|
43
|
+
@overload
|
|
44
|
+
def build_response(*, code: int = CODE_SUCCESS, message: str = '操作成功') -> APIResponse[None, None]: ...
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@overload
|
|
48
|
+
def build_response(*, code: int = CODE_SUCCESS, message: str = '操作成功', data: T) -> APIResponse[T, None]: ...
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@overload
|
|
52
|
+
def build_response(*, code: int = CODE_SUCCESS, message: str = '操作成功', extra: E) -> APIResponse[None, E]: ...
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@overload
|
|
56
|
+
def build_response(*, code: int = CODE_SUCCESS, message: str = '操作成功', data: T, extra: E) -> APIResponse[T, E]: ...
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def build_response(
|
|
60
|
+
*,
|
|
61
|
+
code: int = CODE_SUCCESS,
|
|
62
|
+
message: str = '操作成功',
|
|
63
|
+
data: T | None = None,
|
|
64
|
+
extra: E | None = None,
|
|
65
|
+
) -> APIResponse[T, E]:
|
|
66
|
+
"""底层构建响应,优先使用 response_success / response_fail
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
code: 业务码,0代表成功
|
|
70
|
+
message: 提示文案
|
|
71
|
+
data: 业务主体数据
|
|
72
|
+
extra: 扩展附加信息
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
APIResponse[T, E]
|
|
76
|
+
"""
|
|
77
|
+
return APIResponse(code=code, message=message, data=data, extra=extra)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@overload
|
|
81
|
+
def response_success(*, message: str = '操作成功') -> APIResponse[None, None]: ...
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@overload
|
|
85
|
+
def response_success(*, message: str = '操作成功', data: T) -> APIResponse[T, None]: ...
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@overload
|
|
89
|
+
def response_success(*, message: str = '操作成功', extra: E) -> APIResponse[None, E]: ...
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@overload
|
|
93
|
+
def response_success(*, message: str = '操作成功', data: T, extra: E) -> APIResponse[T, E]: ...
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def response_success(
|
|
97
|
+
*,
|
|
98
|
+
message: str = '操作成功',
|
|
99
|
+
data: T | None = None,
|
|
100
|
+
extra: E | None = None,
|
|
101
|
+
) -> APIResponse[T, E]:
|
|
102
|
+
"""构造成功响应
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
message: 提示文案
|
|
106
|
+
data: 业务主体数据
|
|
107
|
+
extra: 扩展附加信息
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
APIResponse[T, E]
|
|
111
|
+
"""
|
|
112
|
+
return build_response(code=CODE_SUCCESS, message=message, data=data, extra=extra)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@overload
|
|
116
|
+
def response_fail(*, code: int, message: str = '操作失败') -> APIResponse[None, None]: ...
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@overload
|
|
120
|
+
def response_fail(*, code: int, message: str = '操作失败', extra: E) -> APIResponse[None, E]: ...
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def response_fail(
|
|
124
|
+
*,
|
|
125
|
+
code: int,
|
|
126
|
+
message: str = '操作失败',
|
|
127
|
+
extra: E | None = None,
|
|
128
|
+
) -> APIResponse[None, E]:
|
|
129
|
+
"""构造失败响应,给业务代码 & fastapi_handlers异常处理器使用
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
code: 业务码,0代表成功
|
|
133
|
+
message: 提示文案
|
|
134
|
+
extra: 扩展附加信息
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
APIResponse[None, E]
|
|
138
|
+
"""
|
|
139
|
+
return build_response(code=code, message=message, extra=extra)
|