PhoneWork/docs/claude/_sdk_test_common.py
Yuyao Huang ba1b5b76c6 docs(claude): add SDK documentation and test examples
Add comprehensive documentation for Claude Agent SDK including usage patterns, test examples, and development guide. Includes:
- CLAUDE.md with project structure and quick reference
- SDK test examples for query, client, and hooks
- Shared test utilities for auth and tmpdir management
- Detailed SDK overview and capabilities documentation
2026-04-01 08:18:33 +08:00

76 lines
2.5 KiB
Python

"""Shared helpers for Claude Agent SDK tests.
Loads ANTHROPIC_BASE_URL / ANTHROPIC_AUTH_TOKEN from the project root .env
and injects them into the process environment and ClaudeAgentOptions.env.
"""
from __future__ import annotations
import os
import shutil
import tempfile
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parents[2]
DOTENV_PATH = PROJECT_ROOT / ".env"
def load_dotenv(dotenv_path: Path = DOTENV_PATH) -> dict[str, str]:
"""Parse KEY=VALUE lines from a .env file (no third-party deps)."""
values: dict[str, str] = {}
if not dotenv_path.exists():
return values
for raw_line in dotenv_path.read_text(encoding="utf-8").splitlines():
line = raw_line.strip()
if not line or line.startswith("#") or "=" not in line:
continue
key, value = line.split("=", 1)
values[key.strip()] = value.strip().strip('"').strip("'")
return values
def setup_auth() -> tuple[bool, str]:
"""Inject .env auth vars into os.environ; clear ANTHROPIC_API_KEY to avoid conflicts."""
values = load_dotenv()
base_url = values.get("ANTHROPIC_BASE_URL")
auth_token = values.get("ANTHROPIC_AUTH_TOKEN")
oauth_token = values.get("CLAUDE_CODE_OAUTH_TOKEN")
if not base_url:
return False, "Missing ANTHROPIC_BASE_URL in .env"
if not auth_token and not oauth_token:
return False, "Missing ANTHROPIC_AUTH_TOKEN or CLAUDE_CODE_OAUTH_TOKEN in .env"
os.environ["ANTHROPIC_BASE_URL"] = base_url
if auth_token:
os.environ["ANTHROPIC_AUTH_TOKEN"] = auth_token
if oauth_token:
os.environ["CLAUDE_CODE_OAUTH_TOKEN"] = oauth_token
os.environ.pop("ANTHROPIC_API_KEY", None)
return True, f"Auth loaded from {DOTENV_PATH}"
def auth_env() -> dict[str, str]:
"""Return env dict suitable for ClaudeAgentOptions(env=...)."""
return {
"ANTHROPIC_BASE_URL": os.environ["ANTHROPIC_BASE_URL"],
"ANTHROPIC_AUTH_TOKEN": os.environ.get("ANTHROPIC_AUTH_TOKEN", ""),
"CLAUDE_CODE_OAUTH_TOKEN": os.environ.get("CLAUDE_CODE_OAUTH_TOKEN", ""),
}
def make_tmpdir(prefix: str = "sdk-test-") -> Path:
"""Create a temporary directory manually (caller is responsible for cleanup)."""
return Path(tempfile.mkdtemp(prefix=prefix))
def remove_tmpdir(path: Path) -> None:
"""Remove a temporary directory, retrying once on Windows lock errors."""
try:
shutil.rmtree(path)
except OSError:
import time
time.sleep(1)
shutil.rmtree(path, ignore_errors=True)