From b28ff40d4ded866b59a14107ff972db41d4bed2a Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Fri, 20 Feb 2026 14:59:36 -0800 Subject: [PATCH] insource parameterized (#37280) * insource parameterized * lil more * fix --- cereal/messaging/tests/test_messaging.py | 2 +- cereal/messaging/tests/test_services.py | 2 +- common/parameterized.py | 47 +++++++++++++++++++ pyproject.toml | 1 - selfdrive/car/tests/test_car_interfaces.py | 2 +- selfdrive/car/tests/test_cruise_speed.py | 2 +- selfdrive/car/tests/test_models.py | 2 +- .../controls/tests/test_following_distance.py | 2 +- selfdrive/controls/tests/test_latcontrol.py | 2 +- .../tests/test_latcontrol_torque_buffer.py | 2 +- .../test_longitudinal.py | 2 +- selfdrive/test/process_replay/test_fuzzy.py | 2 +- selfdrive/test/process_replay/test_regen.py | 2 +- selfdrive/ui/tests/test_translations.py | 2 +- system/loggerd/tests/test_encoder.py | 2 +- system/webrtc/tests/test_webrtcd.py | 2 +- tools/lib/tests/test_logreader.py | 2 +- uv.lock | 11 ----- 18 files changed, 62 insertions(+), 27 deletions(-) create mode 100644 common/parameterized.py diff --git a/cereal/messaging/tests/test_messaging.py b/cereal/messaging/tests/test_messaging.py index 583eb8b0d8..afdab8a51f 100644 --- a/cereal/messaging/tests/test_messaging.py +++ b/cereal/messaging/tests/test_messaging.py @@ -5,7 +5,7 @@ import numbers import random import threading import time -from parameterized import parameterized +from openpilot.common.parameterized import parameterized import pytest from cereal import log, car diff --git a/cereal/messaging/tests/test_services.py b/cereal/messaging/tests/test_services.py index 8bfd2ea978..3320723fec 100644 --- a/cereal/messaging/tests/test_services.py +++ b/cereal/messaging/tests/test_services.py @@ -1,7 +1,7 @@ import os import tempfile from typing import Dict -from parameterized import parameterized +from openpilot.common.parameterized import parameterized import cereal.services as services from cereal.services import SERVICE_LIST diff --git a/common/parameterized.py b/common/parameterized.py new file mode 100644 index 0000000000..7cd21bb9c5 --- /dev/null +++ b/common/parameterized.py @@ -0,0 +1,47 @@ +import sys +import pytest +import inspect + + +class parameterized: + @staticmethod + def expand(cases): + cases = list(cases) + + if not cases: + return lambda func: pytest.mark.skip("no parameterized cases")(func) + + def decorator(func): + params = [p for p in inspect.signature(func).parameters if p != 'self'] + normalized = [c if isinstance(c, tuple) else (c,) for c in cases] + # Infer arg count from first case so extra params (e.g. from @given) are left untouched + expand_params = params[: len(normalized[0])] + if len(expand_params) == 1: + return pytest.mark.parametrize(expand_params[0], [c[0] for c in normalized])(func) + return pytest.mark.parametrize(', '.join(expand_params), normalized)(func) + + return decorator + + +def parameterized_class(attrs, input_list=None): + if isinstance(attrs, list) and (not attrs or isinstance(attrs[0], dict)): + params_list = attrs + else: + assert input_list is not None + attr_names = (attrs,) if isinstance(attrs, str) else tuple(attrs) + params_list = [dict(zip(attr_names, v if isinstance(v, (tuple, list)) else (v,), strict=False)) for v in input_list] + + def decorator(cls): + globs = sys._getframe(1).f_globals + for i, params in enumerate(params_list): + name = f"{cls.__name__}_{i}" + new_cls = type(name, (cls,), dict(params)) + new_cls.__module__ = cls.__module__ + new_cls.__test__ = True # override inherited False so pytest collects this subclass + globs[name] = new_cls + # Don't collect the un-parametrised base, but return it so outer decorators + # (e.g. @pytest.mark.skip) land on it and propagate to subclasses via MRO. + cls.__test__ = False + return cls + + return decorator diff --git a/pyproject.toml b/pyproject.toml index 92d82e8330..12134ef1d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -97,7 +97,6 @@ dev = [ "av", "matplotlib", "opencv-python-headless", - "parameterized >=0.8, <0.9", ] tools = [ diff --git a/selfdrive/car/tests/test_car_interfaces.py b/selfdrive/car/tests/test_car_interfaces.py index 24d2faa0db..1bc59326a2 100644 --- a/selfdrive/car/tests/test_car_interfaces.py +++ b/selfdrive/car/tests/test_car_interfaces.py @@ -1,7 +1,7 @@ import os import hypothesis.strategies as st from hypothesis import Phase, given, settings -from parameterized import parameterized +from openpilot.common.parameterized import parameterized from cereal import car from opendbc.car import DT_CTRL diff --git a/selfdrive/car/tests/test_cruise_speed.py b/selfdrive/car/tests/test_cruise_speed.py index aa70e49f5d..05fef93b4e 100644 --- a/selfdrive/car/tests/test_cruise_speed.py +++ b/selfdrive/car/tests/test_cruise_speed.py @@ -2,7 +2,7 @@ import pytest import itertools import numpy as np -from parameterized import parameterized_class +from openpilot.common.parameterized import parameterized_class from cereal import log from openpilot.selfdrive.car.cruise import VCruiseHelper, V_CRUISE_MIN, V_CRUISE_MAX, V_CRUISE_INITIAL, IMPERIAL_INCREMENT from cereal import car diff --git a/selfdrive/car/tests/test_models.py b/selfdrive/car/tests/test_models.py index 94f5b33231..a7f3d68c14 100644 --- a/selfdrive/car/tests/test_models.py +++ b/selfdrive/car/tests/test_models.py @@ -6,7 +6,7 @@ import unittest # noqa: TID251 from collections import defaultdict, Counter import hypothesis.strategies as st from hypothesis import Phase, given, settings -from parameterized import parameterized_class +from openpilot.common.parameterized import parameterized_class from opendbc.car import DT_CTRL, gen_empty_fingerprint, structs from opendbc.car.can_definitions import CanData diff --git a/selfdrive/controls/tests/test_following_distance.py b/selfdrive/controls/tests/test_following_distance.py index ad1ff1a189..1eb88d7206 100644 --- a/selfdrive/controls/tests/test_following_distance.py +++ b/selfdrive/controls/tests/test_following_distance.py @@ -1,6 +1,6 @@ import pytest import itertools -from parameterized import parameterized_class +from openpilot.common.parameterized import parameterized_class from cereal import log diff --git a/selfdrive/controls/tests/test_latcontrol.py b/selfdrive/controls/tests/test_latcontrol.py index 354c7f00ad..5c3381edce 100644 --- a/selfdrive/controls/tests/test_latcontrol.py +++ b/selfdrive/controls/tests/test_latcontrol.py @@ -1,4 +1,4 @@ -from parameterized import parameterized +from openpilot.common.parameterized import parameterized from cereal import car, log from opendbc.car.car_helpers import interfaces diff --git a/selfdrive/controls/tests/test_latcontrol_torque_buffer.py b/selfdrive/controls/tests/test_latcontrol_torque_buffer.py index 76d0c28423..ab1d2c7b36 100644 --- a/selfdrive/controls/tests/test_latcontrol_torque_buffer.py +++ b/selfdrive/controls/tests/test_latcontrol_torque_buffer.py @@ -1,4 +1,4 @@ -from parameterized import parameterized +from openpilot.common.parameterized import parameterized from cereal import car, log from opendbc.car.car_helpers import interfaces diff --git a/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py b/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py index ab1800b4fb..90bc46b187 100644 --- a/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py +++ b/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py @@ -1,5 +1,5 @@ import itertools -from parameterized import parameterized_class +from openpilot.common.parameterized import parameterized_class from openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.long_mpc import STOP_DISTANCE from openpilot.selfdrive.test.longitudinal_maneuvers.maneuver import Maneuver diff --git a/selfdrive/test/process_replay/test_fuzzy.py b/selfdrive/test/process_replay/test_fuzzy.py index 723112163e..6989f8957f 100644 --- a/selfdrive/test/process_replay/test_fuzzy.py +++ b/selfdrive/test/process_replay/test_fuzzy.py @@ -2,7 +2,7 @@ import copy import os from hypothesis import given, HealthCheck, Phase, settings import hypothesis.strategies as st -from parameterized import parameterized +from openpilot.common.parameterized import parameterized from cereal import log from opendbc.car.toyota.values import CAR as TOYOTA diff --git a/selfdrive/test/process_replay/test_regen.py b/selfdrive/test/process_replay/test_regen.py index 5f26daf786..f4942e486c 100644 --- a/selfdrive/test/process_replay/test_regen.py +++ b/selfdrive/test/process_replay/test_regen.py @@ -1,4 +1,4 @@ -from parameterized import parameterized +from openpilot.common.parameterized import parameterized from openpilot.selfdrive.test.process_replay.regen import regen_segment from openpilot.selfdrive.test.process_replay.process_replay import check_openpilot_enabled diff --git a/selfdrive/ui/tests/test_translations.py b/selfdrive/ui/tests/test_translations.py index 3177814f9f..599c99013c 100644 --- a/selfdrive/ui/tests/test_translations.py +++ b/selfdrive/ui/tests/test_translations.py @@ -5,7 +5,7 @@ import re import xml.etree.ElementTree as ET import string import requests -from parameterized import parameterized_class +from openpilot.common.parameterized import parameterized_class from openpilot.system.ui.lib.multilang import TRANSLATIONS_DIR, LANGUAGES_FILE with open(str(LANGUAGES_FILE)) as f: diff --git a/system/loggerd/tests/test_encoder.py b/system/loggerd/tests/test_encoder.py index e4dabd3df9..a9de0690aa 100644 --- a/system/loggerd/tests/test_encoder.py +++ b/system/loggerd/tests/test_encoder.py @@ -7,7 +7,7 @@ import subprocess import time from pathlib import Path -from parameterized import parameterized +from openpilot.common.parameterized import parameterized from tqdm import trange from openpilot.common.params import Params diff --git a/system/webrtc/tests/test_webrtcd.py b/system/webrtc/tests/test_webrtcd.py index 4fa6d8953f..e5f6ceaa37 100644 --- a/system/webrtc/tests/test_webrtcd.py +++ b/system/webrtc/tests/test_webrtcd.py @@ -10,7 +10,7 @@ from openpilot.system.webrtc.webrtcd import get_stream import aiortc from teleoprtc import WebRTCOfferBuilder -from parameterized import parameterized_class +from openpilot.common.parameterized import parameterized_class @parameterized_class(("in_services", "out_services"), [ diff --git a/tools/lib/tests/test_logreader.py b/tools/lib/tests/test_logreader.py index 0151940c44..123f142383 100644 --- a/tools/lib/tests/test_logreader.py +++ b/tools/lib/tests/test_logreader.py @@ -7,7 +7,7 @@ import os import pytest import requests -from parameterized import parameterized +from openpilot.common.parameterized import parameterized from cereal import log as capnp_log from openpilot.tools.lib.logreader import LogsUnavailable, LogIterable, LogReader, parse_indirect, ReadMode diff --git a/uv.lock b/uv.lock index 86d324ec4c..e14591deee 100644 --- a/uv.lock +++ b/uv.lock @@ -839,7 +839,6 @@ dev = [ { name = "av" }, { name = "matplotlib" }, { name = "opencv-python-headless" }, - { name = "parameterized" }, ] docs = [ { name = "jinja2" }, @@ -889,7 +888,6 @@ requires-dist = [ { name = "numpy", specifier = ">=2.0" }, { name = "onnx", specifier = ">=1.14.0" }, { name = "opencv-python-headless", marker = "extra == 'dev'" }, - { name = "parameterized", marker = "extra == 'dev'", specifier = ">=0.8,<0.9" }, { name = "pre-commit-hooks", marker = "extra == 'testing'" }, { name = "psutil" }, { name = "pyaudio" }, @@ -972,15 +970,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/11/5d/3744c6550dddf933785a37cdd4a9921fe13284e6d115b5a2637fe390f158/panda3d_simplepbr-0.13.1-py3-none-any.whl", hash = "sha256:cda41cb57cff035b851646956cfbdcc408bee42511dabd4f2d7bd4fbf48c57a9", size = 2457097, upload-time = "2025-03-30T16:57:39.729Z" }, ] -[[package]] -name = "parameterized" -version = "0.8.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c6/23/2288f308d238b4f261c039cafcd650435d624de97c6ffc903f06ea8af50f/parameterized-0.8.1.tar.gz", hash = "sha256:41bbff37d6186430f77f900d777e5bb6a24928a1c46fb1de692f8b52b8833b5c", size = 23936, upload-time = "2021-01-09T20:35:18.235Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/31/13/fe468c8c7400a8eca204e6e160a29bf7dcd45a76e20f1c030f3eaa690d93/parameterized-0.8.1-py2.py3-none-any.whl", hash = "sha256:9cbb0b69a03e8695d68b3399a8a5825200976536fe1cb79db60ed6a4c8c9efe9", size = 26354, upload-time = "2021-01-09T20:35:16.307Z" }, -] - [[package]] name = "pathspec" version = "1.0.4"