[project] name = "bid-doctor" version = "0.1.0" description = "标博士服务端:业务接口(api)和后台任务(worker)是同一套代码、两种进程" requires-python = ">=3.12" dependencies = [ "fastapi>=0.115", "uvicorn[standard]>=0.32", "pydantic>=2.9", "pydantic-settings>=2.6", "sqlalchemy[asyncio]>=2.0.36", "psycopg[binary,pool]>=3.2", "alembic>=1.14", "procrastinate>=3.10,<4", # core/queue.py 直接调用它的 SQL 函数,升级大版本前要核对 "redis>=5.2", "httpx>=0.28", "pypdfium2>=4.30", "pdfplumber>=0.11", "python-multipart>=0.0.18", "cryptography>=44", ] [dependency-groups] dev = [ "pytest>=8.3", "pytest-asyncio>=0.25", "ruff>=0.8", "pyright>=1.1.390", "import-linter>=2.1", "pyyaml>=6", ] [project.scripts] bid-doctor = "bid_doctor.cli:main" [build-system] requires = ["hatchling>=1.26"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] packages = ["src/bid_doctor"] [tool.ruff] line-length = 120 target-version = "py312" src = ["src", "tests"] [tool.ruff.lint] select = ["E", "F", "W", "I", "B", "UP", "SIM", "RUF", "ASYNC", "S", "BLE", "PT"] ignore = [ "RUF001", "RUF002", "RUF003", # 中文全角标点是有意的 "S101", # assert 用来表达不变量 ] [tool.ruff.lint.per-file-ignores] "tests/**" = ["S", "PT011", "PT018"] "migrations/**" = ["E402"] [tool.pyright] include = ["src"] pythonVersion = "3.12" venvPath = ".." venv = ".venv" typeCheckingMode = "strict" reportMissingTypeStubs = false reportUnknownMemberType = false reportUnknownVariableType = false reportUnknownArgumentType = false [tool.pytest.ini_options] asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "session" asyncio_default_test_loop_scope = "session" testpaths = ["tests"] pythonpath = ["."] [tool.importlinter] root_package = "bid_doctor" [[tool.importlinter.contracts]] name = "core 不依赖业务模块" type = "forbidden" source_modules = ["bid_doctor.core"] forbidden_modules = ["bid_doctor.identity", "bid_doctor.billing", "bid_doctor.project", "bid_doctor.document", "bid_doctor.checklist", "bid_doctor.ai", "bid_doctor.audit", "bid_doctor.notification"] [[tool.importlinter.contracts]] name = "业务模块不依赖 api 层的组合模块" type = "forbidden" source_modules = ["bid_doctor.document", "bid_doctor.checklist", "bid_doctor.billing", "bid_doctor.identity.service"] forbidden_modules = ["bid_doctor.project.workbench", "bid_doctor.app"]