From 64c8af96134e88ee0c2ab73556f3bc6554e78ad8 Mon Sep 17 00:00:00 2001 From: Ujjwal Reddy K S <66116582+ujjwalredd@users.noreply.github.com> Date: Mon, 10 Aug 2026 15:30:54 -0400 Subject: [PATCH] style(core): modernize isinstance type checks to Python 3.10+ union syntax --- CHANGELOG.md | 1 + .../src/inspect_robots_agent/_capture.py | 6 +++--- .../src/inspect_robots_agent/_tools.py | 2 +- .../src/inspect_robots_isaacsim/embodiment.py | 4 ++-- .../tests/test_isaacsim_embodiment.py | 2 +- .../inspect-robots-ros/src/inspect_robots_ros/_client.py | 2 +- .../src/inspect_robots_ros/embodiment.py | 2 +- plugins/inspect-robots-ros/tests/_stub_server.py | 2 +- .../src/inspect_robots_voice/__init__.py | 4 ++-- .../src/inspect_robots_xpolicylab/_client.py | 2 +- .../src/inspect_robots_xpolicylab/_protocol.py | 2 +- plugins/inspect-robots-xpolicylab/tests/_stub_server.py | 2 +- src/inspect_robots/_html.py | 6 +++--- src/inspect_robots/_summarize.py | 2 +- src/inspect_robots/_video.py | 2 +- src/inspect_robots/cli.py | 8 ++++---- src/inspect_robots/logging/json_log.py | 2 +- 17 files changed, 26 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 355b10bed..7d91c7a1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to this project are documented here. The format is based on ### Fixed +- **Core & Plugins:** modernized `isinstance` checks to Python 3.10+ union syntax (`X | Y`), addressing Ruff UP038 lints across the core framework and plugins. - **Voice plugin (0.5.1):** operator-ended trials now cut `--speak` narration instead of draining it at eval end ([plan 0061](plans/0061-speak-operator-end-cut.md), diff --git a/plugins/inspect-robots-agent/src/inspect_robots_agent/_capture.py b/plugins/inspect-robots-agent/src/inspect_robots_agent/_capture.py index 6d1d6605e..bf2d307b4 100644 --- a/plugins/inspect-robots-agent/src/inspect_robots_agent/_capture.py +++ b/plugins/inspect-robots-agent/src/inspect_robots_agent/_capture.py @@ -97,7 +97,7 @@ def begin_trial(self, log_dir: str, run_id: str, trial_id: str) -> None: self._relative_path = (Path("wire") / run_id / safe_trial_id / "calls.jsonl").as_posix() except BaseException as exc: self._disable(exc) - if isinstance(exc, (KeyboardInterrupt, SystemExit)): + if isinstance(exc, KeyboardInterrupt | SystemExit): raise def record( @@ -144,7 +144,7 @@ def record( self._rows_written = True except BaseException as exc: self._disable(exc) - if isinstance(exc, (KeyboardInterrupt, SystemExit)): + if isinstance(exc, KeyboardInterrupt | SystemExit): raise def end_trial(self) -> str | None: @@ -159,7 +159,7 @@ def end_trial(self) -> str | None: return pointer except BaseException as exc: self._disable(exc) - if isinstance(exc, (KeyboardInterrupt, SystemExit)): + if isinstance(exc, KeyboardInterrupt | SystemExit): raise return pointer diff --git a/plugins/inspect-robots-agent/src/inspect_robots_agent/_tools.py b/plugins/inspect-robots-agent/src/inspect_robots_agent/_tools.py index deb38b80e..8fe6fdc5b 100644 --- a/plugins/inspect-robots-agent/src/inspect_robots_agent/_tools.py +++ b/plugins/inspect-robots-agent/src/inspect_robots_agent/_tools.py @@ -401,7 +401,7 @@ def _move(self, arguments: dict[str, Any], observation: Observation) -> ToolResu return ToolResult( error=f"unknown dimension {label!r}; valid names: {', '.join(self._labels)}" ) - if isinstance(raw, bool) or not isinstance(raw, (int, float)): + if isinstance(raw, bool) or not isinstance(raw, int | float): return ToolResult(error=f"value for {label!r} must be a finite number, got {raw!r}") try: # Arbitrary-precision JSON integers overflow float() (and crash diff --git a/plugins/inspect-robots-isaacsim/src/inspect_robots_isaacsim/embodiment.py b/plugins/inspect-robots-isaacsim/src/inspect_robots_isaacsim/embodiment.py index 082c97341..47114d7b2 100644 --- a/plugins/inspect-robots-isaacsim/src/inspect_robots_isaacsim/embodiment.py +++ b/plugins/inspect-robots-isaacsim/src/inspect_robots_isaacsim/embodiment.py @@ -93,7 +93,7 @@ def _disable_debug_vis(cfg: Any) -> None: if isinstance(obj, dict): stack.extend(obj.values()) continue - if isinstance(obj, (list, tuple, set)): + if isinstance(obj, list | tuple | set): stack.extend(obj) continue obj_vars = getattr(obj, "__dict__", None) @@ -102,7 +102,7 @@ def _disable_debug_vis(cfg: Any) -> None: for key, value in obj_vars.items(): if key == "debug_vis" and value is True: obj.debug_vis = False - elif isinstance(value, (dict, list, tuple, set)) or hasattr(value, "__dict__"): + elif isinstance(value, dict | list | tuple | set) or hasattr(value, "__dict__"): stack.append(value) diff --git a/plugins/inspect-robots-isaacsim/tests/test_isaacsim_embodiment.py b/plugins/inspect-robots-isaacsim/tests/test_isaacsim_embodiment.py index 6c0af0839..cc1dc41f7 100644 --- a/plugins/inspect-robots-isaacsim/tests/test_isaacsim_embodiment.py +++ b/plugins/inspect-robots-isaacsim/tests/test_isaacsim_embodiment.py @@ -242,7 +242,7 @@ def test_no_ram_leak_over_many_steps() -> None: # The adapter itself must hold no per-step accumulation. assert fake.step_calls == 3200 for value in vars(emb).values(): - assert not isinstance(value, (list, dict)) or len(value) <= 1 + assert not isinstance(value, list | dict) or len(value) <= 1 def test_disable_debug_vis_walks_nested_configs() -> None: diff --git a/plugins/inspect-robots-ros/src/inspect_robots_ros/_client.py b/plugins/inspect-robots-ros/src/inspect_robots_ros/_client.py index d74f4070a..b9ea9a32d 100644 --- a/plugins/inspect-robots-ros/src/inspect_robots_ros/_client.py +++ b/plugins/inspect-robots-ros/src/inspect_robots_ros/_client.py @@ -282,7 +282,7 @@ def _receive_loop(self) -> None: try: while True: raw = ws.recv() - if not isinstance(raw, (str, bytes)): + if not isinstance(raw, str | bytes): raise RosbridgeError( "invalid_frame", f"rosbridge sent unsupported frame type {type(raw).__name__}", diff --git a/plugins/inspect-robots-ros/src/inspect_robots_ros/embodiment.py b/plugins/inspect-robots-ros/src/inspect_robots_ros/embodiment.py index 3b062557a..fdf4d30c6 100644 --- a/plugins/inspect-robots-ros/src/inspect_robots_ros/embodiment.py +++ b/plugins/inspect-robots-ros/src/inspect_robots_ros/embodiment.py @@ -86,7 +86,7 @@ def _parse_numeric_list(value: NumericList | None, arg: str) -> tuple[float, ... raw: Sequence[Any] if isinstance(value, str): raw = tuple(item.strip() for item in value.split(",") if item.strip()) - elif isinstance(value, (int, float)): + elif isinstance(value, int | float): raw = (value,) else: raw = value diff --git a/plugins/inspect-robots-ros/tests/_stub_server.py b/plugins/inspect-robots-ros/tests/_stub_server.py index 548261174..7af4b8349 100644 --- a/plugins/inspect-robots-ros/tests/_stub_server.py +++ b/plugins/inspect-robots-ros/tests/_stub_server.py @@ -129,7 +129,7 @@ def _handler(self, ws: ServerConnection) -> None: self._subscriptions[ws] = {} try: for raw in ws: - if not isinstance(raw, (str, bytes)): + if not isinstance(raw, str | bytes): continue operation = json.loads(raw) if not isinstance(operation, dict): diff --git a/plugins/inspect-robots-voice/src/inspect_robots_voice/__init__.py b/plugins/inspect-robots-voice/src/inspect_robots_voice/__init__.py index 993d4f54f..0e0c1a5cb 100644 --- a/plugins/inspect-robots-voice/src/inspect_robots_voice/__init__.py +++ b/plugins/inspect-robots-voice/src/inspect_robots_voice/__init__.py @@ -44,11 +44,11 @@ def speaker_sink(**kwargs: ScalarValue) -> SpeakerSink: mode = kwargs.get("mode", _DEFAULT_MODE) if not isinstance(voice, str): raise TypeError("voice must be a string") - if not isinstance(speed, (int, float)) or isinstance(speed, bool): + if not isinstance(speed, int | float) or isinstance(speed, bool): raise TypeError("speed must be a number") if speed <= 0: raise TypeError("speed must be positive") - if not isinstance(volume, (int, float)) or isinstance(volume, bool): + if not isinstance(volume, int | float) or isinstance(volume, bool): raise TypeError("volume must be a number") if not 0 <= volume <= 1: raise TypeError("volume must be between 0 and 1") diff --git a/plugins/inspect-robots-xpolicylab/src/inspect_robots_xpolicylab/_client.py b/plugins/inspect-robots-xpolicylab/src/inspect_robots_xpolicylab/_client.py index cba0d03f8..ccb82e5b0 100644 --- a/plugins/inspect-robots-xpolicylab/src/inspect_robots_xpolicylab/_client.py +++ b/plugins/inspect-robots-xpolicylab/src/inspect_robots_xpolicylab/_client.py @@ -136,7 +136,7 @@ def request( if remaining <= 0: raise TimeoutError raw = ws.recv(timeout=remaining) - if not isinstance(raw, (bytes, bytearray)): + if not isinstance(raw, bytes | bytearray): continue # protocol is binary-only; ignore stray text frames try: reply = decode_frame(bytes(raw)) diff --git a/plugins/inspect-robots-xpolicylab/src/inspect_robots_xpolicylab/_protocol.py b/plugins/inspect-robots-xpolicylab/src/inspect_robots_xpolicylab/_protocol.py index e931d38f0..9988fa670 100644 --- a/plugins/inspect-robots-xpolicylab/src/inspect_robots_xpolicylab/_protocol.py +++ b/plugins/inspect-robots-xpolicylab/src/inspect_robots_xpolicylab/_protocol.py @@ -146,7 +146,7 @@ def from_wire(cls, data: dict[str, Any]) -> Frame: def _encode_hook(obj: Any) -> Any: # Same restriction as upstream: object-dtype arrays cannot round-trip. - if isinstance(obj, (np.ndarray, np.generic)) and obj.dtype.kind == "O": + if isinstance(obj, np.ndarray | np.generic) and obj.dtype.kind == "O": raise WsError("invalid_frame", "object dtype numpy arrays are not supported") return msgpack_numpy.encode(obj) diff --git a/plugins/inspect-robots-xpolicylab/tests/_stub_server.py b/plugins/inspect-robots-xpolicylab/tests/_stub_server.py index 1ad7f52d1..7cb3c9209 100644 --- a/plugins/inspect-robots-xpolicylab/tests/_stub_server.py +++ b/plugins/inspect-robots-xpolicylab/tests/_stub_server.py @@ -64,7 +64,7 @@ def stop(self) -> None: def _handler(self, ws: ServerConnection) -> None: for raw in ws: - if not isinstance(raw, (bytes, bytearray)): + if not isinstance(raw, bytes | bytearray): continue frame = decode_frame(bytes(raw)) self.frames.append(frame) diff --git a/src/inspect_robots/_html.py b/src/inspect_robots/_html.py index 55b6fed7e..c3d9c97f8 100644 --- a/src/inspect_robots/_html.py +++ b/src/inspect_robots/_html.py @@ -638,7 +638,7 @@ def _render_tool_call(raw_call: object) -> str: ) elif isinstance(value, list): chips.append(_call_chip(key, ", ".join(str(item) for item in value))) - elif value is None or isinstance(value, (str, int, float, bool)): + elif value is None or isinstance(value, str | int | float | bool): chips.append(_call_chip(key, value)) else: return f"{notes}{_raw_tool_call(name, arguments)}" @@ -650,7 +650,7 @@ def _render_tool_call(raw_call: object) -> str: def _is_number(value: object) -> bool: """Accept real JSON numbers while excluding booleans from numeric chips.""" - return isinstance(value, (int, float)) and not isinstance(value, bool) + return isinstance(value, int | float) and not isinstance(value, bool) def _call_chip(key: object, value: object) -> str: @@ -1245,7 +1245,7 @@ def _render_wire_call( shown_status = "null" if status is None else status shown_duration = ( f"{_number(duration)} s" - if isinstance(duration, (int, float)) and not isinstance(duration, bool) + if isinstance(duration, int | float) and not isinstance(duration, bool) else "n/a" ) summary = ( diff --git a/src/inspect_robots/_summarize.py b/src/inspect_robots/_summarize.py index 9f418db1b..0df8a70e0 100644 --- a/src/inspect_robots/_summarize.py +++ b/src/inspect_robots/_summarize.py @@ -101,7 +101,7 @@ def _parallel_value(values: tuple[Any, ...], index: int) -> Any: def _step_count(scores: dict[str, float]) -> str: value = scores.get("episode_length") - if isinstance(value, (int, float)) and not isinstance(value, bool): + if isinstance(value, int | float) and not isinstance(value, bool): return f"{value:g}" return "not recorded" diff --git a/src/inspect_robots/_video.py b/src/inspect_robots/_video.py index 431067c18..b5c065f85 100644 --- a/src/inspect_robots/_video.py +++ b/src/inspect_robots/_video.py @@ -121,7 +121,7 @@ def default_fps(embodiment_info: Mapping[str, Any]) -> tuple[float, str]: """ rate = embodiment_info.get("control_hz") if ( - isinstance(rate, (int, float)) + isinstance(rate, int | float) and not isinstance(rate, bool) and rate > 0 and math.isfinite(rate) diff --git a/src/inspect_robots/cli.py b/src/inspect_robots/cli.py index 767f3b539..7c733455a 100644 --- a/src/inspect_robots/cli.py +++ b/src/inspect_robots/cli.py @@ -1018,7 +1018,7 @@ def _seconds_horizon(log: EvalLog) -> tuple[float, int, float | None] | None: max_seconds = log.eval.max_seconds max_steps = log.eval.max_steps if not ( - isinstance(max_seconds, (int, float)) + isinstance(max_seconds, int | float) and not isinstance(max_seconds, bool) and math.isfinite(max_seconds) and max_seconds > 0 @@ -1031,7 +1031,7 @@ def _seconds_horizon(log: EvalLog) -> tuple[float, int, float | None] | None: rate = log.eval.embodiment_info.get("control_hz") valid_rate = ( float(rate) - if isinstance(rate, (int, float)) + if isinstance(rate, int | float) and not isinstance(rate, bool) and math.isfinite(rate) and rate > 0 @@ -1097,7 +1097,7 @@ def _print_step_limit_notice(log: EvalLog, is_adhoc: bool) -> None: parenthetical = f"max_steps={max_steps}" rate = log.eval.embodiment_info.get("control_hz") if ( - isinstance(rate, (int, float)) + isinstance(rate, int | float) and not isinstance(rate, bool) and math.isfinite(rate) and rate > 0 @@ -1253,7 +1253,7 @@ def _print_wire_table(trials: list[_WireTrial]) -> None: duration = row.get("duration_s") shown_duration = ( f"{duration:.3f}s" - if isinstance(duration, (int, float)) and not isinstance(duration, bool) + if isinstance(duration, int | float) and not isinstance(duration, bool) else "-" ) status = "-" if row.get("status") is None else str(row["status"]) diff --git a/src/inspect_robots/logging/json_log.py b/src/inspect_robots/logging/json_log.py index 4e8f45c5d..b2c4ec7d9 100644 --- a/src/inspect_robots/logging/json_log.py +++ b/src/inspect_robots/logging/json_log.py @@ -54,7 +54,7 @@ def _sanitize(obj: object) -> object: return obj if math.isfinite(obj) else None if isinstance(obj, dict): return {key: _sanitize(value) for key, value in obj.items()} - if isinstance(obj, (list, tuple)): + if isinstance(obj, list | tuple): return [_sanitize(value) for value in obj] return obj