2026-10-09 06:46:36 -04:00
|
|
|
|
[project]
|
|
|
|
|
|
name = "payroll-backend"
|
|
|
|
|
|
version = "0.1.0"
|
|
|
|
|
|
description = "衍水集团营销人员工资管理系统 —— 后端服务"
|
|
|
|
|
|
readme = "README.md"
|
|
|
|
|
|
# 锁定 3.12:系统默认是 3.14,第三方库轮子覆盖不如 3.12 完备
|
|
|
|
|
|
requires-python = ">=3.12,<3.13"
|
|
|
|
|
|
|
|
|
|
|
|
dependencies = [
|
|
|
|
|
|
"fastapi>=0.115",
|
|
|
|
|
|
# starlette 已进入 1.x(当前 1.7.0)。FastAPI 对它的约束是 `starlette>=0.46.0`,
|
|
|
|
|
|
# **没有上界** —— uv lock --upgrade 时可能漂移到未验证的大版本。
|
|
|
|
|
|
# 我们的异常处理器与 TestClient 直接依赖其 API,故显式限定主版本。
|
|
|
|
|
|
# 当前组合(fastapi 0.143 + starlette 1.7.0)已实测通过全部用例。
|
|
|
|
|
|
"starlette>=1.7,<2",
|
|
|
|
|
|
"uvicorn[standard]>=0.32",
|
|
|
|
|
|
"pydantic>=2.9",
|
|
|
|
|
|
"pydantic-settings>=2.6",
|
|
|
|
|
|
# ORM 与驱动:采用同步 —— 本项目并发极低,异步无吞吐收益;
|
|
|
|
|
|
# 而重活(绩效批量核算、pandas 报表、Excel 导出)全是同步阻塞代码,
|
|
|
|
|
|
# 在异步路由里跑会卡死事件循环。同步路由由 FastAPI 自动放入线程池执行。
|
|
|
|
|
|
"sqlalchemy>=2.0.36",
|
|
|
|
|
|
# 必须带 [rsa]:MySQL 8.0 默认 caching_sha2_password,容器重启后首次连接走
|
|
|
|
|
|
# 全量认证需要 cryptography 做 RSA 交换,缺失时 PyMySQL 直接抛 RuntimeError
|
|
|
|
|
|
# (报错出现在建连阶段,极易被误读成"密码错误")
|
|
|
|
|
|
"pymysql[rsa]>=1.2.3",
|
|
|
|
|
|
"alembic>=1.14",
|
|
|
|
|
|
# 验证码、登录限流、Token 黑名单
|
|
|
|
|
|
"redis[hiredis]>=5.2",
|
|
|
|
|
|
# 鉴权与密码哈希
|
|
|
|
|
|
# 注意:不用 passlib —— 它与 bcrypt>=4.1 存在 __about__ 属性缺失的不兼容问题
|
|
|
|
|
|
"pyjwt>=2.10",
|
|
|
|
|
|
"pwdlib[bcrypt]>=0.2",
|
|
|
|
|
|
# 图形验证码(纯 Python,依赖 Pillow)
|
|
|
|
|
|
"captcha>=0.6",
|
|
|
|
|
|
"pillow>=11.0",
|
2026-10-12 08:24:17 -04:00
|
|
|
|
"openpyxl>=3.1.5",
|
2026-10-15 06:19:58 -04:00
|
|
|
|
"python-multipart>=0.0.32",
|
2026-11-02 22:20:55 -05:00
|
|
|
|
"psutil>=7.2,<8",
|
2026-10-09 06:46:36 -04:00
|
|
|
|
]
|
|
|
|
|
|
|
2026-10-27 23:42:15 -04:00
|
|
|
|
[project.optional-dependencies]
|
|
|
|
|
|
tplus = [
|
|
|
|
|
|
"pyodbc>=5.2,<6",
|
|
|
|
|
|
]
|
|
|
|
|
|
|
2026-10-09 06:46:36 -04:00
|
|
|
|
[dependency-groups]
|
|
|
|
|
|
dev = [
|
|
|
|
|
|
"pytest>=8.3",
|
|
|
|
|
|
"pytest-cov>=7",
|
|
|
|
|
|
"httpx>=0.28,<1.0",
|
|
|
|
|
|
# 用假 Redis 做单测,无需起容器即可覆盖 GETDEL 一次性语义
|
|
|
|
|
|
"fakeredis>=2.30",
|
|
|
|
|
|
# lint + format 二合一,替代 flake8 + isort + black
|
|
|
|
|
|
"ruff>=0.14",
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
# 本项目按应用而非库来管理,不打包安装自身
|
|
|
|
|
|
[tool.uv]
|
|
|
|
|
|
package = false
|
|
|
|
|
|
|
|
|
|
|
|
[tool.pytest.ini_options]
|
|
|
|
|
|
testpaths = ["tests"]
|
|
|
|
|
|
markers = [
|
|
|
|
|
|
"integration: 需要 MySQL/Redis 容器或完整应用实例的测试",
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
# ==================== 代码检查与格式化 ====================
|
|
|
|
|
|
|
|
|
|
|
|
[tool.ruff]
|
|
|
|
|
|
# 与项目根 .editorconfig 保持一致:Python 用 4 空格(缩进由 formatter 控制)
|
|
|
|
|
|
target-version = "py312"
|
|
|
|
|
|
line-length = 100
|
|
|
|
|
|
src = ["app", "tests"]
|
|
|
|
|
|
|
|
|
|
|
|
[tool.ruff.lint]
|
|
|
|
|
|
select = [
|
|
|
|
|
|
"E", # pycodestyle 错误
|
|
|
|
|
|
"W", # pycodestyle 警告
|
|
|
|
|
|
"F", # pyflakes:未使用的导入、未定义的名称等
|
|
|
|
|
|
"I", # isort:导入顺序
|
|
|
|
|
|
"B", # flake8-bugbear:常见陷阱(可变默认参数、循环引用等)
|
|
|
|
|
|
"C4", # flake8-comprehensions:推导式可简化处
|
|
|
|
|
|
"UP", # pyupgrade:按目标 Python 版本升级旧写法
|
|
|
|
|
|
"SIM", # flake8-simplify:可简化的分支与判断
|
|
|
|
|
|
"RUF", # ruff 自有规则
|
|
|
|
|
|
]
|
|
|
|
|
|
ignore = [
|
|
|
|
|
|
# 行宽已由 formatter 控制,lint 不再重复报——长中文注释很容易触发
|
|
|
|
|
|
"E501",
|
|
|
|
|
|
# FastAPI 的依赖注入要求在参数默认值处调用 Depends(),是框架约定而非缺陷。
|
|
|
|
|
|
# 项目内已尽量改用 Annotated 形式(见 api/deps.py),此处兜底。
|
|
|
|
|
|
"B008",
|
|
|
|
|
|
# RUF001/002/003 检查「易混淆的 Unicode 字符」,分别针对字符串字面量、
|
|
|
|
|
|
# 文档字符串、注释 —— 这套规则的默认前提是英文文本。
|
|
|
|
|
|
# 对中文会把全角逗号、句号、括号、冒号全部判定为混淆字符(本项目实测 800+ 条),
|
|
|
|
|
|
# 而中文里全角标点正是规范写法,故一并关闭。
|
|
|
|
|
|
"RUF001",
|
|
|
|
|
|
"RUF002",
|
|
|
|
|
|
"RUF003",
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
[tool.ruff.lint.isort]
|
|
|
|
|
|
# 必须显式声明:本项目 `[tool.uv] package = false`(不作为包安装),
|
|
|
|
|
|
# ruff 无法从项目布局推断出 `app` 是第一方包,否则会把第三方依赖
|
|
|
|
|
|
# 排到 `app.*` 之后(按字母序把两者当成同一组)。
|
|
|
|
|
|
known-first-party = ["app", "tests"]
|
|
|
|
|
|
|
|
|
|
|
|
[tool.ruff.lint.per-file-ignores]
|
|
|
|
|
|
# Alembic 自动生成的迁移脚本不按手写代码的标准要求。
|
|
|
|
|
|
# 这些文件由 `alembic revision --autogenerate` 产出,手工修 lint 会在下次生成时被覆盖。
|
|
|
|
|
|
"alembic/versions/*.py" = ["E501", "I001", "W291"]
|
|
|
|
|
|
|
|
|
|
|
|
[tool.ruff.format]
|
|
|
|
|
|
quote-style = "double"
|