diff --git a/imednet/core/endpoint/mixins/list.py b/imednet/core/endpoint/mixins/list.py index f391a13e..64b1b1c5 100644 --- a/imednet/core/endpoint/mixins/list.py +++ b/imednet/core/endpoint/mixins/list.py @@ -4,6 +4,7 @@ from imednet.constants import DEFAULT_PAGE_SIZE from imednet.core.endpoint.abc import EndpointABC +from imednet.core.endpoint.operations.list import ListOperation from imednet.core.endpoint.structs import ListRequestState from imednet.core.paginator import AsyncPaginator, Paginator from imednet.core.parsing import get_model_parser @@ -73,7 +74,8 @@ async def _execute_async_list( has_filters: bool, cache: Any, ) -> List[T]: - result = [parse_func(item) async for item in paginator] + operation = ListOperation[T]() + result = await operation.execute_async(paginator, parse_func) return self._process_list_result(result, study, has_filters, cache) def _execute_sync_list( @@ -84,7 +86,8 @@ def _execute_sync_list( has_filters: bool, cache: Any, ) -> List[T]: - result = [parse_func(item) for item in paginator] + operation = ListOperation[T]() + result = operation.execute_sync(paginator, parse_func) return self._process_list_result(result, study, has_filters, cache) def _prepare_list_request( diff --git a/imednet/core/endpoint/operations/__init__.py b/imednet/core/endpoint/operations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/imednet/core/endpoint/operations/list.py b/imednet/core/endpoint/operations/list.py new file mode 100644 index 00000000..4944639c --- /dev/null +++ b/imednet/core/endpoint/operations/list.py @@ -0,0 +1,57 @@ +""" +Operation for listing resources. + +Decouples the logic of iterating and parsing from the endpoint definition. +""" + +from __future__ import annotations + +from typing import Any, Callable, Generic, List, TypeVar + +from imednet.core.paginator import AsyncPaginator, Paginator +from imednet.models.json_base import JsonModel + +T = TypeVar("T", bound=JsonModel) + + +class ListOperation(Generic[T]): + """ + Encapsulates the logic for listing resources. + + This class handles the iteration over paginated results and parsing of items. + It is designed to be used via composition within endpoint implementations. + """ + + def execute_sync( + self, + paginator: Paginator, + parse_func: Callable[[Any], T], + ) -> List[T]: + """ + Execute a synchronous list operation. + + Args: + paginator: The paginator instance to iterate over. + parse_func: A function to parse each raw item into a model. + + Returns: + A list of parsed model instances. + """ + return [parse_func(item) for item in paginator] + + async def execute_async( + self, + paginator: AsyncPaginator, + parse_func: Callable[[Any], T], + ) -> List[T]: + """ + Execute an asynchronous list operation. + + Args: + paginator: The async paginator instance to iterate over. + parse_func: A function to parse each raw item into a model. + + Returns: + A list of parsed model instances. + """ + return [parse_func(item) async for item in paginator]