mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-06-07 08:02:23 +00:00
chore: prune unused imports and duplicate import redefinitions
Remove unused imports (F401) and duplicate/shadowed import redefinitions (F811) across the codebase using ruff's safe autofixes. No behavioral changes -- imports only. - ~1400 safe autofixes applied across 644 files (net -1072 lines) - __init__.py re-exports preserved (excluded from F401 removal so public re-export surfaces stay intact) - Re-exports that are imported or monkeypatched by tests but look unused in their defining module are kept with explicit # noqa: F401 (gateway/run.py load_dotenv; run_agent re-exports from agent.message_sanitization, agent.context_compressor, agent.retry_utils, agent.prompt_builder, agent.process_bootstrap, agent.codex_responses_adapter) - Unsafe F841 (unused-variable) fixes deliberately skipped -- those can change behavior when the RHS has side effects - ruff lints remain disabled in pyproject.toml (only PLW1514 is selected); this is a one-time cleanup, not a config change Verification: - python -m compileall: clean - pytest --collect-only: all 27161 tests collect (zero import errors) - core entry points import clean (run_agent, model_tools, cli, toolsets, hermes_state, batch_runner, gateway) - static scan: every name any test imports directly from an edited module still resolves
This commit is contained in:
parent
a4d8f0f62a
commit
66827f8947
644 changed files with 254 additions and 1326 deletions
|
|
@ -6,11 +6,8 @@ Claude Code credentials are available. The fast-path silently proceeds to
|
|||
model selection with a broken token instead of offering re-auth.
|
||||
"""
|
||||
|
||||
import json
|
||||
import pytest
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
from hermes_cli.config import load_env, save_env_value
|
||||
from hermes_cli.config import save_env_value
|
||||
|
||||
|
||||
class TestStaleOAuthTokenDetection:
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import pytest
|
|||
|
||||
from hermes_cli.auth import (
|
||||
PROVIDER_REGISTRY,
|
||||
ProviderConfig,
|
||||
resolve_provider,
|
||||
get_api_key_provider_status,
|
||||
resolve_api_key_provider_credentials,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ import os
|
|||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def _run_apply_profile_override(
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ so the subparser only sets the attribute when the user explicitly provides it.
|
|||
import argparse
|
||||
import os
|
||||
import sys
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
"""Tests for utils.atomic_json_write — crash-safe JSON file writes."""
|
||||
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"""Tests for utils.atomic_yaml_write — crash-safe YAML file writes."""
|
||||
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ from pathlib import Path
|
|||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
|
||||
from hermes_cli.auth import (
|
||||
AuthError,
|
||||
|
|
@ -17,8 +16,6 @@ from hermes_cli.auth import (
|
|||
_save_codex_tokens,
|
||||
_import_codex_cli_tokens,
|
||||
_login_openai_codex,
|
||||
get_codex_auth_status,
|
||||
get_provider_auth_state,
|
||||
refresh_codex_oauth_pure,
|
||||
resolve_codex_runtime_credentials,
|
||||
resolve_provider,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import io
|
|||
import contextlib
|
||||
import socket
|
||||
|
||||
import pytest
|
||||
|
||||
from hermes_cli import auth as auth_mod
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
"""Tests for is_provider_explicitly_configured()."""
|
||||
|
||||
import json
|
||||
import os
|
||||
import pytest
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ resolve_qwen_runtime_credentials, get_qwen_auth_status.
|
|||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import stat
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ from __future__ import annotations
|
|||
import sys
|
||||
from types import SimpleNamespace
|
||||
from typing import cast
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
|
|||
|
|
@ -1029,7 +1029,6 @@ class TestProfileRestoration:
|
|||
args = Namespace(zipfile=str(zip_path), force=True)
|
||||
|
||||
# Simulate profiles module not being available
|
||||
import hermes_cli.backup as backup_mod
|
||||
original_import = __builtins__.__import__ if hasattr(__builtins__, '__import__') else __import__
|
||||
|
||||
def fake_import(name, *a, **kw):
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
_MOCK_SKILLS = [
|
||||
|
|
|
|||
|
|
@ -16,12 +16,10 @@ Covers the three paths changed by fix/bedrock-provider-model-ids-live-discovery:
|
|||
All Bedrock API calls are mocked — no real AWS credentials needed.
|
||||
"""
|
||||
|
||||
import os
|
||||
from contextlib import contextmanager
|
||||
from types import ModuleType
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
@ -95,7 +93,7 @@ class TestProviderModelIdsBedrock:
|
|||
|
||||
def test_falls_back_to_static_list_when_discovery_empty(self, monkeypatch):
|
||||
"""When discover_bedrock_models() returns [], fall back to curated static list."""
|
||||
from hermes_cli.models import _PROVIDER_MODELS, provider_model_ids
|
||||
from hermes_cli.models import provider_model_ids
|
||||
|
||||
with patch("agent.bedrock_adapter.discover_bedrock_models", return_value=[]), \
|
||||
patch("agent.bedrock_adapter.resolve_bedrock_region", return_value="eu-central-1"):
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
"""Tests for hermes_cli/bundles.py — the `hermes bundles` CLI subcommand."""
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
from hermes_cli.config import load_config, save_config, save_env_value, get_env_value
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"""Tests for _coalesce_session_name_args — multi-word session name merging."""
|
||||
|
||||
import pytest
|
||||
from hermes_cli.main import _coalesce_session_name_args
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -13,11 +13,8 @@ existing Codex CLI tokens via `hermes auth openai-codex`. The old
|
|||
|
||||
import base64
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
|
|||
|
|
@ -2,14 +2,12 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from hermes_cli.codex_runtime_plugin_migration import (
|
||||
MIGRATION_MARKER,
|
||||
MIGRATION_END_MARKER,
|
||||
MigrationReport,
|
||||
_build_hermes_tools_mcp_entry,
|
||||
_format_toml_value,
|
||||
_looks_like_test_tempdir,
|
||||
|
|
|
|||
|
|
@ -1003,7 +1003,7 @@ class TestTelegramMenuCommands:
|
|||
|
||||
def test_excludes_telegram_disabled_skills(self, tmp_path, monkeypatch):
|
||||
"""Skills disabled for telegram should not appear in the menu."""
|
||||
from unittest.mock import patch, MagicMock
|
||||
from unittest.mock import patch
|
||||
|
||||
# Set up a config with a telegram-specific disabled list
|
||||
config_file = tmp_path / "config.yaml"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch, MagicMock
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
"""Tests for ${ENV_VAR} substitution in config.yaml values."""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
from hermes_cli.config import _expand_env_vars, load_config
|
||||
from unittest.mock import patch as mock_patch
|
||||
|
||||
|
||||
class TestExpandEnvVars:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"""Tests for config.yaml structure validation (validate_config_structure)."""
|
||||
|
||||
import pytest
|
||||
|
||||
from hermes_cli.config import validate_config_structure, ConfigIssue
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
"""Tests for hermes_cli.copilot_auth — Copilot token validation and resolution."""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
from unittest.mock import patch, MagicMock
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
class TestTokenValidation:
|
||||
|
|
|
|||
|
|
@ -12,12 +12,8 @@ Covers:
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import io
|
||||
from contextlib import redirect_stdout, redirect_stderr
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def _ns(**kwargs):
|
||||
|
|
|
|||
|
|
@ -12,9 +12,8 @@ clamps with ``min(8, curses.COLORS - 1)``.
|
|||
import curses
|
||||
import re
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch, MagicMock, call
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
# Path to the source files under test
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ immediately when provider_info had a saved ``model`` field, making it
|
|||
impossible to switch models on multi-model endpoints.
|
||||
"""
|
||||
|
||||
import os
|
||||
from unittest.mock import patch, MagicMock, call
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
"""Tests for the dashboard-auth cookie helpers."""
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
from fastapi import FastAPI
|
||||
from fastapi.responses import Response
|
||||
from fastapi.testclient import TestClient
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ class TestOAuthRedirectUriRespectsPrefix:
|
|||
# The stub IDP's redirect_url echoes the redirect_uri back. The
|
||||
# real IDP would consume it and later use it to redirect the
|
||||
# user, so the byte-exact value MUST include the prefix.
|
||||
from urllib.parse import urlparse, parse_qs, unquote
|
||||
from urllib.parse import urlparse
|
||||
# Stub returns ``{redirect_uri}?code=stub_code&state=...`` — so
|
||||
# we read up to the first ``?``.
|
||||
redirect_uri = location.split("?", 1)[0]
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ pre-existing regression unrelated to dashboard-auth.
|
|||
from __future__ import annotations
|
||||
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
@ -29,7 +28,6 @@ from fastapi.testclient import TestClient
|
|||
from hermes_cli import web_server
|
||||
from hermes_cli.dashboard_auth import clear_providers, register_provider
|
||||
from hermes_cli.dashboard_auth.ws_tickets import (
|
||||
TicketInvalid,
|
||||
_reset_for_tests,
|
||||
consume_ticket,
|
||||
mint_ticket,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ from unittest.mock import patch, MagicMock
|
|||
|
||||
import pytest
|
||||
|
||||
from hermes_cli.main import cmd_dashboard, _report_dashboard_status
|
||||
from hermes_cli.main import cmd_dashboard
|
||||
|
||||
|
||||
def _ns(**kw):
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
"""Tests for ``hermes debug`` CLI command and debug utilities."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import urllib.error
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock, patch, call
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
@ -337,7 +335,6 @@ class TestCaptureLogSnapshotRedaction:
|
|||
redaction feature ships silently broken for users who opted out of
|
||||
runtime redaction (e.g. developers working on the redactor itself).
|
||||
"""
|
||||
import os
|
||||
|
||||
# Force the runtime flag off so we're exercising the force=True path,
|
||||
# not the default-on path.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
"""Tests for warn_deprecated_cwd_env_vars() migration warning."""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
|
||||
|
||||
class TestDeprecatedCwdWarning:
|
||||
|
|
|
|||
|
|
@ -792,7 +792,7 @@ class TestGitHubTokenCheck:
|
|||
monkeypatch.setenv("HERMES_HOME", str(home))
|
||||
monkeypatch.setenv("PATH", "/nonexistent") # gh not found
|
||||
|
||||
from hermes_cli.doctor import run_doctor, _DHH
|
||||
from hermes_cli.doctor import run_doctor
|
||||
import io, contextlib
|
||||
|
||||
buf = io.StringIO()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"""Tests for the Command Installation check in hermes doctor."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import types
|
||||
from argparse import Namespace
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import importlib
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from hermes_cli.env_loader import load_hermes_dotenv
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
"""Tests for `hermes fallback` — chain reading, add/remove/clear, legacy migration."""
|
||||
from __future__ import annotations
|
||||
|
||||
import io
|
||||
import types
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
import sys
|
||||
from types import ModuleType, SimpleNamespace
|
||||
from unittest.mock import patch, call
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ Currently:
|
|||
Windows path that works.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
class TestMatrixHiddenOnWindows:
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ host systemd/launchd/windows code path.
|
|||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
|
|||
|
|
@ -1321,7 +1321,6 @@ class TestSystemServiceIdentityRootHandling:
|
|||
|
||||
def test_auto_detected_root_is_rejected(self, monkeypatch):
|
||||
"""When root is auto-detected (not explicitly requested), raise."""
|
||||
import grp
|
||||
|
||||
monkeypatch.delenv("SUDO_USER", raising=False)
|
||||
monkeypatch.setenv("USER", "root")
|
||||
|
|
@ -1343,7 +1342,6 @@ class TestSystemServiceIdentityRootHandling:
|
|||
|
||||
def test_non_root_user_passes_through(self, monkeypatch):
|
||||
"""Normal non-root user works as before."""
|
||||
import grp
|
||||
|
||||
monkeypatch.delenv("SUDO_USER", raising=False)
|
||||
monkeypatch.setenv("USER", "nobody")
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
"""Tests for WSL detection and WSL-aware gateway behavior."""
|
||||
|
||||
import io
|
||||
import subprocess
|
||||
import sys
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import patch, MagicMock, mock_open
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"""Tests for Google AI Studio (Gemini) provider integration."""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
|
|
|
|||
|
|
@ -525,7 +525,6 @@ class TestGoalStateSubgoalsBackcompat:
|
|||
def test_old_state_meta_row_loads_without_subgoals(self):
|
||||
"""A goal serialized BEFORE the subgoals field existed must
|
||||
round-trip with an empty list, not crash."""
|
||||
import json
|
||||
from hermes_cli.goals import GoalState
|
||||
|
||||
legacy = json.dumps({
|
||||
|
|
@ -647,7 +646,7 @@ class TestJudgeGoalWithSubgoals:
|
|||
We don't actually call the model — we patch the aux client to
|
||||
capture the prompt that would be sent.
|
||||
"""
|
||||
from unittest.mock import patch, MagicMock
|
||||
from unittest.mock import patch
|
||||
from hermes_cli import goals
|
||||
|
||||
captured = {}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ from __future__ import annotations
|
|||
|
||||
import io
|
||||
import json
|
||||
import sys
|
||||
from contextlib import redirect_stdout
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ from __future__ import annotations
|
|||
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from hermes_cli.inventory import (
|
||||
ConfigContext,
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import threading
|
|||
import time
|
||||
from pathlib import Path
|
||||
from types import SimpleNamespace
|
||||
from typing import Optional
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
|
|||
|
|
@ -2566,7 +2566,6 @@ def test_resolve_hermes_argv_module_actually_runs():
|
|||
Run it as a real subprocess to catch that regression.
|
||||
"""
|
||||
import subprocess
|
||||
import sys
|
||||
import hermes_cli.kanban_db as kb
|
||||
import shutil
|
||||
import unittest.mock as mock
|
||||
|
|
@ -3145,7 +3144,6 @@ def test_detect_stale_skips_recently_started_task(kanban_home, monkeypatch):
|
|||
|
||||
def test_detect_stale_skips_when_timeout_zero(kanban_home, monkeypatch):
|
||||
"""stale_timeout_seconds=0 disables stale detection entirely."""
|
||||
import hermes_cli.kanban_db as _kb
|
||||
|
||||
with kb.connect() as conn:
|
||||
t = kb.create_task(conn, title="disabled", assignee="worker")
|
||||
|
|
@ -3628,7 +3626,7 @@ def test_write_txn_preserves_original_exception_when_rollback_fails(kanban_home)
|
|||
)
|
||||
def test_write_txn_healthy_commit_no_exception(tmp_path):
|
||||
"""Normal commit does not trigger the torn-extend check."""
|
||||
from hermes_cli.kanban_db import connect, write_txn, create_task
|
||||
from hermes_cli.kanban_db import connect, write_txn
|
||||
db = tmp_path / "test.db"
|
||||
conn = connect(db_path=db)
|
||||
# Should not raise
|
||||
|
|
@ -3645,7 +3643,6 @@ def test_write_txn_healthy_commit_no_exception(tmp_path):
|
|||
def test_write_txn_raises_on_truncated_file(tmp_path):
|
||||
"""A mocked smaller file size triggers the torn-extend check."""
|
||||
from hermes_cli.kanban_db import connect, write_txn
|
||||
import hermes_cli.kanban_db as kanban_db_module
|
||||
db = tmp_path / "test.db"
|
||||
conn = connect(db_path=db)
|
||||
# Get actual page size so we can fake a smaller file
|
||||
|
|
@ -3705,7 +3702,7 @@ def test_connect_sets_wal_autocheckpoint_100(tmp_path):
|
|||
def test_write_txn_check_reads_correct_header_fields(tmp_path):
|
||||
"""Synthetic DB file with mismatched header page_count triggers the check."""
|
||||
import struct
|
||||
from hermes_cli.kanban_db import connect, write_txn, _check_file_length_invariant
|
||||
from hermes_cli.kanban_db import connect, _check_file_length_invariant
|
||||
db = tmp_path / "synthetic.db"
|
||||
conn = connect(db_path=db)
|
||||
page_size = conn.execute("PRAGMA page_size").fetchone()[0]
|
||||
|
|
|
|||
|
|
@ -7,14 +7,12 @@ and the assignee-fallback logic.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json as jsonlib
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from hermes_cli import kanban as kanban_cli
|
||||
from hermes_cli import kanban_db as kb
|
||||
from hermes_cli import kanban_decompose as decomp
|
||||
|
||||
|
|
|
|||
|
|
@ -298,7 +298,6 @@ def test_dispatcher_tick_does_not_call_init_db(kanban_home, monkeypatch):
|
|||
"""
|
||||
import hermes_cli.kanban_db as kb
|
||||
from gateway.run import GatewayRunner
|
||||
from unittest.mock import patch
|
||||
|
||||
runner = object.__new__(GatewayRunner)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import json
|
||||
|
||||
from hermes_cli import kanban_db as kb
|
||||
from hermes_cli.kanban_swarm import (
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
"""Tests for hermes_cli.logs — log viewing and filtering."""
|
||||
|
||||
import os
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from hermes_cli.logs import (
|
||||
LOG_FILES,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ launch an MCP is mocked.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
|
|
@ -207,7 +206,7 @@ class TestManifestParsing:
|
|||
class TestInstall:
|
||||
def test_install_simple_stdio_writes_config(self, catalog_dir):
|
||||
_write_manifest(catalog_dir, "demo", _basic_manifest())
|
||||
from hermes_cli.mcp_catalog import install_entry, get_entry
|
||||
from hermes_cli.mcp_catalog import install_entry
|
||||
from hermes_cli.config import load_config
|
||||
|
||||
install_entry(_entry("demo"), enable=True)
|
||||
|
|
@ -240,7 +239,7 @@ class TestInstall:
|
|||
fake_clone.mkdir()
|
||||
|
||||
from hermes_cli import mcp_catalog
|
||||
from hermes_cli.mcp_catalog import install_entry, get_entry
|
||||
from hermes_cli.mcp_catalog import install_entry
|
||||
from hermes_cli.config import load_config
|
||||
|
||||
with patch.object(mcp_catalog, "_do_git_install", return_value=fake_clone):
|
||||
|
|
@ -263,7 +262,7 @@ class TestInstall:
|
|||
|
||||
monkeypatch.setattr(mcp_catalog, "_prompt_input", lambda *a, **kw: "secret-val")
|
||||
|
||||
from hermes_cli.mcp_catalog import install_entry, get_entry
|
||||
from hermes_cli.mcp_catalog import install_entry
|
||||
from hermes_cli.config import get_env_value, load_config
|
||||
|
||||
install_entry(_entry("demo"), enable=True)
|
||||
|
|
@ -278,7 +277,7 @@ class TestInstall:
|
|||
)
|
||||
_write_manifest(catalog_dir, "demo", body)
|
||||
|
||||
from hermes_cli.mcp_catalog import install_entry, get_entry
|
||||
from hermes_cli.mcp_catalog import install_entry
|
||||
from hermes_cli.config import load_config
|
||||
|
||||
install_entry(_entry("demo"), enable=True)
|
||||
|
|
@ -297,7 +296,7 @@ class TestInstall:
|
|||
_write_manifest(catalog_dir, "demo", body)
|
||||
|
||||
from hermes_cli import mcp_catalog
|
||||
from hermes_cli.mcp_catalog import install_entry, get_entry, CatalogError
|
||||
from hermes_cli.mcp_catalog import install_entry, CatalogError
|
||||
|
||||
# User hits enter — empty input, no default
|
||||
monkeypatch.setattr(mcp_catalog, "_prompt_input", lambda *a, **kw: "")
|
||||
|
|
@ -314,7 +313,7 @@ class TestInstall:
|
|||
class TestUninstall:
|
||||
def test_uninstall_removes_server_block(self, catalog_dir):
|
||||
_write_manifest(catalog_dir, "demo", _basic_manifest())
|
||||
from hermes_cli.mcp_catalog import install_entry, get_entry, uninstall_entry
|
||||
from hermes_cli.mcp_catalog import install_entry, uninstall_entry
|
||||
from hermes_cli.config import load_config
|
||||
|
||||
install_entry(_entry("demo"), enable=True)
|
||||
|
|
|
|||
|
|
@ -6,12 +6,7 @@ any actual MCP servers or API keys.
|
|||
"""
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import types
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, List
|
||||
from unittest.mock import MagicMock, patch, PropertyMock
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ run silently.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from copy import deepcopy
|
||||
|
||||
from hermes_cli.config import DEFAULT_CONFIG
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
"""Tests for MCP tools interactive configuration in hermes_cli.tools_config."""
|
||||
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import MagicMock, patch
|
||||
from unittest.mock import patch
|
||||
|
||||
from hermes_cli.tools_config import _configure_mcp_tools_interactive
|
||||
|
||||
|
|
|
|||
|
|
@ -8,10 +8,7 @@ Covers:
|
|||
- Profile-scoped reset (uses HERMES_HOME)
|
||||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
from argparse import Namespace
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
|
@ -39,7 +36,7 @@ def _run_memory_reset(target="all", yes=False, monkeypatch=None, confirm_input="
|
|||
|
||||
Simulates what happens when `hermes memory reset` is run.
|
||||
"""
|
||||
from hermes_constants import get_hermes_home, display_hermes_home
|
||||
from hermes_constants import get_hermes_home
|
||||
|
||||
mem_dir = get_hermes_home() / "memories"
|
||||
files_to_reset = []
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ import pytest
|
|||
from hermes_cli.model_normalize import (
|
||||
normalize_model_for_provider,
|
||||
_DOT_TO_HYPHEN_PROVIDERS,
|
||||
_AGGREGATOR_PROVIDERS,
|
||||
_normalize_for_deepseek,
|
||||
detect_vendor,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ isinstance(model, dict)) to silently fail — leaving the provider unset and
|
|||
falling back to auto-detection.
|
||||
"""
|
||||
|
||||
import os
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
import pytest
|
||||
|
|
@ -194,7 +193,6 @@ class TestProviderPersistsAfterModelSave:
|
|||
# Patch fetch_api_models so the named custom flow returns one model;
|
||||
# patch simple_term_menu to force the input() fallback; patch input to
|
||||
# auto-select the first model from the fallback prompt.
|
||||
from unittest.mock import MagicMock
|
||||
fake_menu_module = MagicMock()
|
||||
fake_menu_module.TerminalMenu.side_effect = OSError("no tty in test")
|
||||
with patch("hermes_cli.auth._save_model_choice"), \
|
||||
|
|
|
|||
|
|
@ -17,10 +17,8 @@ Merging is what lets new models (e.g. ``mimo-v2.5-pro`` on opencode-go)
|
|||
appear in ``/model`` without a Hermes release.
|
||||
"""
|
||||
|
||||
import os
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from hermes_cli.models import (
|
||||
_MODELS_DEV_PREFERRED,
|
||||
|
|
|
|||
|
|
@ -6,10 +6,7 @@ httpx tries to encode the Authorization header as ASCII.
|
|||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
|
||||
import pytest
|
||||
|
||||
from hermes_cli.config import _check_non_ascii_credential
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ These tests verify:
|
|||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import pytest
|
||||
|
||||
from hermes_cli.auth import (
|
||||
DEFAULT_NOUS_INFERENCE_URL,
|
||||
|
|
|
|||
|
|
@ -10,8 +10,6 @@ Covers:
|
|||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"""Tests for Ollama Cloud provider integration."""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
|
|
|
|||
|
|
@ -7,11 +7,9 @@ resolution in list_authenticated_providers() Section 2 must bridge this gap.
|
|||
Covers: #5223, #6492
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from hermes_cli.model_switch import list_authenticated_providers
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -8,13 +8,9 @@ Covers:
|
|||
- Honcho register_cli() builds correct argparse tree
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from hermes_cli.plugins import (
|
||||
PluginContext,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from typing import Any, Dict
|
|||
import pytest
|
||||
import yaml
|
||||
|
||||
from hermes_cli.plugins import PluginManager, PluginManifest
|
||||
from hermes_cli.plugins import PluginManager
|
||||
|
||||
|
||||
# ── Helpers ────────────────────────────────────────────────────────────────
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
"""Tests for the Hermes plugin system (hermes_cli.plugins)."""
|
||||
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import types
|
||||
from pathlib import Path
|
||||
|
|
@ -13,17 +12,13 @@ import yaml
|
|||
from hermes_cli.plugins import (
|
||||
ENTRY_POINTS_GROUP,
|
||||
VALID_HOOKS,
|
||||
LoadedPlugin,
|
||||
PluginContext,
|
||||
PluginManager,
|
||||
PluginManifest,
|
||||
get_plugin_manager,
|
||||
get_plugin_command_handler,
|
||||
get_plugin_commands,
|
||||
get_pre_tool_call_block_message,
|
||||
resolve_plugin_command_result,
|
||||
discover_plugins,
|
||||
invoke_hook,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -1309,7 +1304,6 @@ class TestPluginCommandResultResolution:
|
|||
monkeypatch.setattr("hermes_cli.plugins.asyncio.get_running_loop", lambda: _Loop())
|
||||
monkeypatch.setattr("hermes_cli.plugins._PLUGIN_COMMAND_AWAIT_TIMEOUT_SECS", 0.1)
|
||||
|
||||
import pytest
|
||||
with pytest.raises(TimeoutError):
|
||||
resolve_plugin_command_result(_slow_handler())
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import os
|
||||
import types
|
||||
from pathlib import Path
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
|
|
@ -19,7 +17,6 @@ from hermes_cli.plugins_cmd import (
|
|||
_resolve_git_executable,
|
||||
_resolve_git_url,
|
||||
_sanitize_plugin_name,
|
||||
plugins_command,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -259,7 +256,6 @@ class TestCmdInstall:
|
|||
|
||||
def test_install_requires_identifier(self):
|
||||
from hermes_cli.plugins_cmd import cmd_install
|
||||
import argparse
|
||||
|
||||
with pytest.raises(SystemExit):
|
||||
cmd_install("")
|
||||
|
|
@ -544,7 +540,6 @@ class TestCopyExampleFiles:
|
|||
"""Test example file copying."""
|
||||
|
||||
def test_copies_example_files(self, tmp_path):
|
||||
from hermes_cli.plugins_cmd import _copy_example_files
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
console = MagicMock()
|
||||
|
|
@ -560,7 +555,6 @@ class TestCopyExampleFiles:
|
|||
console.print.assert_called()
|
||||
|
||||
def test_skips_existing_files(self, tmp_path):
|
||||
from hermes_cli.plugins_cmd import _copy_example_files
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
console = MagicMock()
|
||||
|
|
@ -577,7 +571,6 @@ class TestCopyExampleFiles:
|
|||
assert real_file.read_text() == "existing: true"
|
||||
|
||||
def test_handles_copy_error_gracefully(self, tmp_path):
|
||||
from hermes_cli.plugins_cmd import _copy_example_files
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
console = MagicMock()
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ mocking git would just test the mock.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ profiles; leaking credentials in the archive is a security issue.
|
|||
"""
|
||||
|
||||
import tarfile
|
||||
from pathlib import Path
|
||||
|
||||
from hermes_cli.profiles import export_profile, _DEFAULT_EXPORT_EXCLUDE_ROOT
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ and shell completion generation.
|
|||
|
||||
import json
|
||||
import io
|
||||
import os
|
||||
import tarfile
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ These tests pin each layer of the new defence:
|
|||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
|
|
|||
|
|
@ -5,9 +5,7 @@ accepted as base_url, and unknown keys go unreported.
|
|||
"""
|
||||
|
||||
import logging
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from hermes_cli.config import _normalize_custom_provider_entry
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ from __future__ import annotations
|
|||
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
import threading
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict
|
||||
|
|
|
|||
|
|
@ -1,7 +1,4 @@
|
|||
import pytest
|
||||
import sys
|
||||
from unittest.mock import patch
|
||||
from pathlib import Path
|
||||
|
||||
import hermes_cli.model_switch as ms
|
||||
from hermes_cli.model_switch import DirectAlias
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import json
|
|||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from hermes_cli import security_audit as sa
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ from __future__ import annotations
|
|||
|
||||
import io
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
|
|||
|
|
@ -361,7 +361,6 @@ def test_get_service_manager_returns_s6_instance(
|
|||
) -> None:
|
||||
"""The s6 backend ships in Phase 3 — the factory must return an
|
||||
S6ServiceManager when running inside a container."""
|
||||
from hermes_cli.service_manager import S6ServiceManager
|
||||
monkeypatch.setattr(
|
||||
"hermes_cli.service_manager.detect_service_manager", lambda: "s6",
|
||||
)
|
||||
|
|
@ -406,7 +405,6 @@ def fake_subprocess_run(monkeypatch: pytest.MonkeyPatch):
|
|||
|
||||
|
||||
def test_s6_manager_kind_and_supports_registration() -> None:
|
||||
from hermes_cli.service_manager import S6ServiceManager
|
||||
mgr = S6ServiceManager()
|
||||
assert mgr.kind == "s6"
|
||||
assert mgr.supports_runtime_registration() is True
|
||||
|
|
@ -524,7 +522,6 @@ def test_seed_supervise_skeleton_is_idempotent(tmp_path) -> None:
|
|||
def test_s6_register_creates_service_dir_and_triggers_scan(
|
||||
s6_scandir, fake_subprocess_run,
|
||||
) -> None:
|
||||
from hermes_cli.service_manager import S6ServiceManager
|
||||
mgr = S6ServiceManager(scandir=s6_scandir)
|
||||
mgr.register_profile_gateway("coder")
|
||||
|
||||
|
|
@ -576,7 +573,6 @@ def test_s6_register_creates_service_dir_and_triggers_scan(
|
|||
|
||||
|
||||
def test_s6_register_extra_env_is_quoted(s6_scandir, fake_subprocess_run) -> None:
|
||||
from hermes_cli.service_manager import S6ServiceManager
|
||||
mgr = S6ServiceManager(scandir=s6_scandir)
|
||||
mgr.register_profile_gateway(
|
||||
"x", extra_env={"FOO": "bar baz", "QUOTED": "a'b"},
|
||||
|
|
@ -588,7 +584,6 @@ def test_s6_register_extra_env_is_quoted(s6_scandir, fake_subprocess_run) -> Non
|
|||
|
||||
|
||||
def test_render_run_script_resets_home_before_exec() -> None:
|
||||
from hermes_cli.service_manager import S6ServiceManager
|
||||
|
||||
run_text = S6ServiceManager._render_run_script("coder", {})
|
||||
|
||||
|
|
@ -597,14 +592,12 @@ def test_render_run_script_resets_home_before_exec() -> None:
|
|||
|
||||
|
||||
def test_s6_register_rejects_invalid_profile_name(s6_scandir) -> None:
|
||||
from hermes_cli.service_manager import S6ServiceManager
|
||||
mgr = S6ServiceManager(scandir=s6_scandir)
|
||||
with pytest.raises(ValueError):
|
||||
mgr.register_profile_gateway("Bad/Name")
|
||||
|
||||
|
||||
def test_s6_register_rejects_duplicate(s6_scandir, fake_subprocess_run) -> None:
|
||||
from hermes_cli.service_manager import S6ServiceManager
|
||||
mgr = S6ServiceManager(scandir=s6_scandir)
|
||||
(s6_scandir / "gateway-coder").mkdir(parents=True)
|
||||
with pytest.raises(ValueError, match="already registered"):
|
||||
|
|
@ -617,7 +610,6 @@ def test_s6_register_rolls_back_on_svscanctl_failure(
|
|||
"""If s6-svscanctl fails the service dir must be cleaned up so the
|
||||
next register call doesn't see a stale duplicate."""
|
||||
import subprocess as _sp
|
||||
from hermes_cli.service_manager import S6ServiceManager
|
||||
|
||||
def _fail_scanctl(cmd, **kw):
|
||||
# Manager calls s6-svscanctl by absolute path; match on basename.
|
||||
|
|
@ -635,7 +627,6 @@ def test_s6_register_rolls_back_on_svscanctl_failure(
|
|||
def test_s6_unregister_removes_service_dir(
|
||||
s6_scandir, fake_subprocess_run,
|
||||
) -> None:
|
||||
from hermes_cli.service_manager import S6ServiceManager
|
||||
svc_dir = s6_scandir / "gateway-coder"
|
||||
svc_dir.mkdir(parents=True)
|
||||
(svc_dir / "type").write_text("longrun\n")
|
||||
|
|
@ -655,13 +646,11 @@ def test_s6_unregister_removes_service_dir(
|
|||
|
||||
|
||||
def test_s6_unregister_absent_profile_is_noop(s6_scandir) -> None:
|
||||
from hermes_cli.service_manager import S6ServiceManager
|
||||
# Should NOT raise even though "ghost" doesn't exist
|
||||
S6ServiceManager(scandir=s6_scandir).unregister_profile_gateway("ghost")
|
||||
|
||||
|
||||
def test_s6_list_profile_gateways(s6_scandir) -> None:
|
||||
from hermes_cli.service_manager import S6ServiceManager
|
||||
# Three gateway profiles + one unrelated service + one hidden dir
|
||||
(s6_scandir / "gateway-coder").mkdir()
|
||||
(s6_scandir / "gateway-assistant").mkdir()
|
||||
|
|
@ -674,7 +663,6 @@ def test_s6_list_profile_gateways(s6_scandir) -> None:
|
|||
|
||||
|
||||
def test_s6_list_profile_gateways_empty_when_scandir_missing(tmp_path) -> None:
|
||||
from hermes_cli.service_manager import S6ServiceManager
|
||||
missing = tmp_path / "does-not-exist"
|
||||
assert S6ServiceManager(scandir=missing).list_profile_gateways() == []
|
||||
|
||||
|
|
@ -682,7 +670,6 @@ def test_s6_list_profile_gateways_empty_when_scandir_missing(tmp_path) -> None:
|
|||
def test_s6_lifecycle_dispatches_to_s6_svc(
|
||||
s6_scandir, fake_subprocess_run,
|
||||
) -> None:
|
||||
from hermes_cli.service_manager import S6ServiceManager
|
||||
mgr = S6ServiceManager(scandir=s6_scandir)
|
||||
# _run_svc now verifies the slot exists before invoking s6-svc, so
|
||||
# we have to pre-seed the dir. In real use the slot is created by
|
||||
|
|
@ -710,7 +697,6 @@ def test_lifecycle_raises_gateway_not_registered_for_missing_slot(
|
|||
opaque CalledProcessError stacktrace."""
|
||||
from hermes_cli.service_manager import (
|
||||
GatewayNotRegisteredError,
|
||||
S6ServiceManager,
|
||||
)
|
||||
|
||||
mgr = S6ServiceManager(scandir=s6_scandir)
|
||||
|
|
@ -740,7 +726,6 @@ def test_all_lifecycle_methods_check_for_missing_slot(
|
|||
"""start/stop/restart all check for missing slots the same way."""
|
||||
from hermes_cli.service_manager import (
|
||||
GatewayNotRegisteredError,
|
||||
S6ServiceManager,
|
||||
)
|
||||
|
||||
mgr = S6ServiceManager(scandir=s6_scandir)
|
||||
|
|
@ -755,7 +740,6 @@ def test_gateway_not_registered_unprefixed_service_name(s6_scandir) -> None:
|
|||
accidentally strip user-provided text."""
|
||||
from hermes_cli.service_manager import (
|
||||
GatewayNotRegisteredError,
|
||||
S6ServiceManager,
|
||||
)
|
||||
|
||||
mgr = S6ServiceManager(scandir=s6_scandir)
|
||||
|
|
@ -772,7 +756,7 @@ def test_lifecycle_raises_s6_command_error_on_subprocess_failure(
|
|||
CalledProcessError into a named S6CommandError carrying the
|
||||
return code and stderr."""
|
||||
import subprocess as _sp
|
||||
from hermes_cli.service_manager import S6CommandError, S6ServiceManager
|
||||
from hermes_cli.service_manager import S6CommandError
|
||||
|
||||
# Pre-create the slot so we reach the s6-svc call.
|
||||
(s6_scandir / "gateway-coder").mkdir()
|
||||
|
|
@ -801,7 +785,6 @@ def test_s6_is_running_parses_svstat(
|
|||
s6_scandir, monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
import subprocess as _sp
|
||||
from hermes_cli.service_manager import S6ServiceManager
|
||||
|
||||
def _svstat(cmd, **kw):
|
||||
if cmd[0].endswith("/s6-svstat"):
|
||||
|
|
|
|||
|
|
@ -6,11 +6,9 @@ Covers:
|
|||
- Argument parser registration
|
||||
"""
|
||||
|
||||
import os
|
||||
import time
|
||||
from unittest.mock import MagicMock, patch, call
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from hermes_cli.main import _session_browse_picker
|
||||
|
||||
|
|
@ -249,7 +247,6 @@ class TestCursesBrowse:
|
|||
|
||||
def _run_with_keys(self, sessions, key_sequence):
|
||||
"""Simulate running the curses picker with a given key sequence."""
|
||||
import curses
|
||||
|
||||
# Build a mock stdscr that returns keys from the sequence
|
||||
mock_stdscr = MagicMock()
|
||||
|
|
@ -305,7 +302,6 @@ class TestCursesBrowse:
|
|||
|
||||
def test_type_to_filter_then_enter(self):
|
||||
"""Typing characters filters the list, Enter selects from filtered."""
|
||||
import curses
|
||||
sessions = [
|
||||
{"id": "s1", "source": "cli", "title": "Alpha project", "preview": "", "last_active": time.time()},
|
||||
{"id": "s2", "source": "cli", "title": "Beta project", "preview": "", "last_active": time.time()},
|
||||
|
|
@ -325,7 +321,6 @@ class TestCursesBrowse:
|
|||
|
||||
def test_backspace_removes_filter_char(self):
|
||||
"""Backspace removes the last character from the filter."""
|
||||
import curses
|
||||
sessions = [
|
||||
{"id": "s1", "source": "cli", "title": "Alpha", "preview": "", "last_active": time.time()},
|
||||
{"id": "s2", "source": "cli", "title": "Beta", "preview": "", "last_active": time.time()},
|
||||
|
|
@ -337,7 +332,6 @@ class TestCursesBrowse:
|
|||
|
||||
def test_escape_clears_filter_first(self):
|
||||
"""First Esc clears the search text, second Esc exits."""
|
||||
import curses
|
||||
sessions = _make_sessions(3)
|
||||
# Type "ab" then Esc (clears filter) then Enter (selects first)
|
||||
keys = [ord('a'), ord('b'), 27, 10]
|
||||
|
|
@ -391,11 +385,9 @@ class TestSessionBrowseArgparse:
|
|||
|
||||
def test_browse_subcommand_exists(self):
|
||||
"""hermes sessions browse should be parseable."""
|
||||
from hermes_cli.main import main as _main_entry
|
||||
|
||||
# We can't run main(), but we can import and test the parser setup
|
||||
# by checking that argparse doesn't error on "sessions browse"
|
||||
import argparse
|
||||
# Re-create the parser portion
|
||||
# Instead, let's just verify the import works and the function exists
|
||||
from hermes_cli.main import _session_browse_picker
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ from __future__ import annotations
|
|||
|
||||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from hermes_cli.session_recap import build_recap
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
import argparse
|
||||
import os
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch, call
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,8 @@
|
|||
"""Tests for setup.py configuration flows."""
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import types
|
||||
|
||||
import pytest
|
||||
|
||||
from hermes_cli.auth import get_active_provider
|
||||
from hermes_cli.config import load_config, save_config
|
||||
from hermes_cli import setup as setup_mod
|
||||
from hermes_cli.setup import setup_model_provider
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ interactive setup menus.
|
|||
"""
|
||||
|
||||
import os
|
||||
import pytest
|
||||
|
||||
from gateway.platform_registry import PlatformEntry, platform_registry
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
"""Test that setup.py has shutil available for Matrix E2EE auto-install."""
|
||||
import ast
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def _parse_setup_imports():
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
"""Tests for non-interactive setup and first-run headless behavior."""
|
||||
|
||||
from argparse import Namespace
|
||||
from unittest.mock import MagicMock, patch
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from hermes_cli.config import DEFAULT_CONFIG, load_config, save_config
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ serving a stale cache (models.dev only, no live API probe) for up to an hour.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
def test_setup_ollama_cloud_passes_force_refresh(monkeypatch):
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"""Tests for hermes_cli/skills_config.py and skills_tool disabled filtering."""
|
||||
import pytest
|
||||
from unittest.mock import patch, MagicMock
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ Based on PR #1595 by 333Alden333 (salvaged).
|
|||
"""
|
||||
|
||||
import sys
|
||||
from types import SimpleNamespace
|
||||
|
||||
|
||||
def test_cli_skills_install_yes_sets_skip_confirm(monkeypatch):
|
||||
|
|
|
|||
|
|
@ -10,9 +10,8 @@ Based on PR #1595 by 333Alden333 (salvaged).
|
|||
Updated for PR #3586 (cache-aware install/uninstall).
|
||||
"""
|
||||
|
||||
from unittest.mock import patch, MagicMock
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class TestHandleSkillsSlashInstallFlags:
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ def test_no_duplicate_skills_subparser():
|
|||
# Force fresh import of the module where parser is constructed
|
||||
# If there are duplicate 'skills' subparsers, this import will raise
|
||||
# argparse.ArgumentError at module load time
|
||||
import importlib
|
||||
import sys
|
||||
|
||||
# Remove cached module if present
|
||||
|
|
|
|||
|
|
@ -1,10 +1,6 @@
|
|||
"""Tests for hermes_cli.skin_engine — the data-driven skin/theme system."""
|
||||
|
||||
import json
|
||||
import os
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
|
|
@ -185,7 +181,7 @@ class TestSkinManagement:
|
|||
|
||||
class TestUserSkins:
|
||||
def test_load_user_skin_from_yaml(self, tmp_path, monkeypatch):
|
||||
from hermes_cli.skin_engine import load_skin, _skins_dir
|
||||
from hermes_cli.skin_engine import load_skin
|
||||
# Create a user skin YAML
|
||||
skins_dir = tmp_path / "skins"
|
||||
skins_dir.mkdir()
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import argparse
|
|||
import io
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def _build_parser():
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ to prevent a hard crash.
|
|||
from __future__ import annotations
|
||||
|
||||
import errno
|
||||
import os
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ from hermes_cli.auth import (
|
|||
resolve_provider,
|
||||
get_api_key_provider_status,
|
||||
resolve_api_key_provider_credentials,
|
||||
AuthError,
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"""Tests for hermes_cli/tips.py — random tip display at session start."""
|
||||
|
||||
import pytest
|
||||
from hermes_cli.tips import TIPS, get_random_tip
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
"""Tests for tool token estimation and curses_ui status_fn support."""
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
|
|
@ -20,7 +19,7 @@ _needs_tiktoken = pytest.mark.skipif(not _has_tiktoken, reason="tiktoken not ins
|
|||
@_needs_tiktoken
|
||||
def test_estimate_tool_tokens_returns_positive_counts():
|
||||
"""_estimate_tool_tokens should return a non-empty dict with positive values."""
|
||||
from hermes_cli.tools_config import _estimate_tool_tokens, _tool_token_cache
|
||||
from hermes_cli.tools_config import _estimate_tool_tokens
|
||||
|
||||
# Clear cache to force fresh computation
|
||||
import hermes_cli.tools_config as tc
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue