From facdc41a167155182505b19a1b2dcea44da18b3e Mon Sep 17 00:00:00 2001 From: chengyongru Date: Wed, 3 Jun 2026 16:15:12 +0800 Subject: [PATCH] fix: restore top-level import order --- nanobot/cli/commands.py | 48 +++++++++++++------------- tests/channels/test_discord_channel.py | 3 +- tests/tools/test_mcp_probe.py | 7 ++-- tests/tools/test_tool_loader.py | 13 +++---- 4 files changed, 33 insertions(+), 38 deletions(-) diff --git a/nanobot/cli/commands.py b/nanobot/cli/commands.py index b57bd8a6b..62f804ca2 100644 --- a/nanobot/cli/commands.py +++ b/nanobot/cli/commands.py @@ -19,8 +19,9 @@ if sys.platform == "win32": sys.stdout.reconfigure(encoding="utf-8", errors="replace") sys.stderr.reconfigure(encoding="utf-8", errors="replace") -import typer -from loguru import logger +# Keep console encoding setup before importing CLI UI/logging libraries. +import typer # noqa: E402 +from loguru import logger # noqa: E402 # Remove default handler and re-add with unified nanobot format logger.remove() @@ -37,18 +38,28 @@ _log_handler_id = logger.add( filter=lambda record: record["extra"].setdefault("channel", "-") or True, ) -from prompt_toolkit import PromptSession, print_formatted_text -from prompt_toolkit.application import run_in_terminal -from prompt_toolkit.formatted_text import ANSI, HTML -from prompt_toolkit.history import FileHistory -from prompt_toolkit.patch_stdout import patch_stdout -from rich.console import Console -from rich.markdown import Markdown -from rich.table import Table -from rich.text import Text +from prompt_toolkit import PromptSession, print_formatted_text # noqa: E402 +from prompt_toolkit.application import run_in_terminal # noqa: E402 +from prompt_toolkit.formatted_text import ANSI, HTML # noqa: E402 +from prompt_toolkit.history import FileHistory # noqa: E402 +from prompt_toolkit.patch_stdout import patch_stdout # noqa: E402 +from rich.console import Console # noqa: E402 +from rich.markdown import Markdown # noqa: E402 +from rich.table import Table # noqa: E402 +from rich.text import Text # noqa: E402 -from nanobot import __logo__, __version__ -from nanobot.agent.loop import AgentLoop +from nanobot import __logo__, __version__ # noqa: E402 +from nanobot.agent.loop import AgentLoop # noqa: E402 +from nanobot.cli.stream import StreamRenderer, ThinkingSpinner # noqa: E402 +from nanobot.config.paths import get_workspace_path, is_default_workspace # noqa: E402 +from nanobot.config.schema import Config # noqa: E402 +from nanobot.utils.evaluator import evaluate_response # noqa: E402 +from nanobot.utils.helpers import sync_workspace_templates # noqa: E402 +from nanobot.utils.restart import ( # noqa: E402 + consume_restart_notice_from_env, + format_restart_completed_message, + should_show_cli_restart_notice, +) def _sanitize_surrogates(text: str) -> str: @@ -72,17 +83,6 @@ class SafeFileHistory(FileHistory): def store_string(self, string: str) -> None: super().store_string(_sanitize_surrogates(string)) -from nanobot.cli.stream import StreamRenderer, ThinkingSpinner -from nanobot.config.paths import get_workspace_path, is_default_workspace -from nanobot.config.schema import Config -from nanobot.utils.evaluator import evaluate_response -from nanobot.utils.helpers import sync_workspace_templates -from nanobot.utils.restart import ( - consume_restart_notice_from_env, - format_restart_completed_message, - should_show_cli_restart_notice, -) - app = typer.Typer( name="nanobot", context_settings={"help_option_names": ["-h", "--help"]}, diff --git a/tests/channels/test_discord_channel.py b/tests/channels/test_discord_channel.py index 9bd1ab30e..d40276448 100644 --- a/tests/channels/test_discord_channel.py +++ b/tests/channels/test_discord_channel.py @@ -6,7 +6,8 @@ from types import SimpleNamespace import pytest -discord = pytest.importorskip("discord") +pytest.importorskip("discord") +import discord from nanobot.bus.events import OutboundMessage from nanobot.bus.queue import MessageBus diff --git a/tests/tools/test_mcp_probe.py b/tests/tools/test_mcp_probe.py index f8fcea031..38dc8fe7e 100644 --- a/tests/tools/test_mcp_probe.py +++ b/tests/tools/test_mcp_probe.py @@ -1,14 +1,14 @@ """Tests for MCP HTTP probe guard (prevents event-loop crash on unreachable servers).""" from __future__ import annotations -from unittest.mock import AsyncMock, MagicMock, patch +import asyncio +from unittest.mock import MagicMock, patch import pytest from nanobot.agent.tools.mcp import _probe_http_url, connect_mcp_servers from nanobot.agent.tools.registry import ToolRegistry - # --------------------------------------------------------------------------- # _probe_http_url unit tests # --------------------------------------------------------------------------- @@ -101,6 +101,3 @@ async def test_probe_not_called_for_stdio(): await connect_mcp_servers({"s": cfg}, registry) assert not called, "probe should not be called for stdio transport" - - -import asyncio diff --git a/tests/tools/test_tool_loader.py b/tests/tools/test_tool_loader.py index 8499b14fe..4d6f128f1 100644 --- a/tests/tools/test_tool_loader.py +++ b/tests/tools/test_tool_loader.py @@ -2,10 +2,13 @@ from __future__ import annotations from dataclasses import fields +from pathlib import Path from typing import Any from unittest.mock import MagicMock from nanobot.agent.tools.base import Tool +from nanobot.agent.tools.context import ToolContext +from nanobot.agent.tools.loader import _SKIP_MODULES, ToolLoader class _MinimalTool(Tool): @@ -49,8 +52,6 @@ def test_tool_plugin_discoverable_default_is_true(): # --- ToolContext tests --- -from nanobot.agent.tools.context import ToolContext - def test_tool_context_has_required_fields(): field_names = {f.name for f in fields(ToolContext)} @@ -74,8 +75,6 @@ def test_tool_context_defaults(): # --- ToolLoader tests --- -from nanobot.agent.tools.loader import ToolLoader, _SKIP_MODULES - def test_skip_modules_excludes_infrastructure(): infra = {"base", "schema", "registry", "context", "loader", "config", @@ -140,8 +139,6 @@ def test_loader_registers_exec_with_real_tools_config(tmp_path): # --- Task 4: _FsTool.create() --- -from pathlib import Path - def test_fs_tool_create_builds_from_context(): from nanobot.agent.tools.filesystem import ReadFileTool @@ -258,7 +255,7 @@ def test_exec_tool_create(): def test_web_tools_config_cls(): - from nanobot.agent.tools.web import WebSearchTool, WebFetchTool, WebToolsConfig + from nanobot.agent.tools.web import WebFetchTool, WebSearchTool, WebToolsConfig assert WebSearchTool.config_key == "web" assert WebSearchTool.config_cls() is WebToolsConfig assert WebFetchTool.config_key == "web" @@ -347,7 +344,7 @@ def test_my_tool_enabled(): def test_mcp_wrappers_not_discoverable(): - from nanobot.agent.tools.mcp import MCPToolWrapper, MCPResourceWrapper, MCPPromptWrapper + from nanobot.agent.tools.mcp import MCPPromptWrapper, MCPResourceWrapper, MCPToolWrapper assert MCPToolWrapper._plugin_discoverable is False assert MCPResourceWrapper._plugin_discoverable is False assert MCPPromptWrapper._plugin_discoverable is False