Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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:
Expand All @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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__}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion plugins/inspect-robots-ros/tests/_stub_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
2 changes: 1 addition & 1 deletion plugins/inspect-robots-xpolicylab/tests/_stub_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 3 additions & 3 deletions src/inspect_robots/_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)}"
Expand All @@ -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:
Expand Down Expand Up @@ -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 = (
Expand Down
2 changes: 1 addition & 1 deletion src/inspect_robots/_summarize.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down
2 changes: 1 addition & 1 deletion src/inspect_robots/_video.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
8 changes: 4 additions & 4 deletions src/inspect_robots/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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"])
Expand Down
2 changes: 1 addition & 1 deletion src/inspect_robots/logging/json_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down