From bc8bb9f7a8469dcf9798a9fb6e78b103303dca5a Mon Sep 17 00:00:00 2001 From: ajspig Date: Tue, 14 Apr 2026 11:11:05 -0400 Subject: [PATCH] fix: removing all lazy imports --- .../src/honcho_cli/commands/conclusion.py | 2 -- honcho-cli/src/honcho_cli/commands/message.py | 11 +++++------ honcho-cli/src/honcho_cli/commands/peer.py | 14 ++++---------- honcho-cli/src/honcho_cli/commands/session.py | 15 ++++----------- honcho-cli/src/honcho_cli/commands/setup.py | 18 ++++++++++-------- .../src/honcho_cli/commands/workspace.py | 19 +++++++++---------- honcho-cli/src/honcho_cli/common.py | 14 +++++--------- honcho-cli/src/honcho_cli/main.py | 12 ++++-------- honcho-cli/src/honcho_cli/output.py | 3 +-- honcho-cli/src/honcho_cli/validation.py | 4 ++-- 10 files changed, 44 insertions(+), 68 deletions(-) diff --git a/honcho-cli/src/honcho_cli/commands/conclusion.py b/honcho-cli/src/honcho_cli/commands/conclusion.py index 423631fc..a330d8ca 100644 --- a/honcho-cli/src/honcho_cli/commands/conclusion.py +++ b/honcho-cli/src/honcho_cli/commands/conclusion.py @@ -195,8 +195,6 @@ def delete( # SDK doesn't expose a get-by-id on ConclusionScope, so we can't # preview content cheaply — don't paginate the list just to # decorate the prompt. Show identifying fields only. - from honcho_cli.output import use_json - if not use_json(): typer.echo( f" id: {conclusion_id}\n" diff --git a/honcho-cli/src/honcho_cli/commands/message.py b/honcho-cli/src/honcho_cli/commands/message.py index d8068a35..6d604e58 100644 --- a/honcho-cli/src/honcho_cli/commands/message.py +++ b/honcho-cli/src/honcho_cli/commands/message.py @@ -7,6 +7,11 @@ from typing import Optional import typer +from honcho.api_types import MessageResponse +from honcho.http import routes +from honcho.message import Message + +from honcho_cli.commands.session import _get_session_id from honcho_cli.commands.workspace import _handle_error from honcho_cli.output import print_result, status from honcho_cli.validation import validate_resource_id @@ -28,7 +33,6 @@ def list_messages( json_output: bool = typer.Option(False, "--json", help="Force JSON output"), ) -> None: """List messages in a session.""" - from honcho_cli.commands.session import _get_session_id handle_cmd_flags(json_output=json_output, workspace=workspace, session=session) sid = _get_session_id(session_id) @@ -91,7 +95,6 @@ def get_message( json_output: bool = typer.Option(False, "--json", help="Force JSON output"), ) -> None: """Get a single message by ID.""" - from honcho_cli.commands.session import _get_session_id handle_cmd_flags(json_output=json_output, workspace=workspace) validate_resource_id(message_id, "message") @@ -100,10 +103,6 @@ def get_message( try: # Hit the direct message endpoint instead of paging the session. - from honcho.http import routes - from honcho.api_types import MessageResponse - from honcho.message import Message - sess = client.session(sid) data = client._http.get(routes.message(sess.workspace_id, sess.id, message_id)) msg = Message.from_api_response(MessageResponse.model_validate(data)) diff --git a/honcho-cli/src/honcho_cli/commands/peer.py b/honcho-cli/src/honcho_cli/commands/peer.py index 86b46982..d4b39451 100644 --- a/honcho-cli/src/honcho_cli/commands/peer.py +++ b/honcho-cli/src/honcho_cli/commands/peer.py @@ -7,8 +7,10 @@ from typing import Optional import typer -from honcho_cli.commands.workspace import _config_to_dict, _handle_error -from honcho_cli.output import print_result, use_json +from honcho.api_types import PeerConfig + +from honcho_cli.commands.workspace import _config_to_dict, _handle_error, _raw_list +from honcho_cli.output import print_error, print_result, use_json from honcho_cli.validation import validate_resource_id from honcho_cli.common import add_common_options, get_client, get_resolved_config, handle_cmd_flags @@ -22,8 +24,6 @@ def _get_peer_id(peer_id: str | None) -> str: config = get_resolved_config() pid = peer_id or config.peer_id if not pid: - from honcho_cli.output import print_error - print_error("NO_PEER", "No peer ID provided. Pass --peer/-p or set HONCHO_PEER_ID.") raise typer.Exit(1) return validate_resource_id(pid, "peer") @@ -35,8 +35,6 @@ def list_peers( json_output: bool = typer.Option(False, "--json", help="Force JSON output"), ) -> None: """List all peers in the workspace.""" - from honcho_cli.commands.workspace import _raw_list - handle_cmd_flags(json_output=json_output, workspace=workspace) client, config = get_client() @@ -184,8 +182,6 @@ def create_peer( json_output: bool = typer.Option(False, "--json", help="Force JSON output"), ) -> None: """Create or get a peer.""" - from honcho.api_types import PeerConfig - handle_cmd_flags(json_output=json_output, workspace=workspace) pid = validate_resource_id(peer_id, "peer") client, config = get_client() @@ -195,7 +191,6 @@ def create_peer( try: parsed_metadata = json.loads(metadata) except json.JSONDecodeError as e: - from honcho_cli.output import print_error print_error("INVALID_JSON", f"--metadata must be valid JSON: {e}", {}) raise typer.Exit(1) @@ -253,7 +248,6 @@ def set_metadata( try: parsed = json.loads(metadata) except json.JSONDecodeError as e: - from honcho_cli.output import print_error print_error("INVALID_JSON", f"metadata must be valid JSON: {e}", {}) raise typer.Exit(1) diff --git a/honcho-cli/src/honcho_cli/commands/session.py b/honcho-cli/src/honcho_cli/commands/session.py index 61ed341d..7a727f35 100644 --- a/honcho-cli/src/honcho_cli/commands/session.py +++ b/honcho-cli/src/honcho_cli/commands/session.py @@ -7,8 +7,10 @@ from typing import List, Optional import typer -from honcho_cli.commands.workspace import _config_to_dict, _handle_error -from honcho_cli.output import print_result, status, use_json +from honcho import HonchoError + +from honcho_cli.commands.workspace import _config_to_dict, _handle_error, _raw_list +from honcho_cli.output import print_error, print_result, status, use_json from honcho_cli.validation import validate_resource_id from honcho_cli.common import add_common_options, get_client, get_resolved_config, handle_cmd_flags @@ -22,8 +24,6 @@ def _get_session_id(session_id: str | None) -> str: config = get_resolved_config() sid = session_id or config.session_id if not sid: - from honcho_cli.output import print_error - print_error("NO_SESSION", "No session ID provided. Pass --session/-s or set HONCHO_SESSION_ID.") raise typer.Exit(1) return validate_resource_id(sid, "session") @@ -36,8 +36,6 @@ def list_sessions( json_output: bool = typer.Option(False, "--json", help="Force JSON output"), ) -> None: """List sessions in the workspace.""" - from honcho_cli.commands.workspace import _raw_list - handle_cmd_flags(json_output=json_output, workspace=workspace) client, config = get_client() @@ -168,10 +166,6 @@ def delete( # know what they're deleting, and they still need to pass --yes. # Narrow the except to HonchoError so auth/network failures surface # before the user types 'y' on a destructive op. - from honcho import HonchoError - - from honcho_cli.output import use_json - if not use_json(): try: peers = sess.peers() @@ -362,7 +356,6 @@ def set_metadata( try: parsed = json.loads(metadata) except json.JSONDecodeError as e: - from honcho_cli.output import print_error print_error("INVALID_JSON", f"metadata must be valid JSON: {e}", {}) raise typer.Exit(1) diff --git a/honcho-cli/src/honcho_cli/commands/setup.py b/honcho-cli/src/honcho_cli/commands/setup.py index 2be1897e..be8e1829 100644 --- a/honcho-cli/src/honcho_cli/commands/setup.py +++ b/honcho-cli/src/honcho_cli/commands/setup.py @@ -13,6 +13,8 @@ import typer from rich.console import Console from rich.panel import Panel +from honcho import Honcho + from honcho_cli import __version__ from honcho_cli.config import ( CONFIG_FILE, @@ -21,7 +23,7 @@ from honcho_cli.config import ( ) from honcho_cli.branding import BANNER, BRAND, ICON_FAIL, ICON_OK, ICON_RUN from honcho_cli.common import get_resolved_config -from honcho_cli.output import print_error, print_result +from honcho_cli.output import print_error, print_result, set_json_mode, use_json _console = Console(stderr=True) @@ -56,7 +58,7 @@ def _read_file_values() -> tuple[str, str]: def _test_connection(base_url: str, api_key: str) -> tuple[bool, str]: """Probe the Honcho API by listing workspaces. Returns (ok, detail).""" try: - from honcho import Honcho + list(Honcho(base_url=base_url, api_key=api_key).workspaces()) return True, "OK" @@ -95,7 +97,7 @@ def init( Workspace / peer / session scoping is per-command via ``-w`` / ``-p`` / ``-s`` or ``HONCHO_*`` env vars — never persisted. """ - from honcho_cli.output import set_json_mode, use_json + if json_output: set_json_mode(True) @@ -135,7 +137,7 @@ def init( def _confirm_or_prompt_api_key(value: str, source: str) -> str: - from honcho_cli.output import use_json + if value: if not use_json(): @@ -151,7 +153,7 @@ def _confirm_or_prompt_api_key(value: str, source: str) -> str: def _confirm_or_prompt_url(value: str, source: str) -> str: - from honcho_cli.output import use_json + if value: if not use_json(): @@ -164,7 +166,7 @@ def _confirm_or_prompt_url(value: str, source: str) -> str: def _check_connection(base_url: str, api_key: str) -> None: - from honcho_cli.output import use_json + if not use_json(): _console.print(f"\n {ICON_RUN} [dim]Testing connection to {base_url}...[/dim]", end=" ") @@ -188,7 +190,7 @@ def doctor( """Verify config, connectivity, and — when scoped via ``-w`` / ``-p`` — workspace, peer, and queue health. """ - from honcho_cli.output import set_json_mode, use_json + if json_output: set_json_mode(True) @@ -222,7 +224,7 @@ def doctor( ws_ok, client = False, None if config.workspace_id and config.api_key: try: - from honcho import Honcho + client = Honcho(base_url=config.base_url, api_key=config.api_key, workspace_id=config.workspace_id) client.get_configuration() diff --git a/honcho-cli/src/honcho_cli/commands/workspace.py b/honcho-cli/src/honcho_cli/commands/workspace.py index 2c156848..187ae3e2 100644 --- a/honcho-cli/src/honcho_cli/commands/workspace.py +++ b/honcho-cli/src/honcho_cli/commands/workspace.py @@ -6,6 +6,15 @@ from typing import Optional import typer +from honcho import ( + APIError, + AuthenticationError, + Honcho, + NotFoundError, + PermissionDeniedError, + ServerError, +) + from honcho_cli.output import print_error, print_result, status, use_json from honcho_cli.validation import validate_resource_id @@ -214,8 +223,6 @@ def queue_status( def _with_workspace(client, workspace_id: str): """Return a new client pointed at a different workspace.""" - from honcho import Honcho - return Honcho( base_url=str(client.base_url), api_key=client._http._api_key if hasattr(client._http, "_api_key") else None, @@ -243,14 +250,6 @@ def _handle_error(e: Exception, resource: str, resource_id: str) -> None: any APIError subclass we don't enumerate. Substring matching on the message is used only as a last-ditch fallback for non-SDK exceptions. """ - from honcho import ( - APIError, - AuthenticationError, - NotFoundError, - PermissionDeniedError, - ServerError, - ) - if isinstance(e, NotFoundError): print_error( f"{resource.upper()}_NOT_FOUND", diff --git a/honcho-cli/src/honcho_cli/common.py b/honcho-cli/src/honcho_cli/common.py index c936e3ac..5ebd22d8 100644 --- a/honcho-cli/src/honcho_cli/common.py +++ b/honcho-cli/src/honcho_cli/common.py @@ -13,7 +13,11 @@ from typing import Optional import typer -from honcho_cli.output import set_json_mode +from honcho import Honcho + +from honcho_cli.config import CLIConfig, get_client_kwargs +from honcho_cli.output import print_error, set_json_mode +from honcho_cli.validation import validate_resource_id # Global overrides from flags (commands read these) @@ -31,9 +35,6 @@ def get_resolved_config(): ``-w``/``-p``/``-s`` value fails fast with a structured error rather than reaching the API and surfacing as an opaque ``UNKNOWN_ERROR``. """ - from honcho_cli.config import CLIConfig - from honcho_cli.validation import validate_resource_id - config = CLIConfig.load() if _global_overrides["workspace"]: @@ -54,11 +55,6 @@ def get_client(*, require_workspace: bool = True): workspace. Commands that legitimately run without a workspace (e.g. ``workspace list``) pass ``require_workspace=False``. """ - from honcho import Honcho - - from honcho_cli.config import get_client_kwargs - from honcho_cli.output import print_error - config = get_resolved_config() if require_workspace and not config.workspace_id: print_error( diff --git a/honcho-cli/src/honcho_cli/main.py b/honcho-cli/src/honcho_cli/main.py index 460c0a38..c00b4b52 100644 --- a/honcho-cli/src/honcho_cli/main.py +++ b/honcho-cli/src/honcho_cli/main.py @@ -5,14 +5,17 @@ Entry point and top-level command group. from __future__ import annotations +import os +import sys from typing import Optional import typer +from rich.console import Console from honcho_cli import __version__ from honcho_cli.branding import BANNER, BRAND from honcho_cli.common import _global_overrides -from honcho_cli.output import set_json_mode +from honcho_cli.output import set_json_mode, use_json app = typer.Typer( name="honcho", @@ -28,9 +31,6 @@ def _json_requested_early() -> bool: version_callback is eager and fires before set_json_mode() runs, so we can't call use_json() here. Mirror its logic against argv/env/TTY. """ - import os - import sys - return ( "--json" in sys.argv or os.environ.get("HONCHO_JSON", "").lower() in ("1", "true") @@ -64,10 +64,6 @@ def main( _global_overrides["session"] = session if ctx.invoked_subcommand is None: - from rich.console import Console - - from honcho_cli.output import use_json - console = Console() if not use_json(): console.print(f"[bold {BRAND}]{BANNER}[/bold {BRAND}]") diff --git a/honcho-cli/src/honcho_cli/output.py b/honcho-cli/src/honcho_cli/output.py index b231d892..54dc4334 100644 --- a/honcho-cli/src/honcho_cli/output.py +++ b/honcho-cli/src/honcho_cli/output.py @@ -6,6 +6,7 @@ Detects TTY to auto-switch between human-readable and machine-parseable output. from __future__ import annotations import json +import os import sys from typing import Any @@ -33,8 +34,6 @@ def set_json_mode(enabled: bool) -> None: def use_json() -> bool: """Should we output JSON?""" - import os - return _force_json or os.environ.get("HONCHO_JSON", "").lower() in ("1", "true") or not is_tty() diff --git a/honcho-cli/src/honcho_cli/validation.py b/honcho-cli/src/honcho_cli/validation.py index 564bbf45..b1111802 100644 --- a/honcho-cli/src/honcho_cli/validation.py +++ b/honcho-cli/src/honcho_cli/validation.py @@ -7,6 +7,8 @@ from __future__ import annotations import re +from honcho_cli.output import print_error + UNSAFE_CHARS = re.compile(r'[?#%\x00-\x1f\x7f/\\]') @@ -38,7 +40,5 @@ def validate_resource_id(value: str, resource_type: str = "resource") -> str: def _fail(code: str, message: str, details: dict) -> None: """Print structured error and exit.""" - from honcho_cli.output import print_error - print_error(code, message, details) raise SystemExit(1)