Files
MeshTerm/meshterm/tools/advert.py
T
Jean-Pierre MartineauandClaude Opus 5 71b16ec7b7 The annotations, imports, and dead locals answer to ruff
`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>
2026-09-06 17:26:12 -04:00

72 lines
2.5 KiB
Python

"""The ``advert`` tool: announce this node to the mesh, straight from the main menu.
Opens the Send advert flow (see :func:`meshterm.ui.config_editor.send_advert`) — a
zero-hop or flood advertisement, or this node's shareable contact card as a QR code.
A ``popup`` tool: the flow's prompts and result float over the still-pushed main menu
as modal dialogs (the quit-dialog pattern), so the everyday action stays a quick
in-place popup rather than a screen change.
Menu-only: the scripted equivalents are ``config advert`` and ``config share``, so no
duplicate subcommand is registered here (the same pattern as ``device-actions``).
"""
from __future__ import annotations
from typing import Any
import typer
from ..context import AppContext
from .base import Tool, ToolResult, register
@register
class SendAdvertTool(Tool):
"""Send a zero-hop or flood advert, or share this node's contact card."""
name = "advert"
title = "Send advert"
icon = "📡"
help = "Announce this node — zero-hop, flood, or QR"
category = "This node"
order = 40 # your own node announcing itself: a device action, not a view
popup = True # dialog-sized: float over the menu instead of replacing it
async def prompt_params(self, ctx: AppContext) -> dict[str, Any] | None:
"""Run the interactive advert flow; there are never parameters to collect.
The flow presents its own result (the sent-advert note or the contact-card
view) before returning, 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 the Device actions screen).
Args:
ctx: Shared application context.
Returns:
Always ``None``.
"""
from ..ui.config_editor import send_advert
await send_advert(ctx)
return None
async def run(self, ctx: AppContext, params: dict[str, Any]) -> ToolResult:
"""Nothing runs here: the advert is sent 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 — ``config advert`` / ``config share`` cover scripting.
Args:
app: The Typer application (untouched).
"""