[project] name = "enervision-backend" version = "0.1.0" description = "API EnerVision : exposition des series temporelles energetiques" requires-python = ">=3.14,<3.15" dependencies = [ "fastapi>=0.141.1", "uvicorn[standard]>=0.53.0", "pydantic[email]>=2.13.5", "pydantic-settings>=2.15.0", "sqlalchemy[asyncio]>=2.0.52", "asyncpg>=0.31.0", "alembic>=1.20.0", "prometheus-fastapi-instrumentator>=8.1.0", "python-json-logger>=4.2.0", "pyjwt>=2.10", "argon2-cffi>=23.1", "anyio>=4.0", "aiosmtplib>=5.1.3", ] [dependency-groups] dev = [ "ruff>=0.16.7", "mypy>=2.3.1", "pytest>=9.1.1", "pytest-asyncio>=1.4.0", "pytest-cov>=7.1.0", "httpx>=0.28.1", ] [build-system] requires = ["hatchling>=1.32.0"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] packages = ["app"] [tool.ruff] line-length = 100 target-version = "py314" src = ["app", "tests"] extend-exclude = ["alembic/versions"] [tool.ruff.lint] select = [ "E", "W", "F", "I", "N", "UP", "B", "C4", "SIM", "TID", "RUF", "ASYNC", "S", "PT", ] ignore = ["B008"] [tool.ruff.lint.per-file-ignores] # S105 à S107 signalent les secrets en dur, qui sont justement la matière des tests d'auth. "tests/**/*.py" = ["S101", "S105", "S106", "S107"] [tool.ruff.lint.isort] known-first-party = ["app"] [tool.ruff.format] quote-style = "double" [tool.mypy] python_version = "3.14" strict = true warn_unreachable = true plugins = ["pydantic.mypy"] exclude = ["^alembic/"] [[tool.mypy.overrides]] module = ["tests.*"] disallow_untyped_defs = false [tool.pytest.ini_options] testpaths = ["tests"] asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "function" addopts = "-q --strict-markers -m 'not integration' --cov=app --cov-report=term-missing" markers = ["integration: requiert une base PostgreSQL joignable, hors `make test`"] [tool.coverage.run] source = ["app"] branch = true omit = ["alembic/*"] [tool.coverage.report] show_missing = true