Source code for imednet.core.client

"""
Core HTTP client for interacting with the iMednet REST API.

This module defines the `Client` class which handles:
- Authentication headers (API key and security key).
- Configuration of base URL, timeouts, and retry logic.
- Making HTTP GET and POST requests.
- Error mapping to custom errors.
- Context-manager support for automatic cleanup.
"""

from __future__ import annotations

import logging
from types import TracebackType
from typing import Any, Dict, Optional

import httpx

from imednet.core.http.executor import SyncRequestExecutor
from imednet.core.retry import RetryPolicy

from .http_client_base import HTTPClientBase

logger = logging.getLogger(__name__)


[docs]class Client(HTTPClientBase[httpx.Client, SyncRequestExecutor]): """ Core HTTP client for the iMednet API. Attributes: base_url: Base URL for API requests. timeout: Default timeout for requests. retries: Number of retry attempts for transient errors. backoff_factor: Multiplier for exponential backoff. """ def _get_client_class(self) -> type[httpx.Client]: return httpx.Client def _create_executor( self, client: httpx.Client, retry_policy: Optional[RetryPolicy] = None ) -> SyncRequestExecutor: # Use wrapper to allow mocking client.request after initialization def send_wrapper(method: str, url: str, **kwargs: Any) -> httpx.Response: return client.request(method, url, **kwargs) return SyncRequestExecutor( send=send_wrapper, retries=self.retries, backoff_factor=self.backoff_factor, tracer=self._tracer, retry_policy=retry_policy, ) def __enter__(self) -> Client: return self def __exit__( self, exc_type: Optional[type[BaseException]], exc: Optional[BaseException], tb: Optional[TracebackType], ) -> None: self.close()
[docs] def close(self) -> None: """Close the underlying HTTP client.""" self._client.close()
def _request(self, method: str, path: str, **kwargs: Any) -> httpx.Response: return self._executor(method, path, **kwargs)
[docs] def get( self, path: str, params: Optional[Dict[str, Any]] = None, **kwargs: Any, ) -> httpx.Response: """ Make a GET request. Args: path: URL path or full URL. params: Query parameters. """ return self._request("GET", path, params=params, **kwargs)
[docs] def post( self, path: str, json: Optional[Any] = None, **kwargs: Any, ) -> httpx.Response: """ Make a POST request. Args: path: URL path or full URL. json: JSON body for the request. """ return self._request("POST", path, json=json, **kwargs)