[project]
name = "openpilot"
requires-python = ">= 3.11"
license = {text = "MIT License"}
version = "0.1.0"
description = "an open source driver assistance system"
authors = [
  {name ="Vehicle Researcher", email="user@comma.ai"}
]

dependencies = [
  # multiple users
  "sounddevice",  # micd + soundd
  "pyserial",     # pigeond + qcomgpsd
  "requests",     # many one-off uses
  "sympy",        # rednose + friends
  "crcmod",       # cars + qcomgpsd
  "tqdm",         # cars (fw_versions.py) on start + many one-off uses

  # hardwared
  "smbus2", # configuring amp

  # core
  "cffi",
  "scons",
  "pycapnp",
  "Cython",
  "setuptools",
  "numpy < 2.0.0", # control does not support numpy 2

  # body / webrtcd
  "aiohttp",
  "aiortc",
  "pyaudio",

  # panda
  "libusb1",
  "spidev; platform_system == 'Linux'",

  # modeld
  "onnx >= 1.14.0",
  "onnxruntime >=1.16.3; platform_system == 'Linux' and platform_machine == 'aarch64'",
  "onnxruntime-gpu >=1.16.3; platform_system == 'Linux' and platform_machine == 'x86_64'",

  # logging
  "pyzmq",
  "sentry-sdk",

  # athena
  "PyJWT",
  "json-rpc",
  "websocket_client",

  # acados deps
  "casadi",
  "future-fstrings",

  # these should be removed
  "psutil",
  "pycryptodome", # used in updated/casync, panda, body, and a test

  #logreader
  "zstd",
]

[project.optional-dependencies]
docs = [
  "Jinja2",
  "sphinx",
  "sphinx-rtd-theme",
  "sphinx-sitemap"
]

testing = [
  "coverage",
  "hypothesis ==6.47.*",
  "mypy",
  "pre-commit",
  "pytest",
  "pytest-cov",
  "pytest-cpp",
  "pytest-subtests",
  "pytest-xdist",
  "pytest-timeout",
  "pytest-randomly",
  "pytest-asyncio",
  "pytest-mock",
  "pytest-repeat",
  "ruff"
]

dev = [
  "av",
  "azure-identity",
  "azure-storage-blob",
  "breathe",
  "control",
  "dictdiffer",
  "flaky",
  "inputs",
  "lru-dict",
  "matplotlib",
  "metadrive-simulator; platform_machine != 'aarch64'",
  "mpld3",
  "myst-parser",
  "natsort",
  "opencv-python-headless",
  "parameterized >=0.8, <0.9",
  #pprofile = "*"
  "pyautogui",
  "pygame",
  "pyopencl; platform_machine != 'aarch64'", # broken on arm64
  "pywinctl",
  "pyprof2calltree",
  "rerun-sdk",
  "tabulate",
  "types-requests",
  "types-tabulate",

  # this is only pinned since 5.15.11 is broken
  "pyqt5 ==5.15.2; platform_machine == 'x86_64'", # no aarch64 wheels for macOS/linux

]

[tool.uv.sources]
metadrive-simulator = { git = "https://github.com/commaai/metadrive.git", branch = "opencv_headless" }

[project.urls]
Homepage = "https://comma.ai"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = [ "." ]

[tool.pytest.ini_options]
minversion = "6.0"
addopts = "--ignore=openpilot/ --ignore=cereal/ --ignore=opendbc/ --ignore=panda/ --ignore=rednose_repo/ --ignore=tinygrad_repo/ --ignore=teleoprtc_repo/ --ignore=msgq/  -Werror --strict-config --strict-markers --durations=10 -n auto --dist=loadgroup"
cpp_files = "test_*"
cpp_harness = "selfdrive/test/cpp_harness.py"
python_files = "test_*.py"
#timeout = "30"  # you get this long by default
markers = [
  "slow: tests that take awhile to run and can be skipped with -m 'not slow'",
  "tici: tests that are only meant to run on the C3/C3X",
]
testpaths = [
  "common",
  "selfdrive/pandad",
  "selfdrive/car",
  "selfdrive/controls",
  "selfdrive/locationd",
  "selfdrive/monitoring",
  "selfdrive/test/longitudinal_maneuvers",
  "selfdrive/test/process_replay/test_fuzzy.py",
  "system/updated",
  "system/athena",
  "system/camerad",
  "system/hardware",
  "system/loggerd",
  "system/proclogd",
  "system/tests",
  "system/ubloxd",
  "system/webrtc",
  "tools/lib/tests",
  "tools/replay",
  "tools/cabana",
  "cereal/messaging/tests",
]

[tool.mypy]
python_version = "3.11"
plugins = [
  "numpy.typing.mypy_plugin",
]
exclude = [
  "body/",
  "cereal/",
  "opendbc/",
  "panda/",
  "rednose/",
  "rednose_repo/",
  "tinygrad/",
  "tinygrad_repo/",
  "teleoprtc/",
  "teleoprtc_repo/",
  "third_party/",
]

# third-party packages
ignore_missing_imports=true

# helpful warnings
warn_redundant_casts=true
warn_unreachable=true
warn_unused_ignores=true

# restrict dynamic typing
warn_return_any=true

# allow implicit optionals for default args
implicit_optional = true

# https://beta.ruff.rs/docs/configuration/#using-pyprojecttoml
[tool.ruff]
indent-width = 2
lint.select = [
  "E", "F", "W", "PIE", "C4", "ISC", "A", "B",
  "NPY", # numpy
  "UP",  # pyupgrade
  "TRY302", "TRY400", "TRY401", # try/excepts
  "RUF008", "RUF100",
  "TID251",
  "PLR1704",
]
lint.ignore = [
  "E741",
  "E402",
  "C408",
  "ISC003",
  "B027",
  "B024",
  "NPY002",  # new numpy random syntax is worse
  "UP038",   # (x, y) -> x|y for isinstance
]
line-length = 160
target-version="py311"
exclude = [
  "body",
  "cereal",
  "panda",
  "opendbc",
  "rednose_repo",
  "tinygrad_repo",
  "teleoprtc",
  "teleoprtc_repo",
  "third_party",
]
lint.flake8-implicit-str-concat.allow-multiline=false
[tool.ruff.lint.flake8-tidy-imports.banned-api]
"selfdrive".msg = "Use openpilot.selfdrive"
"common".msg = "Use openpilot.common"
"system".msg = "Use openpilot.system"
"third_party".msg = "Use openpilot.third_party"
"tools".msg = "Use openpilot.tools"
"pytest.main".msg = "pytest.main requires special handling that is easy to mess up!"
"unittest".msg = "Use pytest"

[tool.coverage.run]
concurrency = ["multiprocessing", "thread"]
[tool.ruff.format]
quote-style = "preserve"
