use pyupgrade to update to new typing syntax (#31580)

* add pyupgrade hook

* run pyupgrade (pre-commit run -a)

* ruff --fix

* Revert "add pyupgrade hook"

This reverts commit 56ec18bb6b.

* revert changes to third_party/

* manual type fixes

* explicit Optional wrapping capnp objects
old-commit-hash: 995250ae49
This commit is contained in:
Cameron Clough 2024-02-25 00:41:23 +00:00 committed by GitHub
parent 8af72c9330
commit 9bd90112d0
125 changed files with 464 additions and 525 deletions

View File

@ -1,7 +1,6 @@
import os import os
import tempfile import tempfile
import contextlib import contextlib
from typing import Optional
class CallbackReader: class CallbackReader:
@ -24,7 +23,7 @@ class CallbackReader:
@contextlib.contextmanager @contextlib.contextmanager
def atomic_write_in_dir(path: str, mode: str = 'w', buffering: int = -1, encoding: Optional[str] = None, newline: Optional[str] = None, def atomic_write_in_dir(path: str, mode: str = 'w', buffering: int = -1, encoding: str | None = None, newline: str | None = None,
overwrite: bool = False): overwrite: bool = False):
"""Write to a file atomically using a temporary file in the same directory as the destination file.""" """Write to a file atomically using a temporary file in the same directory as the destination file."""
dir_name = os.path.dirname(path) dir_name = os.path.dirname(path)

View File

@ -1,6 +1,5 @@
import os import os
from functools import lru_cache from functools import lru_cache
from typing import Optional, List
def gpio_init(pin: int, output: bool) -> None: def gpio_init(pin: int, output: bool) -> None:
try: try:
@ -16,7 +15,7 @@ def gpio_set(pin: int, high: bool) -> None:
except Exception as e: except Exception as e:
print(f"Failed to set gpio {pin} value: {e}") print(f"Failed to set gpio {pin} value: {e}")
def gpio_read(pin: int) -> Optional[bool]: def gpio_read(pin: int) -> bool | None:
val = None val = None
try: try:
with open(f"/sys/class/gpio/gpio{pin}/value", 'rb') as f: with open(f"/sys/class/gpio/gpio{pin}/value", 'rb') as f:
@ -37,7 +36,7 @@ def gpio_export(pin: int) -> None:
print(f"Failed to export gpio {pin}") print(f"Failed to export gpio {pin}")
@lru_cache(maxsize=None) @lru_cache(maxsize=None)
def get_irq_action(irq: int) -> List[str]: def get_irq_action(irq: int) -> list[str]:
try: try:
with open(f"/sys/kernel/irq/{irq}/actions") as f: with open(f"/sys/kernel/irq/{irq}/actions") as f:
actions = f.read().strip().split(',') actions = f.read().strip().split(',')
@ -45,7 +44,7 @@ def get_irq_action(irq: int) -> List[str]:
except FileNotFoundError: except FileNotFoundError:
return [] return []
def get_irqs_for_action(action: str) -> List[str]: def get_irqs_for_action(action: str) -> list[str]:
ret = [] ret = []
with open("/proc/interrupts") as f: with open("/proc/interrupts") as f:
for l in f.readlines(): for l in f.readlines():

View File

@ -6,7 +6,6 @@ example in common/tests/test_mock.py
import functools import functools
import threading import threading
from typing import List, Union
from cereal.messaging import PubMaster from cereal.messaging import PubMaster
from cereal.services import SERVICE_LIST from cereal.services import SERVICE_LIST
from openpilot.common.mock.generators import generate_liveLocationKalman from openpilot.common.mock.generators import generate_liveLocationKalman
@ -18,7 +17,7 @@ MOCK_GENERATOR = {
} }
def generate_messages_loop(services: List[str], done: threading.Event): def generate_messages_loop(services: list[str], done: threading.Event):
pm = PubMaster(services) pm = PubMaster(services)
rk = Ratekeeper(100) rk = Ratekeeper(100)
i = 0 i = 0
@ -32,7 +31,7 @@ def generate_messages_loop(services: List[str], done: threading.Event):
rk.keep_time() rk.keep_time()
def mock_messages(services: Union[List[str], str]): def mock_messages(services: list[str] | str):
if isinstance(services, str): if isinstance(services, str):
services = [services] services = [services]

View File

@ -2,14 +2,13 @@ import os
import shutil import shutil
import uuid import uuid
from typing import Optional
from openpilot.common.params import Params from openpilot.common.params import Params
from openpilot.system.hardware.hw import Paths from openpilot.system.hardware.hw import Paths
from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT
class OpenpilotPrefix: class OpenpilotPrefix:
def __init__(self, prefix: Optional[str] = None, clean_dirs_on_exit: bool = True, shared_download_cache: bool = False): def __init__(self, prefix: str | None = None, clean_dirs_on_exit: bool = True, shared_download_cache: bool = False):
self.prefix = prefix if prefix else str(uuid.uuid4().hex[0:15]) self.prefix = prefix if prefix else str(uuid.uuid4().hex[0:15])
self.msgq_path = os.path.join('/dev/shm', self.prefix) self.msgq_path = os.path.join('/dev/shm', self.prefix)
self.clean_dirs_on_exit = clean_dirs_on_exit self.clean_dirs_on_exit = clean_dirs_on_exit

View File

@ -3,7 +3,6 @@ import gc
import os import os
import time import time
from collections import deque from collections import deque
from typing import Optional, List, Union
from setproctitle import getproctitle from setproctitle import getproctitle
@ -33,12 +32,12 @@ def set_realtime_priority(level: int) -> None:
os.sched_setscheduler(0, os.SCHED_FIFO, os.sched_param(level)) os.sched_setscheduler(0, os.SCHED_FIFO, os.sched_param(level))
def set_core_affinity(cores: List[int]) -> None: def set_core_affinity(cores: list[int]) -> None:
if not PC: if not PC:
os.sched_setaffinity(0, cores) os.sched_setaffinity(0, cores)
def config_realtime_process(cores: Union[int, List[int]], priority: int) -> None: def config_realtime_process(cores: int | list[int], priority: int) -> None:
gc.disable() gc.disable()
set_realtime_priority(priority) set_realtime_priority(priority)
c = cores if isinstance(cores, list) else [cores, ] c = cores if isinstance(cores, list) else [cores, ]
@ -46,7 +45,7 @@ def config_realtime_process(cores: Union[int, List[int]], priority: int) -> None
class Ratekeeper: class Ratekeeper:
def __init__(self, rate: float, print_delay_threshold: Optional[float] = 0.0) -> None: def __init__(self, rate: float, print_delay_threshold: float | None = 0.0) -> None:
"""Rate in Hz for ratekeeping. print_delay_threshold must be nonnegative.""" """Rate in Hz for ratekeeping. print_delay_threshold must be nonnegative."""
self._interval = 1. / rate self._interval = 1. / rate
self._next_frame_time = time.monotonic() + self._interval self._next_frame_time = time.monotonic() + self._interval

View File

@ -1,5 +1,5 @@
import numpy as np import numpy as np
from typing import Callable from collections.abc import Callable
from openpilot.common.transformations.transformations import (ecef_euler_from_ned_single, from openpilot.common.transformations.transformations import (ecef_euler_from_ned_single,
euler2quat_single, euler2quat_single,

View File

@ -1,3 +0,0 @@

View File

@ -19,7 +19,8 @@ from dataclasses import asdict, dataclass, replace
from datetime import datetime from datetime import datetime
from functools import partial from functools import partial
from queue import Queue from queue import Queue
from typing import Callable, Dict, List, Optional, Set, Union, cast from typing import cast
from collections.abc import Callable
import requests import requests
from jsonrpc import JSONRPCResponseManager, dispatcher from jsonrpc import JSONRPCResponseManager, dispatcher
@ -55,17 +56,17 @@ WS_FRAME_SIZE = 4096
NetworkType = log.DeviceState.NetworkType NetworkType = log.DeviceState.NetworkType
UploadFileDict = Dict[str, Union[str, int, float, bool]] UploadFileDict = dict[str, str | int | float | bool]
UploadItemDict = Dict[str, Union[str, bool, int, float, Dict[str, str]]] UploadItemDict = dict[str, str | bool | int | float | dict[str, str]]
UploadFilesToUrlResponse = Dict[str, Union[int, List[UploadItemDict], List[str]]] UploadFilesToUrlResponse = dict[str, int | list[UploadItemDict] | list[str]]
@dataclass @dataclass
class UploadFile: class UploadFile:
fn: str fn: str
url: str url: str
headers: Dict[str, str] headers: dict[str, str]
allow_cellular: bool allow_cellular: bool
@classmethod @classmethod
@ -77,9 +78,9 @@ class UploadFile:
class UploadItem: class UploadItem:
path: str path: str
url: str url: str
headers: Dict[str, str] headers: dict[str, str]
created_at: int created_at: int
id: Optional[str] id: str | None
retry_count: int = 0 retry_count: int = 0
current: bool = False current: bool = False
progress: float = 0 progress: float = 0
@ -97,9 +98,9 @@ send_queue: Queue[str] = queue.Queue()
upload_queue: Queue[UploadItem] = queue.Queue() upload_queue: Queue[UploadItem] = queue.Queue()
low_priority_send_queue: Queue[str] = queue.Queue() low_priority_send_queue: Queue[str] = queue.Queue()
log_recv_queue: Queue[str] = queue.Queue() log_recv_queue: Queue[str] = queue.Queue()
cancelled_uploads: Set[str] = set() cancelled_uploads: set[str] = set()
cur_upload_items: Dict[int, Optional[UploadItem]] = {} cur_upload_items: dict[int, UploadItem | None] = {}
def strip_bz2_extension(fn: str) -> str: def strip_bz2_extension(fn: str) -> str:
@ -127,14 +128,14 @@ class UploadQueueCache:
@staticmethod @staticmethod
def cache(upload_queue: Queue[UploadItem]) -> None: def cache(upload_queue: Queue[UploadItem]) -> None:
try: try:
queue: List[Optional[UploadItem]] = list(upload_queue.queue) queue: list[UploadItem | None] = list(upload_queue.queue)
items = [asdict(i) for i in queue if i is not None and (i.id not in cancelled_uploads)] items = [asdict(i) for i in queue if i is not None and (i.id not in cancelled_uploads)]
Params().put("AthenadUploadQueue", json.dumps(items)) Params().put("AthenadUploadQueue", json.dumps(items))
except Exception: except Exception:
cloudlog.exception("athena.UploadQueueCache.cache.exception") cloudlog.exception("athena.UploadQueueCache.cache.exception")
def handle_long_poll(ws: WebSocket, exit_event: Optional[threading.Event]) -> None: def handle_long_poll(ws: WebSocket, exit_event: threading.Event | None) -> None:
end_event = threading.Event() end_event = threading.Event()
threads = [ threads = [
@ -278,7 +279,7 @@ def upload_handler(end_event: threading.Event) -> None:
cloudlog.exception("athena.upload_handler.exception") cloudlog.exception("athena.upload_handler.exception")
def _do_upload(upload_item: UploadItem, callback: Optional[Callable] = None) -> requests.Response: def _do_upload(upload_item: UploadItem, callback: Callable | None = None) -> requests.Response:
path = upload_item.path path = upload_item.path
compress = False compress = False
@ -317,7 +318,7 @@ def getMessage(service: str, timeout: int = 1000) -> dict:
@dispatcher.add_method @dispatcher.add_method
def getVersion() -> Dict[str, str]: def getVersion() -> dict[str, str]:
return { return {
"version": get_version(), "version": get_version(),
"remote": get_normalized_origin(), "remote": get_normalized_origin(),
@ -327,7 +328,7 @@ def getVersion() -> Dict[str, str]:
@dispatcher.add_method @dispatcher.add_method
def setNavDestination(latitude: int = 0, longitude: int = 0, place_name: Optional[str] = None, place_details: Optional[str] = None) -> Dict[str, int]: def setNavDestination(latitude: int = 0, longitude: int = 0, place_name: str | None = None, place_details: str | None = None) -> dict[str, int]:
destination = { destination = {
"latitude": latitude, "latitude": latitude,
"longitude": longitude, "longitude": longitude,
@ -339,7 +340,7 @@ def setNavDestination(latitude: int = 0, longitude: int = 0, place_name: Optiona
return {"success": 1} return {"success": 1}
def scan_dir(path: str, prefix: str) -> List[str]: def scan_dir(path: str, prefix: str) -> list[str]:
files = [] files = []
# only walk directories that match the prefix # only walk directories that match the prefix
# (glob and friends traverse entire dir tree) # (glob and friends traverse entire dir tree)
@ -359,12 +360,12 @@ def scan_dir(path: str, prefix: str) -> List[str]:
return files return files
@dispatcher.add_method @dispatcher.add_method
def listDataDirectory(prefix='') -> List[str]: def listDataDirectory(prefix='') -> list[str]:
return scan_dir(Paths.log_root(), prefix) return scan_dir(Paths.log_root(), prefix)
@dispatcher.add_method @dispatcher.add_method
def uploadFileToUrl(fn: str, url: str, headers: Dict[str, str]) -> UploadFilesToUrlResponse: def uploadFileToUrl(fn: str, url: str, headers: dict[str, str]) -> UploadFilesToUrlResponse:
# this is because mypy doesn't understand that the decorator doesn't change the return type # this is because mypy doesn't understand that the decorator doesn't change the return type
response: UploadFilesToUrlResponse = uploadFilesToUrls([{ response: UploadFilesToUrlResponse = uploadFilesToUrls([{
"fn": fn, "fn": fn,
@ -375,11 +376,11 @@ def uploadFileToUrl(fn: str, url: str, headers: Dict[str, str]) -> UploadFilesTo
@dispatcher.add_method @dispatcher.add_method
def uploadFilesToUrls(files_data: List[UploadFileDict]) -> UploadFilesToUrlResponse: def uploadFilesToUrls(files_data: list[UploadFileDict]) -> UploadFilesToUrlResponse:
files = map(UploadFile.from_dict, files_data) files = map(UploadFile.from_dict, files_data)
items: List[UploadItemDict] = [] items: list[UploadItemDict] = []
failed: List[str] = [] failed: list[str] = []
for file in files: for file in files:
if len(file.fn) == 0 or file.fn[0] == '/' or '..' in file.fn or len(file.url) == 0: if len(file.fn) == 0 or file.fn[0] == '/' or '..' in file.fn or len(file.url) == 0:
failed.append(file.fn) failed.append(file.fn)
@ -418,13 +419,13 @@ def uploadFilesToUrls(files_data: List[UploadFileDict]) -> UploadFilesToUrlRespo
@dispatcher.add_method @dispatcher.add_method
def listUploadQueue() -> List[UploadItemDict]: def listUploadQueue() -> list[UploadItemDict]:
items = list(upload_queue.queue) + list(cur_upload_items.values()) items = list(upload_queue.queue) + list(cur_upload_items.values())
return [asdict(i) for i in items if (i is not None) and (i.id not in cancelled_uploads)] return [asdict(i) for i in items if (i is not None) and (i.id not in cancelled_uploads)]
@dispatcher.add_method @dispatcher.add_method
def cancelUpload(upload_id: Union[str, List[str]]) -> Dict[str, Union[int, str]]: def cancelUpload(upload_id: str | list[str]) -> dict[str, int | str]:
if not isinstance(upload_id, list): if not isinstance(upload_id, list):
upload_id = [upload_id] upload_id = [upload_id]
@ -437,7 +438,7 @@ def cancelUpload(upload_id: Union[str, List[str]]) -> Dict[str, Union[int, str]]
return {"success": 1} return {"success": 1}
@dispatcher.add_method @dispatcher.add_method
def setRouteViewed(route: str) -> Dict[str, Union[int, str]]: def setRouteViewed(route: str) -> dict[str, int | str]:
# maintain a list of the last 10 routes viewed in connect # maintain a list of the last 10 routes viewed in connect
params = Params() params = Params()
@ -452,7 +453,7 @@ def setRouteViewed(route: str) -> Dict[str, Union[int, str]]:
return {"success": 1} return {"success": 1}
def startLocalProxy(global_end_event: threading.Event, remote_ws_uri: str, local_port: int) -> Dict[str, int]: def startLocalProxy(global_end_event: threading.Event, remote_ws_uri: str, local_port: int) -> dict[str, int]:
try: try:
if local_port not in LOCAL_PORT_WHITELIST: if local_port not in LOCAL_PORT_WHITELIST:
raise Exception("Requested local port not whitelisted") raise Exception("Requested local port not whitelisted")
@ -486,7 +487,7 @@ def startLocalProxy(global_end_event: threading.Event, remote_ws_uri: str, local
@dispatcher.add_method @dispatcher.add_method
def getPublicKey() -> Optional[str]: def getPublicKey() -> str | None:
if not os.path.isfile(Paths.persist_root() + '/comma/id_rsa.pub'): if not os.path.isfile(Paths.persist_root() + '/comma/id_rsa.pub'):
return None return None
@ -526,7 +527,7 @@ def getNetworks():
@dispatcher.add_method @dispatcher.add_method
def takeSnapshot() -> Optional[Union[str, Dict[str, str]]]: def takeSnapshot() -> str | dict[str, str] | None:
from openpilot.system.camerad.snapshot.snapshot import jpeg_write, snapshot from openpilot.system.camerad.snapshot.snapshot import jpeg_write, snapshot
ret = snapshot() ret = snapshot()
if ret is not None: if ret is not None:
@ -543,7 +544,7 @@ def takeSnapshot() -> Optional[Union[str, Dict[str, str]]]:
raise Exception("not available while camerad is started") raise Exception("not available while camerad is started")
def get_logs_to_send_sorted() -> List[str]: def get_logs_to_send_sorted() -> list[str]:
# TODO: scan once then use inotify to detect file creation/deletion # TODO: scan once then use inotify to detect file creation/deletion
curr_time = int(time.time()) curr_time = int(time.time())
logs = [] logs = []
@ -766,7 +767,7 @@ def backoff(retries: int) -> int:
return random.randrange(0, min(128, int(2 ** retries))) return random.randrange(0, min(128, int(2 ** retries)))
def main(exit_event: Optional[threading.Event] = None): def main(exit_event: threading.Event | None = None):
try: try:
set_core_affinity([0, 1, 2, 3]) set_core_affinity([0, 1, 2, 3])
except Exception: except Exception:

View File

@ -3,7 +3,6 @@ import time
import json import json
import jwt import jwt
from pathlib import Path from pathlib import Path
from typing import Optional
from datetime import datetime, timedelta from datetime import datetime, timedelta
from openpilot.common.api import api_get from openpilot.common.api import api_get
@ -23,12 +22,12 @@ def is_registered_device() -> bool:
return dongle not in (None, UNREGISTERED_DONGLE_ID) return dongle not in (None, UNREGISTERED_DONGLE_ID)
def register(show_spinner=False) -> Optional[str]: def register(show_spinner=False) -> str | None:
params = Params() params = Params()
IMEI = params.get("IMEI", encoding='utf8') IMEI = params.get("IMEI", encoding='utf8')
HardwareSerial = params.get("HardwareSerial", encoding='utf8') HardwareSerial = params.get("HardwareSerial", encoding='utf8')
dongle_id: Optional[str] = params.get("DongleId", encoding='utf8') dongle_id: str | None = params.get("DongleId", encoding='utf8')
needs_registration = None in (IMEI, HardwareSerial, dongle_id) needs_registration = None in (IMEI, HardwareSerial, dongle_id)
pubkey = Path(Paths.persist_root()+"/comma/id_rsa.pub") pubkey = Path(Paths.persist_root()+"/comma/id_rsa.pub")
@ -48,8 +47,8 @@ def register(show_spinner=False) -> Optional[str]:
# Block until we get the imei # Block until we get the imei
serial = HARDWARE.get_serial() serial = HARDWARE.get_serial()
start_time = time.monotonic() start_time = time.monotonic()
imei1: Optional[str] = None imei1: str | None = None
imei2: Optional[str] = None imei2: str | None = None
while imei1 is None and imei2 is None: while imei1 is None and imei2 is None:
try: try:
imei1, imei2 = HARDWARE.get_imei(0), HARDWARE.get_imei(1) imei1, imei2 = HARDWARE.get_imei(0), HARDWARE.get_imei(1)

View File

@ -12,7 +12,6 @@ import unittest
from dataclasses import asdict, replace from dataclasses import asdict, replace
from datetime import datetime, timedelta from datetime import datetime, timedelta
from parameterized import parameterized from parameterized import parameterized
from typing import Optional
from unittest import mock from unittest import mock
from websocket import ABNF from websocket import ABNF
@ -97,7 +96,7 @@ class TestAthenadMethods(unittest.TestCase):
break break
@staticmethod @staticmethod
def _create_file(file: str, parent: Optional[str] = None, data: bytes = b'') -> str: def _create_file(file: str, parent: str | None = None, data: bytes = b'') -> str:
fn = os.path.join(Paths.log_root() if parent is None else parent, file) fn = os.path.join(Paths.log_root() if parent is None else parent, file)
os.makedirs(os.path.dirname(fn), exist_ok=True) os.makedirs(os.path.dirname(fn), exist_ok=True)
with open(fn, 'wb') as f: with open(fn, 'wb') as f:

View File

@ -3,7 +3,7 @@ import subprocess
import threading import threading
import time import time
import unittest import unittest
from typing import cast, Optional from typing import cast
from unittest import mock from unittest import mock
from openpilot.common.params import Params from openpilot.common.params import Params
@ -29,8 +29,8 @@ class TestAthenadPing(unittest.TestCase):
athenad: threading.Thread athenad: threading.Thread
exit_event: threading.Event exit_event: threading.Event
def _get_ping_time(self) -> Optional[str]: def _get_ping_time(self) -> str | None:
return cast(Optional[str], self.params.get("LastAthenaPingTime", encoding="utf-8")) return cast(str | None, self.params.get("LastAthenaPingTime", encoding="utf-8"))
def _clear_ping_time(self) -> None: def _clear_ping_time(self) -> None:
self.params.remove("LastAthenaPingTime") self.params.remove("LastAthenaPingTime")

View File

@ -4,7 +4,7 @@ import os
import usb1 import usb1
import time import time
import subprocess import subprocess
from typing import List, NoReturn from typing import NoReturn
from functools import cmp_to_key from functools import cmp_to_key
from panda import Panda, PandaDFU, PandaProtocolMismatch, FW_PATH from panda import Panda, PandaDFU, PandaProtocolMismatch, FW_PATH
@ -124,7 +124,7 @@ def main() -> NoReturn:
cloudlog.info(f"{len(panda_serials)} panda(s) found, connecting - {panda_serials}") cloudlog.info(f"{len(panda_serials)} panda(s) found, connecting - {panda_serials}")
# Flash pandas # Flash pandas
pandas: List[Panda] = [] pandas: list[Panda] = []
for serial in panda_serials: for serial in panda_serials:
pandas.append(flash_panda(serial)) pandas.append(flash_panda(serial))

View File

@ -2,7 +2,6 @@
from collections import namedtuple from collections import namedtuple
from dataclasses import dataclass from dataclasses import dataclass
from enum import ReprEnum from enum import ReprEnum
from typing import Dict, List, Optional, Union
import capnp import capnp
@ -27,9 +26,9 @@ def apply_hysteresis(val: float, val_steady: float, hyst_gap: float) -> float:
return val_steady return val_steady
def create_button_events(cur_btn: int, prev_btn: int, buttons_dict: Dict[int, capnp.lib.capnp._EnumModule], def create_button_events(cur_btn: int, prev_btn: int, buttons_dict: dict[int, capnp.lib.capnp._EnumModule],
unpressed_btn: int = 0) -> List[capnp.lib.capnp._DynamicStructBuilder]: unpressed_btn: int = 0) -> list[capnp.lib.capnp._DynamicStructBuilder]:
events: List[capnp.lib.capnp._DynamicStructBuilder] = [] events: list[capnp.lib.capnp._DynamicStructBuilder] = []
if cur_btn == prev_btn: if cur_btn == prev_btn:
return events return events
@ -76,7 +75,7 @@ def scale_tire_stiffness(mass, wheelbase, center_to_front, tire_stiffness_factor
return tire_stiffness_front, tire_stiffness_rear return tire_stiffness_front, tire_stiffness_rear
DbcDict = Dict[str, str] DbcDict = dict[str, str]
def dbc_dict(pt_dbc, radar_dbc, chassis_dbc=None, body_dbc=None) -> DbcDict: def dbc_dict(pt_dbc, radar_dbc, chassis_dbc=None, body_dbc=None) -> DbcDict:
@ -214,7 +213,7 @@ def get_safety_config(safety_model, safety_param = None):
class CanBusBase: class CanBusBase:
offset: int offset: int
def __init__(self, CP, fingerprint: Optional[Dict[int, Dict[int, int]]]) -> None: def __init__(self, CP, fingerprint: dict[int, dict[int, int]] | None) -> None:
if CP is None: if CP is None:
assert fingerprint is not None assert fingerprint is not None
num = max([k for k, v in fingerprint.items() if len(v)], default=0) // 4 + 1 num = max([k for k, v in fingerprint.items() if len(v)], default=0) // 4 + 1
@ -244,7 +243,7 @@ class CanSignalRateCalculator:
return self.rate return self.rate
CarInfos = Union[CarInfo, List[CarInfo]] CarInfos = CarInfo | list[CarInfo]
@dataclass @dataclass
@ -260,7 +259,7 @@ class PlatformConfig:
car_info: CarInfos car_info: CarInfos
dbc_dict: DbcDict dbc_dict: DbcDict
specs: Optional[CarSpecs] = None specs: CarSpecs | None = None
def __hash__(self) -> int: def __hash__(self) -> int:
return hash(self.platform_str) return hash(self.platform_str)
@ -276,9 +275,9 @@ class Platforms(str, ReprEnum):
return member return member
@classmethod @classmethod
def create_dbc_map(cls) -> Dict[str, DbcDict]: def create_dbc_map(cls) -> dict[str, DbcDict]:
return {p: p.config.dbc_dict for p in cls} return {p: p.config.dbc_dict for p in cls}
@classmethod @classmethod
def create_carinfo_map(cls) -> Dict[str, CarInfos]: def create_carinfo_map(cls) -> dict[str, CarInfos]:
return {p: p.config.car_info for p in cls} return {p: p.config.car_info for p in cls}

View File

@ -1,6 +1,6 @@
import os import os
import time import time
from typing import Callable, Dict, List, Optional, Tuple from collections.abc import Callable
from cereal import car from cereal import car
from openpilot.common.params import Params from openpilot.common.params import Params
@ -63,7 +63,7 @@ def load_interfaces(brand_names):
return ret return ret
def _get_interface_names() -> Dict[str, List[str]]: def _get_interface_names() -> dict[str, list[str]]:
# returns a dict of brand name and its respective models # returns a dict of brand name and its respective models
brand_names = {} brand_names = {}
for brand_name, brand_models in get_interface_attr("CAR").items(): for brand_name, brand_models in get_interface_attr("CAR").items():
@ -77,7 +77,7 @@ interface_names = _get_interface_names()
interfaces = load_interfaces(interface_names) interfaces = load_interfaces(interface_names)
def can_fingerprint(next_can: Callable) -> Tuple[Optional[str], Dict[int, dict]]: def can_fingerprint(next_can: Callable) -> tuple[str | None, dict[int, dict]]:
finger = gen_empty_fingerprint() finger = gen_empty_fingerprint()
candidate_cars = {i: all_legacy_fingerprint_cars() for i in [0, 1]} # attempt fingerprint on both bus 0 and 1 candidate_cars = {i: all_legacy_fingerprint_cars() for i in [0, 1]} # attempt fingerprint on both bus 0 and 1
frame = 0 frame = 0

View File

@ -1,6 +1,5 @@
from enum import IntFlag, StrEnum from enum import IntFlag, StrEnum
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Dict, List, Optional, Union
from cereal import car from cereal import car
from panda.python import uds from panda.python import uds
@ -66,7 +65,7 @@ class ChryslerCarInfo(CarInfo):
car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.fca])) car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.fca]))
CAR_INFO: Dict[str, Optional[Union[ChryslerCarInfo, List[ChryslerCarInfo]]]] = { CAR_INFO: dict[str, ChryslerCarInfo | list[ChryslerCarInfo] | None] = {
CAR.PACIFICA_2017_HYBRID: ChryslerCarInfo("Chrysler Pacifica Hybrid 2017"), CAR.PACIFICA_2017_HYBRID: ChryslerCarInfo("Chrysler Pacifica Hybrid 2017"),
CAR.PACIFICA_2018_HYBRID: ChryslerCarInfo("Chrysler Pacifica Hybrid 2018"), CAR.PACIFICA_2018_HYBRID: ChryslerCarInfo("Chrysler Pacifica Hybrid 2018"),
CAR.PACIFICA_2019_HYBRID: ChryslerCarInfo("Chrysler Pacifica Hybrid 2019-23"), CAR.PACIFICA_2019_HYBRID: ChryslerCarInfo("Chrysler Pacifica Hybrid 2019-23"),

View File

@ -5,7 +5,6 @@ import jinja2
import os import os
from enum import Enum from enum import Enum
from natsort import natsorted from natsort import natsorted
from typing import Dict, List
from cereal import car from cereal import car
from openpilot.common.basedir import BASEDIR from openpilot.common.basedir import BASEDIR
@ -14,7 +13,7 @@ from openpilot.selfdrive.car.docs_definitions import CarInfo, Column, CommonFoot
from openpilot.selfdrive.car.car_helpers import interfaces, get_interface_attr from openpilot.selfdrive.car.car_helpers import interfaces, get_interface_attr
def get_all_footnotes() -> Dict[Enum, int]: def get_all_footnotes() -> dict[Enum, int]:
all_footnotes = list(CommonFootnote) all_footnotes = list(CommonFootnote)
for footnotes in get_interface_attr("Footnote", ignore_none=True).values(): for footnotes in get_interface_attr("Footnote", ignore_none=True).values():
all_footnotes.extend(footnotes) all_footnotes.extend(footnotes)
@ -25,8 +24,8 @@ CARS_MD_OUT = os.path.join(BASEDIR, "docs", "CARS.md")
CARS_MD_TEMPLATE = os.path.join(BASEDIR, "selfdrive", "car", "CARS_template.md") CARS_MD_TEMPLATE = os.path.join(BASEDIR, "selfdrive", "car", "CARS_template.md")
def get_all_car_info() -> List[CarInfo]: def get_all_car_info() -> list[CarInfo]:
all_car_info: List[CarInfo] = [] all_car_info: list[CarInfo] = []
footnotes = get_all_footnotes() footnotes = get_all_footnotes()
for model, car_info in get_interface_attr("CAR_INFO", combine_brands=True).items(): for model, car_info in get_interface_attr("CAR_INFO", combine_brands=True).items():
# If available, uses experimental longitudinal limits for the docs # If available, uses experimental longitudinal limits for the docs
@ -47,19 +46,19 @@ def get_all_car_info() -> List[CarInfo]:
all_car_info.append(_car_info) all_car_info.append(_car_info)
# Sort cars by make and model + year # Sort cars by make and model + year
sorted_cars: List[CarInfo] = natsorted(all_car_info, key=lambda car: car.name.lower()) sorted_cars: list[CarInfo] = natsorted(all_car_info, key=lambda car: car.name.lower())
return sorted_cars return sorted_cars
def group_by_make(all_car_info: List[CarInfo]) -> Dict[str, List[CarInfo]]: def group_by_make(all_car_info: list[CarInfo]) -> dict[str, list[CarInfo]]:
sorted_car_info = defaultdict(list) sorted_car_info = defaultdict(list)
for car_info in all_car_info: for car_info in all_car_info:
sorted_car_info[car_info.make].append(car_info) sorted_car_info[car_info.make].append(car_info)
return dict(sorted_car_info) return dict(sorted_car_info)
def generate_cars_md(all_car_info: List[CarInfo], template_fn: str) -> str: def generate_cars_md(all_car_info: list[CarInfo], template_fn: str) -> str:
with open(template_fn, "r") as f: with open(template_fn) as f:
template = jinja2.Template(f.read(), trim_blocks=True, lstrip_blocks=True) template = jinja2.Template(f.read(), trim_blocks=True, lstrip_blocks=True)
footnotes = [fn.value.text for fn in get_all_footnotes()] footnotes = [fn.value.text for fn in get_all_footnotes()]

View File

@ -3,7 +3,6 @@ from collections import namedtuple
import copy import copy
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum from enum import Enum
from typing import Dict, List, Optional, Tuple, Union
from cereal import car from cereal import car
from openpilot.common.conversions import Conversions as CV from openpilot.common.conversions import Conversions as CV
@ -35,7 +34,7 @@ class Star(Enum):
@dataclass @dataclass
class BasePart: class BasePart:
name: str name: str
parts: List[Enum] = field(default_factory=list) parts: list[Enum] = field(default_factory=list)
def all_parts(self): def all_parts(self):
# Recursively get all parts # Recursively get all parts
@ -76,7 +75,7 @@ class Accessory(EnumBase):
@dataclass @dataclass
class BaseCarHarness(BasePart): class BaseCarHarness(BasePart):
parts: List[Enum] = field(default_factory=lambda: [Accessory.harness_box, Accessory.comma_power_v2, Cable.rj45_cable_7ft]) parts: list[Enum] = field(default_factory=lambda: [Accessory.harness_box, Accessory.comma_power_v2, Cable.rj45_cable_7ft])
has_connector: bool = True # without are hidden on the harness connector page has_connector: bool = True # without are hidden on the harness connector page
@ -149,18 +148,18 @@ class PartType(Enum):
tool = Tool tool = Tool
DEFAULT_CAR_PARTS: List[EnumBase] = [Device.threex] DEFAULT_CAR_PARTS: list[EnumBase] = [Device.threex]
@dataclass @dataclass
class CarParts: class CarParts:
parts: List[EnumBase] = field(default_factory=list) parts: list[EnumBase] = field(default_factory=list)
def __call__(self): def __call__(self):
return copy.deepcopy(self) return copy.deepcopy(self)
@classmethod @classmethod
def common(cls, add: Optional[List[EnumBase]] = None, remove: Optional[List[EnumBase]] = None): def common(cls, add: list[EnumBase] | None = None, remove: list[EnumBase] | None = None):
p = [part for part in (add or []) + DEFAULT_CAR_PARTS if part not in (remove or [])] p = [part for part in (add or []) + DEFAULT_CAR_PARTS if part not in (remove or [])]
return cls(p) return cls(p)
@ -186,7 +185,7 @@ class CommonFootnote(Enum):
Column.LONGITUDINAL) Column.LONGITUDINAL)
def get_footnotes(footnotes: List[Enum], column: Column) -> List[Enum]: def get_footnotes(footnotes: list[Enum], column: Column) -> list[Enum]:
# Returns applicable footnotes given current column # Returns applicable footnotes given current column
return [fn for fn in footnotes if fn.value.column == column] return [fn for fn in footnotes if fn.value.column == column]
@ -209,7 +208,7 @@ def get_year_list(years):
return years_list return years_list
def split_name(name: str) -> Tuple[str, str, str]: def split_name(name: str) -> tuple[str, str, str]:
make, model = name.split(" ", 1) make, model = name.split(" ", 1)
years = "" years = ""
match = re.search(MODEL_YEARS_RE, model) match = re.search(MODEL_YEARS_RE, model)
@ -233,13 +232,13 @@ class CarInfo:
# the minimum compatibility requirements for this model, regardless # the minimum compatibility requirements for this model, regardless
# of market. can be a package, trim, or list of features # of market. can be a package, trim, or list of features
requirements: Optional[str] = None requirements: str | None = None
video_link: Optional[str] = None video_link: str | None = None
footnotes: List[Enum] = field(default_factory=list) footnotes: list[Enum] = field(default_factory=list)
min_steer_speed: Optional[float] = None min_steer_speed: float | None = None
min_enable_speed: Optional[float] = None min_enable_speed: float | None = None
auto_resume: Optional[bool] = None auto_resume: bool | None = None
# all the parts needed for the supported car # all the parts needed for the supported car
car_parts: CarParts = field(default_factory=CarParts) car_parts: CarParts = field(default_factory=CarParts)
@ -248,7 +247,7 @@ class CarInfo:
self.make, self.model, self.years = split_name(self.name) self.make, self.model, self.years = split_name(self.name)
self.year_list = get_year_list(self.years) self.year_list = get_year_list(self.years)
def init(self, CP: car.CarParams, all_footnotes: Dict[Enum, int]): def init(self, CP: car.CarParams, all_footnotes: dict[Enum, int]):
self.car_name = CP.carName self.car_name = CP.carName
self.car_fingerprint = CP.carFingerprint self.car_fingerprint = CP.carFingerprint
@ -293,7 +292,7 @@ class CarInfo:
if len(tools_docs): if len(tools_docs):
hardware_col += f'<details><summary>Tools</summary><sub>{display_func(tools_docs)}</sub></details>' hardware_col += f'<details><summary>Tools</summary><sub>{display_func(tools_docs)}</sub></details>'
self.row: Dict[Enum, Union[str, Star]] = { self.row: dict[Enum, str | Star] = {
Column.MAKE: self.make, Column.MAKE: self.make,
Column.MODEL: self.model, Column.MODEL: self.model,
Column.PACKAGE: self.package, Column.PACKAGE: self.package,
@ -352,7 +351,7 @@ class CarInfo:
raise Exception(f"This notCar does not have a detail sentence: {CP.carFingerprint}") raise Exception(f"This notCar does not have a detail sentence: {CP.carFingerprint}")
def get_column(self, column: Column, star_icon: str, video_icon: str, footnote_tag: str) -> str: def get_column(self, column: Column, star_icon: str, video_icon: str, footnote_tag: str) -> str:
item: Union[str, Star] = self.row[column] item: str | Star = self.row[column]
if isinstance(item, Star): if isinstance(item, Star):
item = star_icon.format(item.value) item = star_icon.format(item.value)
elif column == Column.MODEL and len(self.years): elif column == Column.MODEL and len(self.years):

View File

@ -1,7 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import capnp import capnp
import time import time
from typing import Optional, Set
import cereal.messaging as messaging import cereal.messaging as messaging
from panda.python.uds import SERVICE_TYPE from panda.python.uds import SERVICE_TYPE
@ -20,7 +19,7 @@ def make_tester_present_msg(addr, bus, subaddr=None):
return make_can_msg(addr, bytes(dat), bus) return make_can_msg(addr, bytes(dat), bus)
def is_tester_present_response(msg: capnp.lib.capnp._DynamicStructReader, subaddr: Optional[int] = None) -> bool: def is_tester_present_response(msg: capnp.lib.capnp._DynamicStructReader, subaddr: int | None = None) -> bool:
# ISO-TP messages are always padded to 8 bytes # ISO-TP messages are always padded to 8 bytes
# tester present response is always a single frame # tester present response is always a single frame
dat_offset = 1 if subaddr is not None else 0 dat_offset = 1 if subaddr is not None else 0
@ -34,16 +33,16 @@ def is_tester_present_response(msg: capnp.lib.capnp._DynamicStructReader, subadd
return False return False
def get_all_ecu_addrs(logcan: messaging.SubSocket, sendcan: messaging.PubSocket, bus: int, timeout: float = 1, debug: bool = True) -> Set[EcuAddrBusType]: def get_all_ecu_addrs(logcan: messaging.SubSocket, sendcan: messaging.PubSocket, bus: int, timeout: float = 1, debug: bool = True) -> set[EcuAddrBusType]:
addr_list = [0x700 + i for i in range(256)] + [0x18da00f1 + (i << 8) for i in range(256)] addr_list = [0x700 + i for i in range(256)] + [0x18da00f1 + (i << 8) for i in range(256)]
queries: Set[EcuAddrBusType] = {(addr, None, bus) for addr in addr_list} queries: set[EcuAddrBusType] = {(addr, None, bus) for addr in addr_list}
responses = queries responses = queries
return get_ecu_addrs(logcan, sendcan, queries, responses, timeout=timeout, debug=debug) return get_ecu_addrs(logcan, sendcan, queries, responses, timeout=timeout, debug=debug)
def get_ecu_addrs(logcan: messaging.SubSocket, sendcan: messaging.PubSocket, queries: Set[EcuAddrBusType], def get_ecu_addrs(logcan: messaging.SubSocket, sendcan: messaging.PubSocket, queries: set[EcuAddrBusType],
responses: Set[EcuAddrBusType], timeout: float = 1, debug: bool = False) -> Set[EcuAddrBusType]: responses: set[EcuAddrBusType], timeout: float = 1, debug: bool = False) -> set[EcuAddrBusType]:
ecu_responses: Set[EcuAddrBusType] = set() # set((addr, subaddr, bus),) ecu_responses: set[EcuAddrBusType] = set() # set((addr, subaddr, bus),)
try: try:
msgs = [make_tester_present_msg(addr, bus, subaddr) for addr, subaddr, bus in queries] msgs = [make_tester_present_msg(addr, bus, subaddr) for addr, subaddr, bus in queries]

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import unittest import unittest
from parameterized import parameterized from parameterized import parameterized
from typing import Dict, Iterable, Optional, Tuple from collections.abc import Iterable
import capnp import capnp
@ -50,7 +50,7 @@ class TestFordFW(unittest.TestCase):
self.assertIsNone(subaddr, "Unexpected ECU subaddress") self.assertIsNone(subaddr, "Unexpected ECU subaddress")
@parameterized.expand(FW_VERSIONS.items()) @parameterized.expand(FW_VERSIONS.items())
def test_fw_versions(self, car_model: str, fw_versions: Dict[Tuple[capnp.lib.capnp._EnumModule, int, Optional[int]], Iterable[bytes]]): def test_fw_versions(self, car_model: str, fw_versions: dict[tuple[capnp.lib.capnp._EnumModule, int, int | None], Iterable[bytes]]):
for (ecu, addr, subaddr), fws in fw_versions.items(): for (ecu, addr, subaddr), fws in fw_versions.items():
self.assertIn(ecu, ECU_FW_CORE, "Unexpected ECU") self.assertIn(ecu, ECU_FW_CORE, "Unexpected ECU")
self.assertEqual(addr, ECU_ADDRESSES[ecu], "ECU address mismatch") self.assertEqual(addr, ECU_ADDRESSES[ecu], "ECU address mismatch")

View File

@ -1,7 +1,6 @@
from collections import defaultdict from collections import defaultdict
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum, StrEnum from enum import Enum, StrEnum
from typing import Dict, List, Union
from cereal import car from cereal import car
from openpilot.selfdrive.car import AngleRateLimit, dbc_dict from openpilot.selfdrive.car import AngleRateLimit, dbc_dict
@ -59,7 +58,7 @@ class RADAR:
DELPHI_MRR = 'FORD_CADS' DELPHI_MRR = 'FORD_CADS'
DBC: Dict[str, Dict[str, str]] = defaultdict(lambda: dbc_dict("ford_lincoln_base_pt", RADAR.DELPHI_MRR)) DBC: dict[str, dict[str, str]] = defaultdict(lambda: dbc_dict("ford_lincoln_base_pt", RADAR.DELPHI_MRR))
# F-150 radar is not yet supported # F-150 radar is not yet supported
DBC[CAR.F_150_MK14] = dbc_dict("ford_lincoln_base_pt", None) DBC[CAR.F_150_MK14] = dbc_dict("ford_lincoln_base_pt", None)
@ -87,7 +86,7 @@ class FordCarInfo(CarInfo):
self.car_parts = CarParts([Device.threex, harness]) self.car_parts = CarParts([Device.threex, harness])
CAR_INFO: Dict[str, Union[CarInfo, List[CarInfo]]] = { CAR_INFO: dict[str, CarInfo | list[CarInfo]] = {
CAR.BRONCO_SPORT_MK1: FordCarInfo("Ford Bronco Sport 2021-22"), CAR.BRONCO_SPORT_MK1: FordCarInfo("Ford Bronco Sport 2021-22"),
CAR.ESCAPE_MK4: [ CAR.ESCAPE_MK4: [
FordCarInfo("Ford Escape 2020-22"), FordCarInfo("Ford Escape 2020-22"),

View File

@ -3,16 +3,16 @@ import capnp
import copy import copy
from dataclasses import dataclass, field from dataclasses import dataclass, field
import struct import struct
from typing import Callable, Dict, List, Optional, Set, Tuple from collections.abc import Callable
import panda.python.uds as uds import panda.python.uds as uds
AddrType = Tuple[int, Optional[int]] AddrType = tuple[int, int | None]
EcuAddrBusType = Tuple[int, Optional[int], int] EcuAddrBusType = tuple[int, int | None, int]
EcuAddrSubAddr = Tuple[int, int, Optional[int]] EcuAddrSubAddr = tuple[int, int, int | None]
LiveFwVersions = Dict[AddrType, Set[bytes]] LiveFwVersions = dict[AddrType, set[bytes]]
OfflineFwVersions = Dict[str, Dict[EcuAddrSubAddr, List[bytes]]] OfflineFwVersions = dict[str, dict[EcuAddrSubAddr, list[bytes]]]
# A global list of addresses we will only ever consider for VIN responses # A global list of addresses we will only ever consider for VIN responses
# engine, hybrid controller, Ford abs, Hyundai CAN FD cluster, 29-bit engine, PGM-FI # engine, hybrid controller, Ford abs, Hyundai CAN FD cluster, 29-bit engine, PGM-FI
@ -71,9 +71,9 @@ class StdQueries:
@dataclass @dataclass
class Request: class Request:
request: List[bytes] request: list[bytes]
response: List[bytes] response: list[bytes]
whitelist_ecus: List[int] = field(default_factory=list) whitelist_ecus: list[int] = field(default_factory=list)
rx_offset: int = 0x8 rx_offset: int = 0x8
bus: int = 1 bus: int = 1
# Whether this query should be run on the first auxiliary panda (CAN FD cars for example) # Whether this query should be run on the first auxiliary panda (CAN FD cars for example)
@ -86,15 +86,15 @@ class Request:
@dataclass @dataclass
class FwQueryConfig: class FwQueryConfig:
requests: List[Request] requests: list[Request]
# TODO: make this automatic and remove hardcoded lists, or do fingerprinting with ecus # TODO: make this automatic and remove hardcoded lists, or do fingerprinting with ecus
# Overrides and removes from essential ecus for specific models and ecus (exact matching) # Overrides and removes from essential ecus for specific models and ecus (exact matching)
non_essential_ecus: Dict[capnp.lib.capnp._EnumModule, List[str]] = field(default_factory=dict) non_essential_ecus: dict[capnp.lib.capnp._EnumModule, list[str]] = field(default_factory=dict)
# Ecus added for data collection, not to be fingerprinted on # Ecus added for data collection, not to be fingerprinted on
extra_ecus: List[Tuple[capnp.lib.capnp._EnumModule, int, Optional[int]]] = field(default_factory=list) extra_ecus: list[tuple[capnp.lib.capnp._EnumModule, int, int | None]] = field(default_factory=list)
# Function a brand can implement to provide better fuzzy matching. Takes in FW versions, # Function a brand can implement to provide better fuzzy matching. Takes in FW versions,
# returns set of candidates. Only will match if one candidate is returned # returns set of candidates. Only will match if one candidate is returned
match_fw_to_car_fuzzy: Optional[Callable[[LiveFwVersions, OfflineFwVersions], Set[str]]] = None match_fw_to_car_fuzzy: Callable[[LiveFwVersions, OfflineFwVersions], set[str]] | None = None
def __post_init__(self): def __post_init__(self):
for i in range(len(self.requests)): for i in range(len(self.requests)):

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from collections import defaultdict from collections import defaultdict
from typing import Any, DefaultDict, Dict, Iterator, List, Optional, Set, TypeVar from typing import Any, TypeVar
from collections.abc import Iterator
from tqdm import tqdm from tqdm import tqdm
import capnp import capnp
@ -27,19 +28,19 @@ REQUESTS = [(brand, config, r) for brand, config in FW_QUERY_CONFIGS.items() for
T = TypeVar('T') T = TypeVar('T')
def chunks(l: List[T], n: int = 128) -> Iterator[List[T]]: def chunks(l: list[T], n: int = 128) -> Iterator[list[T]]:
for i in range(0, len(l), n): for i in range(0, len(l), n):
yield l[i:i + n] yield l[i:i + n]
def is_brand(brand: str, filter_brand: Optional[str]) -> bool: def is_brand(brand: str, filter_brand: str | None) -> bool:
"""Returns if brand matches filter_brand or no brand filter is specified""" """Returns if brand matches filter_brand or no brand filter is specified"""
return filter_brand is None or brand == filter_brand return filter_brand is None or brand == filter_brand
def build_fw_dict(fw_versions: List[capnp.lib.capnp._DynamicStructBuilder], def build_fw_dict(fw_versions: list[capnp.lib.capnp._DynamicStructBuilder],
filter_brand: Optional[str] = None) -> Dict[AddrType, Set[bytes]]: filter_brand: str | None = None) -> dict[AddrType, set[bytes]]:
fw_versions_dict: DefaultDict[AddrType, Set[bytes]] = defaultdict(set) fw_versions_dict: defaultdict[AddrType, set[bytes]] = defaultdict(set)
for fw in fw_versions: for fw in fw_versions:
if is_brand(fw.brand, filter_brand) and not fw.logging: if is_brand(fw.brand, filter_brand) and not fw.logging:
sub_addr = fw.subAddress if fw.subAddress != 0 else None sub_addr = fw.subAddress if fw.subAddress != 0 else None
@ -97,7 +98,7 @@ def match_fw_to_car_fuzzy(live_fw_versions, match_brand=None, log=True, exclude=
return set() return set()
def match_fw_to_car_exact(live_fw_versions, match_brand=None, log=True, extra_fw_versions=None) -> Set[str]: def match_fw_to_car_exact(live_fw_versions, match_brand=None, log=True, extra_fw_versions=None) -> set[str]:
"""Do an exact FW match. Returns all cars that match the given """Do an exact FW match. Returns all cars that match the given
FW versions for a list of "essential" ECUs. If an ECU is not considered FW versions for a list of "essential" ECUs. If an ECU is not considered
essential the FW version can be missing to get a fingerprint, but if it's present it essential the FW version can be missing to get a fingerprint, but if it's present it
@ -164,11 +165,11 @@ def match_fw_to_car(fw_versions, allow_exact=True, allow_fuzzy=True, log=True):
return True, set() return True, set()
def get_present_ecus(logcan, sendcan, num_pandas=1) -> Set[EcuAddrBusType]: def get_present_ecus(logcan, sendcan, num_pandas=1) -> set[EcuAddrBusType]:
params = Params() params = Params()
# queries are split by OBD multiplexing mode # queries are split by OBD multiplexing mode
queries: Dict[bool, List[List[EcuAddrBusType]]] = {True: [], False: []} queries: dict[bool, list[list[EcuAddrBusType]]] = {True: [], False: []}
parallel_queries: Dict[bool, List[EcuAddrBusType]] = {True: [], False: []} parallel_queries: dict[bool, list[EcuAddrBusType]] = {True: [], False: []}
responses = set() responses = set()
for brand, config, r in REQUESTS: for brand, config, r in REQUESTS:
@ -203,7 +204,7 @@ def get_present_ecus(logcan, sendcan, num_pandas=1) -> Set[EcuAddrBusType]:
return ecu_responses return ecu_responses
def get_brand_ecu_matches(ecu_rx_addrs: Set[EcuAddrBusType]) -> dict[str, set[AddrType]]: def get_brand_ecu_matches(ecu_rx_addrs: set[EcuAddrBusType]) -> dict[str, set[AddrType]]:
"""Returns dictionary of brands and matches with ECUs in their FW versions""" """Returns dictionary of brands and matches with ECUs in their FW versions"""
brand_addrs = {brand: {(addr, subaddr) for _, addr, subaddr in config.get_all_ecus(VERSIONS[brand])} for brand_addrs = {brand: {(addr, subaddr) for _, addr, subaddr in config.get_all_ecus(VERSIONS[brand])} for
@ -231,7 +232,7 @@ def set_obd_multiplexing(params: Params, obd_multiplexing: bool):
def get_fw_versions_ordered(logcan, sendcan, ecu_rx_addrs, timeout=0.1, num_pandas=1, debug=False, progress=False) -> \ def get_fw_versions_ordered(logcan, sendcan, ecu_rx_addrs, timeout=0.1, num_pandas=1, debug=False, progress=False) -> \
List[capnp.lib.capnp._DynamicStructBuilder]: list[capnp.lib.capnp._DynamicStructBuilder]:
"""Queries for FW versions ordering brands by likelihood, breaks when exact match is found""" """Queries for FW versions ordering brands by likelihood, breaks when exact match is found"""
all_car_fw = [] all_car_fw = []
@ -254,7 +255,7 @@ def get_fw_versions_ordered(logcan, sendcan, ecu_rx_addrs, timeout=0.1, num_pand
def get_fw_versions(logcan, sendcan, query_brand=None, extra=None, timeout=0.1, num_pandas=1, debug=False, progress=False) -> \ def get_fw_versions(logcan, sendcan, query_brand=None, extra=None, timeout=0.1, num_pandas=1, debug=False, progress=False) -> \
List[capnp.lib.capnp._DynamicStructBuilder]: list[capnp.lib.capnp._DynamicStructBuilder]:
versions = VERSIONS.copy() versions = VERSIONS.copy()
params = Params() params = Params()

View File

@ -1,7 +1,6 @@
from collections import defaultdict from collections import defaultdict
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum, StrEnum from enum import Enum, StrEnum
from typing import Dict, List, Union
from cereal import car from cereal import car
from openpilot.selfdrive.car import dbc_dict from openpilot.selfdrive.car import dbc_dict
@ -98,7 +97,7 @@ class GMCarInfo(CarInfo):
self.footnotes.append(Footnote.OBD_II) self.footnotes.append(Footnote.OBD_II)
CAR_INFO: Dict[str, Union[GMCarInfo, List[GMCarInfo]]] = { CAR_INFO: dict[str, GMCarInfo | list[GMCarInfo]] = {
CAR.HOLDEN_ASTRA: GMCarInfo("Holden Astra 2017"), CAR.HOLDEN_ASTRA: GMCarInfo("Holden Astra 2017"),
CAR.VOLT: GMCarInfo("Chevrolet Volt 2017-18", min_enable_speed=0, video_link="https://youtu.be/QeMCN_4TFfQ"), CAR.VOLT: GMCarInfo("Chevrolet Volt 2017-18", min_enable_speed=0, video_link="https://youtu.be/QeMCN_4TFfQ"),
CAR.CADILLAC_ATS: GMCarInfo("Cadillac ATS Premium Performance 2018"), CAR.CADILLAC_ATS: GMCarInfo("Cadillac ATS Premium Performance 2018"),
@ -181,7 +180,7 @@ FW_QUERY_CONFIG = FwQueryConfig(
extra_ecus=[(Ecu.fwdCamera, 0x24b, None)], extra_ecus=[(Ecu.fwdCamera, 0x24b, None)],
) )
DBC: Dict[str, Dict[str, str]] = defaultdict(lambda: dbc_dict('gm_global_a_powertrain_generated', 'gm_global_a_object', chassis_dbc='gm_global_a_chassis')) DBC: dict[str, dict[str, str]] = defaultdict(lambda: dbc_dict('gm_global_a_powertrain_generated', 'gm_global_a_object', chassis_dbc='gm_global_a_chassis'))
EV_CAR = {CAR.VOLT, CAR.BOLT_EUV} EV_CAR = {CAR.VOLT, CAR.BOLT_EUV}

View File

@ -1,6 +1,5 @@
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum, IntFlag, StrEnum from enum import Enum, IntFlag, StrEnum
from typing import Dict, List, Optional, Union
from cereal import car from cereal import car
from openpilot.common.conversions import Conversions as CV from openpilot.common.conversions import Conversions as CV
@ -116,7 +115,7 @@ class HondaCarInfo(CarInfo):
self.car_parts = CarParts.common([CarHarness.nidec]) self.car_parts = CarParts.common([CarHarness.nidec])
CAR_INFO: Dict[str, Optional[Union[HondaCarInfo, List[HondaCarInfo]]]] = { CAR_INFO: dict[str, HondaCarInfo | list[HondaCarInfo] | None] = {
CAR.ACCORD: [ CAR.ACCORD: [
HondaCarInfo("Honda Accord 2018-22", "All", video_link="https://www.youtube.com/watch?v=mrUwlj3Mi58", min_steer_speed=3. * CV.MPH_TO_MS), HondaCarInfo("Honda Accord 2018-22", "All", video_link="https://www.youtube.com/watch?v=mrUwlj3Mi58", min_steer_speed=3. * CV.MPH_TO_MS),
HondaCarInfo("Honda Inspire 2018", "All", min_steer_speed=3. * CV.MPH_TO_MS), HondaCarInfo("Honda Inspire 2018", "All", min_steer_speed=3. * CV.MPH_TO_MS),

View File

@ -1,7 +1,6 @@
import re import re
from dataclasses import dataclass from dataclasses import dataclass
from enum import Enum, IntFlag, StrEnum from enum import Enum, IntFlag, StrEnum
from typing import Dict, List, Optional, Set, Tuple, Union
from cereal import car from cereal import car
from panda.python import uds from panda.python import uds
@ -157,7 +156,7 @@ class HyundaiCarInfo(CarInfo):
self.footnotes.insert(0, Footnote.CANFD) self.footnotes.insert(0, Footnote.CANFD)
CAR_INFO: Dict[str, Optional[Union[HyundaiCarInfo, List[HyundaiCarInfo]]]] = { CAR_INFO: dict[str, HyundaiCarInfo | list[HyundaiCarInfo] | None] = {
CAR.AZERA_6TH_GEN: HyundaiCarInfo("Hyundai Azera 2022", "All", car_parts=CarParts.common([CarHarness.hyundai_k])), CAR.AZERA_6TH_GEN: HyundaiCarInfo("Hyundai Azera 2022", "All", car_parts=CarParts.common([CarHarness.hyundai_k])),
CAR.AZERA_HEV_6TH_GEN: [ CAR.AZERA_HEV_6TH_GEN: [
HyundaiCarInfo("Hyundai Azera Hybrid 2019", "All", car_parts=CarParts.common([CarHarness.hyundai_c])), HyundaiCarInfo("Hyundai Azera Hybrid 2019", "All", car_parts=CarParts.common([CarHarness.hyundai_c])),
@ -316,7 +315,7 @@ class Buttons:
CANCEL = 4 # on newer models, this is a pause/resume button CANCEL = 4 # on newer models, this is a pause/resume button
def get_platform_codes(fw_versions: List[bytes]) -> Set[Tuple[bytes, Optional[bytes]]]: def get_platform_codes(fw_versions: list[bytes]) -> set[tuple[bytes, bytes | None]]:
# Returns unique, platform-specific identification codes for a set of versions # Returns unique, platform-specific identification codes for a set of versions
codes = set() # (code-Optional[part], date) codes = set() # (code-Optional[part], date)
for fw in fw_versions: for fw in fw_versions:
@ -335,12 +334,12 @@ def get_platform_codes(fw_versions: List[bytes]) -> Set[Tuple[bytes, Optional[by
return codes return codes
def match_fw_to_car_fuzzy(live_fw_versions, offline_fw_versions) -> Set[str]: def match_fw_to_car_fuzzy(live_fw_versions, offline_fw_versions) -> set[str]:
# Non-electric CAN FD platforms often do not have platform code specifiers needed # Non-electric CAN FD platforms often do not have platform code specifiers needed
# to distinguish between hybrid and ICE. All EVs so far are either exclusively # to distinguish between hybrid and ICE. All EVs so far are either exclusively
# electric or specify electric in the platform code. # electric or specify electric in the platform code.
fuzzy_platform_blacklist = {str(c) for c in (CANFD_CAR - EV_CAR - CANFD_FUZZY_WHITELIST)} fuzzy_platform_blacklist = {str(c) for c in (CANFD_CAR - EV_CAR - CANFD_FUZZY_WHITELIST)}
candidates: Set[str] = set() candidates: set[str] = set()
for candidate, fws in offline_fw_versions.items(): for candidate, fws in offline_fw_versions.items():
# Keep track of ECUs which pass all checks (platform codes, within date range) # Keep track of ECUs which pass all checks (platform codes, within date range)

View File

@ -4,7 +4,8 @@ import numpy as np
import tomllib import tomllib
from abc import abstractmethod, ABC from abc import abstractmethod, ABC
from enum import StrEnum from enum import StrEnum
from typing import Any, Dict, Optional, Tuple, List, Callable, NamedTuple, cast from typing import Any, NamedTuple, cast
from collections.abc import Callable
from cereal import car from cereal import car
from openpilot.common.basedir import BASEDIR from openpilot.common.basedir import BASEDIR
@ -107,7 +108,7 @@ class CarInterfaceBase(ABC):
return cls.get_params(candidate, gen_empty_fingerprint(), list(), False, False) return cls.get_params(candidate, gen_empty_fingerprint(), list(), False, False)
@classmethod @classmethod
def get_params(cls, candidate: str, fingerprint: Dict[int, Dict[int, int]], car_fw: List[car.CarParams.CarFw], experimental_long: bool, docs: bool): def get_params(cls, candidate: str, fingerprint: dict[int, dict[int, int]], car_fw: list[car.CarParams.CarFw], experimental_long: bool, docs: bool):
ret = CarInterfaceBase.get_std_params(candidate) ret = CarInterfaceBase.get_std_params(candidate)
if hasattr(candidate, "config"): if hasattr(candidate, "config"):
@ -131,8 +132,8 @@ class CarInterfaceBase(ABC):
@staticmethod @staticmethod
@abstractmethod @abstractmethod
def _get_params(ret: car.CarParams, candidate: str, fingerprint: Dict[int, Dict[int, int]], def _get_params(ret: car.CarParams, candidate: str, fingerprint: dict[int, dict[int, int]],
car_fw: List[car.CarParams.CarFw], experimental_long: bool, docs: bool): car_fw: list[car.CarParams.CarFw], experimental_long: bool, docs: bool):
raise NotImplementedError raise NotImplementedError
@staticmethod @staticmethod
@ -212,7 +213,7 @@ class CarInterfaceBase(ABC):
def _update(self, c: car.CarControl) -> car.CarState: def _update(self, c: car.CarControl) -> car.CarState:
pass pass
def update(self, c: car.CarControl, can_strings: List[bytes]) -> car.CarState: def update(self, c: car.CarControl, can_strings: list[bytes]) -> car.CarState:
# parse can # parse can
for cp in self.can_parsers: for cp in self.can_parsers:
if cp is not None: if cp is not None:
@ -246,7 +247,7 @@ class CarInterfaceBase(ABC):
return reader return reader
@abstractmethod @abstractmethod
def apply(self, c: car.CarControl, now_nanos: int) -> Tuple[car.CarControl.Actuators, List[bytes]]: def apply(self, c: car.CarControl, now_nanos: int) -> tuple[car.CarControl.Actuators, list[bytes]]:
pass pass
def create_common_events(self, cs_out, extra_gears=None, pcm_enable=True, allow_enable=True, def create_common_events(self, cs_out, extra_gears=None, pcm_enable=True, allow_enable=True,
@ -417,11 +418,11 @@ class CarStateBase(ABC):
return bool(left_blinker_stalk or self.left_blinker_cnt > 0), bool(right_blinker_stalk or self.right_blinker_cnt > 0) return bool(left_blinker_stalk or self.left_blinker_cnt > 0), bool(right_blinker_stalk or self.right_blinker_cnt > 0)
@staticmethod @staticmethod
def parse_gear_shifter(gear: Optional[str]) -> car.CarState.GearShifter: def parse_gear_shifter(gear: str | None) -> car.CarState.GearShifter:
if gear is None: if gear is None:
return GearShifter.unknown return GearShifter.unknown
d: Dict[str, car.CarState.GearShifter] = { d: dict[str, car.CarState.GearShifter] = {
'P': GearShifter.park, 'PARK': GearShifter.park, 'P': GearShifter.park, 'PARK': GearShifter.park,
'R': GearShifter.reverse, 'REVERSE': GearShifter.reverse, 'R': GearShifter.reverse, 'REVERSE': GearShifter.reverse,
'N': GearShifter.neutral, 'NEUTRAL': GearShifter.neutral, 'N': GearShifter.neutral, 'NEUTRAL': GearShifter.neutral,
@ -458,7 +459,7 @@ INTERFACE_ATTR_FILE = {
# interface-specific helpers # interface-specific helpers
def get_interface_attr(attr: str, combine_brands: bool = False, ignore_none: bool = False) -> Dict[str | StrEnum, Any]: def get_interface_attr(attr: str, combine_brands: bool = False, ignore_none: bool = False) -> dict[str | StrEnum, Any]:
# read all the folders in selfdrive/car and return a dict where: # read all the folders in selfdrive/car and return a dict where:
# - keys are all the car models or brand names # - keys are all the car models or brand names
# - values are attr values from all car folders # - values are attr values from all car folders
@ -491,7 +492,7 @@ class NanoFFModel:
self.load_weights(platform) self.load_weights(platform)
def load_weights(self, platform: str): def load_weights(self, platform: str):
with open(self.weights_loc, 'r') as fob: with open(self.weights_loc) as fob:
self.weights = {k: np.array(v) for k, v in json.load(fob)[platform].items()} self.weights = {k: np.array(v) for k, v in json.load(fob)[platform].items()}
def relu(self, x: np.ndarray): def relu(self, x: np.ndarray):
@ -506,7 +507,7 @@ class NanoFFModel:
x = np.dot(x, self.weights['w_4']) + self.weights['b_4'] x = np.dot(x, self.weights['w_4']) + self.weights['b_4']
return x return x
def predict(self, x: List[float], do_sample: bool = False): def predict(self, x: list[float], do_sample: bool = False):
x = self.forward(np.array(x)) x = self.forward(np.array(x))
if do_sample: if do_sample:
pred = np.random.laplace(x[0], np.exp(x[1]) / self.weights['temperature']) pred = np.random.laplace(x[0], np.exp(x[1]) / self.weights['temperature'])

View File

@ -1,6 +1,5 @@
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import StrEnum from enum import StrEnum
from typing import Dict, List, Union
from cereal import car from cereal import car
from openpilot.selfdrive.car import dbc_dict from openpilot.selfdrive.car import dbc_dict
@ -41,7 +40,7 @@ class MazdaCarInfo(CarInfo):
car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.mazda])) car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.mazda]))
CAR_INFO: Dict[str, Union[MazdaCarInfo, List[MazdaCarInfo]]] = { CAR_INFO: dict[str, MazdaCarInfo | list[MazdaCarInfo]] = {
CAR.CX5: MazdaCarInfo("Mazda CX-5 2017-21"), CAR.CX5: MazdaCarInfo("Mazda CX-5 2017-21"),
CAR.CX9: MazdaCarInfo("Mazda CX-9 2016-20"), CAR.CX9: MazdaCarInfo("Mazda CX-9 2016-20"),
CAR.MAZDA3: MazdaCarInfo("Mazda 3 2017-18"), CAR.MAZDA3: MazdaCarInfo("Mazda 3 2017-18"),

View File

@ -1,5 +1,4 @@
from enum import StrEnum from enum import StrEnum
from typing import Dict, List, Optional, Union
from openpilot.selfdrive.car.docs_definitions import CarInfo from openpilot.selfdrive.car.docs_definitions import CarInfo
@ -8,6 +7,6 @@ class CAR(StrEnum):
MOCK = 'mock' MOCK = 'mock'
CAR_INFO: Dict[str, Optional[Union[CarInfo, List[CarInfo]]]] = { CAR_INFO: dict[str, CarInfo | list[CarInfo] | None] = {
CAR.MOCK: None, CAR.MOCK: None,
} }

View File

@ -1,6 +1,5 @@
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import StrEnum from enum import StrEnum
from typing import Dict, List, Optional, Union
from cereal import car from cereal import car
from panda.python import uds from panda.python import uds
@ -37,7 +36,7 @@ class NissanCarInfo(CarInfo):
car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.nissan_a])) car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.nissan_a]))
CAR_INFO: Dict[str, Optional[Union[NissanCarInfo, List[NissanCarInfo]]]] = { CAR_INFO: dict[str, NissanCarInfo | list[NissanCarInfo] | None] = {
CAR.XTRAIL: NissanCarInfo("Nissan X-Trail 2017"), CAR.XTRAIL: NissanCarInfo("Nissan X-Trail 2017"),
CAR.LEAF: NissanCarInfo("Nissan Leaf 2018-23", video_link="https://youtu.be/vaMbtAh_0cY"), CAR.LEAF: NissanCarInfo("Nissan Leaf 2018-23", video_link="https://youtu.be/vaMbtAh_0cY"),
CAR.LEAF_IC: None, # same platforms CAR.LEAF_IC: None, # same platforms

View File

@ -1,6 +1,5 @@
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum, IntFlag from enum import Enum, IntFlag
from typing import List
from cereal import car from cereal import car
from panda.python import uds from panda.python import uds
@ -81,7 +80,7 @@ class Footnote(Enum):
class SubaruCarInfo(CarInfo): class SubaruCarInfo(CarInfo):
package: str = "EyeSight Driver Assistance" package: str = "EyeSight Driver Assistance"
car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.subaru_a])) car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.subaru_a]))
footnotes: List[Enum] = field(default_factory=lambda: [Footnote.GLOBAL]) footnotes: list[Enum] = field(default_factory=lambda: [Footnote.GLOBAL])
def init_make(self, CP: car.CarParams): def init_make(self, CP: car.CarParams):
self.car_parts.parts.extend([Tool.socket_8mm_deep, Tool.pry_tool]) self.car_parts.parts.extend([Tool.socket_8mm_deep, Tool.pry_tool])

View File

@ -1,6 +1,5 @@
from collections import namedtuple from collections import namedtuple
from enum import StrEnum from enum import StrEnum
from typing import Dict, List, Union
from cereal import car from cereal import car
from openpilot.selfdrive.car import AngleRateLimit, dbc_dict from openpilot.selfdrive.car import AngleRateLimit, dbc_dict
@ -17,7 +16,7 @@ class CAR(StrEnum):
AP2_MODELS = 'TESLA AP2 MODEL S' AP2_MODELS = 'TESLA AP2 MODEL S'
CAR_INFO: Dict[str, Union[CarInfo, List[CarInfo]]] = { CAR_INFO: dict[str, CarInfo | list[CarInfo]] = {
CAR.AP1_MODELS: CarInfo("Tesla AP1 Model S", "All"), CAR.AP1_MODELS: CarInfo("Tesla AP1 Model S", "All"),
CAR.AP2_MODELS: CarInfo("Tesla AP2 Model S", "All"), CAR.AP2_MODELS: CarInfo("Tesla AP2 Model S", "All"),
} }

View File

@ -1,5 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from typing import NamedTuple, Optional from typing import NamedTuple
from openpilot.selfdrive.car.chrysler.values import CAR as CHRYSLER from openpilot.selfdrive.car.chrysler.values import CAR as CHRYSLER
from openpilot.selfdrive.car.gm.values import CAR as GM from openpilot.selfdrive.car.gm.values import CAR as GM
@ -29,8 +29,8 @@ non_tested_cars = [
class CarTestRoute(NamedTuple): class CarTestRoute(NamedTuple):
route: str route: str
car_model: Optional[str] car_model: str | None
segment: Optional[int] = None segment: int | None = None
routes = [ routes = [

View File

@ -20,7 +20,7 @@ class TestCarDocs(unittest.TestCase):
def test_generator(self): def test_generator(self):
generated_cars_md = generate_cars_md(self.all_cars, CARS_MD_TEMPLATE) generated_cars_md = generate_cars_md(self.all_cars, CARS_MD_TEMPLATE)
with open(CARS_MD_OUT, "r") as f: with open(CARS_MD_OUT) as f:
current_cars_md = f.read() current_cars_md = f.read()
self.assertEqual(generated_cars_md, current_cars_md, self.assertEqual(generated_cars_md, current_cars_md,
@ -45,7 +45,7 @@ class TestCarDocs(unittest.TestCase):
all_car_info_platforms = get_interface_attr("CAR_INFO", combine_brands=True).keys() all_car_info_platforms = get_interface_attr("CAR_INFO", combine_brands=True).keys()
for platform in sorted(interfaces.keys()): for platform in sorted(interfaces.keys()):
with self.subTest(platform=platform): with self.subTest(platform=platform):
self.assertTrue(platform in all_car_info_platforms, "Platform: {} doesn't exist in CarInfo".format(platform)) self.assertTrue(platform in all_car_info_platforms, f"Platform: {platform} doesn't exist in CarInfo")
def test_naming_conventions(self): def test_naming_conventions(self):
# Asserts market-standard car naming conventions by brand # Asserts market-standard car naming conventions by brand

View File

@ -1,7 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
import sys import sys
from typing import Dict, List
from openpilot.common.basedir import BASEDIR from openpilot.common.basedir import BASEDIR
@ -64,7 +63,7 @@ def check_can_ignition_conflicts(fingerprints, brands):
if __name__ == "__main__": if __name__ == "__main__":
fingerprints = _get_fingerprints() fingerprints = _get_fingerprints()
fingerprints_flat: List[Dict] = [] fingerprints_flat: list[dict] = []
car_names = [] car_names = []
brand_names = [] brand_names = []
for brand in fingerprints: for brand in fingerprints:

View File

@ -3,7 +3,6 @@ from collections import defaultdict
import importlib import importlib
from parameterized import parameterized_class from parameterized import parameterized_class
import sys import sys
from typing import DefaultDict, Dict
import unittest import unittest
from openpilot.common.realtime import DT_CTRL from openpilot.common.realtime import DT_CTRL
@ -29,7 +28,7 @@ ABOVE_LIMITS_CARS = [
SUBARU.OUTBACK, SUBARU.OUTBACK,
] ]
car_model_jerks: DefaultDict[str, Dict[str, float]] = defaultdict(dict) car_model_jerks: defaultdict[str, dict[str, float]] = defaultdict(dict)
@parameterized_class('car_model', [(c,) for c in sorted(CAR_MODELS)]) @parameterized_class('car_model', [(c,) for c in sorted(CAR_MODELS)])

View File

@ -8,7 +8,6 @@ import unittest
from collections import defaultdict, Counter from collections import defaultdict, Counter
import hypothesis.strategies as st import hypothesis.strategies as st
from hypothesis import Phase, given, settings from hypothesis import Phase, given, settings
from typing import List, Optional, Tuple
from parameterized import parameterized_class from parameterized import parameterized_class
from cereal import messaging, log, car from cereal import messaging, log, car
@ -40,7 +39,7 @@ MAX_EXAMPLES = int(os.environ.get("MAX_EXAMPLES", "300"))
CI = os.environ.get("CI", None) is not None CI = os.environ.get("CI", None) is not None
def get_test_cases() -> List[Tuple[str, Optional[CarTestRoute]]]: def get_test_cases() -> list[tuple[str, CarTestRoute | None]]:
# build list of test cases # build list of test cases
test_cases = [] test_cases = []
if not len(INTERNAL_SEG_LIST): if not len(INTERNAL_SEG_LIST):
@ -65,14 +64,14 @@ def get_test_cases() -> List[Tuple[str, Optional[CarTestRoute]]]:
@pytest.mark.slow @pytest.mark.slow
@pytest.mark.shared_download_cache @pytest.mark.shared_download_cache
class TestCarModelBase(unittest.TestCase): class TestCarModelBase(unittest.TestCase):
car_model: Optional[str] = None car_model: str | None = None
test_route: Optional[CarTestRoute] = None test_route: CarTestRoute | None = None
test_route_on_bucket: bool = True # whether the route is on the preserved CI bucket test_route_on_bucket: bool = True # whether the route is on the preserved CI bucket
can_msgs: List[capnp.lib.capnp._DynamicStructReader] can_msgs: list[capnp.lib.capnp._DynamicStructReader]
fingerprint: dict[int, dict[int, int]] fingerprint: dict[int, dict[int, int]]
elm_frame: Optional[int] elm_frame: int | None
car_safety_mode_frame: Optional[int] car_safety_mode_frame: int | None
@classmethod @classmethod
def get_testing_data_from_logreader(cls, lr): def get_testing_data_from_logreader(cls, lr):
@ -408,7 +407,7 @@ class TestCarModelBase(unittest.TestCase):
controls_allowed_prev = False controls_allowed_prev = False
CS_prev = car.CarState.new_message() CS_prev = car.CarState.new_message()
checks = defaultdict(lambda: 0) checks = defaultdict(int)
controlsd = Controls(CI=self.CI) controlsd = Controls(CI=self.CI)
controlsd.initialized = True controlsd.initialized = True
for idx, can in enumerate(self.can_msgs): for idx, can in enumerate(self.can_msgs):

View File

@ -2,7 +2,6 @@ import re
from collections import defaultdict from collections import defaultdict
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum, IntFlag, StrEnum from enum import Enum, IntFlag, StrEnum
from typing import Dict, List, Set, Union
from cereal import car from cereal import car
from openpilot.common.conversions import Conversions as CV from openpilot.common.conversions import Conversions as CV
@ -100,7 +99,7 @@ class ToyotaCarInfo(CarInfo):
car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.toyota_a])) car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.toyota_a]))
CAR_INFO: Dict[str, Union[ToyotaCarInfo, List[ToyotaCarInfo]]] = { CAR_INFO: dict[str, ToyotaCarInfo | list[ToyotaCarInfo]] = {
# Toyota # Toyota
CAR.ALPHARD_TSS2: [ CAR.ALPHARD_TSS2: [
ToyotaCarInfo("Toyota Alphard 2019-20"), ToyotaCarInfo("Toyota Alphard 2019-20"),
@ -253,7 +252,7 @@ STATIC_DSU_MSGS = [
] ]
def get_platform_codes(fw_versions: List[bytes]) -> Dict[bytes, Set[bytes]]: def get_platform_codes(fw_versions: list[bytes]) -> dict[bytes, set[bytes]]:
# Returns sub versions in a dict so comparisons can be made within part-platform-major_version combos # Returns sub versions in a dict so comparisons can be made within part-platform-major_version combos
codes = defaultdict(set) # Optional[part]-platform-major_version: set of sub_version codes = defaultdict(set) # Optional[part]-platform-major_version: set of sub_version
for fw in fw_versions: for fw in fw_versions:
@ -297,7 +296,7 @@ def get_platform_codes(fw_versions: List[bytes]) -> Dict[bytes, Set[bytes]]:
return dict(codes) return dict(codes)
def match_fw_to_car_fuzzy(live_fw_versions, offline_fw_versions) -> Set[str]: def match_fw_to_car_fuzzy(live_fw_versions, offline_fw_versions) -> set[str]:
candidates = set() candidates = set()
for candidate, fws in offline_fw_versions.items(): for candidate, fws in offline_fw_versions.items():

View File

@ -1,7 +1,6 @@
from collections import defaultdict, namedtuple from collections import defaultdict, namedtuple
from dataclasses import dataclass, field from dataclasses import dataclass, field
from enum import Enum, IntFlag, StrEnum from enum import Enum, IntFlag, StrEnum
from typing import Dict, List, Union
from cereal import car from cereal import car
from panda.python import uds from panda.python import uds
@ -151,7 +150,7 @@ class CAR(StrEnum):
PQ_CARS = {CAR.PASSAT_NMS, CAR.SHARAN_MK2} PQ_CARS = {CAR.PASSAT_NMS, CAR.SHARAN_MK2}
DBC: Dict[str, Dict[str, str]] = defaultdict(lambda: dbc_dict("vw_mqb_2010", None)) DBC: dict[str, dict[str, str]] = defaultdict(lambda: dbc_dict("vw_mqb_2010", None))
for car_type in PQ_CARS: for car_type in PQ_CARS:
DBC[car_type] = dbc_dict("vw_golf_mk4", None) DBC[car_type] = dbc_dict("vw_golf_mk4", None)
@ -191,7 +190,7 @@ class VWCarInfo(CarInfo):
self.car_parts = CarParts([Device.threex_angled_mount, CarHarness.j533]) self.car_parts = CarParts([Device.threex_angled_mount, CarHarness.j533])
CAR_INFO: Dict[str, Union[VWCarInfo, List[VWCarInfo]]] = { CAR_INFO: dict[str, VWCarInfo | list[VWCarInfo]] = {
CAR.ARTEON_MK1: [ CAR.ARTEON_MK1: [
VWCarInfo("Volkswagen Arteon 2018-23", video_link="https://youtu.be/FAomFKPFlDA"), VWCarInfo("Volkswagen Arteon 2018-23", video_link="https://youtu.be/FAomFKPFlDA"),
VWCarInfo("Volkswagen Arteon R 2020-23", video_link="https://youtu.be/FAomFKPFlDA"), VWCarInfo("Volkswagen Arteon R 2020-23", video_link="https://youtu.be/FAomFKPFlDA"),

View File

@ -3,7 +3,6 @@ import os
import json import json
from collections import defaultdict from collections import defaultdict
from dataclasses import dataclass from dataclasses import dataclass
from typing import List, Dict, Optional
from openpilot.common.basedir import BASEDIR from openpilot.common.basedir import BASEDIR
from openpilot.common.params import Params from openpilot.common.params import Params
@ -14,7 +13,7 @@ with open(os.path.join(BASEDIR, "selfdrive/controls/lib/alerts_offroad.json")) a
OFFROAD_ALERTS = json.load(f) OFFROAD_ALERTS = json.load(f)
def set_offroad_alert(alert: str, show_alert: bool, extra_text: Optional[str] = None) -> None: def set_offroad_alert(alert: str, show_alert: bool, extra_text: str | None = None) -> None:
if show_alert: if show_alert:
a = copy.copy(OFFROAD_ALERTS[alert]) a = copy.copy(OFFROAD_ALERTS[alert])
a['extra'] = extra_text or '' a['extra'] = extra_text or ''
@ -25,7 +24,7 @@ def set_offroad_alert(alert: str, show_alert: bool, extra_text: Optional[str] =
@dataclass @dataclass
class AlertEntry: class AlertEntry:
alert: Optional[Alert] = None alert: Alert | None = None
start_frame: int = -1 start_frame: int = -1
end_frame: int = -1 end_frame: int = -1
@ -34,9 +33,9 @@ class AlertEntry:
class AlertManager: class AlertManager:
def __init__(self): def __init__(self):
self.alerts: Dict[str, AlertEntry] = defaultdict(AlertEntry) self.alerts: dict[str, AlertEntry] = defaultdict(AlertEntry)
def add_many(self, frame: int, alerts: List[Alert]) -> None: def add_many(self, frame: int, alerts: list[Alert]) -> None:
for alert in alerts: for alert in alerts:
entry = self.alerts[alert.alert_type] entry = self.alerts[alert.alert_type]
entry.alert = alert entry.alert = alert
@ -45,7 +44,7 @@ class AlertManager:
min_end_frame = entry.start_frame + alert.duration min_end_frame = entry.start_frame + alert.duration
entry.end_frame = max(frame + 1, min_end_frame) entry.end_frame = max(frame + 1, min_end_frame)
def process_alerts(self, frame: int, clear_event_types: set) -> Optional[Alert]: def process_alerts(self, frame: int, clear_event_types: set) -> Alert | None:
current_alert = AlertEntry() current_alert = AlertEntry()
for v in self.alerts.values(): for v in self.alerts.values():
if not v.alert: if not v.alert:

View File

@ -2,7 +2,7 @@
import math import math
import os import os
from enum import IntEnum from enum import IntEnum
from typing import Dict, Union, Callable, List, Optional from collections.abc import Callable
from cereal import log, car from cereal import log, car
import cereal.messaging as messaging import cereal.messaging as messaging
@ -48,12 +48,12 @@ EVENT_NAME = {v: k for k, v in EventName.schema.enumerants.items()}
class Events: class Events:
def __init__(self): def __init__(self):
self.events: List[int] = [] self.events: list[int] = []
self.static_events: List[int] = [] self.static_events: list[int] = []
self.events_prev = dict.fromkeys(EVENTS.keys(), 0) self.events_prev = dict.fromkeys(EVENTS.keys(), 0)
@property @property
def names(self) -> List[int]: def names(self) -> list[int]:
return self.events return self.events
def __len__(self) -> int: def __len__(self) -> int:
@ -71,7 +71,7 @@ class Events:
def contains(self, event_type: str) -> bool: def contains(self, event_type: str) -> bool:
return any(event_type in EVENTS.get(e, {}) for e in self.events) return any(event_type in EVENTS.get(e, {}) for e in self.events)
def create_alerts(self, event_types: List[str], callback_args=None): def create_alerts(self, event_types: list[str], callback_args=None):
if callback_args is None: if callback_args is None:
callback_args = [] callback_args = []
@ -132,7 +132,7 @@ class Alert:
self.creation_delay = creation_delay self.creation_delay = creation_delay
self.alert_type = "" self.alert_type = ""
self.event_type: Optional[str] = None self.event_type: str | None = None
def __str__(self) -> str: def __str__(self) -> str:
return f"{self.alert_text_1}/{self.alert_text_2} {self.priority} {self.visual_alert} {self.audible_alert}" return f"{self.alert_text_1}/{self.alert_text_2} {self.priority} {self.visual_alert} {self.audible_alert}"
@ -333,7 +333,7 @@ def joystick_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster,
EVENTS: Dict[int, Dict[str, Union[Alert, AlertCallbackType]]] = { EVENTS: dict[int, dict[str, Alert | AlertCallbackType]] = {
# ********** events with no alerts ********** # ********** events with no alerts **********
EventName.stockFcw: {}, EventName.stockFcw: {},
@ -965,7 +965,7 @@ if __name__ == '__main__':
from collections import defaultdict from collections import defaultdict
event_names = {v: k for k, v in EventName.schema.enumerants.items()} event_names = {v: k for k, v in EventName.schema.enumerants.items()}
alerts_by_type: Dict[str, Dict[Priority, List[str]]] = defaultdict(lambda: defaultdict(list)) alerts_by_type: dict[str, dict[Priority, list[str]]] = defaultdict(lambda: defaultdict(list))
CP = car.CarParams.new_message() CP = car.CarParams.new_message()
CS = car.CarState.new_message() CS = car.CarState.new_message()
@ -977,7 +977,7 @@ if __name__ == '__main__':
alert = alert(CP, CS, sm, False, 1) alert = alert(CP, CS, sm, False, 1)
alerts_by_type[et][alert.priority].append(event_names[i]) alerts_by_type[et][alert.priority].append(event_names[i])
all_alerts: Dict[str, List[tuple[Priority, List[str]]]] = {} all_alerts: dict[str, list[tuple[Priority, list[str]]]] = {}
for et, priority_alerts in alerts_by_type.items(): for et, priority_alerts in alerts_by_type.items():
all_alerts[et] = sorted(priority_alerts.items(), key=lambda x: x[0], reverse=True) all_alerts[et] = sorted(priority_alerts.items(), key=lambda x: x[0], reverse=True)

View File

@ -12,7 +12,6 @@ x_dot = A*x + B*u
A depends on longitudinal speed, u [m/s], and vehicle parameters CP A depends on longitudinal speed, u [m/s], and vehicle parameters CP
""" """
from typing import Tuple
import numpy as np import numpy as np
from numpy.linalg import solve from numpy.linalg import solve
@ -169,7 +168,7 @@ def kin_ss_sol(sa: float, u: float, VM: VehicleModel) -> np.ndarray:
return K * sa return K * sa
def create_dyn_state_matrices(u: float, VM: VehicleModel) -> Tuple[np.ndarray, np.ndarray]: def create_dyn_state_matrices(u: float, VM: VehicleModel) -> tuple[np.ndarray, np.ndarray]:
"""Returns the A and B matrix for the dynamics system """Returns the A and B matrix for the dynamics system
Args: Args:

View File

@ -2,7 +2,7 @@
import importlib import importlib
import math import math
from collections import deque from collections import deque
from typing import Optional, Dict, Any from typing import Any, Optional
import capnp import capnp
from cereal import messaging, log, car from cereal import messaging, log, car
@ -125,7 +125,7 @@ def laplacian_pdf(x: float, mu: float, b: float):
return math.exp(-abs(x-mu)/b) return math.exp(-abs(x-mu)/b)
def match_vision_to_track(v_ego: float, lead: capnp._DynamicStructReader, tracks: Dict[int, Track]): def match_vision_to_track(v_ego: float, lead: capnp._DynamicStructReader, tracks: dict[int, Track]):
offset_vision_dist = lead.x[0] - RADAR_TO_CAMERA offset_vision_dist = lead.x[0] - RADAR_TO_CAMERA
def prob(c): def prob(c):
@ -166,8 +166,8 @@ def get_RadarState_from_vision(lead_msg: capnp._DynamicStructReader, v_ego: floa
} }
def get_lead(v_ego: float, ready: bool, tracks: Dict[int, Track], lead_msg: capnp._DynamicStructReader, def get_lead(v_ego: float, ready: bool, tracks: dict[int, Track], lead_msg: capnp._DynamicStructReader,
model_v_ego: float, low_speed_override: bool = True) -> Dict[str, Any]: model_v_ego: float, low_speed_override: bool = True) -> dict[str, Any]:
# Determine leads, this is where the essential logic happens # Determine leads, this is where the essential logic happens
if len(tracks) > 0 and ready and lead_msg.prob > .5: if len(tracks) > 0 and ready and lead_msg.prob > .5:
track = match_vision_to_track(v_ego, lead_msg, tracks) track = match_vision_to_track(v_ego, lead_msg, tracks)
@ -196,14 +196,14 @@ class RadarD:
def __init__(self, radar_ts: float, delay: int = 0): def __init__(self, radar_ts: float, delay: int = 0):
self.current_time = 0.0 self.current_time = 0.0
self.tracks: Dict[int, Track] = {} self.tracks: dict[int, Track] = {}
self.kalman_params = KalmanParams(radar_ts) self.kalman_params = KalmanParams(radar_ts)
self.v_ego = 0.0 self.v_ego = 0.0
self.v_ego_hist = deque([0.0], maxlen=delay+1) self.v_ego_hist = deque([0.0], maxlen=delay+1)
self.last_v_ego_frame = -1 self.last_v_ego_frame = -1
self.radar_state: Optional[capnp._DynamicStructBuilder] = None self.radar_state: capnp._DynamicStructBuilder | None = None
self.radar_state_valid = False self.radar_state_valid = False
self.ready = False self.ready = False

View File

@ -3,7 +3,6 @@ import argparse
import binascii import binascii
import time import time
from collections import defaultdict from collections import defaultdict
from typing import Optional
import cereal.messaging as messaging import cereal.messaging as messaging
from openpilot.selfdrive.debug.can_table import can_table from openpilot.selfdrive.debug.can_table import can_table
@ -96,8 +95,8 @@ if __name__ == "__main__":
args = parser.parse_args() args = parser.parse_args()
init_lr: Optional[LogIterable] = None init_lr: LogIterable | None = None
new_lr: Optional[LogIterable] = None new_lr: LogIterable | None = None
if args.init: if args.init:
if args.init == '': if args.init == '':

View File

@ -3,7 +3,7 @@ import argparse
import numpy as np import numpy as np
import time import time
from collections import defaultdict, deque from collections import defaultdict, deque
from typing import DefaultDict, Deque, MutableSequence from collections.abc import MutableSequence
import cereal.messaging as messaging import cereal.messaging as messaging
@ -19,8 +19,8 @@ if __name__ == "__main__":
socket_names = args.socket socket_names = args.socket
sockets = {} sockets = {}
rcv_times: DefaultDict[str, MutableSequence[float]] = defaultdict(lambda: deque(maxlen=100)) rcv_times: defaultdict[str, MutableSequence[float]] = defaultdict(lambda: deque(maxlen=100))
valids: DefaultDict[str, Deque[bool]] = defaultdict(lambda: deque(maxlen=100)) valids: defaultdict[str, deque[bool]] = defaultdict(lambda: deque(maxlen=100))
t = time.monotonic() t = time.monotonic()
for name in socket_names: for name in socket_names:

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from typing import Dict
import cereal.messaging as messaging import cereal.messaging as messaging
from cereal.services import SERVICE_LIST from cereal.services import SERVICE_LIST
@ -10,7 +9,7 @@ TO_CHECK = ['carState']
if __name__ == "__main__": if __name__ == "__main__":
sm = messaging.SubMaster(TO_CHECK) sm = messaging.SubMaster(TO_CHECK)
prev_t: Dict[str, float] = {} prev_t: dict[str, float] = {}
while True: while True:
sm.update() sm.update()

View File

@ -3,13 +3,13 @@
import sys import sys
import time import time
import numpy as np import numpy as np
from typing import DefaultDict, MutableSequence from collections.abc import MutableSequence
from collections import defaultdict, deque from collections import defaultdict, deque
import cereal.messaging as messaging import cereal.messaging as messaging
socks = {s: messaging.sub_sock(s, conflate=False) for s in sys.argv[1:]} socks = {s: messaging.sub_sock(s, conflate=False) for s in sys.argv[1:]}
ts: DefaultDict[str, MutableSequence[float]] = defaultdict(lambda: deque(maxlen=100)) ts: defaultdict[str, MutableSequence[float]] = defaultdict(lambda: deque(maxlen=100))
if __name__ == "__main__": if __name__ == "__main__":
while True: while True:

View File

@ -4,7 +4,7 @@ import math
import datetime import datetime
from collections import Counter from collections import Counter
from pprint import pprint from pprint import pprint
from typing import List, Tuple, cast from typing import cast
from cereal.services import SERVICE_LIST from cereal.services import SERVICE_LIST
from openpilot.tools.lib.logreader import LogReader, ReadMode from openpilot.tools.lib.logreader import LogReader, ReadMode
@ -15,8 +15,8 @@ if __name__ == "__main__":
cams = [s for s in SERVICE_LIST if s.endswith('CameraState')] cams = [s for s in SERVICE_LIST if s.endswith('CameraState')]
cnt_cameras = dict.fromkeys(cams, 0) cnt_cameras = dict.fromkeys(cams, 0)
events: List[Tuple[float, set[str]]] = [] events: list[tuple[float, set[str]]] = []
alerts: List[Tuple[float, str]] = [] alerts: list[tuple[float, str]] = []
start_time = math.inf start_time = math.inf
end_time = -math.inf end_time = -math.inf
ignition_off = None ignition_off = None

View File

@ -66,12 +66,12 @@ if __name__ == "__main__":
for p in psutil.process_iter(): for p in psutil.process_iter():
if p == psutil.Process(): if p == psutil.Process():
continue continue
matched = any(l for l in p.cmdline() if any(pn for pn in monitored_proc_names if re.match(r'.*{}.*'.format(pn), l, re.M | re.I))) matched = any(l for l in p.cmdline() if any(pn for pn in monitored_proc_names if re.match(fr'.*{pn}.*', l, re.M | re.I)))
if matched: if matched:
k = ' '.join(p.cmdline()) k = ' '.join(p.cmdline())
print('Add monitored proc:', k) print('Add monitored proc:', k)
stats[k] = {'cpu_samples': defaultdict(list), 'min': defaultdict(lambda: None), 'max': defaultdict(lambda: None), stats[k] = {'cpu_samples': defaultdict(list), 'min': defaultdict(lambda: None), 'max': defaultdict(lambda: None),
'avg': defaultdict(lambda: 0.0), 'last_cpu_times': None, 'last_sys_time': None} 'avg': defaultdict(float), 'last_cpu_times': None, 'last_sys_time': None}
stats[k]['last_sys_time'] = timer() stats[k]['last_sys_time'] = timer()
stats[k]['last_cpu_times'] = p.cpu_times() stats[k]['last_cpu_times'] = p.cpu_times()
monitored_procs.append(p) monitored_procs.append(p)

View File

@ -67,7 +67,7 @@ def format_brand_fw_versions(brand, extra_fw_versions: None | dict[str, dict[tup
extra_fw_versions = extra_fw_versions or {} extra_fw_versions = extra_fw_versions or {}
fingerprints_file = os.path.join(BASEDIR, f"selfdrive/car/{brand}/fingerprints.py") fingerprints_file = os.path.join(BASEDIR, f"selfdrive/car/{brand}/fingerprints.py")
with open(fingerprints_file, "r") as f: with open(fingerprints_file) as f:
comments = [line for line in f.readlines() if line.startswith("#") and "noqa" not in line] comments = [line for line in f.readlines() if line.startswith("#") and "noqa" not in line]
with open(fingerprints_file, "w") as f: with open(fingerprints_file, "w") as f:

View File

@ -1,12 +1,11 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import cereal.messaging as messaging import cereal.messaging as messaging
from typing import Optional
if __name__ == "__main__": if __name__ == "__main__":
modeld_sock = messaging.sub_sock("modelV2") modeld_sock = messaging.sub_sock("modelV2")
last_frame_id = None last_frame_id = None
start_t: Optional[int] = None start_t: int | None = None
frame_cnt = 0 frame_cnt = 0
dropped = 0 dropped = 0

View File

@ -5,7 +5,6 @@ from collections import defaultdict
from cereal.messaging import SubMaster from cereal.messaging import SubMaster
from openpilot.common.numpy_fast import mean from openpilot.common.numpy_fast import mean
from typing import Optional, Dict
def cputime_total(ct): def cputime_total(ct):
return ct.user + ct.nice + ct.system + ct.idle + ct.iowait + ct.irq + ct.softirq return ct.user + ct.nice + ct.system + ct.idle + ct.iowait + ct.irq + ct.softirq
@ -42,8 +41,8 @@ if __name__ == "__main__":
total_times = [0.]*8 total_times = [0.]*8
busy_times = [0.]*8 busy_times = [0.]*8
prev_proclog: Optional[capnp._DynamicStructReader] = None prev_proclog: capnp._DynamicStructReader | None = None
prev_proclog_t: Optional[int] = None prev_proclog_t: int | None = None
while True: while True:
sm.update() sm.update()
@ -76,7 +75,7 @@ if __name__ == "__main__":
print(f"CPU {100.0 * mean(cores):.2f}% - RAM: {last_mem:.2f}% - Temp {last_temp:.2f}C") print(f"CPU {100.0 * mean(cores):.2f}% - RAM: {last_mem:.2f}% - Temp {last_temp:.2f}C")
if args.cpu and prev_proclog is not None and prev_proclog_t is not None: if args.cpu and prev_proclog is not None and prev_proclog_t is not None:
procs: Dict[str, float] = defaultdict(float) procs: dict[str, float] = defaultdict(float)
dt = (sm.logMonoTime['procLog'] - prev_proclog_t) / 1e9 dt = (sm.logMonoTime['procLog'] - prev_proclog_t) / 1e9
for proc in m.procs: for proc in m.procs:
try: try:

View File

@ -10,7 +10,7 @@ import gc
import os import os
import capnp import capnp
import numpy as np import numpy as np
from typing import List, NoReturn, Optional from typing import NoReturn
from cereal import log from cereal import log
import cereal.messaging as messaging import cereal.messaging as messaging
@ -89,7 +89,7 @@ class Calibrator:
valid_blocks: int = 0, valid_blocks: int = 0,
wide_from_device_euler_init: np.ndarray = WIDE_FROM_DEVICE_EULER_INIT, wide_from_device_euler_init: np.ndarray = WIDE_FROM_DEVICE_EULER_INIT,
height_init: np.ndarray = HEIGHT_INIT, height_init: np.ndarray = HEIGHT_INIT,
smooth_from: Optional[np.ndarray] = None) -> None: smooth_from: np.ndarray | None = None) -> None:
if not np.isfinite(rpy_init).all(): if not np.isfinite(rpy_init).all():
self.rpy = RPY_INIT.copy() self.rpy = RPY_INIT.copy()
else: else:
@ -125,7 +125,7 @@ class Calibrator:
self.old_rpy = smooth_from self.old_rpy = smooth_from
self.old_rpy_weight = 1.0 self.old_rpy_weight = 1.0
def get_valid_idxs(self) -> List[int]: def get_valid_idxs(self) -> list[int]:
# exclude current block_idx from validity window # exclude current block_idx from validity window
before_current = list(range(self.block_idx)) before_current = list(range(self.block_idx))
after_current = list(range(min(self.valid_blocks, self.block_idx + 1), self.valid_blocks)) after_current = list(range(min(self.valid_blocks, self.block_idx + 1), self.valid_blocks))
@ -175,12 +175,12 @@ class Calibrator:
else: else:
return self.rpy return self.rpy
def handle_cam_odom(self, trans: List[float], def handle_cam_odom(self, trans: list[float],
rot: List[float], rot: list[float],
wide_from_device_euler: List[float], wide_from_device_euler: list[float],
trans_std: List[float], trans_std: list[float],
road_transform_trans: List[float], road_transform_trans: list[float],
road_transform_trans_std: List[float]) -> Optional[np.ndarray]: road_transform_trans_std: list[float]) -> np.ndarray | None:
self.old_rpy_weight = max(0.0, self.old_rpy_weight - 1/SMOOTH_CYCLES) self.old_rpy_weight = max(0.0, self.old_rpy_weight - 1/SMOOTH_CYCLES)
straight_and_fast = ((self.v_ego > MIN_SPEED_FILTER) and (trans[0] > MIN_SPEED_FILTER) and (abs(rot[2]) < MAX_YAW_RATE_FILTER)) straight_and_fast = ((self.v_ego > MIN_SPEED_FILTER) and (trans[0] > MIN_SPEED_FILTER) and (abs(rot[2]) < MAX_YAW_RATE_FILTER))

View File

@ -1,5 +1,5 @@
import numpy as np import numpy as np
from typing import List, Optional, Tuple, Any from typing import Any
from cereal import log from cereal import log
@ -12,7 +12,7 @@ class NPQueue:
def __len__(self) -> int: def __len__(self) -> int:
return len(self.arr) return len(self.arr)
def append(self, pt: List[float]) -> None: def append(self, pt: list[float]) -> None:
if len(self.arr) < self.maxlen: if len(self.arr) < self.maxlen:
self.arr = np.append(self.arr, [pt], axis=0) self.arr = np.append(self.arr, [pt], axis=0)
else: else:
@ -21,7 +21,7 @@ class NPQueue:
class PointBuckets: class PointBuckets:
def __init__(self, x_bounds: List[Tuple[float, float]], min_points: List[float], min_points_total: int, points_per_bucket: int, rowsize: int) -> None: def __init__(self, x_bounds: list[tuple[float, float]], min_points: list[float], min_points_total: int, points_per_bucket: int, rowsize: int) -> None:
self.x_bounds = x_bounds self.x_bounds = x_bounds
self.buckets = {bounds: NPQueue(maxlen=points_per_bucket, rowsize=rowsize) for bounds in x_bounds} self.buckets = {bounds: NPQueue(maxlen=points_per_bucket, rowsize=rowsize) for bounds in x_bounds}
self.buckets_min_points = dict(zip(x_bounds, min_points, strict=True)) self.buckets_min_points = dict(zip(x_bounds, min_points, strict=True))
@ -41,13 +41,13 @@ class PointBuckets:
def add_point(self, x: float, y: float, bucket_val: float) -> None: def add_point(self, x: float, y: float, bucket_val: float) -> None:
raise NotImplementedError raise NotImplementedError
def get_points(self, num_points: Optional[int] = None) -> Any: def get_points(self, num_points: int | None = None) -> Any:
points = np.vstack([x.arr for x in self.buckets.values()]) points = np.vstack([x.arr for x in self.buckets.values()])
if num_points is None: if num_points is None:
return points return points
return points[np.random.choice(np.arange(len(points)), min(len(points), num_points), replace=False)] return points[np.random.choice(np.arange(len(points)), min(len(points), num_points), replace=False)]
def load_points(self, points: List[List[float]]) -> None: def load_points(self, points: list[list[float]]) -> None:
for point in points: for point in points:
self.add_point(*point) self.add_point(*point)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import math import math
import sys import sys
from typing import Any, Dict from typing import Any
import numpy as np import numpy as np
@ -70,7 +70,7 @@ class CarKalman(KalmanFilter):
]) ])
P_initial = Q.copy() P_initial = Q.copy()
obs_noise: Dict[int, Any] = { obs_noise: dict[int, Any] = {
ObservationKind.STEER_ANGLE: np.atleast_2d(math.radians(0.05)**2), ObservationKind.STEER_ANGLE: np.atleast_2d(math.radians(0.05)**2),
ObservationKind.ANGLE_OFFSET_FAST: np.atleast_2d(math.radians(10.0)**2), ObservationKind.ANGLE_OFFSET_FAST: np.atleast_2d(math.radians(10.0)**2),
ObservationKind.ROAD_ROLL: np.atleast_2d(math.radians(1.0)**2), ObservationKind.ROAD_ROLL: np.atleast_2d(math.radians(1.0)**2),

View File

@ -2,7 +2,6 @@
import os import os
import subprocess import subprocess
from pathlib import Path from pathlib import Path
from typing import List
# NOTE: Do NOT import anything here that needs be built (e.g. params) # NOTE: Do NOT import anything here that needs be built (e.g. params)
from openpilot.common.basedir import BASEDIR from openpilot.common.basedir import BASEDIR
@ -29,7 +28,7 @@ def build(spinner: Spinner, dirty: bool = False, minimal: bool = False) -> None:
# building with all cores can result in using too # building with all cores can result in using too
# much memory, so retry with less parallelism # much memory, so retry with less parallelism
compile_output: List[bytes] = [] compile_output: list[bytes] = []
for n in (nproc, nproc/2, 1): for n in (nproc, nproc/2, 1):
compile_output.clear() compile_output.clear()
scons: subprocess.Popen = subprocess.Popen(["scons", f"-j{int(n)}", "--cache-populate", *extra_args], cwd=BASEDIR, env=env, stderr=subprocess.PIPE) scons: subprocess.Popen = subprocess.Popen(["scons", f"-j{int(n)}", "--cache-populate", *extra_args], cwd=BASEDIR, env=env, stderr=subprocess.PIPE)

View File

@ -4,7 +4,6 @@ import os
import signal import signal
import sys import sys
import traceback import traceback
from typing import List, Tuple, Union
from cereal import log from cereal import log
import cereal.messaging as messaging import cereal.messaging as messaging
@ -33,7 +32,7 @@ def manager_init() -> None:
if is_release_branch(): if is_release_branch():
params.clear_all(ParamKeyType.DEVELOPMENT_ONLY) params.clear_all(ParamKeyType.DEVELOPMENT_ONLY)
default_params: List[Tuple[str, Union[str, bytes]]] = [ default_params: list[tuple[str, str | bytes]] = [
("CompletedTrainingVersion", "0"), ("CompletedTrainingVersion", "0"),
("DisengageOnAccelerator", "0"), ("DisengageOnAccelerator", "0"),
("GsmMetered", "1"), ("GsmMetered", "1"),
@ -121,7 +120,7 @@ def manager_thread() -> None:
params = Params() params = Params()
ignore: List[str] = [] ignore: list[str] = []
if params.get("DongleId", encoding='utf8') in (None, UNREGISTERED_DONGLE_ID): if params.get("DongleId", encoding='utf8') in (None, UNREGISTERED_DONGLE_ID):
ignore += ["manage_athenad", "uploader"] ignore += ["manage_athenad", "uploader"]
if os.getenv("NOBOARD") is not None: if os.getenv("NOBOARD") is not None:
@ -154,7 +153,7 @@ def manager_thread() -> None:
ensure_running(managed_processes.values(), started, params=params, CP=sm['carParams'], not_run=ignore) ensure_running(managed_processes.values(), started, params=params, CP=sm['carParams'], not_run=ignore)
running = ' '.join("%s%s\u001b[0m" % ("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name) running = ' '.join("{}{}\u001b[0m".format("\u001b[32m" if p.proc.is_alive() else "\u001b[31m", p.name)
for p in managed_processes.values() if p.proc) for p in managed_processes.values() if p.proc)
print(running) print(running)
cloudlog.debug(running) cloudlog.debug(running)

View File

@ -4,7 +4,7 @@ import signal
import struct import struct
import time import time
import subprocess import subprocess
from typing import Optional, Callable, List, ValuesView from collections.abc import Callable, ValuesView
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from multiprocessing import Process from multiprocessing import Process
@ -47,7 +47,7 @@ def launcher(proc: str, name: str) -> None:
raise raise
def nativelauncher(pargs: List[str], cwd: str, name: str) -> None: def nativelauncher(pargs: list[str], cwd: str, name: str) -> None:
os.environ['MANAGER_DAEMON'] = name os.environ['MANAGER_DAEMON'] = name
# exec the process # exec the process
@ -67,12 +67,12 @@ class ManagerProcess(ABC):
daemon = False daemon = False
sigkill = False sigkill = False
should_run: Callable[[bool, Params, car.CarParams], bool] should_run: Callable[[bool, Params, car.CarParams], bool]
proc: Optional[Process] = None proc: Process | None = None
enabled = True enabled = True
name = "" name = ""
last_watchdog_time = 0 last_watchdog_time = 0
watchdog_max_dt: Optional[int] = None watchdog_max_dt: int | None = None
watchdog_seen = False watchdog_seen = False
shutting_down = False shutting_down = False
@ -109,7 +109,7 @@ class ManagerProcess(ABC):
else: else:
self.watchdog_seen = True self.watchdog_seen = True
def stop(self, retry: bool = True, block: bool = True, sig: Optional[signal.Signals] = None) -> Optional[int]: def stop(self, retry: bool = True, block: bool = True, sig: signal.Signals | None = None) -> int | None:
if self.proc is None: if self.proc is None:
return None return None
@ -274,7 +274,7 @@ class DaemonProcess(ManagerProcess):
def ensure_running(procs: ValuesView[ManagerProcess], started: bool, params=None, CP: car.CarParams=None, def ensure_running(procs: ValuesView[ManagerProcess], started: bool, params=None, CP: car.CarParams=None,
not_run: Optional[List[str]]=None) -> List[ManagerProcess]: not_run: list[str] | None=None) -> list[ManagerProcess]:
if not_run is None: if not_run is None:
not_run = [] not_run = []

View File

@ -6,7 +6,6 @@ import time
import ctypes import ctypes
import numpy as np import numpy as np
from pathlib import Path from pathlib import Path
from typing import Tuple, Dict
from cereal import messaging from cereal import messaging
from cereal.messaging import PubMaster, SubMaster from cereal.messaging import PubMaster, SubMaster
@ -53,7 +52,7 @@ class DMonitoringModelResult(ctypes.Structure):
("wheel_on_right_prob", ctypes.c_float)] ("wheel_on_right_prob", ctypes.c_float)]
class ModelState: class ModelState:
inputs: Dict[str, np.ndarray] inputs: dict[str, np.ndarray]
output: np.ndarray output: np.ndarray
model: ModelRunner model: ModelRunner
@ -68,7 +67,7 @@ class ModelState:
self.model.addInput("input_img", None) self.model.addInput("input_img", None)
self.model.addInput("calib", self.inputs['calib']) self.model.addInput("calib", self.inputs['calib'])
def run(self, buf:VisionBuf, calib:np.ndarray) -> Tuple[np.ndarray, float]: def run(self, buf:VisionBuf, calib:np.ndarray) -> tuple[np.ndarray, float]:
self.inputs['calib'][:] = calib self.inputs['calib'][:] = calib
v_offset = buf.height - MODEL_HEIGHT v_offset = buf.height - MODEL_HEIGHT

View File

@ -1,7 +1,6 @@
import os import os
import capnp import capnp
import numpy as np import numpy as np
from typing import Dict
from cereal import log from cereal import log
from openpilot.selfdrive.modeld.constants import ModelConstants, Plan, Meta from openpilot.selfdrive.modeld.constants import ModelConstants, Plan, Meta
@ -42,7 +41,7 @@ def fill_xyvat(builder, t, x, y, v, a, x_std=None, y_std=None, v_std=None, a_std
if a_std is not None: if a_std is not None:
builder.aStd = a_std.tolist() builder.aStd = a_std.tolist()
def fill_model_msg(msg: capnp._DynamicStructBuilder, net_output_data: Dict[str, np.ndarray], publish_state: PublishState, def fill_model_msg(msg: capnp._DynamicStructBuilder, net_output_data: dict[str, np.ndarray], publish_state: PublishState,
vipc_frame_id: int, vipc_frame_id_extra: int, frame_id: int, frame_drop: float, vipc_frame_id: int, vipc_frame_id_extra: int, frame_id: int, frame_drop: float,
timestamp_eof: int, timestamp_llk: int, model_execution_time: float, timestamp_eof: int, timestamp_llk: int, model_execution_time: float,
nav_enabled: bool, valid: bool) -> None: nav_enabled: bool, valid: bool) -> None:
@ -174,7 +173,7 @@ def fill_model_msg(msg: capnp._DynamicStructBuilder, net_output_data: Dict[str,
if SEND_RAW_PRED: if SEND_RAW_PRED:
modelV2.rawPredictions = net_output_data['raw_pred'].tobytes() modelV2.rawPredictions = net_output_data['raw_pred'].tobytes()
def fill_pose_msg(msg: capnp._DynamicStructBuilder, net_output_data: Dict[str, np.ndarray], def fill_pose_msg(msg: capnp._DynamicStructBuilder, net_output_data: dict[str, np.ndarray],
vipc_frame_id: int, vipc_dropped_frames: int, timestamp_eof: int, live_calib_seen: bool) -> None: vipc_frame_id: int, vipc_dropped_frames: int, timestamp_eof: int, live_calib_seen: bool) -> None:
msg.valid = live_calib_seen & (vipc_dropped_frames < 1) msg.valid = live_calib_seen & (vipc_dropped_frames < 1)
cameraOdometry = msg.cameraOdometry cameraOdometry = msg.cameraOdometry

View File

@ -4,9 +4,8 @@ import pathlib
import onnx import onnx
import codecs import codecs
import pickle import pickle
from typing import Tuple
def get_name_and_shape(value_info:onnx.ValueInfoProto) -> Tuple[str, Tuple[int,...]]: def get_name_and_shape(value_info:onnx.ValueInfoProto) -> tuple[str, tuple[int,...]]:
shape = tuple([int(dim.dim_value) for dim in value_info.type.tensor_type.shape.dim]) shape = tuple([int(dim.dim_value) for dim in value_info.type.tensor_type.shape.dim])
name = value_info.name name = value_info.name
return name, shape return name, shape

View File

@ -6,7 +6,6 @@ import numpy as np
import cereal.messaging as messaging import cereal.messaging as messaging
from cereal import car, log from cereal import car, log
from pathlib import Path from pathlib import Path
from typing import Dict, Optional
from setproctitle import setproctitle from setproctitle import setproctitle
from cereal.messaging import PubMaster, SubMaster from cereal.messaging import PubMaster, SubMaster
from cereal.visionipc import VisionIpcClient, VisionStreamType, VisionBuf from cereal.visionipc import VisionIpcClient, VisionStreamType, VisionBuf
@ -45,7 +44,7 @@ class FrameMeta:
class ModelState: class ModelState:
frame: ModelFrame frame: ModelFrame
wide_frame: ModelFrame wide_frame: ModelFrame
inputs: Dict[str, np.ndarray] inputs: dict[str, np.ndarray]
output: np.ndarray output: np.ndarray
prev_desire: np.ndarray # for tracking the rising edge of the pulse prev_desire: np.ndarray # for tracking the rising edge of the pulse
model: ModelRunner model: ModelRunner
@ -78,14 +77,14 @@ class ModelState:
for k,v in self.inputs.items(): for k,v in self.inputs.items():
self.model.addInput(k, v) self.model.addInput(k, v)
def slice_outputs(self, model_outputs: np.ndarray) -> Dict[str, np.ndarray]: def slice_outputs(self, model_outputs: np.ndarray) -> dict[str, np.ndarray]:
parsed_model_outputs = {k: model_outputs[np.newaxis, v] for k,v in self.output_slices.items()} parsed_model_outputs = {k: model_outputs[np.newaxis, v] for k,v in self.output_slices.items()}
if SEND_RAW_PRED: if SEND_RAW_PRED:
parsed_model_outputs['raw_pred'] = model_outputs.copy() parsed_model_outputs['raw_pred'] = model_outputs.copy()
return parsed_model_outputs return parsed_model_outputs
def run(self, buf: VisionBuf, wbuf: VisionBuf, transform: np.ndarray, transform_wide: np.ndarray, def run(self, buf: VisionBuf, wbuf: VisionBuf, transform: np.ndarray, transform_wide: np.ndarray,
inputs: Dict[str, np.ndarray], prepare_only: bool) -> Optional[Dict[str, np.ndarray]]: inputs: dict[str, np.ndarray], prepare_only: bool) -> dict[str, np.ndarray] | None:
# Model decides when action is completed, so desire input is just a pulse triggered on rising edge # Model decides when action is completed, so desire input is just a pulse triggered on rising edge
inputs['desire'][0] = 0 inputs['desire'][0] = 0
self.inputs['desire'][:-ModelConstants.DESIRE_LEN] = self.inputs['desire'][ModelConstants.DESIRE_LEN:] self.inputs['desire'][:-ModelConstants.DESIRE_LEN] = self.inputs['desire'][ModelConstants.DESIRE_LEN:]
@ -276,7 +275,7 @@ def main(demo=False):
if prepare_only: if prepare_only:
cloudlog.error(f"skipping model eval. Dropped {vipc_dropped_frames} frames") cloudlog.error(f"skipping model eval. Dropped {vipc_dropped_frames} frames")
inputs:Dict[str, np.ndarray] = { inputs:dict[str, np.ndarray] = {
'desire': vec_desire, 'desire': vec_desire,
'traffic_convention': traffic_convention, 'traffic_convention': traffic_convention,
'lateral_control_params': lateral_control_params, 'lateral_control_params': lateral_control_params,

View File

@ -5,7 +5,6 @@ import time
import ctypes import ctypes
import numpy as np import numpy as np
from pathlib import Path from pathlib import Path
from typing import Tuple, Dict
from cereal import messaging from cereal import messaging
from cereal.messaging import PubMaster, SubMaster from cereal.messaging import PubMaster, SubMaster
@ -41,7 +40,7 @@ class NavModelResult(ctypes.Structure):
("features", ctypes.c_float*NAV_FEATURE_LEN)] ("features", ctypes.c_float*NAV_FEATURE_LEN)]
class ModelState: class ModelState:
inputs: Dict[str, np.ndarray] inputs: dict[str, np.ndarray]
output: np.ndarray output: np.ndarray
model: ModelRunner model: ModelRunner
@ -52,7 +51,7 @@ class ModelState:
self.model = ModelRunner(MODEL_PATHS, self.output, Runtime.DSP, True, None) self.model = ModelRunner(MODEL_PATHS, self.output, Runtime.DSP, True, None)
self.model.addInput("input_img", None) self.model.addInput("input_img", None)
def run(self, buf:np.ndarray) -> Tuple[np.ndarray, float]: def run(self, buf:np.ndarray) -> tuple[np.ndarray, float]:
self.inputs['input_img'][:] = buf self.inputs['input_img'][:] = buf
t1 = time.perf_counter() t1 = time.perf_counter()

View File

@ -1,5 +1,4 @@
import numpy as np import numpy as np
from typing import Dict
from openpilot.selfdrive.modeld.constants import ModelConstants from openpilot.selfdrive.modeld.constants import ModelConstants
def sigmoid(x): def sigmoid(x):
@ -82,7 +81,7 @@ class Parser:
outs[name] = pred_mu_final.reshape(final_shape) outs[name] = pred_mu_final.reshape(final_shape)
outs[name + '_stds'] = pred_std_final.reshape(final_shape) outs[name + '_stds'] = pred_std_final.reshape(final_shape)
def parse_outputs(self, outs: Dict[str, np.ndarray]) -> Dict[str, np.ndarray]: def parse_outputs(self, outs: dict[str, np.ndarray]) -> dict[str, np.ndarray]:
self.parse_mdn('plan', outs, in_N=ModelConstants.PLAN_MHP_N, out_N=ModelConstants.PLAN_MHP_SELECTION, self.parse_mdn('plan', outs, in_N=ModelConstants.PLAN_MHP_N, out_N=ModelConstants.PLAN_MHP_SELECTION,
out_shape=(ModelConstants.IDX_N,ModelConstants.PLAN_WIDTH)) out_shape=(ModelConstants.IDX_N,ModelConstants.PLAN_WIDTH))
self.parse_mdn('lane_lines', outs, in_N=0, out_N=0, out_shape=(ModelConstants.NUM_LANE_LINES,ModelConstants.IDX_N,ModelConstants.LANE_LINES_WIDTH)) self.parse_mdn('lane_lines', outs, in_N=0, out_N=0, out_shape=(ModelConstants.NUM_LANE_LINES,ModelConstants.IDX_N,ModelConstants.LANE_LINES_WIDTH))

View File

@ -3,7 +3,7 @@ import itertools
import os import os
import sys import sys
import numpy as np import numpy as np
from typing import Tuple, Dict, Union, Any from typing import Any
from openpilot.selfdrive.modeld.runners.runmodel_pyx import RunModel from openpilot.selfdrive.modeld.runners.runmodel_pyx import RunModel
@ -38,7 +38,7 @@ def create_ort_session(path, fp16_to_fp32):
options = ort.SessionOptions() options = ort.SessionOptions()
options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_DISABLE_ALL options.graph_optimization_level = ort.GraphOptimizationLevel.ORT_DISABLE_ALL
provider: Union[str, Tuple[str, Dict[Any, Any]]] provider: str | tuple[str, dict[Any, Any]]
if 'OpenVINOExecutionProvider' in ort.get_available_providers() and 'ONNXCPU' not in os.environ: if 'OpenVINOExecutionProvider' in ort.get_available_providers() and 'ONNXCPU' not in os.environ:
provider = 'OpenVINOExecutionProvider' provider = 'OpenVINOExecutionProvider'
elif 'CUDAExecutionProvider' in ort.get_available_providers() and 'ONNXCPU' not in os.environ: elif 'CUDAExecutionProvider' in ort.get_available_providers() and 'ONNXCPU' not in os.environ:

View File

@ -2,7 +2,7 @@ from __future__ import annotations
import json import json
import math import math
from typing import Any, Dict, List, Optional, Tuple, Union, cast from typing import Any, cast
from openpilot.common.conversions import Conversions from openpilot.common.conversions import Conversions
from openpilot.common.numpy_fast import clip from openpilot.common.numpy_fast import clip
@ -22,13 +22,13 @@ class Coordinate:
def __init__(self, latitude: float, longitude: float) -> None: def __init__(self, latitude: float, longitude: float) -> None:
self.latitude = latitude self.latitude = latitude
self.longitude = longitude self.longitude = longitude
self.annotations: Dict[str, float] = {} self.annotations: dict[str, float] = {}
@classmethod @classmethod
def from_mapbox_tuple(cls, t: Tuple[float, float]) -> Coordinate: def from_mapbox_tuple(cls, t: tuple[float, float]) -> Coordinate:
return cls(t[1], t[0]) return cls(t[1], t[0])
def as_dict(self) -> Dict[str, float]: def as_dict(self) -> dict[str, float]:
return {'latitude': self.latitude, 'longitude': self.longitude} return {'latitude': self.latitude, 'longitude': self.longitude}
def __str__(self) -> str: def __str__(self) -> str:
@ -83,7 +83,7 @@ def minimum_distance(a: Coordinate, b: Coordinate, p: Coordinate):
return projection.distance_to(p) return projection.distance_to(p)
def distance_along_geometry(geometry: List[Coordinate], pos: Coordinate) -> float: def distance_along_geometry(geometry: list[Coordinate], pos: Coordinate) -> float:
if len(geometry) <= 2: if len(geometry) <= 2:
return geometry[0].distance_to(pos) return geometry[0].distance_to(pos)
@ -106,7 +106,7 @@ def distance_along_geometry(geometry: List[Coordinate], pos: Coordinate) -> floa
return total_distance_closest return total_distance_closest
def coordinate_from_param(param: str, params: Optional[Params] = None) -> Optional[Coordinate]: def coordinate_from_param(param: str, params: Params | None = None) -> Coordinate | None:
if params is None: if params is None:
params = Params() params = Params()
@ -130,7 +130,7 @@ def string_to_direction(direction: str) -> str:
return 'none' return 'none'
def maxspeed_to_ms(maxspeed: Dict[str, Union[str, float]]) -> float: def maxspeed_to_ms(maxspeed: dict[str, str | float]) -> float:
unit = cast(str, maxspeed['unit']) unit = cast(str, maxspeed['unit'])
speed = cast(float, maxspeed['speed']) speed = cast(float, maxspeed['speed'])
return SPEED_CONVERSIONS[unit] * speed return SPEED_CONVERSIONS[unit] * speed
@ -140,7 +140,7 @@ def field_valid(dat: dict, field: str) -> bool:
return field in dat and dat[field] is not None return field in dat and dat[field] is not None
def parse_banner_instructions(banners: Any, distance_to_maneuver: float = 0.0) -> Optional[Dict[str, Any]]: def parse_banner_instructions(banners: Any, distance_to_maneuver: float = 0.0) -> dict[str, Any] | None:
if not len(banners): if not len(banners):
return None return None

View File

@ -5,7 +5,7 @@ import time
from pathlib import Path from pathlib import Path
from collections import defaultdict from collections import defaultdict
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import NoReturn, Union, List, Dict from typing import NoReturn
from openpilot.common.params import Params from openpilot.common.params import Params
from cereal.messaging import SubMaster from cereal.messaging import SubMaster
@ -61,7 +61,7 @@ class StatLog:
def main() -> NoReturn: def main() -> NoReturn:
dongle_id = Params().get("DongleId", encoding='utf-8') dongle_id = Params().get("DongleId", encoding='utf-8')
def get_influxdb_line(measurement: str, value: Union[float, Dict[str, float]], timestamp: datetime, tags: dict) -> str: def get_influxdb_line(measurement: str, value: float | dict[str, float], timestamp: datetime, tags: dict) -> str:
res = f"{measurement}" res = f"{measurement}"
for k, v in tags.items(): for k, v in tags.items():
res += f",{k}={str(v)}" res += f",{k}={str(v)}"
@ -102,7 +102,7 @@ def main() -> NoReturn:
idx = 0 idx = 0
last_flush_time = time.monotonic() last_flush_time = time.monotonic()
gauges = {} gauges = {}
samples: Dict[str, List[float]] = defaultdict(list) samples: dict[str, list[float]] = defaultdict(list)
try: try:
while True: while True:
started_prev = sm['deviceState'].started started_prev = sm['deviceState'].started

View File

@ -11,7 +11,7 @@ from openpilot.selfdrive.ui.qt.python_helpers import set_main_window
class Window(QWidget): class Window(QWidget):
def __init__(self, parent=None): def __init__(self, parent=None):
super(Window, self).__init__(parent) super().__init__(parent)
layout = QVBoxLayout() layout = QVBoxLayout()
self.setLayout(layout) self.setLayout(layout)
@ -47,7 +47,7 @@ class Window(QWidget):
def update(self): def update(self):
for cmd, label in self.labels.items(): for cmd, label in self.labels.items():
out = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, out = subprocess.run(cmd, capture_output=True,
shell=True, check=False, encoding='utf8').stdout shell=True, check=False, encoding='utf8').stdout
label.setText(out.strip()) label.setText(out.strip())

View File

@ -1,6 +1,7 @@
import capnp import capnp
import hypothesis.strategies as st import hypothesis.strategies as st
from typing import Any, Callable, Dict, List, Optional, Union from typing import Any
from collections.abc import Callable
from cereal import log from cereal import log
@ -12,7 +13,7 @@ class FuzzyGenerator:
self.draw = draw self.draw = draw
self.real_floats = real_floats self.real_floats = real_floats
def generate_native_type(self, field: str) -> st.SearchStrategy[Union[bool, int, float, str, bytes]]: def generate_native_type(self, field: str) -> st.SearchStrategy[bool | int | float | str | bytes]:
def floats(**kwargs) -> st.SearchStrategy[float]: def floats(**kwargs) -> st.SearchStrategy[float]:
allow_nan = not self.real_floats allow_nan = not self.real_floats
allow_infinity = not self.real_floats allow_infinity = not self.real_floats
@ -67,18 +68,18 @@ class FuzzyGenerator:
else: else:
return self.generate_struct(field.schema) return self.generate_struct(field.schema)
def generate_struct(self, schema: capnp.lib.capnp._StructSchema, event: Optional[str] = None) -> st.SearchStrategy[Dict[str, Any]]: def generate_struct(self, schema: capnp.lib.capnp._StructSchema, event: str | None = None) -> st.SearchStrategy[dict[str, Any]]:
full_fill: List[str] = list(schema.non_union_fields) full_fill: list[str] = list(schema.non_union_fields)
single_fill: List[str] = [event] if event else [self.draw(st.sampled_from(schema.union_fields))] if schema.union_fields else [] single_fill: list[str] = [event] if event else [self.draw(st.sampled_from(schema.union_fields))] if schema.union_fields else []
return st.fixed_dictionaries({field: self.generate_field(schema.fields[field]) for field in full_fill + single_fill}) return st.fixed_dictionaries({field: self.generate_field(schema.fields[field]) for field in full_fill + single_fill})
@classmethod @classmethod
def get_random_msg(cls, draw: DrawType, struct: capnp.lib.capnp._StructModule, real_floats: bool = False) -> Dict[str, Any]: def get_random_msg(cls, draw: DrawType, struct: capnp.lib.capnp._StructModule, real_floats: bool = False) -> dict[str, Any]:
fg = cls(draw, real_floats=real_floats) fg = cls(draw, real_floats=real_floats)
data: Dict[str, Any] = draw(fg.generate_struct(struct.schema)) data: dict[str, Any] = draw(fg.generate_struct(struct.schema))
return data return data
@classmethod @classmethod
def get_random_event_msg(cls, draw: DrawType, events: List[str], real_floats: bool = False) -> List[Dict[str, Any]]: def get_random_event_msg(cls, draw: DrawType, events: list[str], real_floats: bool = False) -> list[dict[str, Any]]:
fg = cls(draw, real_floats=real_floats) fg = cls(draw, real_floats=real_floats)
return [draw(fg.generate_struct(log.Event.schema, e)) for e in sorted(events)] return [draw(fg.generate_struct(log.Event.schema, e)) for e in sorted(events)]

View File

@ -72,7 +72,7 @@ def noop(*args, **kwargs):
def read_segment_list(segment_list_path): def read_segment_list(segment_list_path):
with open(segment_list_path, "r") as f: with open(segment_list_path) as f:
seg_list = f.read().splitlines() seg_list = f.read().splitlines()
return [(platform[2:], segment) for platform, segment in zip(seg_list[::2], seg_list[1::2], strict=True)] return [(platform[2:], segment) for platform, segment in zip(seg_list[::2], seg_list[1::2], strict=True)]

View File

@ -1,7 +1,7 @@
import os import os
import sys import sys
from typing import Tuple, no_type_check from typing import no_type_check
class FdRedirect: class FdRedirect:
def __init__(self, file_prefix: str, fd: int): def __init__(self, file_prefix: str, fd: int):
@ -53,7 +53,7 @@ class ProcessOutputCapture:
self.stdout_redirect.link() self.stdout_redirect.link()
self.stderr_redirect.link() self.stderr_redirect.link()
def read_outerr(self) -> Tuple[str, str]: def read_outerr(self) -> tuple[str, str]:
out_str = self.stdout_redirect.read().decode() out_str = self.stdout_redirect.read().decode()
err_str = self.stderr_redirect.read().decode() err_str = self.stderr_redirect.read().decode()
return out_str, err_str return out_str, err_str

View File

@ -5,7 +5,6 @@ import capnp
import numbers import numbers
import dictdiffer import dictdiffer
from collections import Counter from collections import Counter
from typing import Dict
from openpilot.tools.lib.logreader import LogReader from openpilot.tools.lib.logreader import LogReader
@ -97,7 +96,7 @@ def format_process_diff(diff):
diff_short += f" {diff}\n" diff_short += f" {diff}\n"
diff_long += f"\t{diff}\n" diff_long += f"\t{diff}\n"
else: else:
cnt: Dict[str, int] = {} cnt: dict[str, int] = {}
for d in diff: for d in diff:
diff_long += f"\t{str(d)}\n" diff_long += f"\t{str(d)}\n"

View File

@ -8,7 +8,8 @@ import signal
import platform import platform
from collections import OrderedDict from collections import OrderedDict
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Dict, List, Optional, Callable, Union, Any, Iterable, Tuple from typing import Any
from collections.abc import Callable, Iterable
from tqdm import tqdm from tqdm import tqdm
import capnp import capnp
@ -36,9 +37,9 @@ FAKEDATA = os.path.join(PROC_REPLAY_DIR, "fakedata/")
class DummySocket: class DummySocket:
def __init__(self): def __init__(self):
self.data: List[bytes] = [] self.data: list[bytes] = []
def receive(self, non_blocking: bool = False) -> Optional[bytes]: def receive(self, non_blocking: bool = False) -> bytes | None:
if non_blocking: if non_blocking:
return None return None
@ -128,21 +129,21 @@ class ReplayContext:
@dataclass @dataclass
class ProcessConfig: class ProcessConfig:
proc_name: str proc_name: str
pubs: List[str] pubs: list[str]
subs: List[str] subs: list[str]
ignore: List[str] ignore: list[str]
config_callback: Optional[Callable] = None config_callback: Callable | None = None
init_callback: Optional[Callable] = None init_callback: Callable | None = None
should_recv_callback: Optional[Callable] = None should_recv_callback: Callable | None = None
tolerance: Optional[float] = None tolerance: float | None = None
processing_time: float = 0.001 processing_time: float = 0.001
timeout: int = 30 timeout: int = 30
simulation: bool = True simulation: bool = True
main_pub: Optional[str] = None main_pub: str | None = None
main_pub_drained: bool = True main_pub_drained: bool = True
vision_pubs: List[str] = field(default_factory=list) vision_pubs: list[str] = field(default_factory=list)
ignore_alive_pubs: List[str] = field(default_factory=list) ignore_alive_pubs: list[str] = field(default_factory=list)
unlocked_pubs: List[str] = field(default_factory=list) unlocked_pubs: list[str] = field(default_factory=list)
class ProcessContainer: class ProcessContainer:
@ -150,25 +151,25 @@ class ProcessContainer:
self.prefix = OpenpilotPrefix(clean_dirs_on_exit=False) self.prefix = OpenpilotPrefix(clean_dirs_on_exit=False)
self.cfg = copy.deepcopy(cfg) self.cfg = copy.deepcopy(cfg)
self.process = copy.deepcopy(managed_processes[cfg.proc_name]) self.process = copy.deepcopy(managed_processes[cfg.proc_name])
self.msg_queue: List[capnp._DynamicStructReader] = [] self.msg_queue: list[capnp._DynamicStructReader] = []
self.cnt = 0 self.cnt = 0
self.pm: Optional[messaging.PubMaster] = None self.pm: messaging.PubMaster | None = None
self.sockets: Optional[List[messaging.SubSocket]] = None self.sockets: list[messaging.SubSocket] | None = None
self.rc: Optional[ReplayContext] = None self.rc: ReplayContext | None = None
self.vipc_server: Optional[VisionIpcServer] = None self.vipc_server: VisionIpcServer | None = None
self.environ_config: Optional[Dict[str, Any]] = None self.environ_config: dict[str, Any] | None = None
self.capture: Optional[ProcessOutputCapture] = None self.capture: ProcessOutputCapture | None = None
@property @property
def has_empty_queue(self) -> bool: def has_empty_queue(self) -> bool:
return len(self.msg_queue) == 0 return len(self.msg_queue) == 0
@property @property
def pubs(self) -> List[str]: def pubs(self) -> list[str]:
return self.cfg.pubs return self.cfg.pubs
@property @property
def subs(self) -> List[str]: def subs(self) -> list[str]:
return self.cfg.subs return self.cfg.subs
def _clean_env(self): def _clean_env(self):
@ -180,7 +181,7 @@ class ProcessContainer:
if k in os.environ: if k in os.environ:
del os.environ[k] del os.environ[k]
def _setup_env(self, params_config: Dict[str, Any], environ_config: Dict[str, Any]): def _setup_env(self, params_config: dict[str, Any], environ_config: dict[str, Any]):
for k, v in environ_config.items(): for k, v in environ_config.items():
if len(v) != 0: if len(v) != 0:
os.environ[k] = v os.environ[k] = v
@ -202,7 +203,7 @@ class ProcessContainer:
self.environ_config = environ_config self.environ_config = environ_config
def _setup_vision_ipc(self, all_msgs: LogIterable, frs: Dict[str, Any]): def _setup_vision_ipc(self, all_msgs: LogIterable, frs: dict[str, Any]):
assert len(self.cfg.vision_pubs) != 0 assert len(self.cfg.vision_pubs) != 0
vipc_server = VisionIpcServer("camerad") vipc_server = VisionIpcServer("camerad")
@ -223,9 +224,9 @@ class ProcessContainer:
self.process.start() self.process.start()
def start( def start(
self, params_config: Dict[str, Any], environ_config: Dict[str, Any], self, params_config: dict[str, Any], environ_config: dict[str, Any],
all_msgs: LogIterable, frs: Optional[Dict[str, BaseFrameReader]], all_msgs: LogIterable, frs: dict[str, BaseFrameReader] | None,
fingerprint: Optional[str], capture_output: bool fingerprint: str | None, capture_output: bool
): ):
with self.prefix as p: with self.prefix as p:
self._setup_env(params_config, environ_config) self._setup_env(params_config, environ_config)
@ -266,7 +267,7 @@ class ProcessContainer:
self.prefix.clean_dirs() self.prefix.clean_dirs()
self._clean_env() self._clean_env()
def run_step(self, msg: capnp._DynamicStructReader, frs: Optional[Dict[str, BaseFrameReader]]) -> List[capnp._DynamicStructReader]: def run_step(self, msg: capnp._DynamicStructReader, frs: dict[str, BaseFrameReader] | None) -> list[capnp._DynamicStructReader]:
assert self.rc and self.pm and self.sockets and self.process.proc assert self.rc and self.pm and self.sockets and self.process.proc
output_msgs = [] output_msgs = []
@ -580,7 +581,7 @@ def get_process_config(name: str) -> ProcessConfig:
raise Exception(f"Cannot find process config with name: {name}") from ex raise Exception(f"Cannot find process config with name: {name}") from ex
def get_custom_params_from_lr(lr: LogIterable, initial_state: str = "first") -> Dict[str, Any]: def get_custom_params_from_lr(lr: LogIterable, initial_state: str = "first") -> dict[str, Any]:
""" """
Use this to get custom params dict based on provided logs. Use this to get custom params dict based on provided logs.
Useful when replaying following processes: calibrationd, paramsd, torqued Useful when replaying following processes: calibrationd, paramsd, torqued
@ -614,7 +615,7 @@ def get_custom_params_from_lr(lr: LogIterable, initial_state: str = "first") ->
return custom_params return custom_params
def replay_process_with_name(name: Union[str, Iterable[str]], lr: LogIterable, *args, **kwargs) -> List[capnp._DynamicStructReader]: def replay_process_with_name(name: str | Iterable[str], lr: LogIterable, *args, **kwargs) -> list[capnp._DynamicStructReader]:
if isinstance(name, str): if isinstance(name, str):
cfgs = [get_process_config(name)] cfgs = [get_process_config(name)]
elif isinstance(name, Iterable): elif isinstance(name, Iterable):
@ -626,10 +627,10 @@ def replay_process_with_name(name: Union[str, Iterable[str]], lr: LogIterable, *
def replay_process( def replay_process(
cfg: Union[ProcessConfig, Iterable[ProcessConfig]], lr: LogIterable, frs: Optional[Dict[str, BaseFrameReader]] = None, cfg: ProcessConfig | Iterable[ProcessConfig], lr: LogIterable, frs: dict[str, BaseFrameReader] | None = None,
fingerprint: Optional[str] = None, return_all_logs: bool = False, custom_params: Optional[Dict[str, Any]] = None, fingerprint: str | None = None, return_all_logs: bool = False, custom_params: dict[str, Any] | None = None,
captured_output_store: Optional[Dict[str, Dict[str, str]]] = None, disable_progress: bool = False captured_output_store: dict[str, dict[str, str]] | None = None, disable_progress: bool = False
) -> List[capnp._DynamicStructReader]: ) -> list[capnp._DynamicStructReader]:
if isinstance(cfg, Iterable): if isinstance(cfg, Iterable):
cfgs = list(cfg) cfgs = list(cfg)
else: else:
@ -654,9 +655,9 @@ def replay_process(
def _replay_multi_process( def _replay_multi_process(
cfgs: List[ProcessConfig], lr: LogIterable, frs: Optional[Dict[str, BaseFrameReader]], fingerprint: Optional[str], cfgs: list[ProcessConfig], lr: LogIterable, frs: dict[str, BaseFrameReader] | None, fingerprint: str | None,
custom_params: Optional[Dict[str, Any]], captured_output_store: Optional[Dict[str, Dict[str, str]]], disable_progress: bool custom_params: dict[str, Any] | None, captured_output_store: dict[str, dict[str, str]] | None, disable_progress: bool
) -> List[capnp._DynamicStructReader]: ) -> list[capnp._DynamicStructReader]:
if fingerprint is not None: if fingerprint is not None:
params_config = generate_params_config(lr=lr, fingerprint=fingerprint, custom_params=custom_params) params_config = generate_params_config(lr=lr, fingerprint=fingerprint, custom_params=custom_params)
env_config = generate_environ_config(fingerprint=fingerprint) env_config = generate_environ_config(fingerprint=fingerprint)
@ -690,10 +691,10 @@ def _replay_multi_process(
pub_msgs = [msg for msg in all_msgs if msg.which() in lr_pubs] pub_msgs = [msg for msg in all_msgs if msg.which() in lr_pubs]
# external queue for messages taken from logs; internal queue for messages generated by processes, which will be republished # external queue for messages taken from logs; internal queue for messages generated by processes, which will be republished
external_pub_queue: List[capnp._DynamicStructReader] = pub_msgs.copy() external_pub_queue: list[capnp._DynamicStructReader] = pub_msgs.copy()
internal_pub_queue: List[capnp._DynamicStructReader] = [] internal_pub_queue: list[capnp._DynamicStructReader] = []
# heap for maintaining the order of messages generated by processes, where each element: (logMonoTime, index in internal_pub_queue) # heap for maintaining the order of messages generated by processes, where each element: (logMonoTime, index in internal_pub_queue)
internal_pub_index_heap: List[Tuple[int, int]] = [] internal_pub_index_heap: list[tuple[int, int]] = []
pbar = tqdm(total=len(external_pub_queue), disable=disable_progress) pbar = tqdm(total=len(external_pub_queue), disable=disable_progress)
while len(external_pub_queue) != 0 or (len(internal_pub_index_heap) != 0 and not all(c.has_empty_queue for c in containers)): while len(external_pub_queue) != 0 or (len(internal_pub_index_heap) != 0 and not all(c.has_empty_queue for c in containers)):
@ -723,7 +724,7 @@ def _replay_multi_process(
return log_msgs return log_msgs
def generate_params_config(lr=None, CP=None, fingerprint=None, custom_params=None) -> Dict[str, Any]: def generate_params_config(lr=None, CP=None, fingerprint=None, custom_params=None) -> dict[str, Any]:
params_dict = { params_dict = {
"OpenpilotEnabledToggle": True, "OpenpilotEnabledToggle": True,
"DisengageOnAccelerator": True, "DisengageOnAccelerator": True,
@ -755,7 +756,7 @@ def generate_params_config(lr=None, CP=None, fingerprint=None, custom_params=Non
return params_dict return params_dict
def generate_environ_config(CP=None, fingerprint=None, log_dir=None) -> Dict[str, Any]: def generate_environ_config(CP=None, fingerprint=None, log_dir=None) -> dict[str, Any]:
environ_dict = {} environ_dict = {}
if platform.system() != "Darwin": if platform.system() != "Darwin":
environ_dict["PARAMS_ROOT"] = "/dev/shm/params" environ_dict["PARAMS_ROOT"] = "/dev/shm/params"

View File

@ -5,7 +5,8 @@ import time
import capnp import capnp
import numpy as np import numpy as np
from typing import Union, Iterable, Optional, List, Any, Dict, Tuple from typing import Any
from collections.abc import Iterable
from openpilot.selfdrive.test.process_replay.process_replay import CONFIGS, FAKEDATA, ProcessConfig, replay_process, get_process_config, \ from openpilot.selfdrive.test.process_replay.process_replay import CONFIGS, FAKEDATA, ProcessConfig, replay_process, get_process_config, \
check_openpilot_enabled, get_custom_params_from_lr check_openpilot_enabled, get_custom_params_from_lr
@ -40,9 +41,9 @@ class DummyFrameReader(BaseFrameReader):
def regen_segment( def regen_segment(
lr: LogIterable, frs: Optional[Dict[str, Any]] = None, lr: LogIterable, frs: dict[str, Any] | None = None,
processes: Iterable[ProcessConfig] = CONFIGS, disable_tqdm: bool = False processes: Iterable[ProcessConfig] = CONFIGS, disable_tqdm: bool = False
) -> List[capnp._DynamicStructReader]: ) -> list[capnp._DynamicStructReader]:
all_msgs = sorted(lr, key=lambda m: m.logMonoTime) all_msgs = sorted(lr, key=lambda m: m.logMonoTime)
custom_params = get_custom_params_from_lr(all_msgs) custom_params = get_custom_params_from_lr(all_msgs)
@ -57,7 +58,7 @@ def regen_segment(
def setup_data_readers( def setup_data_readers(
route: str, sidx: int, use_route_meta: bool, route: str, sidx: int, use_route_meta: bool,
needs_driver_cam: bool = True, needs_road_cam: bool = True, dummy_driver_cam: bool = False needs_driver_cam: bool = True, needs_road_cam: bool = True, dummy_driver_cam: bool = False
) -> Tuple[LogReader, Dict[str, Any]]: ) -> tuple[LogReader, dict[str, Any]]:
if use_route_meta: if use_route_meta:
r = Route(route) r = Route(route)
lr = LogReader(r.log_paths()[sidx]) lr = LogReader(r.log_paths()[sidx])
@ -92,7 +93,7 @@ def setup_data_readers(
def regen_and_save( def regen_and_save(
route: str, sidx: int, processes: Union[str, Iterable[str]] = "all", outdir: str = FAKEDATA, route: str, sidx: int, processes: str | Iterable[str] = "all", outdir: str = FAKEDATA,
upload: bool = False, use_route_meta: bool = False, disable_tqdm: bool = False, dummy_driver_cam: bool = False upload: bool = False, use_route_meta: bool = False, disable_tqdm: bool = False, dummy_driver_cam: bool = False
) -> str: ) -> str:
if not isinstance(processes, str) and not hasattr(processes, "__iter__"): if not isinstance(processes, str) and not hasattr(processes, "__iter__"):

View File

@ -30,7 +30,7 @@ def get_frame_fn(ref_commit, test_route, tici=True):
def bzip_frames(frames): def bzip_frames(frames):
data = bytes() data = b''
for y, u, v in frames: for y, u, v in frames:
data += y.tobytes() data += y.tobytes()
data += u.tobytes() data += u.tobytes()

View File

@ -5,7 +5,7 @@ import os
import sys import sys
from collections import defaultdict from collections import defaultdict
from tqdm import tqdm from tqdm import tqdm
from typing import Any, DefaultDict, Dict from typing import Any
from openpilot.selfdrive.car.car_helpers import interface_names from openpilot.selfdrive.car.car_helpers import interface_names
from openpilot.tools.lib.openpilotci import get_url, upload_file from openpilot.tools.lib.openpilotci import get_url, upload_file
@ -172,11 +172,11 @@ if __name__ == "__main__":
untested = (set(interface_names) - set(excluded_interfaces)) - {c.lower() for c in tested_cars} untested = (set(interface_names) - set(excluded_interfaces)) - {c.lower() for c in tested_cars}
assert len(untested) == 0, f"Cars missing routes: {str(untested)}" assert len(untested) == 0, f"Cars missing routes: {str(untested)}"
log_paths: DefaultDict[str, Dict[str, Dict[str, str]]] = defaultdict(lambda: defaultdict(dict)) log_paths: defaultdict[str, dict[str, dict[str, str]]] = defaultdict(lambda: defaultdict(dict))
with concurrent.futures.ProcessPoolExecutor(max_workers=args.jobs) as pool: with concurrent.futures.ProcessPoolExecutor(max_workers=args.jobs) as pool:
if not args.upload_only: if not args.upload_only:
download_segments = [seg for car, seg in segments if car in tested_cars] download_segments = [seg for car, seg in segments if car in tested_cars]
log_data: Dict[str, LogReader] = {} log_data: dict[str, LogReader] = {}
p1 = pool.map(get_log_data, download_segments) p1 = pool.map(get_log_data, download_segments)
for segment, lr in tqdm(p1, desc="Getting Logs", total=len(download_segments)): for segment, lr in tqdm(p1, desc="Getting Logs", total=len(download_segments)):
log_data[segment] = lr log_data[segment] = lr

View File

@ -3,7 +3,7 @@ import os
import re import re
import subprocess import subprocess
import sys import sys
from typing import Iterable, List, Optional from collections.abc import Iterable
from tqdm import tqdm from tqdm import tqdm
@ -12,14 +12,14 @@ from openpilot.selfdrive.test.process_replay.test_processes import source_segmen
from openpilot.tools.lib.azure_container import AzureContainer from openpilot.tools.lib.azure_container import AzureContainer
from openpilot.tools.lib.openpilotcontainers import DataCIContainer, DataProdContainer, OpenpilotCIContainer from openpilot.tools.lib.openpilotcontainers import DataCIContainer, DataProdContainer, OpenpilotCIContainer
SOURCES: List[AzureContainer] = [ SOURCES: list[AzureContainer] = [
DataProdContainer, DataProdContainer,
DataCIContainer DataCIContainer
] ]
DEST = OpenpilotCIContainer DEST = OpenpilotCIContainer
def upload_route(path: str, exclude_patterns: Optional[Iterable[str]] = None) -> None: def upload_route(path: str, exclude_patterns: Iterable[str] | None = None) -> None:
if exclude_patterns is None: if exclude_patterns is None:
exclude_patterns = [r'dcamera\.hevc'] exclude_patterns = [r'dcamera\.hevc']

View File

@ -1,6 +1,5 @@
import time import time
import threading import threading
from typing import Optional
from openpilot.common.params import Params from openpilot.common.params import Params
from openpilot.system.hardware import HARDWARE from openpilot.system.hardware import HARDWARE
@ -38,7 +37,7 @@ class PowerMonitoring:
self.car_battery_capacity_uWh = max((CAR_BATTERY_CAPACITY_uWh / 10), int(car_battery_capacity_uWh)) self.car_battery_capacity_uWh = max((CAR_BATTERY_CAPACITY_uWh / 10), int(car_battery_capacity_uWh))
# Calculation tick # Calculation tick
def calculate(self, voltage: Optional[int], ignition: bool): def calculate(self, voltage: int | None, ignition: bool):
try: try:
now = time.monotonic() now = time.monotonic()
@ -108,7 +107,7 @@ class PowerMonitoring:
return int(self.car_battery_capacity_uWh) return int(self.car_battery_capacity_uWh)
# See if we need to shutdown # See if we need to shutdown
def should_shutdown(self, ignition: bool, in_car: bool, offroad_timestamp: Optional[float], started_seen: bool): def should_shutdown(self, ignition: bool, in_car: bool, offroad_timestamp: float | None, started_seen: bool):
if offroad_timestamp is None: if offroad_timestamp is None:
return False return False

View File

@ -6,7 +6,6 @@ import threading
import time import time
from collections import OrderedDict, namedtuple from collections import OrderedDict, namedtuple
from pathlib import Path from pathlib import Path
from typing import Dict, Optional, Tuple
import psutil import psutil
@ -50,9 +49,9 @@ THERMAL_BANDS = OrderedDict({
# Override to highest thermal band when offroad and above this temp # Override to highest thermal band when offroad and above this temp
OFFROAD_DANGER_TEMP = 75 OFFROAD_DANGER_TEMP = 75
prev_offroad_states: Dict[str, Tuple[bool, Optional[str]]] = {} prev_offroad_states: dict[str, tuple[bool, str | None]] = {}
tz_by_type: Optional[Dict[str, int]] = None tz_by_type: dict[str, int] | None = None
def populate_tz_by_type(): def populate_tz_by_type():
global tz_by_type global tz_by_type
tz_by_type = {} tz_by_type = {}
@ -87,7 +86,7 @@ def read_thermal(thermal_config):
return dat return dat
def set_offroad_alert_if_changed(offroad_alert: str, show_alert: bool, extra_text: Optional[str]=None): def set_offroad_alert_if_changed(offroad_alert: str, show_alert: bool, extra_text: str | None=None):
if prev_offroad_states.get(offroad_alert, None) == (show_alert, extra_text): if prev_offroad_states.get(offroad_alert, None) == (show_alert, extra_text):
return return
prev_offroad_states[offroad_alert] = (show_alert, extra_text) prev_offroad_states[offroad_alert] = (show_alert, extra_text)
@ -169,16 +168,16 @@ def thermald_thread(end_event, hw_queue) -> None:
count = 0 count = 0
onroad_conditions: Dict[str, bool] = { onroad_conditions: dict[str, bool] = {
"ignition": False, "ignition": False,
} }
startup_conditions: Dict[str, bool] = {} startup_conditions: dict[str, bool] = {}
startup_conditions_prev: Dict[str, bool] = {} startup_conditions_prev: dict[str, bool] = {}
off_ts: Optional[float] = None off_ts: float | None = None
started_ts: Optional[float] = None started_ts: float | None = None
started_seen = False started_seen = False
startup_blocked_ts: Optional[float] = None startup_blocked_ts: float | None = None
thermal_status = ThermalStatus.yellow thermal_status = ThermalStatus.yellow
last_hw_state = HardwareState( last_hw_state = HardwareState(

View File

@ -3,7 +3,6 @@ import numpy as np
import time import time
import wave import wave
from typing import Dict, Optional, Tuple
from cereal import car, messaging from cereal import car, messaging
from openpilot.common.basedir import BASEDIR from openpilot.common.basedir import BASEDIR
@ -27,7 +26,7 @@ DB_SCALE = 30 # AMBIENT_DB + DB_SCALE is where MAX_VOLUME is applied
AudibleAlert = car.CarControl.HUDControl.AudibleAlert AudibleAlert = car.CarControl.HUDControl.AudibleAlert
sound_list: Dict[int, Tuple[str, Optional[int], float]] = { sound_list: dict[int, tuple[str, int | None, float]] = {
# AudibleAlert, file name, play count (none for infinite) # AudibleAlert, file name, play count (none for infinite)
AudibleAlert.engage: ("engage.wav", 1, MAX_VOLUME), AudibleAlert.engage: ("engage.wav", 1, MAX_VOLUME),
AudibleAlert.disengage: ("disengage.wav", 1, MAX_VOLUME), AudibleAlert.disengage: ("disengage.wav", 1, MAX_VOLUME),
@ -64,7 +63,7 @@ class Soundd:
self.spl_filter_weighted = FirstOrderFilter(0, 2.5, FILTER_DT, initialized=False) self.spl_filter_weighted = FirstOrderFilter(0, 2.5, FILTER_DT, initialized=False)
def load_sounds(self): def load_sounds(self):
self.loaded_sounds: Dict[int, np.ndarray] = {} self.loaded_sounds: dict[int, np.ndarray] = {}
# Load all sounds # Load all sounds
for sound in sound_list: for sound in sound_list:

View File

@ -12,7 +12,7 @@ from parameterized import parameterized_class
from openpilot.selfdrive.ui.update_translations import TRANSLATIONS_DIR, LANGUAGES_FILE, update_translations from openpilot.selfdrive.ui.update_translations import TRANSLATIONS_DIR, LANGUAGES_FILE, update_translations
with open(LANGUAGES_FILE, "r") as f: with open(LANGUAGES_FILE) as f:
translation_files = json.load(f) translation_files = json.load(f)
UNFINISHED_TRANSLATION_TAG = "<translation type=\"unfinished\"" # non-empty translations can be marked unfinished UNFINISHED_TRANSLATION_TAG = "<translation type=\"unfinished\"" # non-empty translations can be marked unfinished
@ -28,7 +28,7 @@ class TestTranslations(unittest.TestCase):
@staticmethod @staticmethod
def _read_translation_file(path, file): def _read_translation_file(path, file):
tr_file = os.path.join(path, f"{file}.ts") tr_file = os.path.join(path, f"{file}.ts")
with open(tr_file, "r") as f: with open(tr_file) as f:
return f.read() return f.read()
def test_missing_translation_files(self): def test_missing_translation_files(self):
@ -83,7 +83,7 @@ class TestTranslations(unittest.TestCase):
for nf in numerusform: for nf in numerusform:
self.assertIsNotNone(nf, f"Ensure all plural translation forms are completed: {source_text}") self.assertIsNotNone(nf, f"Ensure all plural translation forms are completed: {source_text}")
self.assertIn("%n", nf, "Ensure numerus argument (%n) exists in translation.") self.assertIn("%n", nf, "Ensure numerus argument (%n) exists in translation.")
self.assertIsNone(FORMAT_ARG.search(nf), "Plural translations must use %n, not %1, %2, etc.: {}".format(numerusform)) self.assertIsNone(FORMAT_ARG.search(nf), f"Plural translations must use %n, not %1, %2, etc.: {numerusform}")
else: else:
self.assertIsNotNone(translation.text, f"Ensure translation is completed: {source_text}") self.assertIsNotNone(translation.text, f"Ensure translation is completed: {source_text}")

View File

@ -13,13 +13,13 @@ BADGE_HEIGHT = 20 + 8
SHIELDS_URL = "https://img.shields.io/badge" SHIELDS_URL = "https://img.shields.io/badge"
if __name__ == "__main__": if __name__ == "__main__":
with open(LANGUAGES_FILE, "r") as f: with open(LANGUAGES_FILE) as f:
translation_files = json.load(f) translation_files = json.load(f)
badge_svg = [] badge_svg = []
max_badge_width = 0 # keep track of max width to set parent element max_badge_width = 0 # keep track of max width to set parent element
for idx, (name, file) in enumerate(translation_files.items()): for idx, (name, file) in enumerate(translation_files.items()):
with open(os.path.join(TRANSLATIONS_DIR, f"{file}.ts"), "r") as tr_f: with open(os.path.join(TRANSLATIONS_DIR, f"{file}.ts")) as tr_f:
tr_file = tr_f.read() tr_file = tr_f.read()
total_translations = 0 total_translations = 0

View File

@ -28,7 +28,7 @@ def update_translations(vanish: bool = False, translation_files: None | list[str
generate_translations_include() generate_translations_include()
if translation_files is None: if translation_files is None:
with open(LANGUAGES_FILE, "r") as f: with open(LANGUAGES_FILE) as f:
translation_files = json.load(f).values() translation_files = json.load(f).values()
for file in translation_files: for file in translation_files:

View File

@ -11,7 +11,6 @@ import time
import threading import threading
from collections import defaultdict from collections import defaultdict
from pathlib import Path from pathlib import Path
from typing import List, Union, Optional
from markdown_it import MarkdownIt from markdown_it import MarkdownIt
from openpilot.common.basedir import BASEDIR from openpilot.common.basedir import BASEDIR
@ -64,7 +63,7 @@ def write_time_to_param(params, param) -> None:
t = datetime.datetime.utcnow() t = datetime.datetime.utcnow()
params.put(param, t.isoformat().encode('utf8')) params.put(param, t.isoformat().encode('utf8'))
def read_time_from_param(params, param) -> Optional[datetime.datetime]: def read_time_from_param(params, param) -> datetime.datetime | None:
t = params.get(param, encoding='utf8') t = params.get(param, encoding='utf8')
try: try:
return datetime.datetime.fromisoformat(t) return datetime.datetime.fromisoformat(t)
@ -72,7 +71,7 @@ def read_time_from_param(params, param) -> Optional[datetime.datetime]:
pass pass
return None return None
def run(cmd: List[str], cwd: Optional[str] = None) -> str: def run(cmd: list[str], cwd: str | None = None) -> str:
return subprocess.check_output(cmd, cwd=cwd, stderr=subprocess.STDOUT, encoding='utf8') return subprocess.check_output(cmd, cwd=cwd, stderr=subprocess.STDOUT, encoding='utf8')
@ -234,7 +233,7 @@ def handle_agnos_update() -> None:
class Updater: class Updater:
def __init__(self): def __init__(self):
self.params = Params() self.params = Params()
self.branches = defaultdict(lambda: '') self.branches = defaultdict(str)
self._has_internet: bool = False self._has_internet: bool = False
@property @property
@ -243,7 +242,7 @@ class Updater:
@property @property
def target_branch(self) -> str: def target_branch(self) -> str:
b: Union[str, None] = self.params.get("UpdaterTargetBranch", encoding='utf-8') b: str | None = self.params.get("UpdaterTargetBranch", encoding='utf-8')
if b is None: if b is None:
b = self.get_branch(BASEDIR) b = self.get_branch(BASEDIR)
return b return b
@ -272,7 +271,7 @@ class Updater:
def get_commit_hash(self, path: str = OVERLAY_MERGED) -> str: def get_commit_hash(self, path: str = OVERLAY_MERGED) -> str:
return run(["git", "rev-parse", "HEAD"], path).rstrip() return run(["git", "rev-parse", "HEAD"], path).rstrip()
def set_params(self, update_success: bool, failed_count: int, exception: Optional[str]) -> None: def set_params(self, update_success: bool, failed_count: int, exception: str | None) -> None:
self.params.put("UpdateFailedCount", str(failed_count)) self.params.put("UpdateFailedCount", str(failed_count))
self.params.put("UpdaterTargetBranch", self.target_branch) self.params.put("UpdaterTargetBranch", self.target_branch)

View File

@ -1,6 +1,5 @@
from abc import abstractmethod, ABC from abc import abstractmethod, ABC
from collections import namedtuple from collections import namedtuple
from typing import Dict
from cereal import log from cereal import log
@ -10,7 +9,7 @@ NetworkType = log.DeviceState.NetworkType
class HardwareBase(ABC): class HardwareBase(ABC):
@staticmethod @staticmethod
def get_cmdline() -> Dict[str, str]: def get_cmdline() -> dict[str, str]:
with open('/proc/cmdline') as f: with open('/proc/cmdline') as f:
cmdline = f.read() cmdline = f.read()
return {kv[0]: kv[1] for kv in [s.split('=') for s in cmdline.split(' ')] if len(kv) == 2} return {kv[0]: kv[1] for kv in [s.split('=') for s in cmdline.split(' ')] if len(kv) == 2}

View File

@ -6,7 +6,7 @@ import os
import struct import struct
import subprocess import subprocess
import time import time
from typing import Dict, Generator, List, Tuple, Union from collections.abc import Generator
import requests import requests
@ -117,7 +117,7 @@ def get_raw_hash(path: str, partition_size: int) -> str:
return raw_hash.hexdigest().lower() return raw_hash.hexdigest().lower()
def verify_partition(target_slot_number: int, partition: Dict[str, Union[str, int]], force_full_check: bool = False) -> bool: def verify_partition(target_slot_number: int, partition: dict[str, str | int], force_full_check: bool = False) -> bool:
full_check = partition['full_check'] or force_full_check full_check = partition['full_check'] or force_full_check
path = get_partition_path(target_slot_number, partition) path = get_partition_path(target_slot_number, partition)
@ -184,7 +184,7 @@ def extract_casync_image(target_slot_number: int, partition: dict, cloudlog):
target = casync.parse_caibx(partition['casync_caibx']) target = casync.parse_caibx(partition['casync_caibx'])
sources: List[Tuple[str, casync.ChunkReader, casync.ChunkDict]] = [] sources: list[tuple[str, casync.ChunkReader, casync.ChunkDict]] = []
# First source is the current partition. # First source is the current partition.
try: try:

View File

@ -2,7 +2,6 @@
import time import time
from smbus2 import SMBus from smbus2 import SMBus
from collections import namedtuple from collections import namedtuple
from typing import List
# https://datasheets.maximintegrated.com/en/ds/MAX98089.pdf # https://datasheets.maximintegrated.com/en/ds/MAX98089.pdf
@ -110,7 +109,7 @@ class Amplifier:
def _get_shutdown_config(self, amp_disabled: bool) -> AmpConfig: def _get_shutdown_config(self, amp_disabled: bool) -> AmpConfig:
return AmpConfig("Global shutdown", 0b0 if amp_disabled else 0b1, 0x51, 7, 0b10000000) return AmpConfig("Global shutdown", 0b0 if amp_disabled else 0b1, 0x51, 7, 0b10000000)
def _set_configs(self, configs: List[AmpConfig]) -> None: def _set_configs(self, configs: list[AmpConfig]) -> None:
with SMBus(self.AMP_I2C_BUS) as bus: with SMBus(self.AMP_I2C_BUS) as bus:
for config in configs: for config in configs:
if self.debug: if self.debug:
@ -123,7 +122,7 @@ class Amplifier:
if self.debug: if self.debug:
print(f" Changed {hex(config.register)}: {hex(old_value)} -> {hex(new_value)}") print(f" Changed {hex(config.register)}: {hex(old_value)} -> {hex(new_value)}")
def set_configs(self, configs: List[AmpConfig]) -> bool: def set_configs(self, configs: list[AmpConfig]) -> bool:
# retry in case panda is using the amp # retry in case panda is using the amp
tries = 15 tries = 15
for i in range(15): for i in range(15):

View File

@ -7,7 +7,7 @@ import sys
import time import time
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from collections import defaultdict, namedtuple from collections import defaultdict, namedtuple
from typing import Callable, Dict, List, Optional, Tuple from collections.abc import Callable
import requests import requests
from Crypto.Hash import SHA512 from Crypto.Hash import SHA512
@ -28,7 +28,7 @@ CHUNK_DOWNLOAD_RETRIES = 3
CAIBX_DOWNLOAD_TIMEOUT = 120 CAIBX_DOWNLOAD_TIMEOUT = 120
Chunk = namedtuple('Chunk', ['sha', 'offset', 'length']) Chunk = namedtuple('Chunk', ['sha', 'offset', 'length'])
ChunkDict = Dict[bytes, Chunk] ChunkDict = dict[bytes, Chunk]
class ChunkReader(ABC): class ChunkReader(ABC):
@ -83,7 +83,7 @@ class RemoteChunkReader(ChunkReader):
return decompressor.decompress(contents) return decompressor.decompress(contents)
def parse_caibx(caibx_path: str) -> List[Chunk]: def parse_caibx(caibx_path: str) -> list[Chunk]:
"""Parses the chunks from a caibx file. Can handle both local and remote files. """Parses the chunks from a caibx file. Can handle both local and remote files.
Returns a list of chunks with hash, offset and length""" Returns a list of chunks with hash, offset and length"""
caibx: io.BufferedIOBase caibx: io.BufferedIOBase
@ -132,7 +132,7 @@ def parse_caibx(caibx_path: str) -> List[Chunk]:
return chunks return chunks
def build_chunk_dict(chunks: List[Chunk]) -> ChunkDict: def build_chunk_dict(chunks: list[Chunk]) -> ChunkDict:
"""Turn a list of chunks into a dict for faster lookups based on hash. """Turn a list of chunks into a dict for faster lookups based on hash.
Keep first chunk since it's more likely to be already downloaded.""" Keep first chunk since it's more likely to be already downloaded."""
r = {} r = {}
@ -142,11 +142,11 @@ def build_chunk_dict(chunks: List[Chunk]) -> ChunkDict:
return r return r
def extract(target: List[Chunk], def extract(target: list[Chunk],
sources: List[Tuple[str, ChunkReader, ChunkDict]], sources: list[tuple[str, ChunkReader, ChunkDict]],
out_path: str, out_path: str,
progress: Optional[Callable[[int], None]] = None): progress: Callable[[int], None] | None = None):
stats: Dict[str, int] = defaultdict(int) stats: dict[str, int] = defaultdict(int)
mode = 'rb+' if os.path.exists(out_path) else 'wb' mode = 'rb+' if os.path.exists(out_path) else 'wb'
with open(out_path, mode) as out: with open(out_path, mode) as out:
@ -181,7 +181,7 @@ def extract(target: List[Chunk],
return stats return stats
def print_stats(stats: Dict[str, int]): def print_stats(stats: dict[str, int]):
total_bytes = sum(stats.values()) total_bytes = sum(stats.values())
print(f"Total size: {total_bytes / 1024 / 1024:.2f} MB") print(f"Total size: {total_bytes / 1024 / 1024:.2f} MB")
for name, total in stats.items(): for name, total in stats.items():

View File

@ -3,7 +3,6 @@ import sys
import time import time
import datetime import datetime
import numpy as np import numpy as np
from typing import List
from collections import deque from collections import deque
from openpilot.common.realtime import Ratekeeper from openpilot.common.realtime import Ratekeeper
@ -14,7 +13,7 @@ def read_power():
with open("/sys/bus/i2c/devices/0-0040/hwmon/hwmon1/power1_input") as f: with open("/sys/bus/i2c/devices/0-0040/hwmon/hwmon1/power1_input") as f:
return int(f.read()) / 1e6 return int(f.read()) / 1e6
def sample_power(seconds=5) -> List[float]: def sample_power(seconds=5) -> list[float]:
rate = 123 rate = 123
rk = Ratekeeper(rate, print_delay_threshold=None) rk = Ratekeeper(rate, print_delay_threshold=None)

View File

@ -6,4 +6,4 @@ if __name__ == '__main__':
print("measuring for 5 seconds") print("measuring for 5 seconds")
for _ in range(3): for _ in range(3):
pwrs = sample_power() pwrs = sample_power()
print("mean %.2f std %.2f" % (np.mean(pwrs), np.std(pwrs))) print(f"mean {np.mean(pwrs):.2f} std {np.std(pwrs):.2f}")

View File

@ -3,7 +3,6 @@ import argparse
import collections import collections
import multiprocessing import multiprocessing
import os import os
from typing import Dict, List
import requests import requests
from tqdm import tqdm from tqdm import tqdm
@ -42,7 +41,7 @@ if __name__ == "__main__":
szs = list(tqdm(pool.imap(get_chunk_download_size, to), total=len(to))) szs = list(tqdm(pool.imap(get_chunk_download_size, to), total=len(to)))
chunk_sizes = {t.sha: sz for (t, sz) in zip(to, szs, strict=True)} chunk_sizes = {t.sha: sz for (t, sz) in zip(to, szs, strict=True)}
sources: Dict[str, List[int]] = { sources: dict[str, list[int]] = {
'seed': [], 'seed': [],
'remote_uncompressed': [], 'remote_uncompressed': [],
'remote_compressed': [], 'remote_compressed': [],

View File

@ -7,7 +7,6 @@ import time
import numpy as np import numpy as np
from dataclasses import dataclass from dataclasses import dataclass
from tabulate import tabulate from tabulate import tabulate
from typing import List
import cereal.messaging as messaging import cereal.messaging as messaging
from cereal.services import SERVICE_LIST from cereal.services import SERVICE_LIST
@ -22,9 +21,9 @@ MAX_WARMUP_TIME = 30 # seconds to wait for SAMPLE_TIME consecutive valid sample
@dataclass @dataclass
class Proc: class Proc:
procs: List[str] procs: list[str]
power: float power: float
msgs: List[str] msgs: list[str]
rtol: float = 0.05 rtol: float = 0.05
atol: float = 0.12 atol: float = 0.12
@ -66,7 +65,7 @@ class TestPowerDraw(unittest.TestCase):
return np.core.numeric.isclose(used, proc.power, rtol=proc.rtol, atol=proc.atol) return np.core.numeric.isclose(used, proc.power, rtol=proc.rtol, atol=proc.atol)
def tabulate_msg_counts(self, msgs_and_power): def tabulate_msg_counts(self, msgs_and_power):
msg_counts = defaultdict(lambda: 0) msg_counts = defaultdict(int)
for _, counts in msgs_and_power: for _, counts in msgs_and_power:
for msg, count in counts.items(): for msg, count in counts.items():
msg_counts[msg] += count msg_counts[msg] += count

View File

@ -2,7 +2,6 @@
import os import os
import shutil import shutil
import threading import threading
from typing import List
from openpilot.system.hardware.hw import Paths from openpilot.system.hardware.hw import Paths
from openpilot.common.swaglog import cloudlog from openpilot.common.swaglog import cloudlog
from openpilot.system.loggerd.config import get_available_bytes, get_available_percent from openpilot.system.loggerd.config import get_available_bytes, get_available_percent
@ -23,7 +22,7 @@ def has_preserve_xattr(d: str) -> bool:
return getxattr(os.path.join(Paths.log_root(), d), PRESERVE_ATTR_NAME) == PRESERVE_ATTR_VALUE return getxattr(os.path.join(Paths.log_root(), d), PRESERVE_ATTR_NAME) == PRESERVE_ATTR_VALUE
def get_preserved_segments(dirs_by_creation: List[str]) -> List[str]: def get_preserved_segments(dirs_by_creation: list[str]) -> list[str]:
preserved = [] preserved = []
for n, d in enumerate(filter(has_preserve_xattr, reversed(dirs_by_creation))): for n, d in enumerate(filter(has_preserve_xattr, reversed(dirs_by_creation))):
if n == PRESERVE_COUNT: if n == PRESERVE_COUNT:

View File

@ -2,7 +2,6 @@ import os
import random import random
import unittest import unittest
from pathlib import Path from pathlib import Path
from typing import Optional
import openpilot.system.loggerd.deleter as deleter import openpilot.system.loggerd.deleter as deleter
@ -12,7 +11,7 @@ from openpilot.system.hardware.hw import Paths
from openpilot.system.loggerd.xattr_cache import setxattr from openpilot.system.loggerd.xattr_cache import setxattr
def create_random_file(file_path: Path, size_mb: float, lock: bool = False, upload_xattr: Optional[bytes] = None) -> None: def create_random_file(file_path: Path, size_mb: float, lock: bool = False, upload_xattr: bytes | None = None) -> None:
file_path.parent.mkdir(parents=True, exist_ok=True) file_path.parent.mkdir(parents=True, exist_ok=True)
if lock: if lock:
@ -82,7 +81,7 @@ class UploaderTestCase(unittest.TestCase):
self.params.put("DongleId", "0000000000000000") self.params.put("DongleId", "0000000000000000")
def make_file_with_data(self, f_dir: str, fn: str, size_mb: float = .1, lock: bool = False, def make_file_with_data(self, f_dir: str, fn: str, size_mb: float = .1, lock: bool = False,
upload_xattr: Optional[bytes] = None, preserve_xattr: Optional[bytes] = None) -> Path: upload_xattr: bytes | None = None, preserve_xattr: bytes | None = None) -> Path:
file_path = Path(Paths.log_root()) / f_dir / fn file_path = Path(Paths.log_root()) / f_dir / fn
create_random_file(file_path, size_mb, lock, upload_xattr) create_random_file(file_path, size_mb, lock, upload_xattr)

View File

@ -4,7 +4,7 @@ import threading
import unittest import unittest
from collections import namedtuple from collections import namedtuple
from pathlib import Path from pathlib import Path
from typing import Sequence from collections.abc import Sequence
import openpilot.system.loggerd.deleter as deleter import openpilot.system.loggerd.deleter as deleter
from openpilot.common.timeout import Timeout, TimeoutException from openpilot.common.timeout import Timeout, TimeoutException

View File

@ -8,7 +8,6 @@ import subprocess
import time import time
from collections import defaultdict from collections import defaultdict
from pathlib import Path from pathlib import Path
from typing import Dict, List
from flaky import flaky from flaky import flaky
import cereal.messaging as messaging import cereal.messaging as messaging
@ -76,7 +75,7 @@ class TestLoggerd:
end_type = SentinelType.endOfRoute if route else SentinelType.endOfSegment end_type = SentinelType.endOfRoute if route else SentinelType.endOfSegment
assert msgs[-1].sentinel.type == end_type assert msgs[-1].sentinel.type == end_type
def _publish_random_messages(self, services: List[str]) -> Dict[str, list]: def _publish_random_messages(self, services: list[str]) -> dict[str, list]:
pm = messaging.PubMaster(services) pm = messaging.PubMaster(services)
managed_processes["loggerd"].start() managed_processes["loggerd"].start()

View File

@ -6,7 +6,6 @@ import unittest
import logging import logging
import json import json
from pathlib import Path from pathlib import Path
from typing import List, Optional
from openpilot.system.hardware.hw import Paths from openpilot.system.hardware.hw import Paths
from openpilot.common.swaglog import cloudlog from openpilot.common.swaglog import cloudlog
@ -53,7 +52,7 @@ class TestUploader(UploaderTestCase):
self.end_event.set() self.end_event.set()
self.up_thread.join() self.up_thread.join()
def gen_files(self, lock=False, xattr: Optional[bytes] = None, boot=True) -> List[Path]: def gen_files(self, lock=False, xattr: bytes | None = None, boot=True) -> list[Path]:
f_paths = [] f_paths = []
for t in ["qlog", "rlog", "dcamera.hevc", "fcamera.hevc"]: for t in ["qlog", "rlog", "dcamera.hevc", "fcamera.hevc"]:
f_paths.append(self.make_file_with_data(self.seg_dir, t, 1, lock=lock, upload_xattr=xattr)) f_paths.append(self.make_file_with_data(self.seg_dir, t, 1, lock=lock, upload_xattr=xattr))
@ -62,7 +61,7 @@ class TestUploader(UploaderTestCase):
f_paths.append(self.make_file_with_data("boot", f"{self.seg_dir}", 1, lock=lock, upload_xattr=xattr)) f_paths.append(self.make_file_with_data("boot", f"{self.seg_dir}", 1, lock=lock, upload_xattr=xattr))
return f_paths return f_paths
def gen_order(self, seg1: List[int], seg2: List[int], boot=True) -> List[str]: def gen_order(self, seg1: list[int], seg2: list[int], boot=True) -> list[str]:
keys = [] keys = []
if boot: if boot:
keys += [f"boot/{self.seg_format.format(i)}.bz2" for i in seg1] keys += [f"boot/{self.seg_format.format(i)}.bz2" for i in seg1]

View File

@ -9,7 +9,8 @@ import threading
import time import time
import traceback import traceback
import datetime import datetime
from typing import BinaryIO, Iterator, List, Optional, Tuple from typing import BinaryIO
from collections.abc import Iterator
from cereal import log from cereal import log
import cereal.messaging as messaging import cereal.messaging as messaging
@ -42,10 +43,10 @@ class FakeResponse:
self.request = FakeRequest() self.request = FakeRequest()
def get_directory_sort(d: str) -> List[str]: def get_directory_sort(d: str) -> list[str]:
return [s.rjust(10, '0') for s in d.rsplit('--', 1)] return [s.rjust(10, '0') for s in d.rsplit('--', 1)]
def listdir_by_creation(d: str) -> List[str]: def listdir_by_creation(d: str) -> list[str]:
if not os.path.isdir(d): if not os.path.isdir(d):
return [] return []
@ -82,7 +83,7 @@ class Uploader:
self.immediate_folders = ["crash/", "boot/"] self.immediate_folders = ["crash/", "boot/"]
self.immediate_priority = {"qlog": 0, "qlog.bz2": 0, "qcamera.ts": 1} self.immediate_priority = {"qlog": 0, "qlog.bz2": 0, "qcamera.ts": 1}
def list_upload_files(self, metered: bool) -> Iterator[Tuple[str, str, str]]: def list_upload_files(self, metered: bool) -> Iterator[tuple[str, str, str]]:
r = self.params.get("AthenadRecentlyViewedRoutes", encoding="utf8") r = self.params.get("AthenadRecentlyViewedRoutes", encoding="utf8")
requested_routes = [] if r is None else r.split(",") requested_routes = [] if r is None else r.split(",")
@ -121,7 +122,7 @@ class Uploader:
yield name, key, fn yield name, key, fn
def next_file_to_upload(self, metered: bool) -> Optional[Tuple[str, str, str]]: def next_file_to_upload(self, metered: bool) -> tuple[str, str, str] | None:
upload_files = list(self.list_upload_files(metered)) upload_files = list(self.list_upload_files(metered))
for name, key, fn in upload_files: for name, key, fn in upload_files:
@ -207,7 +208,7 @@ class Uploader:
return success return success
def step(self, network_type: int, metered: bool) -> Optional[bool]: def step(self, network_type: int, metered: bool) -> bool | None:
d = self.next_file_to_upload(metered) d = self.next_file_to_upload(metered)
if d is None: if d is None:
return None return None
@ -221,7 +222,7 @@ class Uploader:
return self.upload(name, key, fn, network_type, metered) return self.upload(name, key, fn, network_type, metered)
def main(exit_event: Optional[threading.Event] = None) -> None: def main(exit_event: threading.Event | None = None) -> None:
if exit_event is None: if exit_event is None:
exit_event = threading.Event() exit_event = threading.Event()

View File

@ -1,10 +1,9 @@
import os import os
import errno import errno
from typing import Dict, Optional, Tuple
_cached_attributes: Dict[Tuple, Optional[bytes]] = {} _cached_attributes: dict[tuple, bytes | None] = {}
def getxattr(path: str, attr_name: str) -> Optional[bytes]: def getxattr(path: str, attr_name: str) -> bytes | None:
key = (path, attr_name) key = (path, attr_name)
if key not in _cached_attributes: if key not in _cached_attributes:
try: try:

View File

@ -93,7 +93,7 @@ def nmea_checksum_ok(s):
def process_nmea_port_messages(device:str="/dev/ttyUSB1") -> NoReturn: def process_nmea_port_messages(device:str="/dev/ttyUSB1") -> NoReturn:
while True: while True:
try: try:
with open(device, "r") as nmeaport: with open(device) as nmeaport:
for line in nmeaport: for line in nmeaport:
line = line.strip() line = line.strip()
if DEBUG: if DEBUG:

View File

@ -10,7 +10,7 @@ import shutil
import subprocess import subprocess
import datetime import datetime
from multiprocessing import Process, Event from multiprocessing import Process, Event
from typing import NoReturn, Optional from typing import NoReturn
from struct import unpack_from, calcsize, pack from struct import unpack_from, calcsize, pack
from cereal import log from cereal import log
@ -90,7 +90,7 @@ def try_setup_logs(diag, logs):
return setup_logs(diag, logs) return setup_logs(diag, logs)
@retry(attempts=3, delay=1.0) @retry(attempts=3, delay=1.0)
def at_cmd(cmd: str) -> Optional[str]: def at_cmd(cmd: str) -> str | None:
return subprocess.check_output(f"mmcli -m any --timeout 30 --command='{cmd}'", shell=True, encoding='utf8') return subprocess.check_output(f"mmcli -m any --timeout 30 --command='{cmd}'", shell=True, encoding='utf8')
def gps_enabled() -> bool: def gps_enabled() -> bool:
@ -342,7 +342,7 @@ def main() -> NoReturn:
gps.bearingDeg = report["q_FltHeadingRad"] * 180/math.pi gps.bearingDeg = report["q_FltHeadingRad"] * 180/math.pi
# TODO needs update if there is another leap second, after june 2024? # TODO needs update if there is another leap second, after june 2024?
dt_timestamp = (datetime.datetime(1980, 1, 6, 0, 0, 0, 0, datetime.timezone.utc) + dt_timestamp = (datetime.datetime(1980, 1, 6, 0, 0, 0, 0, datetime.UTC) +
datetime.timedelta(weeks=report['w_GpsWeekNumber']) + datetime.timedelta(weeks=report['w_GpsWeekNumber']) +
datetime.timedelta(seconds=(1e-3*report['q_GpsFixTimeMs'] - 18))) datetime.timedelta(seconds=(1e-3*report['q_GpsFixTimeMs'] - 18)))
gps.unixTimestampMillis = dt_timestamp.timestamp()*1e3 gps.unixTimestampMillis = dt_timestamp.timestamp()*1e3

Some files were not shown because too many files have changed in this diff Show More