mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-07-23 16:32:04 +08:00
more ty (#38378)
* enable no matching overload * enable call non callable * enable unsupported-operator * enable not subscriptable * refactor pass
This commit is contained in:
@@ -92,6 +92,7 @@ class TestSubMaster:
|
||||
|
||||
for service, (max_freq, min_freq) in checks.items():
|
||||
if max_freq is not None:
|
||||
assert min_freq is not None
|
||||
assert sm._check_avg_freq(service)
|
||||
assert sm.freq_tracker[service].max_freq == max_freq*1.2
|
||||
assert sm.freq_tracker[service].min_freq == min_freq*0.8
|
||||
|
||||
@@ -27,7 +27,7 @@ class SwaglogRotatingFileHandler(BaseRotatingHandler):
|
||||
self.log_files = self.get_existing_logfiles()
|
||||
log_indexes = [f.split(".")[-1] for f in self.log_files]
|
||||
self.last_file_idx = max([int(i) for i in log_indexes if i.isdigit()] or [-1])
|
||||
self.last_rollover = None
|
||||
self.last_rollover = 0.0
|
||||
self.doRollover()
|
||||
|
||||
def _open(self):
|
||||
|
||||
@@ -250,7 +250,7 @@ class TestCarModelBase(unittest.TestCase):
|
||||
|
||||
# Don't check relay malfunction on disabled routes (relay closed),
|
||||
# or before fingerprinting is done (elm327 and noOutput)
|
||||
if self.openpilot_enabled and t / 1e4 > self.car_safety_mode_frame:
|
||||
if self.car_safety_mode_frame is not None and t / 1e4 > self.car_safety_mode_frame:
|
||||
self.assertFalse(self.safety.get_relay_malfunction())
|
||||
else:
|
||||
self.safety.set_relay_malfunction(False)
|
||||
|
||||
@@ -37,9 +37,9 @@ def get_select_fields_data(logs):
|
||||
def sig_smooth(signal):
|
||||
return masked_symmetric_moving_average(signal, np.ones_like(signal), 5, 1.0)
|
||||
def get_nested_keys(msg, keys):
|
||||
val = None
|
||||
val = msg
|
||||
for key in keys:
|
||||
val = getattr(msg if val is None else val, key) if isinstance(key, str) else val[key]
|
||||
val = getattr(val, key) if isinstance(key, str) else val[key]
|
||||
return val
|
||||
lp = [x.livePose for x in logs if x.which() == 'livePose']
|
||||
data = defaultdict(list)
|
||||
|
||||
@@ -250,12 +250,12 @@ class MiciOffroadAlerts(Scroller):
|
||||
{alert_data.key: self.params.get(alert_data.key) for alert_data in self.sorted_alerts})
|
||||
time.sleep(REFRESH_INTERVAL)
|
||||
|
||||
def _refresh(self) -> int:
|
||||
def _refresh(self, pending_params: dict) -> int:
|
||||
"""Refresh alerts from params and return active count."""
|
||||
active_count = 0
|
||||
|
||||
# Handle UpdateAvailable alert specially
|
||||
update_available = self._pending_params["UpdateAvailable"]
|
||||
update_available = pending_params["UpdateAvailable"]
|
||||
update_alert_data = next((alert_data for alert_data in self.sorted_alerts if alert_data.key == "UpdateAvailable"), None)
|
||||
|
||||
if update_alert_data:
|
||||
@@ -263,7 +263,7 @@ class MiciOffroadAlerts(Scroller):
|
||||
version_string = ""
|
||||
|
||||
# Get new version description and parse version and date
|
||||
new_desc = self._pending_params["UpdaterNewDescription"] or ""
|
||||
new_desc = pending_params["UpdaterNewDescription"] or ""
|
||||
if new_desc:
|
||||
# format: "version / branch / commit / date"
|
||||
parts = new_desc.split(" / ")
|
||||
@@ -284,7 +284,7 @@ class MiciOffroadAlerts(Scroller):
|
||||
continue # Skip, already handled above
|
||||
|
||||
text = ""
|
||||
alert_json = self._pending_params[alert_data.key]
|
||||
alert_json = pending_params[alert_data.key]
|
||||
|
||||
if alert_json:
|
||||
text = alert_json.get("text", "").replace("%1", alert_json.get("extra", ""))
|
||||
@@ -311,8 +311,9 @@ class MiciOffroadAlerts(Scroller):
|
||||
def _update_state(self):
|
||||
"""Periodically refresh alerts."""
|
||||
# Refresh alerts when thread updates params
|
||||
if self._pending_params is not None:
|
||||
self._refresh()
|
||||
pending_params = self._pending_params
|
||||
if pending_params is not None:
|
||||
self._refresh(pending_params)
|
||||
self._pending_params = None
|
||||
|
||||
def _render(self, rect: rl.Rectangle):
|
||||
|
||||
@@ -375,6 +375,7 @@ class GreyBigButton(BigButton):
|
||||
class BigMultiParamToggle(BigMultiToggle):
|
||||
def __init__(self, text: str, param: str, options: list[str], toggle_callback: Callable | None = None,
|
||||
select_callback: Callable | None = None):
|
||||
assert Params is not None
|
||||
super().__init__(text, options, toggle_callback, select_callback)
|
||||
self._param = param
|
||||
|
||||
@@ -392,6 +393,7 @@ class BigMultiParamToggle(BigMultiToggle):
|
||||
|
||||
class BigParamControl(BigToggle):
|
||||
def __init__(self, text: str, param: str, toggle_callback: Callable | None = None):
|
||||
assert Params is not None
|
||||
super().__init__(text, "", toggle_callback=toggle_callback)
|
||||
self.param = param
|
||||
self.params = Params()
|
||||
@@ -409,6 +411,7 @@ class BigParamControl(BigToggle):
|
||||
class BigCircleParamControl(BigCircleToggle):
|
||||
def __init__(self, icon: rl.Texture, param: str, toggle_callback: Callable | None = None,
|
||||
icon_offset: tuple[int, int] = (0, 0)):
|
||||
assert Params is not None
|
||||
super().__init__(icon, toggle_callback, icon_offset=icon_offset)
|
||||
self._param = param
|
||||
self.params = Params()
|
||||
|
||||
@@ -12,9 +12,9 @@ POT_FILE = os.path.join(str(TRANSLATIONS_DIR), "app.pot")
|
||||
def update_translations():
|
||||
files = []
|
||||
for root, _, filenames in chain(os.walk(SYSTEM_UI_DIR),
|
||||
os.walk(os.path.join(UI_DIR, "widgets")),
|
||||
os.walk(os.path.join(UI_DIR, "layouts")),
|
||||
os.walk(os.path.join(UI_DIR, "onroad"))):
|
||||
os.walk(os.path.join(str(UI_DIR), "widgets")),
|
||||
os.walk(os.path.join(str(UI_DIR), "layouts")),
|
||||
os.walk(os.path.join(str(UI_DIR), "onroad"))):
|
||||
for filename in filenames:
|
||||
if filename.endswith(".py"):
|
||||
files.append(os.path.relpath(os.path.join(root, filename), BASEDIR))
|
||||
@@ -25,7 +25,7 @@ def update_translations():
|
||||
|
||||
# Generate/update translation files for each language
|
||||
for name in multilang.languages.values():
|
||||
po_file = os.path.join(TRANSLATIONS_DIR, f"app_{name}.po")
|
||||
po_file = os.path.join(str(TRANSLATIONS_DIR), f"app_{name}.po")
|
||||
if os.path.exists(po_file):
|
||||
merge_po(po_file, POT_FILE)
|
||||
else:
|
||||
|
||||
@@ -277,7 +277,9 @@ class TestLoggerd:
|
||||
assert recv_cnt == 0, f"got {recv_cnt} {s} msgs in qlog"
|
||||
else:
|
||||
# check logged message count matches decimation
|
||||
expected_cnt = (len(msgs) - 1) // SERVICE_LIST[s].decimation + 1
|
||||
decimation = SERVICE_LIST[s].decimation
|
||||
assert decimation is not None
|
||||
expected_cnt = (len(msgs) - 1) // decimation + 1
|
||||
assert recv_cnt == expected_cnt, f"expected {expected_cnt} msgs for {s}, got {recv_cnt}"
|
||||
|
||||
def test_rlog(self):
|
||||
|
||||
@@ -3,7 +3,7 @@ import sys
|
||||
from dataclasses import dataclass, fields
|
||||
from subprocess import check_output, CalledProcessError
|
||||
from time import sleep
|
||||
from typing import NoReturn
|
||||
from typing import NoReturn, cast
|
||||
|
||||
DEBUG = int(os.environ.get("DEBUG", "0"))
|
||||
|
||||
@@ -30,7 +30,8 @@ class GnssClockNmeaPort:
|
||||
def __post_init__(self):
|
||||
for field in fields(self):
|
||||
val = getattr(self, field.name)
|
||||
setattr(self, field.name, field.type(val) if val else None)
|
||||
field_type = cast(type, field.type)
|
||||
setattr(self, field.name, field_type(val) if val else None)
|
||||
|
||||
@dataclass
|
||||
class GnssMeasNmeaPort:
|
||||
@@ -73,7 +74,8 @@ class GnssMeasNmeaPort:
|
||||
def __post_init__(self):
|
||||
for field in fields(self):
|
||||
val = getattr(self, field.name)
|
||||
setattr(self, field.name, field.type(val) if val else None)
|
||||
field_type = cast(type, field.type)
|
||||
setattr(self, field.name, field_type(val) if val else None)
|
||||
|
||||
def nmea_checksum_ok(s):
|
||||
checksum = 0
|
||||
|
||||
@@ -823,6 +823,7 @@ class GuiApplication:
|
||||
import pstats
|
||||
|
||||
self._render_profiler.disable()
|
||||
assert self._render_profile_start_time is not None
|
||||
elapsed_ms = (time.monotonic() - self._render_profile_start_time) * 1e3
|
||||
avg_frame_time = elapsed_ms / self._frame if self._frame > 0 else 0
|
||||
|
||||
|
||||
@@ -105,6 +105,7 @@ class NetworkUI(Widget):
|
||||
|
||||
class AdvancedNetworkSettings(Widget):
|
||||
def __init__(self, wifi_manager: WifiManager):
|
||||
assert Params is not None
|
||||
super().__init__()
|
||||
self._wifi_manager = wifi_manager
|
||||
self._wifi_manager.add_callbacks(networks_updated=self._on_network_updated)
|
||||
|
||||
@@ -11,6 +11,7 @@ import itertools
|
||||
import numpy as np
|
||||
import tqdm
|
||||
from argparse import ArgumentParser
|
||||
from collections.abc import Callable
|
||||
from pathlib import Path
|
||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||
|
||||
@@ -138,7 +139,7 @@ def iter_segment_frames(camera_paths, start_time, end_time, fps=20, use_qcam=Fal
|
||||
frames_per_seg = fps * 60
|
||||
start_frame, end_frame = int(start_time * fps), int(end_time * fps)
|
||||
current_seg: int = -1
|
||||
seg_frames: FrameReader | np.ndarray | None = None
|
||||
get_frame: Callable[[int], np.ndarray] | None = None
|
||||
|
||||
for global_idx in range(start_frame, end_frame):
|
||||
seg_idx, local_idx = global_idx // frames_per_seg, global_idx % frames_per_seg
|
||||
@@ -157,12 +158,12 @@ def iter_segment_frames(camera_paths, start_time, end_time, fps=20, use_qcam=Fal
|
||||
if result.returncode != 0:
|
||||
raise RuntimeError(f"ffmpeg failed: {result.stderr.decode()}")
|
||||
seg_frames = np.frombuffer(result.stdout, dtype=np.uint8).reshape(-1, w * h * 3 // 2)
|
||||
get_frame = seg_frames.__getitem__
|
||||
else:
|
||||
seg_frames = FrameReader(path, pix_fmt="nv12")
|
||||
get_frame = FrameReader(path, pix_fmt="nv12").get
|
||||
|
||||
assert seg_frames is not None
|
||||
frame = seg_frames[local_idx] if use_qcam else seg_frames.get(local_idx)
|
||||
yield global_idx, frame
|
||||
assert get_frame is not None
|
||||
yield global_idx, get_frame(local_idx)
|
||||
|
||||
|
||||
class FrameQueue:
|
||||
|
||||
@@ -74,7 +74,7 @@ def get_repo_url(path):
|
||||
|
||||
response = requests.head(get_repo_raw_url(path))
|
||||
|
||||
if "text/plain" in response.headers.get("content-type"):
|
||||
if "text/plain" in response.headers.get("content-type", ""):
|
||||
# This is an LFS pointer, so download the raw data from lfs
|
||||
response = requests.get(get_repo_raw_url(path))
|
||||
assert response.status_code == 200
|
||||
|
||||
@@ -97,7 +97,7 @@ class MetaDriveWorld(World):
|
||||
self.op_engaged.set()
|
||||
|
||||
# check moving 5 seconds after engaged, doesn't move right away
|
||||
after_engaged_check = is_engaged and time.monotonic() - self.first_engage >= 5 and self.test_run
|
||||
after_engaged_check = is_engaged and self.first_engage is not None and time.monotonic() - self.first_engage >= 5 and self.test_run
|
||||
|
||||
x_dist = abs(curr_pos[0] - self.vehicle_last_pos[0])
|
||||
y_dist = abs(curr_pos[1] - self.vehicle_last_pos[1])
|
||||
|
||||
@@ -189,11 +189,7 @@ unresolved-attribute = "ignore" # many from capnp and Cython modules
|
||||
invalid-method-override = "ignore" # signature variance issues
|
||||
possibly-missing-attribute = "ignore" # too many false positives
|
||||
invalid-assignment = "ignore" # often intentional monkey-patching
|
||||
no-matching-overload = "ignore" # numpy/ctypes overload matching issues
|
||||
invalid-argument-type = "ignore" # many false positives from raylib, ctypes, numpy
|
||||
call-non-callable = "ignore" # false positives from dynamic types
|
||||
unsupported-operator = "ignore" # false positives from dynamic types
|
||||
not-subscriptable = "ignore" # false positives from dynamic types
|
||||
|
||||
[tool.uv]
|
||||
python-preference = "only-managed"
|
||||
|
||||
Reference in New Issue
Block a user