Co-Study4Grid / pyproject.toml
github-actions[bot]
Deploy 7688ef1
13d4e44
Raw
History Blame Contribute Delete
5.31 kB
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
[project]
name = "co_study4grid"
version = "0.9.0"
authors = [
{ name="RTE", email="rte@rte-france.com" },
]
description = "Co-Study4Grid — power grid contingency analysis interface"
readme = "README.md"
requires-python = ">=3.10"
license = "MPL-2.0"
classifiers = [
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Operating System :: OS Independent",
]
dependencies = [
"ExpertOp4Grid>=0.3.2.post1",
# Pinned below 1.15 until the test baseline
# (`expert_backend/tests/baseline_scenario.json`) is regenerated with
# the newer solver. pypowsybl 1.15.0 shifts both P (~±2.6 MW) and Q
# (sign-flipping +1.8 → −10.2 Mvar on COUCHY632) on double-busbar
# node_merging actions, breaking the ±1 MW tolerance of
# `test_independent_actions_simulation`. See PR #99 discussion.
"pypowsybl>=1.13.0,<1.15",
"pypowsybl_jupyter",
"pydantic-settings",
"uv",
"fastapi",
"uvicorn",
"python-multipart",
# Required by the overflow-graph rendering pipeline. ``pydot`` is the
# Python wrapper; the ``dot`` system binary it shells out to is
# installed best-effort by ``setup.py`` via ``scripts/install_graphviz.py``
# (see also the ``costudy4grid-install-graphviz`` console script).
"pydot",
]
[project.optional-dependencies]
test = [
"pytest",
"pytest-cov",
"httpx",
"lxml",
"pandas",
]
quality = [
"ruff>=0.6",
# radon is no longer required by the gate (cyclomatic complexity +
# nesting are computed from the AST in scripts/code_quality_report.py);
# kept for ad-hoc `radon cc` exploration.
"radon>=6.0",
# Pinned to a minor for CI reproducibility now that mypy GATES the build
# (a newer minor could surface new diagnostics and break an unrelated PR).
"mypy==1.19.*",
]
[project.scripts]
# Manual fallback when the post-install hook can't elevate to install
# the Graphviz ``dot`` binary on a user's machine.
costudy4grid-install-graphviz = "expert_backend.install_graphviz:ensure_dot"
[tool.setuptools.packages.find]
where = ["."]
include = ["expert_backend*"]
exclude = ["frontend*", "tests*", "venv*"]
# --- Code-quality tooling ---------------------------------------------------
# Ruff is scoped to a light, non-stylistic ruleset: we catch real bugs
# (undefined names, unused imports, common bug patterns) and leave formatting
# choices alone until the team adopts a formatter.
[tool.ruff]
line-length = 120
target-version = "py310"
extend-exclude = [
"scripts/parity_e2e",
# Ad-hoc data-prep scripts that rely on top-level `exec()` chaining —
# ruff cannot resolve names introduced by the exec'd child script.
"scripts/add_limits_and_overloads.py",
"scripts/add_detailed_topology.py",
"Overflow_Graph",
"frontend",
"standalone_interface_legacy.html",
]
[tool.ruff.lint]
# Start strict-but-narrow: only real bugs gate CI today. Broader
# ruleset (`B`, `W`, `UP`) is available via
# `ruff check --select E9,F,B,W,UP` for local clean-up work.
select = [
"E9", # syntax errors
"F", # pyflakes (undefined names, unused imports, etc.)
]
ignore = [
"E501", # line length is tracked as a metric, not a blocker
"F401", # test / scripts modules have legitimate `import X # noqa` fixtures
"F841", # debug/inspection scripts intentionally keep unused locals
]
[tool.ruff.lint.per-file-ignores]
"expert_backend/tests/*" = ["F811"] # pytest fixture redefinitions
"scripts/*" = []
# --- mypy (GATING) ----------------------------------------------------------
# The shared RecommenderService surface is declared in
# services/_recommender_state.py (a TYPE_CHECKING-only base the mixins inherit
# at type-check time, `object` at runtime), so per-class checking no longer
# false-positives on the mixin composition. mypy is clean (0 errors) and now
# GATES the build in CI. See docs/architecture/code-quality-analysis.md §19.
[tool.mypy]
files = ["expert_backend"]
exclude = '(^|/)(tests/|test_backend\.py|install_graphviz\.py)'
ignore_missing_imports = true
warn_unused_configs = true
# Lenient: advisory visibility, not strictness. Tighten incrementally.
check_untyped_defs = false
disallow_untyped_defs = false
# The pluggable-model layer deliberately re-binds service methods per active
# model (its whole job), so `method-assign` is expected there — scope-disable
# it for that one module rather than sprinkling `# type: ignore`.
[[tool.mypy.overrides]]
module = "expert_backend.recommenders._service_integration"
disable_error_code = ["method-assign"]
# --- coverage (GATED) -------------------------------------------------------
# Floor read off the first green CI run (backend was 78% on the no-graphviz
# job, 849 passed). `fail_under` sits 6 points below at 72 so a routine PR
# passes but coverage can't erode; ratchet up as it climbs. Enforced wherever
# `pytest --cov` runs (CI test jobs); can't be measured offline (the real
# recommender is needed). See §20.
[tool.coverage.run]
source = ["expert_backend"]
omit = [
"expert_backend/tests/*",
"expert_backend/test_backend.py",
"expert_backend/install_graphviz.py",
]
[tool.coverage.report]
fail_under = 72