[project] name = "ypms" version = "0.1.0" description = "DC Youth Program Management System" requires-python = ">=3.12" dependencies = [ "fastapi>=0.115", "uvicorn[standard]>=0.30", "sqlalchemy>=2.0", "alembic>=1.13", "psycopg[binary]>=3.2", "pydantic[email]>=2.8", "pydantic-settings>=2.4", "passlib>=1.7", "python-jose[cryptography]>=3.3", "python-multipart>=0.0.9", "structlog>=24.4", "cryptography>=43", "jinja2>=3.1", ] [project.optional-dependencies] dev = [ "pytest>=8.3", "pytest-asyncio>=0.24", "pytest-cov>=5.0", "httpx>=0.27", "ruff>=0.6", "mypy>=1.11", "bandit>=1.7", "pip-audit>=2.7", ] [build-system] requires = ["setuptools>=68"] build-backend = "setuptools.build_meta" [tool.setuptools.packages.find] where = ["src"] [tool.pytest.ini_options] testpaths = ["tests"] asyncio_mode = "auto" addopts = "-ra --strict-markers" [tool.coverage.run] source = ["src/ypms"] omit = [ "tests/*", # router.py is testable end-to-end only once the auth stack lands in # milestone 0.3. The framework tests exercise its underlying CRUDService # + BulkOps directly, which is where the real logic lives. "src/ypms/framework/router.py", ] [tool.coverage.report] show_missing = true skip_covered = false [tool.ruff] line-length = 100 target-version = "py312" [tool.ruff.lint] select = ["E", "F", "I", "UP", "B", "SIM"] # E501: handled by formatter; B008: FastAPI's Depends() in defaults is canonical ignore = ["E501", "B008"] [tool.mypy] python_version = "3.12" strict = true ignore_missing_imports = true # The generic router factory has to work with runtime-bound type variables # that FastAPI introspects via typing.get_type_hints. That means the closure # uses `create_t: type[BaseModel]` bindings which mypy can't model precisely. # See ARCHITECTURE.md §4.1. Same suppression pattern as OWC's framework. [[tool.mypy.overrides]] module = "ypms.framework.router" disable_error_code = ["valid-type", "type-arg", "attr-defined", "unused-ignore"] # Generic CRUD uses TypeVars mypy can't fully model — the ModelT.id and # ModelT.deleted_at accesses require a Protocol bound we don't ship for # ergonomics. Same suppression pattern OWC uses in practice. [[tool.mypy.overrides]] module = "ypms.framework.crud" disable_error_code = ["attr-defined", "valid-type", "unused-ignore"] [tool.bandit] exclude_dirs = ["tests", "migrations"]