[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "gps-denied-onboard"
version = "0.1.0"
description = "Companion onboard system for GPS-denied UAV navigation"
readme = "README.md"
requires-python = ">=3.10,<3.12"
license = {text = "Proprietary"}
authors = [{name = "AZAION onboard team"}]

dependencies = [
    "numpy>=1.26,<2.0",
    "scipy>=1.11,<2.0",
    "pyyaml>=6.0",
    "pydantic>=2.5,<3.0",
    # OpenCV pin gate originally enforced >= 4.12.0 (D-CROSS-CVE-1). Held to
    # 4.11.x while gtsam (4.2 on PyPI) only ships numpy-1.x wheels and
    # opencv-python>=4.12 mandates numpy>=2. See
    # _docs/_process_leftovers/<dated>_d_cross_cve_1_deferred.md — the gate
    # will be restored to >=4.12.0 once a numpy-2-compatible gtsam wheel is
    # available.
    "opencv-python>=4.11.0.86,<4.12",
    "psycopg[binary]>=3.1",
    "sqlalchemy>=2.0",
    "alembic>=1.13",
    "pymavlink>=2.4",
    # iNav MSP2 wire decoder for C8 inbound (AZ-391). MSPy is request-response
    # on a serial transport; AP uses pymavlink for the same role.
    "yamspy>=0.3.3,<0.4",
    "pyserial>=3.5",
    "requests>=2.31",
    "structlog>=24.1",
    "click>=8.1",
    # SE(3) math backend for helpers.se3_utils + C1/C2.5/C3/C3.5/C4/C5/C8 consumers (AZ-264 / AZ-277).
    "gtsam>=4.2,<5.0",
    # Atomic-rename backend for helpers.sha256_sidecar (D-C10-3, AZ-280).
    "atomicwrites>=1.4,<2.0",
    # WGS84 geodesy backend for helpers.wgs_converter (AZ-264 / AZ-279).
    "pyproj>=3.6,<4.0",
    # FDR wire format for fdr_client.records (E-CC-FDR-CLIENT / AZ-272).
    "orjson>=3.9,<4.0",
    # HTTPS client for C12 FlightsApiClient (AZ-489 / ADR-010). Picked over
    # `requests` because httpx ships `MockTransport` natively, so the
    # FlightsApi unit tests need no extra HTTP-mocking dep.
    "httpx>=0.28,<1.0",
]

[project.optional-dependencies]
dev = [
    "pytest>=7.4",
    "pytest-cov>=4.1",
    "pytest-asyncio>=0.23",
    "ruff>=0.4",
    "mypy>=1.8",
    "types-PyYAML",
    "types-requests",
]
inference = [
    "torch>=2.2",
    "torchvision>=0.17",
    "onnxruntime>=1.17",
    # tensorrt is installed out-of-band on Jetson — not a pip dep
]
# AZ-302: thermal telemetry backends used by C7's ThermalStatePublisher.
# Both are Jetson / NVIDIA-host-only and not import-required for Tier-1;
# the publisher selects whichever is importable at start() time and
# raises TelemetryUnavailableError if neither is present.
telemetry = [
    "jetson-stats>=4.2",
    "pynvml>=11.5",
]
indexing = [
    "faiss-cpu>=1.7",
]

[project.scripts]
gps-denied-replay = "gps_denied_onboard.cli.replay:main"

[tool.setuptools]
package-dir = {"" = "src"}

[tool.setuptools.packages.find]
where = ["src"]
include = ["gps_denied_onboard*"]

[tool.pytest.ini_options]
minversion = "7.0"
testpaths = ["tests"]
pythonpath = ["src"]
# log_schema.py is the contract-mandated file name (AZ-245 AC-4); kept
# in python_files so the contract test is discovered alongside the
# standard `test_*.py` pattern.
python_files = ["test_*.py", "*_test.py", "log_schema.py"]
addopts = [
    "--strict-markers",
    "-ra",
]
markers = [
    "tier2: tests that require Jetson hardware (auto-skipped on Tier-1)",
    "gpu: tests that require an NVIDIA GPU",
    "docker: tests that require Docker compose services",
    "ardupilot_sitl: tests that require ArduPilot SITL container",
    "slow: tests slower than ~5s",
    "contract: contract-suite test (frozen public surfaces)",
]

[tool.coverage.run]
source = ["src/gps_denied_onboard"]
branch = true

[tool.coverage.report]
show_missing = true
skip_covered = false

[tool.ruff]
line-length = 100
target-version = "py310"
src = ["src", "tests"]

[tool.ruff.lint]
select = ["E", "F", "W", "I", "B", "UP", "RUF"]
ignore = ["E501"]

[tool.mypy]
python_version = "3.10"
strict = true
warn_unused_ignores = true
warn_return_any = true
ignore_missing_imports = true
mypy_path = "src"
packages = ["gps_denied_onboard"]
