|
| 1 | +from collections.abc import Iterator |
| 2 | +from typing import Any, ClassVar, Self, override |
| 3 | + |
| 4 | +from httpx import Response |
| 5 | + |
| 6 | +from mpt_api_client.models.base import BaseCollection, ResourceData |
| 7 | +from mpt_api_client.models.meta import Meta |
| 8 | +from mpt_api_client.models.resource import Resource |
| 9 | + |
| 10 | + |
| 11 | +class Collection[ResourceType](BaseCollection): |
| 12 | + """Provides a base collection to interact with api collection data using fluent interfaces.""" |
| 13 | + |
| 14 | + _data_key: ClassVar[str] = "data" |
| 15 | + _resource_model: type[Resource] = Resource |
| 16 | + |
| 17 | + def __init__( |
| 18 | + self, collection_data: list[ResourceData] | None = None, meta: Meta | None = None |
| 19 | + ) -> None: |
| 20 | + self.meta = meta |
| 21 | + collection_data = collection_data or [] |
| 22 | + self._resource_collection = [ |
| 23 | + self._resource_model.new(resource_data, meta) for resource_data in collection_data |
| 24 | + ] |
| 25 | + |
| 26 | + def __getitem__(self, index: int) -> ResourceType: |
| 27 | + """Returns the collection item at the given index.""" |
| 28 | + return self._resource_collection[index] # type: ignore[return-value] |
| 29 | + |
| 30 | + def __iter__(self) -> Iterator[ResourceType]: |
| 31 | + """Make GenericCollection iterable.""" |
| 32 | + return iter(self._resource_collection) # type: ignore[arg-type] |
| 33 | + |
| 34 | + def __len__(self) -> int: |
| 35 | + """Return the number of items in the collection.""" |
| 36 | + return len(self._resource_collection) |
| 37 | + |
| 38 | + def __bool__(self) -> bool: |
| 39 | + """Returns True if collection has items.""" |
| 40 | + return len(self._resource_collection) > 0 |
| 41 | + |
| 42 | + @override |
| 43 | + @classmethod |
| 44 | + def from_response(cls, response: Response) -> Self: |
| 45 | + response_data = response.json().get(cls._data_key) |
| 46 | + meta = Meta.from_response(response) |
| 47 | + if not isinstance(response_data, list): |
| 48 | + raise TypeError(f"Response `{cls._data_key}` must be a list for collection endpoints.") |
| 49 | + |
| 50 | + return cls(response_data, meta) |
| 51 | + |
| 52 | + @override |
| 53 | + def to_list(self) -> list[dict[str, Any]]: |
| 54 | + return [resource.to_dict() for resource in self._resource_collection] |
0 commit comments