[project] name = "backend" version = "0.1.0" requires-python = ">=3.11" dependencies = [ "fastapi>=0.115.6", "uvicorn>=0.34.0", "sqlalchemy[asyncio]>=2.0.36", "asyncpg>=0.30.0", "bcrypt>=4.0.0", "python-jose[cryptography]>=3.3.0", "email-validator>=2.0.0", "bech32>=1.2.0", "pgqueuer>=0.14.0", ] [dependency-groups] dev = [ "pytest>=8.3.4", "pytest-asyncio>=0.25.0", "httpx>=0.28.1", "aiosqlite>=0.20.0", "mypy>=1.13.0", "ruff>=0.14.10", "pytest-cov>=7.0.0", "bandit>=1.9.2", "pre-commit>=4.5.1", ] [tool.mypy] python_version = "3.11" warn_return_any = true warn_unused_ignores = true check_untyped_defs = true ignore_missing_imports = true exclude = ["tests/"] [tool.ruff] line-length = 88 target-version = "py311" [tool.ruff.lint] select = [ "E", # pycodestyle errors "F", # pyflakes "I", # isort "B", # flake8-bugbear "UP", # pyupgrade "SIM", # flake8-simplify "RUF", # ruff-specific rules ] ignore = [ "B008", # function-call-in-default-argument (standard FastAPI pattern with Depends) ] [tool.ruff.format] quote-style = "double" [tool.ruff.lint.per-file-ignores] "tests/*" = ["E501"] # Allow longer lines in tests for readability [tool.coverage.run] source = ["."] omit = ["tests/*", "__pycache__/*", "seed.py"] branch = true [tool.coverage.report] exclude_lines = [ "pragma: no cover", "if TYPE_CHECKING:", ] show_missing = true [tool.bandit] exclude_dirs = ["tests", ".venv"] skips = [ "B101", # assert warnings (used in tests) "B311", # random for non-security purposes (invite codes) ]