[project] name = "gps-denied-onboard" version = "0.1.0" description = "GPS-denied UAV geolocalization service" requires-python = ">=3.11" dependencies = [ "fastapi", "uvicorn[standard]", "pydantic>=2", "pydantic-settings>=2", "sqlalchemy>=2", "alembic>=1.14", "sse-starlette>=2.0", "aiosqlite>=0.20", "python-multipart>=0.0.9", "httpx>=0.27", "diskcache>=5.6", "numpy>=1.26,<2.0", # NumPy 2.0 silently breaks GTSAM Python bindings (issue #2264) "opencv-python-headless>=4.9,<4.11", # 4.11+ requires numpy>=2.0 (incompatible with GTSAM) "orjson>=3.10", "gtsam>=4.3a0", "pymavlink>=2.4", "pyyaml>=6.0", "structlog>=25.1,<26", ] [project.optional-dependencies] dev = [ "ruff>=0.9", "pytest>=8.0", "pytest-asyncio>=0.24", "httpx>=0.28", ] [build-system] requires = ["setuptools>=75"] build-backend = "setuptools.build_meta" [tool.setuptools.packages.find] where = ["src"] [tool.ruff] target-version = "py311" line-length = 120 [tool.ruff.lint.per-file-ignores] # Abstract interfaces have long method signatures — allow up to 170 "src/gps_denied/core/factor_graph.py" = ["E501"] "src/gps_denied/components/satellite_matcher/metric_refinement.py" = ["E501"] "src/gps_denied/core/chunk_manager.py" = ["E501"] [tool.ruff.lint] select = ["E", "F", "I", "W"] [tool.pytest.ini_options] testpaths = ["tests"] asyncio_mode = "auto" # --strict-markers makes unregistered @pytest.mark. fail collection rather than warn. # Per Phase 2 / TEST-02 contract; do not weaken without an explicit Phase 2 retrospective entry. addopts = "--strict-markers" markers = [ # Phase 2 / TEST-01 taxonomy "unit: pure-math or single-class test; only mocks; no I/O / no real DB / no real engines / no SITL; runs in <1s", "integration: cross-subsystem (in-memory SQLite, ASGI transport, full FlightProcessor wiring across >=3 real components); no external process", "blackbox: validates an external contract (e.g. MAVLink GPS_INPUT wire encoding per MAVLink #232) without a live producer", "sitl: requires ARDUPILOT_SITL_HOST env var; talks to an ArduPilot SITL process over MAVLink; nightly-only", "e2e: full-pipeline run against a real dataset (EuRoC, VPAIR, MARS-LVIG, Azaion) or its synthetic stand-in via E2EHarness; nightly-only", # Phase 2 / TEST-03 traceability "ac(ac_id): link test to one or more Acceptance Criteria (e.g. AC-1.1, AC-NEW-3); validated against _docs/00_problem/acceptance_criteria.md by scripts/gen_ac_traceability.py", # Pre-existing (kept verbatim) "e2e_slow: e2e test that takes > 2 minutes, nightly-only", "needs_dataset: test requires an external dataset to be downloaded", ]