fix: auto-fix ruff linting errors and remove unsupported upload-artifact
This commit is contained in:
@@ -57,12 +57,6 @@ jobs:
|
|||||||
- name: Run tests with coverage
|
- name: Run tests with coverage
|
||||||
run: uv run pytest --cov=handler_base --cov-report=xml --cov-report=term
|
run: uv run pytest --cov=handler_base --cov-report=xml --cov-report=term
|
||||||
|
|
||||||
- name: Upload coverage artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: coverage
|
|
||||||
path: coverage.xml
|
|
||||||
|
|
||||||
release:
|
release:
|
||||||
name: Release
|
name: Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
@@ -8,11 +8,12 @@ Provides consistent patterns for:
|
|||||||
- Graceful shutdown
|
- Graceful shutdown
|
||||||
- Service client wrappers
|
- Service client wrappers
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from handler_base.config import Settings
|
from handler_base.config import Settings
|
||||||
from handler_base.handler import Handler
|
from handler_base.handler import Handler
|
||||||
from handler_base.health import HealthServer
|
from handler_base.health import HealthServer
|
||||||
from handler_base.nats_client import NATSClient
|
from handler_base.nats_client import NATSClient
|
||||||
from handler_base.telemetry import setup_telemetry, get_tracer, get_meter
|
from handler_base.telemetry import get_meter, get_tracer, setup_telemetry
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Handler",
|
"Handler",
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
"""
|
"""
|
||||||
Service client wrappers for AI/ML backends.
|
Service client wrappers for AI/ML backends.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from handler_base.clients.embeddings import EmbeddingsClient
|
from handler_base.clients.embeddings import EmbeddingsClient
|
||||||
from handler_base.clients.reranker import RerankerClient
|
|
||||||
from handler_base.clients.llm import LLMClient
|
from handler_base.clients.llm import LLMClient
|
||||||
from handler_base.clients.tts import TTSClient
|
|
||||||
from handler_base.clients.stt import STTClient
|
|
||||||
from handler_base.clients.milvus import MilvusClient
|
from handler_base.clients.milvus import MilvusClient
|
||||||
|
from handler_base.clients.reranker import RerankerClient
|
||||||
|
from handler_base.clients.stt import STTClient
|
||||||
|
from handler_base.clients.tts import TTSClient
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"EmbeddingsClient",
|
"EmbeddingsClient",
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
Embeddings service client (Infinity/BGE).
|
Embeddings service client (Infinity/BGE).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
"""
|
"""
|
||||||
LLM service client (vLLM/OpenAI-compatible).
|
LLM service client (vLLM/OpenAI-compatible).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Optional, AsyncIterator
|
from typing import AsyncIterator, Optional
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
|
|
||||||
@@ -131,9 +132,7 @@ class LLMClient:
|
|||||||
"stream": True,
|
"stream": True,
|
||||||
}
|
}
|
||||||
|
|
||||||
async with self._client.stream(
|
async with self._client.stream("POST", "/v1/chat/completions", json=payload) as response:
|
||||||
"POST", "/v1/chat/completions", json=payload
|
|
||||||
) as response:
|
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
|
|
||||||
async for line in response.aiter_lines():
|
async for line in response.aiter_lines():
|
||||||
@@ -143,6 +142,7 @@ class LLMClient:
|
|||||||
break
|
break
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
|
||||||
chunk = json.loads(data)
|
chunk = json.loads(data)
|
||||||
delta = chunk["choices"][0].get("delta", {})
|
delta = chunk["choices"][0].get("delta", {})
|
||||||
content = delta.get("content", "")
|
content = delta.get("content", "")
|
||||||
@@ -163,21 +163,25 @@ class LLMClient:
|
|||||||
messages.append({"role": "system", "content": system_prompt})
|
messages.append({"role": "system", "content": system_prompt})
|
||||||
elif context:
|
elif context:
|
||||||
# Default RAG system prompt
|
# Default RAG system prompt
|
||||||
messages.append({
|
messages.append(
|
||||||
|
{
|
||||||
"role": "system",
|
"role": "system",
|
||||||
"content": (
|
"content": (
|
||||||
"You are a helpful assistant. Use the provided context to answer "
|
"You are a helpful assistant. Use the provided context to answer "
|
||||||
"the user's question. If the context doesn't contain relevant "
|
"the user's question. If the context doesn't contain relevant "
|
||||||
"information, say so."
|
"information, say so."
|
||||||
),
|
),
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
# Add context as a separate message if provided
|
# Add context as a separate message if provided
|
||||||
if context:
|
if context:
|
||||||
messages.append({
|
messages.append(
|
||||||
|
{
|
||||||
"role": "user",
|
"role": "user",
|
||||||
"content": f"Context:\n{context}\n\nQuestion: {prompt}",
|
"content": f"Context:\n{context}\n\nQuestion: {prompt}",
|
||||||
})
|
}
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
messages.append({"role": "user", "content": prompt})
|
messages.append({"role": "user", "content": prompt})
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
"""
|
"""
|
||||||
Milvus vector database client.
|
Milvus vector database client.
|
||||||
"""
|
"""
|
||||||
import logging
|
|
||||||
from typing import Optional, Any
|
|
||||||
|
|
||||||
from pymilvus import connections, Collection, utility
|
import logging
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from pymilvus import Collection, connections, utility
|
||||||
|
|
||||||
from handler_base.config import Settings
|
from handler_base.config import Settings
|
||||||
from handler_base.telemetry import create_span
|
from handler_base.telemetry import create_span
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
Reranker service client (Infinity/BGE Reranker).
|
Reranker service client (Infinity/BGE Reranker).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
@@ -73,11 +74,13 @@ class RerankerClient:
|
|||||||
enriched = []
|
enriched = []
|
||||||
for r in results:
|
for r in results:
|
||||||
idx = r.get("index", 0)
|
idx = r.get("index", 0)
|
||||||
enriched.append({
|
enriched.append(
|
||||||
|
{
|
||||||
"index": idx,
|
"index": idx,
|
||||||
"score": r.get("relevance_score", r.get("score", 0)),
|
"score": r.get("relevance_score", r.get("score", 0)),
|
||||||
"document": documents[idx] if idx < len(documents) else "",
|
"document": documents[idx] if idx < len(documents) else "",
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
return enriched
|
return enriched
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
STT service client (Whisper/faster-whisper).
|
STT service client (Whisper/faster-whisper).
|
||||||
"""
|
"""
|
||||||
import io
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
TTS service client (Coqui XTTS).
|
TTS service client (Coqui XTTS).
|
||||||
"""
|
"""
|
||||||
import io
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ Configuration management using Pydantic Settings.
|
|||||||
|
|
||||||
Environment variables are automatically loaded and validated.
|
Environment variables are automatically loaded and validated.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from pydantic_settings import BaseSettings, SettingsConfigDict
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
"""
|
"""
|
||||||
Base handler class for building NATS-based services.
|
Base handler class for building NATS-based services.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import signal
|
import signal
|
||||||
@@ -12,7 +13,7 @@ from nats.aio.msg import Msg
|
|||||||
from handler_base.config import Settings
|
from handler_base.config import Settings
|
||||||
from handler_base.health import HealthServer
|
from handler_base.health import HealthServer
|
||||||
from handler_base.nats_client import NATSClient
|
from handler_base.nats_client import NATSClient
|
||||||
from handler_base.telemetry import setup_telemetry, create_span
|
from handler_base.telemetry import create_span, setup_telemetry
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -178,7 +179,7 @@ class Handler(ABC):
|
|||||||
# Wait for shutdown signal
|
# Wait for shutdown signal
|
||||||
await self._shutdown_event.wait()
|
await self._shutdown_event.wait()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception:
|
||||||
logger.exception("Fatal error in handler")
|
logger.exception("Fatal error in handler")
|
||||||
raise
|
raise
|
||||||
finally:
|
finally:
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ HTTP health check server.
|
|||||||
|
|
||||||
Provides /health and /ready endpoints for Kubernetes probes.
|
Provides /health and /ready endpoints for Kubernetes probes.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
|
||||||
from typing import Callable, Optional, Awaitable
|
|
||||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
|
||||||
import threading
|
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
|
import threading
|
||||||
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
||||||
|
from typing import Awaitable, Callable, Optional
|
||||||
|
|
||||||
from handler_base.config import Settings
|
from handler_base.config import Settings
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
"""
|
"""
|
||||||
NATS client wrapper with connection management and utilities.
|
NATS client wrapper with connection management and utilities.
|
||||||
"""
|
"""
|
||||||
import asyncio
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Callable, Optional, Awaitable
|
from typing import Any, Awaitable, Callable, Optional
|
||||||
|
|
||||||
import msgpack
|
import msgpack
|
||||||
import nats
|
import nats
|
||||||
@@ -129,6 +129,7 @@ class NATSClient:
|
|||||||
payload = msgpack.packb(data, use_bin_type=True)
|
payload = msgpack.packb(data, use_bin_type=True)
|
||||||
else:
|
else:
|
||||||
import json
|
import json
|
||||||
|
|
||||||
payload = json.dumps(data).encode()
|
payload = json.dumps(data).encode()
|
||||||
|
|
||||||
await self.nc.publish(subject, payload)
|
await self.nc.publish(subject, payload)
|
||||||
@@ -162,6 +163,7 @@ class NATSClient:
|
|||||||
payload = msgpack.packb(data, use_bin_type=True)
|
payload = msgpack.packb(data, use_bin_type=True)
|
||||||
else:
|
else:
|
||||||
import json
|
import json
|
||||||
|
|
||||||
payload = json.dumps(data).encode()
|
payload = json.dumps(data).encode()
|
||||||
|
|
||||||
response = await self.nc.request(subject, payload, timeout=timeout)
|
response = await self.nc.request(subject, payload, timeout=timeout)
|
||||||
@@ -170,6 +172,7 @@ class NATSClient:
|
|||||||
return msgpack.unpackb(response.data, raw=False)
|
return msgpack.unpackb(response.data, raw=False)
|
||||||
else:
|
else:
|
||||||
import json
|
import json
|
||||||
|
|
||||||
return json.loads(response.data.decode())
|
return json.loads(response.data.decode())
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -181,4 +184,5 @@ class NATSClient:
|
|||||||
def decode_json(msg: Msg) -> Any:
|
def decode_json(msg: Msg) -> Any:
|
||||||
"""Decode a JSON message."""
|
"""Decode a JSON message."""
|
||||||
import json
|
import json
|
||||||
|
|
||||||
return json.loads(msg.data.decode())
|
return json.loads(msg.data.decode())
|
||||||
|
|||||||
@@ -3,26 +3,27 @@ OpenTelemetry setup for tracing and metrics.
|
|||||||
|
|
||||||
Supports both gRPC and HTTP exporters, with optional HyperDX integration.
|
Supports both gRPC and HTTP exporters, with optional HyperDX integration.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from typing import Optional, Tuple
|
from typing import Optional, Tuple
|
||||||
|
|
||||||
from opentelemetry import trace, metrics
|
from opentelemetry import metrics, trace
|
||||||
from opentelemetry.sdk.trace import TracerProvider
|
|
||||||
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
||||||
from opentelemetry.sdk.metrics import MeterProvider
|
|
||||||
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
|
|
||||||
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
|
|
||||||
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
|
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
|
||||||
from opentelemetry.exporter.otlp.proto.http.trace_exporter import (
|
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
|
||||||
OTLPSpanExporter as OTLPSpanExporterHTTP,
|
|
||||||
)
|
|
||||||
from opentelemetry.exporter.otlp.proto.http.metric_exporter import (
|
from opentelemetry.exporter.otlp.proto.http.metric_exporter import (
|
||||||
OTLPMetricExporter as OTLPMetricExporterHTTP,
|
OTLPMetricExporter as OTLPMetricExporterHTTP,
|
||||||
)
|
)
|
||||||
from opentelemetry.sdk.resources import Resource, SERVICE_NAME, SERVICE_VERSION, SERVICE_NAMESPACE
|
from opentelemetry.exporter.otlp.proto.http.trace_exporter import (
|
||||||
|
OTLPSpanExporter as OTLPSpanExporterHTTP,
|
||||||
|
)
|
||||||
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
|
from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
|
||||||
from opentelemetry.instrumentation.logging import LoggingInstrumentor
|
from opentelemetry.instrumentation.logging import LoggingInstrumentor
|
||||||
|
from opentelemetry.sdk.metrics import MeterProvider
|
||||||
|
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
|
||||||
|
from opentelemetry.sdk.resources import SERVICE_NAME, SERVICE_NAMESPACE, SERVICE_VERSION, Resource
|
||||||
|
from opentelemetry.sdk.trace import TracerProvider
|
||||||
|
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
||||||
|
|
||||||
from handler_base.config import Settings
|
from handler_base.config import Settings
|
||||||
|
|
||||||
@@ -60,13 +61,15 @@ def setup_telemetry(
|
|||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
# Create resource with service information
|
# Create resource with service information
|
||||||
resource = Resource.create({
|
resource = Resource.create(
|
||||||
|
{
|
||||||
SERVICE_NAME: settings.service_name,
|
SERVICE_NAME: settings.service_name,
|
||||||
SERVICE_VERSION: settings.service_version,
|
SERVICE_VERSION: settings.service_version,
|
||||||
SERVICE_NAMESPACE: settings.service_namespace,
|
SERVICE_NAMESPACE: settings.service_namespace,
|
||||||
"deployment.environment": settings.deployment_env,
|
"deployment.environment": settings.deployment_env,
|
||||||
"host.name": os.environ.get("HOSTNAME", "unknown"),
|
"host.name": os.environ.get("HOSTNAME", "unknown"),
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
|
||||||
# Determine endpoint and exporter type
|
# Determine endpoint and exporter type
|
||||||
if settings.hyperdx_enabled and settings.hyperdx_api_key:
|
if settings.hyperdx_enabled and settings.hyperdx_api_key:
|
||||||
@@ -150,5 +153,6 @@ def create_span(name: str, **kwargs):
|
|||||||
if _tracer is None:
|
if _tracer is None:
|
||||||
# Return a no-op context manager
|
# Return a no-op context manager
|
||||||
from contextlib import nullcontext
|
from contextlib import nullcontext
|
||||||
|
|
||||||
return nullcontext()
|
return nullcontext()
|
||||||
return _tracer.start_as_current_span(name, **kwargs)
|
return _tracer.start_as_current_span(name, **kwargs)
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
"""
|
"""
|
||||||
Pytest configuration and fixtures.
|
Pytest configuration and fixtures.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import os
|
import os
|
||||||
from typing import AsyncGenerator
|
|
||||||
from unittest.mock import AsyncMock, MagicMock
|
from unittest.mock import AsyncMock, MagicMock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
# Set test environment variables before importing handler_base
|
# Set test environment variables before importing handler_base
|
||||||
os.environ.setdefault("NATS_URL", "nats://localhost:4222")
|
os.environ.setdefault("NATS_URL", "nats://localhost:4222")
|
||||||
os.environ.setdefault("REDIS_URL", "redis://localhost:6379")
|
os.environ.setdefault("REDIS_URL", "redis://localhost:6379")
|
||||||
@@ -29,6 +28,7 @@ def event_loop():
|
|||||||
def settings():
|
def settings():
|
||||||
"""Create test settings."""
|
"""Create test settings."""
|
||||||
from handler_base.config import Settings
|
from handler_base.config import Settings
|
||||||
|
|
||||||
return Settings(
|
return Settings(
|
||||||
service_name="test-service",
|
service_name="test-service",
|
||||||
service_version="1.0.0-test",
|
service_version="1.0.0-test",
|
||||||
@@ -56,7 +56,7 @@ def mock_nats_message():
|
|||||||
msg = MagicMock()
|
msg = MagicMock()
|
||||||
msg.subject = "test.subject"
|
msg.subject = "test.subject"
|
||||||
msg.reply = "test.reply"
|
msg.reply = "test.reply"
|
||||||
msg.data = b'\x82\xa8query\xa5hello\xaarequest_id\xa4test' # msgpack
|
msg.data = b"\x82\xa8query\xa5hello\xaarequest_id\xa4test" # msgpack
|
||||||
return msg
|
return msg
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
"""
|
"""
|
||||||
Unit tests for service clients.
|
Unit tests for service clients.
|
||||||
"""
|
"""
|
||||||
import json
|
|
||||||
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from unittest.mock import AsyncMock, MagicMock, patch
|
|
||||||
|
|
||||||
|
|
||||||
class TestEmbeddingsClient:
|
class TestEmbeddingsClient:
|
||||||
@@ -23,9 +24,7 @@ class TestEmbeddingsClient:
|
|||||||
"""Test embedding a single text."""
|
"""Test embedding a single text."""
|
||||||
# Setup mock response
|
# Setup mock response
|
||||||
mock_response = MagicMock()
|
mock_response = MagicMock()
|
||||||
mock_response.json.return_value = {
|
mock_response.json.return_value = {"data": [{"embedding": sample_embedding, "index": 0}]}
|
||||||
"data": [{"embedding": sample_embedding, "index": 0}]
|
|
||||||
}
|
|
||||||
mock_response.raise_for_status = MagicMock()
|
mock_response.raise_for_status = MagicMock()
|
||||||
mock_httpx_client.post.return_value = mock_response
|
mock_httpx_client.post.return_value = mock_response
|
||||||
|
|
||||||
@@ -118,10 +117,8 @@ class TestLLMClient:
|
|||||||
"""Test generating a response."""
|
"""Test generating a response."""
|
||||||
mock_response = MagicMock()
|
mock_response = MagicMock()
|
||||||
mock_response.json.return_value = {
|
mock_response.json.return_value = {
|
||||||
"choices": [
|
"choices": [{"message": {"content": "Hello! I'm an AI assistant."}}],
|
||||||
{"message": {"content": "Hello! I'm an AI assistant."}}
|
"usage": {"prompt_tokens": 10, "completion_tokens": 20},
|
||||||
],
|
|
||||||
"usage": {"prompt_tokens": 10, "completion_tokens": 20}
|
|
||||||
}
|
}
|
||||||
mock_response.raise_for_status = MagicMock()
|
mock_response.raise_for_status = MagicMock()
|
||||||
mock_httpx_client.post.return_value = mock_response
|
mock_httpx_client.post.return_value = mock_response
|
||||||
@@ -135,17 +132,14 @@ class TestLLMClient:
|
|||||||
"""Test generating with RAG context."""
|
"""Test generating with RAG context."""
|
||||||
mock_response = MagicMock()
|
mock_response = MagicMock()
|
||||||
mock_response.json.return_value = {
|
mock_response.json.return_value = {
|
||||||
"choices": [
|
"choices": [{"message": {"content": "Based on the context..."}}],
|
||||||
{"message": {"content": "Based on the context..."}}
|
"usage": {},
|
||||||
],
|
|
||||||
"usage": {}
|
|
||||||
}
|
}
|
||||||
mock_response.raise_for_status = MagicMock()
|
mock_response.raise_for_status = MagicMock()
|
||||||
mock_httpx_client.post.return_value = mock_response
|
mock_httpx_client.post.return_value = mock_response
|
||||||
|
|
||||||
result = await llm_client.generate(
|
result = await llm_client.generate(
|
||||||
"What is Python?",
|
"What is Python?", context="Python is a programming language."
|
||||||
context="Python is a programming language."
|
|
||||||
)
|
)
|
||||||
|
|
||||||
assert "Based on the context" in result
|
assert "Based on the context" in result
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
"""
|
"""
|
||||||
Unit tests for handler_base.config module.
|
Unit tests for handler_base.config module.
|
||||||
"""
|
"""
|
||||||
import os
|
|
||||||
import pytest
|
|
||||||
|
|
||||||
|
|
||||||
class TestSettings:
|
class TestSettings:
|
||||||
@@ -22,6 +20,7 @@ class TestSettings:
|
|||||||
|
|
||||||
# Need to reimport to pick up env changes
|
# Need to reimport to pick up env changes
|
||||||
from handler_base.config import Settings
|
from handler_base.config import Settings
|
||||||
|
|
||||||
s = Settings()
|
s = Settings()
|
||||||
|
|
||||||
assert s.service_name == "env-service"
|
assert s.service_name == "env-service"
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
"""
|
"""
|
||||||
Unit tests for handler_base.health module.
|
Unit tests for handler_base.health module.
|
||||||
"""
|
"""
|
||||||
import pytest
|
|
||||||
import json
|
import json
|
||||||
import threading
|
|
||||||
import time
|
import time
|
||||||
from http.client import HTTPConnection
|
from http.client import HTTPConnection
|
||||||
from unittest.mock import AsyncMock
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
class TestHealthServer:
|
class TestHealthServer:
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
"""
|
"""
|
||||||
Unit tests for handler_base.nats_client module.
|
Unit tests for handler_base.nats_client module.
|
||||||
"""
|
"""
|
||||||
import pytest
|
|
||||||
from unittest.mock import AsyncMock, MagicMock, patch
|
from unittest.mock import AsyncMock, MagicMock, patch
|
||||||
|
|
||||||
import msgpack
|
import msgpack
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
class TestNATSClient:
|
class TestNATSClient:
|
||||||
@@ -13,6 +15,7 @@ class TestNATSClient:
|
|||||||
def nats_client(self, settings):
|
def nats_client(self, settings):
|
||||||
"""Create a NATSClient instance."""
|
"""Create a NATSClient instance."""
|
||||||
from handler_base.nats_client import NATSClient
|
from handler_base.nats_client import NATSClient
|
||||||
|
|
||||||
return NATSClient(settings)
|
return NATSClient(settings)
|
||||||
|
|
||||||
def test_init(self, nats_client, settings):
|
def test_init(self, nats_client, settings):
|
||||||
@@ -35,6 +38,7 @@ class TestNATSClient:
|
|||||||
def test_decode_json(self, nats_client):
|
def test_decode_json(self, nats_client):
|
||||||
"""Test JSON decoding."""
|
"""Test JSON decoding."""
|
||||||
import json
|
import json
|
||||||
|
|
||||||
data = {"query": "hello"}
|
data = {"query": "hello"}
|
||||||
|
|
||||||
msg = MagicMock()
|
msg = MagicMock()
|
||||||
|
|||||||
Reference in New Issue
Block a user