Archived
异步基础层(core/):
- db.py aiosqlite + WAL:读路径无锁并发、写路径 asyncio.Lock 串行,
busy_timeout 自旋——实现「读写同时进行」(旧实现用 RLock 全读串行)
- http_client.py aiohttp 连接池 + 有界重试(5xx 重试 / 4xx 不重试)+
响应体上限 + 流式接口;按事件循环隔离 session(支持迁移期双 loop)
工具链:
- pyproject.toml ruff(E/F/W/I/B/UP/C4/ASYNC/S/RUF) + pyright(basic) + pytest(asyncio auto)
- requirements-fastapi.txt FastAPI/aiohttp/aiosqlite/aiofiles 等目标栈
- requirements-dev.txt 开发依赖(pytest/ruff/pyright)
清理:删除无用脚本 _csscheck.py 与产物标记 _css_ok.txt/_pkg_ok.txt,同步 .gitignore
验证:pytest 10/10(含「写 200 条同时 4 读协程零异常」并发用例);
ruff All checks passed;pyright 0 errors。
64 lines
2.4 KiB
TOML
64 lines
2.4 KiB
TOML
# -*- coding: utf-8 -*-
|
||
[project]
|
||
name = "yunmusic-assistant"
|
||
version = "3.0.0"
|
||
description = "云村小助手 · 网易云音乐解析/下载服务(FastAPI + asyncio + aiohttp)"
|
||
requires-python = ">=3.12"
|
||
|
||
# ============ Ruff:静态检查 + 导入排序 + 格式化 ============
|
||
[tool.ruff]
|
||
target-version = "py312"
|
||
line-length = 120
|
||
extend-exclude = [".venv", ".zcode", "templates", "static", "data"]
|
||
|
||
[tool.ruff.lint]
|
||
# E/F 基础错误、I 导入排序、B bugbear、UP 升级、ASYNC 异步陷阱、S 安全、RUF
|
||
select = ["E", "F", "W", "I", "B", "UP", "C4", "ASYNC", "S", "RUF"]
|
||
ignore = [
|
||
"E501", # 行宽交给 formatter,不强制
|
||
"E402", # main.py 存在「先定义后 import」的历史结构,迁移期暂放行
|
||
"S101", # 生产代码外的 assert(测试/断言脚本)
|
||
"S104", # 绑定 0.0.0.0(服务端有意为之)
|
||
"S110", # try/except/pass(本项目大量「失败静默降级」策略,见交接文档)
|
||
"S112", # try/except/continue
|
||
"S324", # hashlib.md5 用于非安全场景(上游签名口径)
|
||
"S603", "S607", # subprocess(打包/运维脚本)
|
||
"UP009", # 保留 `# -*- coding: utf-8 -*-` 文件头(全项目既有约定)
|
||
"RUF001", "RUF002", "RUF003", # 全角字符(中文注释/文案,误报)
|
||
]
|
||
|
||
[tool.ruff.lint.per-file-ignores]
|
||
"tests/**" = ["S", "ASYNC"]
|
||
".zcode/**" = ["S", "ASYNC", "F"]
|
||
"_mkpkg.py" = ["S"]
|
||
# ASYNC109:timeout 参数是有意 API——直接转发给 aiohttp 的 ClientTimeout,
|
||
# 不是「用 sleep 当超时」的反模式。
|
||
"core/http_client.py" = ["ASYNC109"]
|
||
|
||
[tool.ruff.lint.isort]
|
||
known-first-party = ["core", "web", "music_api", "auth_system"]
|
||
|
||
[tool.ruff.format]
|
||
quote-style = "preserve"
|
||
|
||
# ============ Pyright:类型检查 ============
|
||
[tool.pyright]
|
||
include = ["core", "web"]
|
||
exclude = [".venv", ".zcode", "data", "downloads", "templates", "static"]
|
||
venvPath = "."
|
||
venv = ".venv"
|
||
pythonVersion = "3.12"
|
||
typeCheckingMode = "basic"
|
||
# 迁移期口径:存量 Flask 巨石(main.py/auth_*.py)暂不纳入严格检查,
|
||
# 新写的 core/ 与 web/ 要求类型干净。随迁移推进逐步把模块移入 include。
|
||
reportMissingImports = true
|
||
reportOptionalMemberAccess = "warning"
|
||
reportAttributeAccessIssue = "warning"
|
||
reportGeneralTypeIssues = "warning"
|
||
|
||
# ============ Pytest ============
|
||
[tool.pytest.ini_options]
|
||
asyncio_mode = "auto"
|
||
testpaths = ["tests"]
|
||
addopts = "-q"
|