`ruff check --fix` over the whole tree, ahead of putting the linter in CI: 1977 mechanical fixes, overwhelmingly `Optional[X]` → `X | None` (1186 in the package alone) and the quoted annotations that `from __future__ import annotations` already made unnecessary, plus import sorting and unused imports. Nothing here changes behaviour — the suite is 1885 green before and after. Four findings were real rather than stylistic and are fixed by hand: a dead `cells` range in `MapCanvas`, a dead slot dict in the heat-ladder test, a `ProgressScreen` task handle nobody read, and a tab loop binding a `label` it never used. The two `F821`s were quoted forward references to names imported inside their function bodies — now declared under `TYPE_CHECKING`, which keeps `test_performance`'s local import (it guards the startup import graph) while letting the linter resolve the name. 412 findings remain and are deliberately untouched: they need a decision about the rule, not an edit to the code. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
73 lines
2.5 KiB
Python
73 lines
2.5 KiB
Python
"""The ``device-actions`` tool: immediate operations on the companion device itself.
|
|
|
|
Opens the Device actions screen (see :func:`meshterm.ui.config_editor.device_actions`) —
|
|
clock sync, backup/restore, the identity key, reboot, and factory reset. Where the
|
|
sibling ``config`` tool *stages* value changes for review, everything here acts on the
|
|
box the moment it is confirmed, so the two concerns get their own menu entries and
|
|
screens. Sending an advert is not here: that everyday operation lives in its own
|
|
main-menu entry (the sibling ``advert`` tool — see :mod:`meshterm.tools.advert`).
|
|
|
|
Menu-only: every action already has a first-class scripted equivalent under the ``config``
|
|
CLI group (``config backup``, ``config restore``, ``config reboot``, ...), so no duplicate
|
|
subcommand is registered here.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
import typer
|
|
|
|
from ..context import AppContext
|
|
from .base import Tool, ToolResult, register
|
|
|
|
|
|
@register
|
|
class DeviceActionsTool(Tool):
|
|
"""Run immediate device operations: clock, backup, identity key, reboot, reset."""
|
|
|
|
name = "device-actions"
|
|
title = "Device actions"
|
|
icon = "🔨"
|
|
help = "Clock, backup, identity key, reboot, reset"
|
|
category = "This node"
|
|
order = 30
|
|
|
|
async def prompt_params(self, ctx: AppContext) -> dict[str, Any] | None:
|
|
"""Run the interactive actions screen; there are never parameters to collect.
|
|
|
|
Each action executes and presents its result inside the screen itself, so by the
|
|
time the user backs out there is nothing left for :meth:`run` to do — returning
|
|
``None`` tells the menu the invocation is complete (the same pattern as backing
|
|
out of the config editor with nothing staged).
|
|
|
|
Args:
|
|
ctx: Shared application context.
|
|
|
|
Returns:
|
|
Always ``None``.
|
|
"""
|
|
from ..ui.config_editor import device_actions
|
|
|
|
await device_actions(ctx)
|
|
return None
|
|
|
|
async def run(self, ctx: AppContext, params: dict[str, Any]) -> ToolResult:
|
|
"""Nothing runs here: the actions execute inside :meth:`prompt_params`.
|
|
|
|
Args:
|
|
ctx: Shared application context.
|
|
params: Unused.
|
|
|
|
Returns:
|
|
An empty :class:`ToolResult` (only reachable from a scripted call).
|
|
"""
|
|
return ToolResult(summary={})
|
|
|
|
def register_cli(self, app: typer.Typer) -> None:
|
|
"""Register no CLI command — the scripted equivalents live under ``config``.
|
|
|
|
Args:
|
|
app: The Typer application (untouched).
|
|
"""
|