[project]
name = "gtpcnz"
version = "1.8.1"
description = "Quarto and Streamlit package for primary care funding architecture modelling"
requires-python = ">=3.11"
dependencies = [
    "altair",
    "numpy",
    "pandas",
    "scipy",
    "networkx",
    "streamlit",
    "matplotlib",
    "plotly",
    "scikit-learn",
    "jupyter",
    "pyyaml",
    "pydantic>=2,<3",
    "dash>=3,<4",
    "gunicorn>=23,<24",
    "orjson>=3,<4",
]

[project.optional-dependencies]
dev = [
    "basedpyright>=1.39.7,<2",
    "hypothesis>=6.155.2,<7",
    "mutmut>=3.6.0,<4",
    "mypy>=2,<3",
    "pandera>=0.31,<0.32",
    "pip-audit>=2.10.1,<3",
    "pre-commit>=4,<5",
    "pytest",
    "pytest-cov>=7,<8",
    "pytest-mock",
    "playwright>=1.57,<2",
    "ruff>=0.15.17,<0.16",
    "scalene>=2.3,<3; platform_system != 'Windows'",
    "ty>=0.0.49,<0.1",
]

[dependency-groups]
dev = [
    "basedpyright>=1.39.7,<2",
    "hypothesis>=6.155.2,<7",
    "mutmut>=3.6.0,<4",
    "mypy>=2,<3",
    "pandera>=0.31,<0.32",
    "pip-audit>=2.10.1,<3",
    "pre-commit>=4,<5",
    "pytest",
    "pytest-cov>=7,<8",
    "pytest-mock",
    "playwright>=1.57,<2",
    "ruff>=0.15.17,<0.16",
    "scalene>=2.3,<3; platform_system != 'Windows'",
    "ty>=0.0.49,<0.1",
]
edge = [
    "pytest",
]

[tool.uv]
package = false

[tool.pixi.workspace]
channels = ["conda-forge"]
platforms = ["linux-64", "win-64"]

[tool.pixi.environments]
default = { features = [], solve-group = "default" }
dev = { features = ["dev"], solve-group = "default" }
edge = { features = ["edge"], solve-group = "default" }

[tool.pixi.dependencies]
python = ">=3.11,<3.12"

[tool.pixi.tasks]
dash = "python -m dash_app.app"
dash-prod = "gunicorn dash_app.app:server --bind 0.0.0.0:7860 --workers 2 --threads 4 --timeout 120"
test-dash = "python -m pytest -q models/tests/test_dashboard_service.py models/tests/test_dash_app.py models/tests/test_pixi_guard.py tests/browser/test_dash_browser_contract.py"
test-runtime = "python -m pytest -q models/tests/test_runtime_lab.py models/tests/test_scenario_service.py models/tests/test_dashboard_claims.py"
test-public-gates = "python scripts/check_public_only_boundary.py && python scripts/check_concern_boundaries.py && python scripts/run_accessibility_audit.py --check-only"
check-pixi = "python scripts/check_pixi_package_manager.py"
test-browser-dash = "python scripts/check_dash_browser_smoke.py"
profile-scalene = "python scripts/run_scalene_profile.py"
profile-dashboard = "python scripts/run_scalene_profile.py && python -m pytest -q models/tests/test_dashboard_service.py models/tests/test_dash_app.py"

[tool.pytest.ini_options]
pythonpath = ["models"]
testpaths = ["models/tests", "tests"]
norecursedirs = ["codex-tmp", "public", "_site", ".hypothesis"]
addopts = ["--import-mode=importlib"]

[tool.coverage.run]
source = ["models/primarycare_model"]
omit = [
  "models/primarycare_model/app.py",
  "models/primarycare_model/engines/*",
  "models/primarycare_model/contracts/oia.py",
  "models/primarycare_model/validation/arrow_schemas.py",
  "models/primarycare_model/validation/runtime_checks.py",
]

[tool.coverage.report]
fail_under = 90
show_missing = true
skip_empty = true

[tool.ruff]
target-version = "py311"
line-length = 120
extend-exclude = [
  ".venv",
  "_site",
  "public",
  "codex-tmp",
  "build",
  ".tmp",
]

[tool.ruff.lint]
select = ["E", "W", "F", "I", "UP", "B", "SIM", "RUF"]
ignore = [
  "E501",
  # Public dashboard strings intentionally use mathematical glyphs and range dashes.
  "RUF001",
]

[tool.ruff.lint.per-file-ignores]
# Historical analytical modules retained for reproducibility of earlier track outputs.
# The active public app/runtime and strict contract layers remain covered by the full Ruff gate.
"models/primarycare_model/abm.py" = ["F841", "SIM108"]
"models/primarycare_model/calibration_v150.py" = ["E701", "E702"]
"models/primarycare_model/diffusion.py" = ["B007", "E701"]
"models/primarycare_model/game.py" = ["UP042"]
"models/primarycare_model/gnn_pathways.py" = ["B905"]
"models/primarycare_model/hybrid_model.py" = ["RUF005"]
"models/primarycare_model/ipc.py" = ["E701", "E702", "RUF059", "SIM105", "UP028"]
"models/primarycare_model/jax_mc.py" = ["RUF046"]
"models/primarycare_model/mcda.py" = ["E701", "E702"]
"models/primarycare_model/nash_opt.py" = ["B905", "E702", "F401"]

[tool.mutmut]
paths_to_mutate = [
  "models/primarycare_model/runtime_lab.py",
  "models/primarycare_model/scenario_service.py",
]
tests_dir = "models/tests"
runner = "python -m pytest -q models/tests/test_runtime_lab.py models/tests/test_scenario_service.py models/tests/test_property_invariants.py"

[tool.mypy]
strict = true
python_version = "3.11"
warn_unused_configs = true
exclude = [
  ".venv/",
  "_site/",
  "public/",
  "codex-tmp/",
  "build/",
  "__pycache__/",
  ".tmp/"
]

# Per-module overrides for known untyped third-party dependencies
[[tool.mypy.overrides]]
module = [
  "numpy.*",
  "pandas.*",
  "streamlit.*",
  "matplotlib.*",
  "plotly.*",
  "networkx.*",
  "yaml.*",
]
ignore_missing_imports = true

[[tool.mypy.overrides]]
module = "pydantic.*"
ignore_missing_imports = false
warn_unused_ignores = true
