UI Runtime API
Shared runtime helpers used by the pywebview launcher, preview windows, Flask server, Dash integrations, and form generation.
GONet Wizard Unified UI Runtime
This subpackage implements the shared desktop UI runtime used across GONet Wizard to present interactive outputs in a consistent way, regardless of whether a workflow is launched from the CLI or from the GUI launcher.
Scope and Motivation
GONet Wizard commands historically behaved like traditional CLI utilities: they parsed arguments, performed work, and printed results to stdout (or wrote files). As the project expanded to include interactive tooling (Dash apps, HTML previews, and a PyWebview-based desktop experience), a central requirement emerged:
The same command handler should be able to produce a terminal-only result or a GUI-presented result without duplicating logic.
This subpackage provides that bridge by defining a small set of primitives for:
hosting UI content at stable local URLs (via a unified Flask server),
publishing “latest output” previews under stable channel names, and
opening/focusing windows in a controlled, process-safe way (via pywebview).
This allows command handlers to return structured UI intents (publish preview, open window, or both) while keeping the handler itself independent of the window backend and event-loop lifecycle.
Core Concepts
- Unified local server
A single Flask application hosts the GUI launcher pages and the preview endpoints. Any part of the application can rely on stable URLs such as
/view/<channel>to display the most recent output for a given channel.- Preview channels
Command outputs can be published under a channel name (often the command name, such as
"show"). The preview registry stores only the latest HTML for each channel, making it easy to re-run a command and refresh a window without creating new routes or templates.- Window registry
Pywebview windows are managed through a key-based registry. A window can be “ensured” (created if missing, reused if already open), which prevents duplicate windows and supports workflows where repeated command execution should update an existing view.
- Event-loop discipline
Pywebview’s event loop must be started at most once per process. This subpackage includes runtime checks and launcher-mode signaling so that command handlers invoked from inside the GUI do not accidentally attempt to start a second event loop.
Module Layout
GONet_Wizard.ui.serverCreates and starts the unified Flask server used by the desktop runtime.GONet_Wizard.ui.previewImplements the preview registry and the Flask blueprint providing stable preview routes (shell + raw HTML views).GONet_Wizard.ui.windowsProvidesWindowSpecand the process-wide window registryWINDOWS.GONet_Wizard.ui.runtimeManages launcher-mode signaling and safe startup of the pywebview event loop, and exposes a stable API to ensure the unified server is running.GONet_Wizard.ui.apiDefinesWebviewAPI, the Python-side JavaScript bridge exposed to frontend pages aswindow.pywebview.api.GONet_Wizard.ui.dash_runnerProvides shared utilities for launching Dash servers in background threads and reusing running instances, enabling multiple Dash-based tools to share a consistent startup pattern.
Public API
This package re-exports a small set of stable objects and helpers that are used throughout GONet Wizard:
WINDOWSandWindowSpecfor window creation and managementlauncher-mode helpers (
set_launcher_mode(),in_launcher_mode())event-loop startup helper (
start_event_loop_if_needed())unified server helper (
ensure_server_running())preview_managerfor publishing preview content
- class GONet_Wizard.ui.WindowSpec(title, url, width=1200, height=800, resizable=True, on_closed=None)[source]
Bases:
objectDeclarative specification for a pywebview window.
- url
URL string or WSGI app object.
- Type:
UrlLike
- on_closed
Callback invoked after the window is closed and removed from the registry.
- Type:
callable, optional
- GONet_Wizard.ui.set_launcher_mode()[source]
Mark the current process as a running UI process.
This is intended for environments where GUI code invokes CLI handlers internally. In that situation, downstream handler wrappers should avoid starting a new pywebview loop because it is already running.
- Return type:
- Returns:
None
- GONet_Wizard.ui.in_launcher_mode()[source]
Determine whether the current process is running in launcher mode.
- GONet_Wizard.ui.start_event_loop_if_needed(*, debug=False)[source]
Backwards-compatible wrapper for legacy call sites.
- GONet_Wizard.ui.ensure_server_running(port=5050)[source]
Ensure the unified UI server is running and return the port.
This is implemented in
GONet_Wizard.ui.serverand imported here to provide a stable public API for command wrappers and UI entry points.- Parameters:
port (
int, optional) – Preferred port for the unified UI server. Defaults to5050.- Return type:
- Returns:
int– The port on which the server is running.- Raises:
RuntimeError – If the server cannot be started.
PyWebview JavaScript API Bridge
This module defines the Python-side JavaScript API exposed to pywebview windows
as window.pywebview.api. The API provides a small set of UI affordances that
frontend pages can invoke to interact with the host OS, such as:
opening native file/folder selection dialogs, and
triggering window management actions (e.g., closing a window).
The API is intentionally lightweight and uses lazy imports to avoid importing
webview at import time. File dialog actions are debounced and guarded by
a lock to prevent double-triggered dialogs from rapid user interactions.
Classes
WebviewAPIJavaScript API object exposed by pywebview as
window.pywebview.api.
- class GONet_Wizard.ui.api.WebviewAPI[source]
Bases:
objectJavaScript API for pywebview interactions.
Instances of this class are attached to pywebview windows and are accessible from JavaScript as
window.pywebview.api.- _dialog_lock
Lock guarding access to native dialog creation.
- Type:
- close_window()[source]
Close the first pywebview window.
- Return type:
- Returns:
None
Notes
Window destruction is scheduled on a short timer to avoid interfering with the calling JavaScript event loop.
- pick_paths(mode='files')[source]
Open a native file/folder dialog and return selected paths.
- Parameters:
mode (
str, optional) –Selection mode:
"files": file picker (multi-select)"folder": folder picker (single)
- Return type:
- Returns:
Notes
Dialog creation is debounced and guarded by a lock to prevent duplicate dialogs from rapid user interactions.
- pick_save_path(default_name='gonet_figure.pdf', file_types=None)[source]
Open a native save dialog and return the selected output path.
- Parameters:
- Return type:
- Returns:
str– Selected save path, or an empty string when the dialog is canceled.
- download_json(data, default_name='data.json')[source]
Save JSON-serializable data through the native save dialog.
- Parameters:
- Return type:
- Returns:
str – The final path written, or an empty string when the dialog is canceled or unavailable.
- Raises:
Notes
The selected filename is normalized again after the dialog closes, so entering another extension cannot produce a non-JSON output file.
- download_json_url(url, default_name='data.json')[source]
Save a JSON payload exposed by the local Dash server.
Only loopback HTTP(S) URLs are accepted. This keeps the pywebview API narrowly scoped to files staged by GONet Wizard rather than turning it into a general-purpose downloader.
- Parameters:
- Return type:
- Returns:
str – The final path written, or an empty string when the dialog is canceled.
- Raises:
ValueError – If url is not a loopback HTTP(S) URL.
OSError – If the staged payload cannot be fetched or written.
- class GONet_Wizard.ui.dash_runner.DashLaunchSpec(app, app_key, configure, layout, register_callbacks, index_string=None)[source]
Bases:
objectSpecification describing how to configure and launch a Dash app.
A
DashLaunchSpecprovides the app instance and a set of callables that supply app-specific configuration, layout construction, and callback registration. Theapp_keyis used to cache and re-use already-running servers.- app
Dash app instance to run.
- Type:
dash.Dash
- app_key
Unique identifier for this app type (e.g.,
"dashboard","extract-gui"). Used to cache/reuse running threads.- Type:
- configure
Callable invoked before starting the server. Use this to populate
app.server.configand apply any runtime settings.- Type:
- layout
Callable that returns the layout object assigned to
app.layout.- Type:
- register_callbacks
Callable invoked after the layout is assigned and before the server starts. Typical usage is importing a callbacks module for side effects.
- Type:
- index_string
Optional callable returning a full Dash
index_stringoverride.- Type:
collections.abc.Callable, optional
- GONet_Wizard.ui.dash_runner.wait_for_port(host, port, *, timeout=30.0, poll_interval=0.1, startup_errors=None, app_key=None)[source]
Block until a TCP port is accepting connections.
- Parameters:
host (
str) – Hostname or IP address (e.g."127.0.0.1").port (
int) – TCP port number.timeout (
float, optional) – Maximum time to wait in seconds. Defaults to30.0. Frozen desktop apps can take longer than source-mode runs to import, configure, and bind Dash apps.poll_interval (
float, optional) – Time between connection attempts in seconds. Defaults to0.1.startup_errors (
queue.Queue, optional) – Queue populated by the background server thread if startup fails before the port opens.app_key (
str, optional) – App key included in startup error messages.
- Return type:
- Returns:
None
- Raises:
RuntimeError – If the port does not open within
timeoutseconds, or if the Dash server reports a startup exception before the port opens.
- GONet_Wizard.ui.dash_runner.ensure_dash_running(spec, *, debug, port=8050, startup_timeout=30.0)[source]
Ensure a Dash server is running for the given spec and port, and return its URL.
If a server is already running for
(spec.app_key, port), it is reused.- Parameters:
spec (
DashLaunchSpec) – Launch specification for the Dash app.debug (
bool) – Whether to run Dash in debug mode.port (
int, optional) – Port to bind to on localhost. Defaults to8050.startup_timeout (
float, optional) – Maximum time to wait for the server port to open. Defaults to30.0.
- Return type:
- Returns:
str– Local URL for the running server (e.g.,"http://127.0.0.1:8050").- Raises:
RuntimeError – If the server fails during startup or does not open its port before the timeout expires.
Command Form Launcher Utilities
This module provides a small helper to open a specific command form page served by the unified local UI server in a managed pywebview window.
The primary use case is routing CLI invocations to the GUI form for a command
when the invocation includes only the command token sequence and omits required
arguments. The helper ensures the unified UI server is running, loads the
appropriate /cmd/... route, and starts the pywebview event loop if needed.
Functions
open_command_form()Ensure the unified UI server is running and load the command form page in a managed launcher window.
- GONet_Wizard.ui.launch_forms.open_command_form(*, cmd_tokens, port, debug_webview)[source]
Open a GUI command form page in the managed launcher window.
The command form URL is derived from
cmd_tokensand points to the unified UI server route/cmd/<path>. The window is created or reused under the stable key"launcher".- Parameters:
cmd_tokens (
Sequenceofstr) – Command token sequence identifying the command form to load (e.g.,("show",)or("connect", "snap")). Tokens are joined with"/"to form the form route path.port (
int) – Preferred port for the unified local UI server.debug_webview (
bool) – IfTrue, start the pywebview event loop with debugging enabled.
- Return type:
- Returns:
None – This function does not return a value.
- Raises:
RuntimeError – If the unified UI server cannot be started or the window cannot be created.
Preview Publishing and Viewing for the Unified UI Server
This module implements the preview subsystem used by GONet Wizard commands to publish renderable HTML output and view it through the unified local UI server. It provides:
a thread-safe in-memory registry mapping preview channels to their latest HTML,
a small Flask
Blueprintexposing routes to display previews, anda consistent HTML wrapper that injects shared UI styling.
Previews are keyed by a channel name (typically a command name such as
"show"), allowing command handlers to update the content for a known view
without managing windows or templates directly.
Classes
PreviewPayloadContainer for the latest HTML and title associated with a preview channel.
PreviewManagerThread-safe registry for publishing and retrieving preview payloads.
Constants
preview_managerSingleton
PreviewManagerused across the UI layer.preview_bpFlask
Blueprintthat registers preview routes.
Functions
view_shell()Render a styled shell page that embeds a preview channel via an iframe.
view_raw()Return the raw HTML document for a preview channel with shared CSS injected.
- class GONet_Wizard.ui.preview.PreviewPayload(title, html=None)[source]
Bases:
objectPayload containing the latest renderable output for a preview channel.
- class GONet_Wizard.ui.preview.PreviewManager[source]
Bases:
objectThread-safe registry of preview outputs keyed by channel name.
Preview content is stored in-memory and intended for local interactive use. Typical usage publishes HTML output under a stable channel name:
preview_manager.publish_html("show", html, title="Show")- _lock
Mutex protecting registry operations.
- Type:
- _data
Mapping of channel name to
PreviewPayload.- Type:
- publish_html(channel, html, *, title=None)[source]
Publish HTML for a preview channel.
If the channel does not exist, it is created. If it exists, the stored HTML is replaced, and the title is updated only when explicitly provided.
- get(channel)[source]
Retrieve the payload for a preview channel.
If the channel does not exist, a placeholder payload is created and stored with no HTML content.
- Parameters:
channel (
str) – Preview channel name.- Return type:
- Returns:
PreviewPayload– Payload for the requested channel.
- GONet_Wizard.ui.preview.view_shell(channel)[source]
Render the shell view for a preview channel.
This route returns a styled page (template-driven) that embeds the raw HTML output for the channel, typically via an iframe pointed at
/view/<channel>/raw.
- GONet_Wizard.ui.preview.view_raw(channel)[source]
Return the raw HTML document for a preview channel.
If no HTML has been published for the channel, a placeholder page is returned. Otherwise, the published HTML is wrapped in a minimal document that injects the shared stylesheet and disables caching to ensure reloads always reflect the latest published output.
- Parameters:
channel (
str) – Preview channel name.- Returns:
flask.Response– HTTP response containing an HTML document.
UI Runtime Mode and Event Loop Control
This module centralizes process-level runtime controls for the GONet Wizard UI. It provides:
a simple environment-variable mechanism to indicate that the current process is already running inside a GUI/webview context, and
a process-local guard to ensure
webview.start()is invoked at most once.
These utilities allow CLI command handlers to be reused from GUI workflows without accidentally starting additional pywebview loops. The module also re-exports a stable helper for ensuring the unified UI server is running.
Constants
CONFIGUIRuntimeConfiginstance defining runtime configuration defaults.
Classes
UIRuntimeConfigConfiguration values used to determine UI mode behavior.
_WebviewLoopStateInternal state tracking whether the pywebview loop has been started.
Functions
set_launcher_mode()Mark the current process as running inside the GUI launcher.
in_launcher_mode()Check whether the process is running inside a GUI/webview loop.
start_webview_loop()Start the pywebview event loop exactly once per process.
start_event_loop_if_needed()Backwards-compatible wrapper around
start_webview_loop().ensure_server_running()Ensure the unified UI server is running and return the selected port.
- class GONet_Wizard.ui.runtime.UIRuntimeConfig(ui_mode_env='GONET_WIZARD_UI_MODE')[source]
Bases:
objectConfiguration for determining UI runtime behavior.
- GONet_Wizard.ui.runtime.set_launcher_mode()[source]
Mark the current process as a running UI process.
This is intended for environments where GUI code invokes CLI handlers internally. In that situation, downstream handler wrappers should avoid starting a new pywebview loop because it is already running.
- Return type:
- Returns:
None
- GONet_Wizard.ui.runtime.in_launcher_mode()[source]
Determine whether the current process is running in launcher mode.
- GONet_Wizard.ui.runtime.start_webview_loop(*, debug_webview=False, private_mode=False, force=False)[source]
Start the pywebview event loop exactly once per process.
Calls to this function are idempotent. If the loop has already been started, the function returns immediately.
- Parameters:
debug_webview (
bool, optional) – Enable pywebview debug mode. Defaults toFalse.private_mode (
bool, optional) – Enable pywebview private mode. Defaults toFalse.force (
bool, optional) – IfTrue, start the loop even ifin_launcher_mode()isTrue. Defaults toFalse.
- Return type:
- Returns:
None
- GONet_Wizard.ui.runtime.start_event_loop_if_needed(*, debug=False)[source]
Backwards-compatible wrapper for legacy call sites.
- GONet_Wizard.ui.runtime.ensure_server_running(port=5050)[source]
Ensure the unified UI server is running and return the port.
This is implemented in
GONet_Wizard.ui.serverand imported here to provide a stable public API for command wrappers and UI entry points.- Parameters:
port (
int, optional) – Preferred port for the unified UI server. Defaults to5050.- Return type:
- Returns:
int– The port on which the server is running.- Raises:
RuntimeError – If the server cannot be started.
Unified Local UI Server for Desktop Runtime
This module hosts the unified Flask server used by the GONet Wizard desktop UI. The server provides a single local HTTP surface for:
the GUI launcher pages (main menu and command forms),
preview endpoints for command output (e.g.
/view/<channel>), andfuture UI endpoints shared across windows.
The server is started on demand via ensure_server_running() and runs in a
single daemon thread. This allows CLI commands and UI workflows to publish and
render previews without requiring an external web server setup.
Global State
The server is managed as a process singleton using module-level state:
_appholds theflask.Flaskinstance_server_threadholds the background thread running the server_server_portstores the configured port_server_lockserializes startup so callers never open windows early
Functions
create_app()Create and configure the unified Flask application.
ensure_server_running()Start the Flask server thread if needed and return the active port.
wait_for_server()Block until the local Flask server answers its health endpoint.
get_app()Return the singleton Flask app instance, creating it if needed.
get_server_port()Return the configured server port.
- GONet_Wizard.ui.server.create_app()[source]
Create the unified Flask application for the desktop UI runtime.
The returned app registers blueprints for the GUI launcher pages and the preview subsystem. Template and static folders are configured using package settings so the app can be run from different working directories.
- Return type:
- Returns:
flask.Flask– Configured Flask application instance.- Raises:
RuntimeError – If blueprint registration fails due to import cycles or missing assets.
- GONet_Wizard.ui.server.wait_for_server(host, port, *, path='/health', timeout=10.0, poll_interval=0.1)[source]
Block until the unified UI server answers its health endpoint.
The desktop bundle starts Flask in a background thread before creating the pywebview window. Frozen apps can take slightly longer to bind and serve their first request, so probing the HTTP health endpoint avoids opening a blank webview against a server that is not ready yet.
- Parameters:
host (
str) – Hostname or IP address to probe, usually"127.0.0.1".port (
int) – TCP port used by the unified UI server.path (
str, optional) – Health endpoint path. Defaults to"/health".timeout (
float, optional) – Maximum time to wait in seconds. Defaults to10.0.poll_interval (
float, optional) – Time between readiness checks in seconds. Defaults to0.1.
- Return type:
- Returns:
None
- Raises:
RuntimeError – If the health endpoint does not respond before
timeoutexpires.
- GONet_Wizard.ui.server.ensure_server_running(*, port=5050)[source]
Ensure the unified Flask server is running and return the port.
This function is safe to call multiple times. If the server thread is already running, the existing port is returned. Otherwise, the server is created and started in a single daemon thread.
- Parameters:
port (
int, optional) – Localhost port to bind the server to. Defaults to5050.- Return type:
- Returns:
int– The port the server is running on.- Raises:
RuntimeError – If the server cannot be started.
- GONet_Wizard.ui.server.get_app()[source]
Return the singleton Flask app instance, creating it if needed.
This helper is primarily intended for tests or advanced embedding scenarios.
- Return type:
- Returns:
flask.Flask– The process singleton Flask application instance.
- GONet_Wizard.ui.server.get_server_port()[source]
Return the configured server port (whether started or not).
PyWebview Window Specifications and Registry
This module provides the window-management layer for the GONet Wizard desktop
UI. It defines a lightweight, declarative WindowSpec used to describe
pywebview windows and a WindowManager that maintains a process-wide
registry of open windows under stable string keys.
The registry supports common UI workflows such as: - opening a window once and reusing it on subsequent requests, - focusing/reloading an existing window rather than spawning duplicates, and - removing registry entries when a user closes a window.
The module avoids importing webview at import time to prevent side effects
and to keep non-GUI entry points lightweight. The singleton WINDOWS
instance is used across the package to centralize window creation.
Type Aliases
UrlLikeUnion type accepted as a window URL, including string URLs and WSGI app-like objects supported by pywebview.
Classes
WindowSpecDeclarative specification for a pywebview window (title, URL, size, flags).
WindowManagerThread-safe registry for creating, retrieving, and managing pywebview windows.
Constants
WINDOWSSingleton
WindowManagerused across the UI layer.
- class GONet_Wizard.ui.windows.WindowSpec(title, url, width=1200, height=800, resizable=True, on_closed=None)[source]
Bases:
objectDeclarative specification for a pywebview window.
- url
URL string or WSGI app object.
- Type:
UrlLike
- on_closed
Callback invoked after the window is closed and removed from the registry.
- Type:
callable, optional
- class GONet_Wizard.ui.windows.WindowManager[source]
Bases:
objectThread-safe registry for pywebview windows.
The window manager creates and tracks windows under stable keys (e.g.
"launcher","show","dashboard"). If a window already exists for a key, calls toensure()return the existing window and attempt a best-effort refresh of its URL. Closed windows are detected and removed from the registry so subsequent calls recreate them.This module does not start the pywebview event loop; it only manages window objects. Importing this module avoids importing
webviewto prevent import-time side effects.- _api
JavaScript API instance attached to created windows.
- Type:
- _lock
Mutex protecting the window registry.
- Type:
- ensure(key, spec)[source]
Ensure a window exists for the given key.
If a window already exists, it is returned and a best-effort URL refresh is attempted. If no window exists (or the previous one was closed), a new window is created, registered, and monitored for closure.
- Parameters:
key (
str) – Stable key for the window (e.g."launcher","show","dashboard").spec (
WindowSpec) – Window configuration.
- Return type:
- Returns:
webview.Window– The created or existing window.- Raises:
RuntimeError – If pywebview window creation fails.