Source code for xnatctl.services.base
"""Base service with common methods for all XNAT services."""
from __future__ import annotations
from collections.abc import Iterator
from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from xnatctl.core.client import XNATClient
[docs]
class BaseService:
"""Base service class with common functionality."""
def __init__(self, client: XNATClient) -> None:
"""Initialize service with XNAT client.
Args:
client: Authenticated XNATClient instance
"""
self.client = client
def _get(self, path: str, **kwargs: Any) -> Any:
"""Execute GET request and return JSON data.
Args:
path: API endpoint path
**kwargs: Additional request parameters
Returns:
Parsed JSON response data
"""
resp = self.client.get(path, **kwargs)
return resp.json()
def _post(self, path: str, **kwargs: Any) -> Any:
"""Execute POST request and return response.
Args:
path: API endpoint path
**kwargs: Additional request parameters
Returns:
Parsed JSON response or response text
"""
resp = self.client.post(path, **kwargs)
if resp.headers.get("content-type", "").startswith("application/json"):
return resp.json()
return resp.text
def _put(self, path: str, **kwargs: Any) -> Any:
"""Execute PUT request and return response.
Args:
path: API endpoint path
**kwargs: Additional request parameters
Returns:
Parsed JSON response or response text
"""
resp = self.client.put(path, **kwargs)
if resp.headers.get("content-type", "").startswith("application/json"):
return resp.json()
return resp.text
def _delete(self, path: str, **kwargs: Any) -> bool:
"""Execute DELETE request.
Args:
path: API endpoint path
**kwargs: Additional request parameters
Returns:
True if successful
"""
self.client.delete(path, **kwargs)
return True
def _paginate(
self,
path: str,
page_size: int = 100,
result_key: str = "ResultSet.Result",
) -> Iterator[dict[str, Any]]:
"""Iterate over paginated results.
Args:
path: API endpoint path
page_size: Results per page
result_key: Dot-notation key to extract results
Yields:
Individual result items
"""
yield from self.client.paginate(
path,
page_size=page_size,
result_key=result_key,
)
def _extract_results(
self,
data: dict[str, Any],
result_key: str = "ResultSet.Result",
) -> list[dict[str, Any]]:
"""Extract results from XNAT response.
Args:
data: Raw API response data
result_key: Dot-notation key to extract results
Returns:
List of result items
"""
results = data
for key in result_key.split("."):
if isinstance(results, dict):
results = results.get(key, [])
else:
return []
return results if isinstance(results, list) else []
def _build_path(self, *parts: str) -> str:
"""Build API path from parts.
Args:
*parts: Path segments
Returns:
Joined path string
"""
return "/" + "/".join(p.strip("/") for p in parts if p)