"""GLiNER client: local URL only, fail-soft, no request text in logs.""" from __future__ import annotations import os import sys from pathlib import Path from unittest.mock import patch import httpx ROOT = Path(__file__).resolve().parents[1] sys.path.insert(0, str(ROOT)) os.environ.setdefault("KANSHO_PROVIDER_KEY", "") os.environ.setdefault("KANSHO_DETECT_PROVIDER_KEY", "") from gliner_client import DEFAULT_URL, extract_entities, health, normalize_base_url def expect(ok: bool, message: str) -> None: if not ok: raise SystemExit(f"FAIL: {message}") print(f"OK {message}") class _Resp: def __init__(self, status_code: int, payload): self.status_code = status_code self._payload = payload def json(self): return self._payload def main() -> None: expect(normalize_base_url("http://192.168.2.144:8090/") == DEFAULT_URL, "default GLiNER URL is normalized") expect(extract_entities("Anna", url="https://openrouter.ai/api/v1") is None, "OpenRouter URL is rejected") expect(health("https://openrouter.ai").get("reason") == "not_local", "health rejects non-local URL") with patch("gliner_client.httpx.post", return_value=_Resp(200, {"spans": [{"text": "Anna", "start": 0, "end": 4, "label": "person", "score": 0.9}]})): spans = extract_entities("Anna kam.", url="http://192.168.2.144:8090") expect(spans == [{"text": "Anna", "start": 0, "end": 4, "label": "person", "score": 0.9}], "extract returns spans") with patch("gliner_client.httpx.post", side_effect=httpx.ConnectError("down")): expect(extract_entities("Anna kam.", url="http://192.168.2.144:8090") is None, "extract is fail-soft on errors") with patch("gliner_client.httpx.get", return_value=_Resp(200, {"status": "ok", "model": "urchade/gliner_multi-v2.1", "offline": True})): ping = health("http://192.168.2.144:8090") expect(ping.get("ok") is True and ping.get("offline") is True, "health reports ready offline model") print("gliner client: OK") if __name__ == "__main__": main()