exlab_wizard.tray#
Tray application package. Backend Spec §4.3.2.
Public API:
AutostartManager– per-platform autostart register / unregister / is_registered.NotificationBus– coalesced OS notifications via plyer.QuitCoordinator– §4.3.2 graceful-shutdown protocol.ServerRunner– in-process uvicorn host with atomicserver.jsonwrites.StatusTicker– 5-second status submenu refresh.TrayApp– the long-lived wiring assembly used byexlab_wizard.tray.main().WindowLauncher– spawns / focusesexlab-wizard-windowsubprocess.build_icon()– pystray icon factory.
- class exlab_wizard.tray.AutostartManager(*, executable_path=None, filesystem_root=None, platform=None)[source]#
Bases:
objectPer-platform autostart register / unregister / is_registered.
Construction-time parameters:
executable_path– absolute path toExLab-Wizard-Tray. The production launcher resolvessys.executable(PyInstaller bundles setsys.executableto the launcher binary).filesystem_root– root directory for per-user files. Defaults toPath.home()in production; tests injecttmp_path. The env-var overrideEXLAB_AUTOSTART_ROOTwins over the constructor default.platform– override the OS dispatch, used by tests to exercise every branch on a single host.
- Parameters:
- property platform: Platform#
Return the platform dispatch this manager is configured for.
- class exlab_wizard.tray.NotificationBus(*, notifier=None, is_window_foregrounded=None, coalescing_window=5.0)[source]#
Bases:
objectCoalescing layer over
notify().The launcher constructs one bus and threads it through to the components that emit notification-eligible events (plugin host, NAS-sync). Components call
emit(); the bus handles coalescing, foreground suppression, and the actual plyer call.- Parameters:
- class exlab_wizard.tray.QuitCoordinator(*, server_runner, window_launcher, session_store, nas_sync, on_force_quit_prompt=None, timeout_seconds=30.0, sigterm_timeout_seconds=5.0, poll_interval_seconds=0.1)[source]#
Bases:
objectDrive the §4.3.2 graceful-shutdown protocol.
Construction-time dependencies are kept loosely typed so the coordinator can integrate with whatever stub fixtures unit tests pass. The runtime contract is documented per parameter.
- Parameters:
- class exlab_wizard.tray.ServerRunner(*, app, state_dir)[source]#
Bases:
objectStarts uvicorn on a free localhost port and tracks its state file.
Backend Spec §4.3.2 + §15.3.1.
- property port: int#
Return the port the server is bound to.
Raises
RuntimeErrorwhen called beforestart().
- class exlab_wizard.tray.StatusSnapshot(active_sessions=0, sync_queue_depth=0, input_required_count=0)[source]#
Bases:
objectImmutable view over the §4.3.2 status inputs.
- class exlab_wizard.tray.StatusTicker(*, session_store=None, nas_sync=None, on_update=None, interval_seconds=5.0)[source]#
Bases:
objectPolls
snapshot_status()on a fixed cadence.On every tick the formatted string is computed; if it differs from the previous label the
on_updatecallback is invoked with the new label. The callback is the tray menu’s “set status text” hook; tests pass a recording callable.- Parameters:
- class exlab_wizard.tray.TrayApp(server_runner, window_launcher, quit_coordinator, status_ticker, notification_bus, autostart, icon=None)[source]#
Bases:
objectBundle of long-lived tray components.
The launcher constructs one and calls
run(); tests build one with stub components and exerciseshutdown()/open()individually.- Parameters:
server_runner (
ServerRunner)window_launcher (
WindowLauncher)quit_coordinator (
QuitCoordinator)status_ticker (
StatusTicker)notification_bus (
NotificationBus)autostart (
AutostartManager)icon (
Any)
- autostart: AutostartManager#
- notification_bus: NotificationBus#
- quit_coordinator: QuitCoordinator#
- run(*, run_loop=None)[source]#
Start the server, build the icon, run the pystray loop.
run_loopis injected by tests so they don’t actually callIcon.run(which would block on a real backend). Returns the exit code.
- server_runner: ServerRunner#
- status_ticker: StatusTicker#
- window_launcher: WindowLauncher#
- class exlab_wizard.tray.WindowLauncher(*, window_executable=None, state_dir)[source]#
Bases:
objectSpawn
exlab-wizard-windowas a subprocess, track its PID.On a re-open request with an existing live child, focuses the existing window (best-effort) rather than spawning a duplicate (Backend §4.1: “single-instance window”).
- exlab_wizard.tray.build_icon(*, on_open, on_quit, status_provider, pystray_module=None, icon_image=None, icon_name='exlab-wizard', title='ExLab-Wizard')[source]#
Build the pystray icon with the §4.1 menu.
status_provideris invoked every time pystray re-renders the menu (pystray supports lazily-evaluated text via callable labels) so the operator sees live status without a separate refresh notification.
- exlab_wizard.tray.format_status(snapshot)[source]#
Return the menu-label string for the §4.3.2 formatter.
- Parameters:
snapshot (
StatusSnapshot)- Return type:
- exlab_wizard.tray.notify(*, title, message, notifier=None)[source]#
Fire a plyer notification (or an injected stub).
notifierdefaults toplyer.notification.notifywhich the plyer wheel auto-resolves to the platform-appropriate backend (UNUserNotificationCenter / ToastNotificationManager / libnotify). Tests pass a recording callable.
- exlab_wizard.tray.snapshot_status(*, session_store=None, nas_sync=None)[source]#
Build a
StatusSnapshotfrom live component references.Each component is read defensively so the launcher can pass
None(setup-incomplete state) without the formatter crashing. The function readsactive_sessionsandinput_required-style counts fromsession_storeandin_flight_jobs/queue_depthfromnas_sync.- Parameters:
- Return type:
Modules
Per-platform autostart registration. |
|
pystray icon construction. |
|
|
|
OS notifications via plyer with 5-second coalescing. |
|
Graceful tray shutdown coordinator. |
|
Programmatic uvicorn launcher with atomic |
|
Status-submenu rendering. |
|
Spawn / focus the on-demand window subprocess. |