|
4 | 4 | from urllib.parse import urljoin |
5 | 5 |
|
6 | 6 | from mpt_api_client.constants import APPLICATION_JSON |
| 7 | +from mpt_api_client.exceptions import MPTError |
7 | 8 | from mpt_api_client.http.query_state import QueryState |
8 | 9 | from mpt_api_client.http.types import FileTypes, Response |
9 | 10 | from mpt_api_client.models import Collection, FileModel, ResourceData |
@@ -60,7 +61,32 @@ def update(self, resource_id: str, resource_data: ResourceData) -> Model: |
60 | 61 | return self._resource_action(resource_id, "PUT", json=resource_data) # type: ignore[attr-defined, no-any-return] |
61 | 62 |
|
62 | 63 |
|
63 | | -class FileOperationsMixin[Model]: |
| 64 | +class DownloadFileMixin[Model]: |
| 65 | + """Download file mixin.""" |
| 66 | + |
| 67 | + def download(self, resource_id: str, accept: str | None = None) -> FileModel: |
| 68 | + """Download the file for the given resource ID. |
| 69 | +
|
| 70 | + Args: |
| 71 | + resource_id: Resource ID. |
| 72 | + accept: The content type expected for the file. |
| 73 | + If not provided, the content type will be fetched from the resource. |
| 74 | +
|
| 75 | + Returns: |
| 76 | + File model containing the downloaded file. |
| 77 | + """ |
| 78 | + if not accept: |
| 79 | + resource: Model = self._resource_action(resource_id, method="GET") # type: ignore[attr-defined] |
| 80 | + accept = resource.content_type # type: ignore[attr-defined] |
| 81 | + if not accept: |
| 82 | + raise MPTError("Unable to download file. Content type not found in resource") |
| 83 | + response: Response = self._resource_do_request( # type: ignore[attr-defined] |
| 84 | + resource_id, method="GET", headers={"Accept": accept} |
| 85 | + ) |
| 86 | + return FileModel(response) |
| 87 | + |
| 88 | + |
| 89 | +class FilesOperationsMixin[Model](DownloadFileMixin[Model]): |
64 | 90 | """Mixin that provides create and download methods for file-based resources.""" |
65 | 91 |
|
66 | 92 | def create( |
@@ -91,20 +117,6 @@ def create( |
91 | 117 |
|
92 | 118 | return self._model_class.from_response(response) # type: ignore[attr-defined, no-any-return] |
93 | 119 |
|
94 | | - def download(self, resource_id: str) -> FileModel: |
95 | | - """Download the file for the given resource ID. |
96 | | -
|
97 | | - Args: |
98 | | - resource_id: Resource ID. |
99 | | -
|
100 | | - Returns: |
101 | | - File model containing the downloaded file. |
102 | | - """ |
103 | | - response: Response = self._resource_do_request( # type: ignore[attr-defined] |
104 | | - resource_id, method="GET", headers={"Accept": "*"} |
105 | | - ) |
106 | | - return FileModel(response) |
107 | | - |
108 | 120 |
|
109 | 121 | class CreateWithIconMixin[Model]: |
110 | 122 | """Create resource with icon mixin.""" |
@@ -221,7 +233,32 @@ async def update(self, resource_id: str, resource_data: ResourceData) -> Model: |
221 | 233 | return await self._resource_action(resource_id, "PUT", json=resource_data) # type: ignore[attr-defined, no-any-return] |
222 | 234 |
|
223 | 235 |
|
224 | | -class AsyncFileOperationsMixin[Model]: |
| 236 | +class AsyncDownloadFileMixin[Model]: |
| 237 | + """Download file mixin.""" |
| 238 | + |
| 239 | + async def download(self, resource_id: str, accept: str | None = None) -> FileModel: |
| 240 | + """Download the file for the given resource ID. |
| 241 | +
|
| 242 | + Args: |
| 243 | + resource_id: Resource ID. |
| 244 | + accept: The content type expected for the file. |
| 245 | + If not provided, the content type will be fetched from the resource. |
| 246 | +
|
| 247 | + Returns: |
| 248 | + File model containing the downloaded file. |
| 249 | + """ |
| 250 | + if not accept: |
| 251 | + resource: Model = await self._resource_action(resource_id, method="GET") # type: ignore[attr-defined] |
| 252 | + accept = resource.content_type # type: ignore[attr-defined] |
| 253 | + if not accept: |
| 254 | + raise MPTError("Unable to download file. Content type not found in resource") |
| 255 | + response = await self._resource_do_request( # type: ignore[attr-defined] |
| 256 | + resource_id, method="GET", headers={"Accept": accept} |
| 257 | + ) |
| 258 | + return FileModel(response) |
| 259 | + |
| 260 | + |
| 261 | +class AsyncFilesOperationsMixin[Model](AsyncDownloadFileMixin[Model]): |
225 | 262 | """Async mixin that provides create and download methods for file-based resources.""" |
226 | 263 |
|
227 | 264 | async def create( |
@@ -253,20 +290,6 @@ async def create( |
253 | 290 |
|
254 | 291 | return self._model_class.from_response(response) # type: ignore[attr-defined, no-any-return] |
255 | 292 |
|
256 | | - async def download(self, resource_id: str) -> FileModel: |
257 | | - """Download the file for the given resource ID. |
258 | | -
|
259 | | - Args: |
260 | | - resource_id: Resource ID. |
261 | | -
|
262 | | - Returns: |
263 | | - File model containing the downloaded file. |
264 | | - """ |
265 | | - response = await self._resource_do_request( # type: ignore[attr-defined] |
266 | | - resource_id, method="GET", headers={"Accept": "*"} |
267 | | - ) |
268 | | - return FileModel(response) |
269 | | - |
270 | 293 |
|
271 | 294 | class AsyncCreateWithIconMixin[Model]: |
272 | 295 | """Create resource with icon mixin.""" |
|
0 commit comments