Spaces:
Sleeping
Sleeping
| [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 | |