PayrollManagementSystem/backend/pyproject.toml
liuwenxin efed29647c feat(settings): 公司信息配置与 logo 管理(public 端点供登录页)
- system_settings 单行 CRUD:GET/PUT(AdminUser)+ GET /public(无鉴权,
  SettingPublicOut 白名单仅 company_name/logo_url 两字段,短缓存 300s)
- logo 上传:后缀+magic bytes+2MB 三重校验,固定名覆盖落盘 uploads/logo/
  (不使用上传方文件名,杜绝路径拼接);旧扩展名文件清理;文件流端点
  no-cache,URL 带 update_time 版本参数破缓存
- logo 存目录不存库:图片入 DB 让每次读取与 mysqldump 放大传输且无法
  独立替换;DB 只持一行相对路径
- 新增依赖 python-multipart(FastAPI UploadFile 必备传输层);.gitignore
  增 backend/uploads/ 与 db/backups/
- 集成 11 例:单行语义/白名单字段/三重校验/越权 403/匿名 401/审计留痕

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-15 18:22:12 +08:00

110 lines
4.3 KiB
TOML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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",
"openpyxl>=3.1.5",
"python-multipart>=0.0.32",
]
[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"