101 lines
2.8 KiB
Python
101 lines
2.8 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
_REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
if str(_REPO_ROOT) not in sys.path:
|
|
sys.path.insert(0, str(_REPO_ROOT))
|
|
|
|
_PYTEST_STATE_ROOT = Path(tempfile.gettempdir()) / f"opensquilla-pytest-{os.getpid()}"
|
|
|
|
os.environ.setdefault("OPENSQUILLA_STATE_DIR", str(_PYTEST_STATE_ROOT / "state"))
|
|
os.environ.setdefault("OPENSQUILLA_LOG_DIR", str(_PYTEST_STATE_ROOT / "logs"))
|
|
os.environ.setdefault("OPENSQUILLA_TURN_CALL_LOG", "0")
|
|
os.environ.setdefault("OPENSQUILLA_TEST_PROFILE_LOCK_ROOT", "1")
|
|
os.environ.setdefault(
|
|
"OPENSQUILLA_USER_STATE_DIR",
|
|
str(_PYTEST_STATE_ROOT / "profile-lock-state"),
|
|
)
|
|
|
|
_PROVIDER_ENV_KEYS = (
|
|
"ANTHROPIC_API_KEY",
|
|
"ARK_API_KEY",
|
|
"BOCHA_SEARCH_API_KEY",
|
|
"BRAVE_API_KEY",
|
|
"BRAVE_SEARCH_API_KEY",
|
|
"BYTEPLUS_API_KEY",
|
|
"DEEPSEEK_API_KEY",
|
|
"EXA_API_KEY",
|
|
"FIRECRAWL_API_KEY",
|
|
"GEMINI_API_KEY",
|
|
"GOOGLE_API_KEY",
|
|
"IQS_SEARCH_API_KEY",
|
|
"MOONSHOT_API_KEY",
|
|
"OPENAI_API_KEY",
|
|
"OPENROUTER_API_KEY",
|
|
"TAVILY_API_KEY",
|
|
"TENCENT_TOKEN_PLAN_API_KEY",
|
|
"TENCENT_TOKENHUB_API_KEY",
|
|
"TENCENT_TOKENHUB_INTL_API_KEY",
|
|
"TOKENRHYTHM_API_KEY",
|
|
"VOLCENGINE_API_KEY",
|
|
"VOLC_ARK_API_KEY",
|
|
)
|
|
|
|
_LIVE_MARKERS = (
|
|
"llm",
|
|
"llm_smoke",
|
|
"llm_costly",
|
|
"llm_tools",
|
|
"llm_embedding",
|
|
"llm_reasoning",
|
|
"llm_gateway",
|
|
"llm_image",
|
|
"llm_router_acc",
|
|
"live_channel",
|
|
"live_search",
|
|
)
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _isolate_provider_credentials(
|
|
monkeypatch: pytest.MonkeyPatch,
|
|
request: pytest.FixtureRequest,
|
|
) -> None:
|
|
"""Keep default tests offline even when the developer shell has API keys."""
|
|
if any(request.node.get_closest_marker(marker) for marker in _LIVE_MARKERS):
|
|
return
|
|
for env_key in _PROVIDER_ENV_KEYS:
|
|
monkeypatch.delenv(env_key, raising=False)
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _undo_leaked_cli_structlog_default():
|
|
"""Revert the CLI structlog default when a test leaves it behind.
|
|
|
|
The CLI entry callback installs a process-wide structlog default (stderr
|
|
output, WARNING+ filter; ``observability/cli_logging.py``). Tests that
|
|
invoke the Typer app would otherwise leak that filter into later tests
|
|
that capture info-level structlog events. Only the CLI default is
|
|
reverted; any other configuration a test installs is left for that test's
|
|
own teardown.
|
|
"""
|
|
import structlog
|
|
|
|
from opensquilla.observability.cli_logging import is_cli_default_active
|
|
|
|
was_configured = structlog.is_configured()
|
|
old_config = structlog.get_config()
|
|
was_cli_default = is_cli_default_active()
|
|
yield
|
|
if is_cli_default_active() and not was_cli_default:
|
|
if was_configured:
|
|
structlog.configure(**old_config)
|
|
else:
|
|
structlog.reset_defaults()
|