Source code for imednet.core.base_client

# Base HTTP client for iMednet SDK

"""Common base client initialization for both synchronous and asynchronous SDKs."""

from __future__ import annotations

import logging
from typing import TYPE_CHECKING, Any

if TYPE_CHECKING:
    from opentelemetry.trace import Tracer
else:  # pragma: no cover - typing fallback for optional dependency
    Tracer = Any

import httpx

from imednet.auth.api_key import ApiKeyAuth
from imednet.auth.strategy import AuthStrategy
from imednet.config import load_config
from imednet.constants import (
    DEFAULT_BASE_URL,
    DEFAULT_TIMEOUT,
)
from imednet.core.retry import RetryConfig
from imednet.utils import sanitize_base_url

trace: Any = None
try:
    from opentelemetry import trace as _trace

    trace = _trace
except Exception:  # pragma: no cover - optional dependency  # noqa: S110
    pass
logger = logging.getLogger(__name__)


[docs]class BaseClient: """Common initialization logic for HTTP clients."""
[docs] def __init__( self, api_key: str | None = None, security_key: str | None = None, base_url: str | None = None, timeout: float | httpx.Timeout = DEFAULT_TIMEOUT, tracer: Tracer | None = None, retry_config: RetryConfig | None = None, auth: AuthStrategy | None = None, ) -> None: """Initialize common client settings. Args: api_key: iMednet API key. security_key: iMednet security key. base_url: Base URL for the iMednet API. timeout: Default request timeout in seconds or httpx.Timeout. tracer: Optional OpenTelemetry tracer instance. retry_config: Centralized configuration for retry behaviors. auth: Optional pre-configured AuthStrategy. """ config = load_config(api_key=api_key, security_key=security_key, base_url=base_url) self.base_url = sanitize_base_url(config.base_url or DEFAULT_BASE_URL) self._base_url = httpx.URL(self.base_url) self.timeout = timeout if isinstance(timeout, httpx.Timeout) else httpx.Timeout(timeout) self.retry_config = retry_config or RetryConfig() if auth: self.auth = auth else: self.auth = ApiKeyAuth(config.api_key or "", config.security_key or "") self._client = self._create_client(self.auth) self._tracer: Tracer | None = None if tracer is not None: self._tracer = tracer elif trace is not None: self._tracer = trace.get_tracer(__name__) else: self._tracer = None
def _create_client(self, auth: AuthStrategy) -> Any: """Create the underlying HTTP client (to be implemented by subclasses).""" raise NotImplementedError