From 6f7a2f1ce82a3625fdd425f7e18d5bd371011d3c Mon Sep 17 00:00:00 2001 From: Youri Westerman Date: Wed, 6 Nov 2024 14:54:00 +0100 Subject: [PATCH] Support downloading optimized attachments --- meldingen_core/actions/attachment.py | 18 ++++++++++++-- tests/test_actions/test_attachment.py | 36 +++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/meldingen_core/actions/attachment.py b/meldingen_core/actions/attachment.py index 1c0f466..ae6af90 100644 --- a/meldingen_core/actions/attachment.py +++ b/meldingen_core/actions/attachment.py @@ -1,4 +1,5 @@ from collections.abc import Collection +from enum import StrEnum from typing import AsyncIterator, Generic, TypeVar from uuid import uuid4 @@ -71,6 +72,11 @@ async def __call__( return attachment +class AttachmentTypes(StrEnum): + ORIGINAL = "original" + OPTIMIZED = "optimized" + + class DownloadAttachmentAction(Generic[A, A_co, M, M_co]): _verify_token: TokenVerifier[M, M_co] _attachment_repository: BaseAttachmentRepository[A, A_co] @@ -86,7 +92,9 @@ def __init__( self._attachment_repository = attachment_repository self._filesystem = filesystem - async def __call__(self, melding_id: int, attachment_id: int, token: str) -> AsyncIterator[bytes]: + async def __call__( + self, melding_id: int, attachment_id: int, token: str, _type: AttachmentTypes + ) -> AsyncIterator[bytes]: melding = await self._verify_token(melding_id, token) attachment = await self._attachment_repository.retrieve(attachment_id) @@ -96,8 +104,14 @@ async def __call__(self, melding_id: int, attachment_id: int, token: str) -> Asy if attachment.melding != melding: raise NotFoundException(f"Melding with id {melding_id} does not have attachment with id {attachment_id}") + file_path = attachment.file_path + if _type == AttachmentTypes.OPTIMIZED: + if attachment.optimized_path is None: + raise NotFoundException("Optimized file not found") + file_path = attachment.optimized_path + try: - file = await self._filesystem.get_file(attachment.file_path) + file = await self._filesystem.get_file(file_path) return await file.get_iterator() except filesystem.NotFoundException as exception: raise NotFoundException("File not found") from exception diff --git a/tests/test_actions/test_attachment.py b/tests/test_actions/test_attachment.py index 6100af2..0892e3b 100644 --- a/tests/test_actions/test_attachment.py +++ b/tests/test_actions/test_attachment.py @@ -6,6 +6,7 @@ from plugfs.filesystem import File, Filesystem from meldingen_core.actions.attachment import ( + AttachmentTypes, DeleteAttachmentAction, DownloadAttachmentAction, ListAttachmentsAction, @@ -67,7 +68,7 @@ async def test_attachment_not_found(self) -> None: ) with pytest.raises(NotFoundException) as exception_info: - await action(123, 456, "supersecrettoken") + await action(123, 456, "supersecrettoken", AttachmentTypes.ORIGINAL) assert str(exception_info.value) == "Attachment not found" @@ -85,18 +86,20 @@ async def test_attachment_does_not_belong_to_melding(self) -> None: ) with pytest.raises(NotFoundException) as exception_info: - await action(123, 456, "supersecrettoken") + await action(123, 456, "supersecrettoken", AttachmentTypes.ORIGINAL) assert str(exception_info.value) == "Melding with id 123 does not have attachment with id 456" @pytest.mark.anyio - async def test_can_handle_attachment_download(self) -> None: + @pytest.mark.parametrize("_type", AttachmentTypes) + async def test_can_handle_attachment_download(self, _type: AttachmentTypes) -> None: melding = Melding(text="text") token_verifier = AsyncMock(TokenVerifier) token_verifier.return_value = melding attachment = Attachment("bla", melding) attachment.file_path = "/path/to/file.ext" + attachment.optimized_path = "/path/to/file-optimized.ext" attachment_repository = Mock(BaseAttachmentRepository) attachment_repository.retrieve.return_value = attachment @@ -107,7 +110,30 @@ async def test_can_handle_attachment_download(self) -> None: Mock(Filesystem), ) - await action(123, 456, "supersecrettoken") + await action(123, 456, "supersecrettoken", _type) + + @pytest.mark.anyio + async def test_optimized_path_none(self) -> None: + melding = Melding(text="text") + token_verifier = AsyncMock(TokenVerifier) + token_verifier.return_value = melding + + attachment = Attachment("bla", melding) + attachment.file_path = "/path/to/file.ext" + + attachment_repository = Mock(BaseAttachmentRepository) + attachment_repository.retrieve.return_value = attachment + + action: DownloadAttachmentAction[Attachment, Attachment, Melding, Melding] = DownloadAttachmentAction( + token_verifier, + attachment_repository, + Mock(Filesystem), + ) + + with pytest.raises(NotFoundException) as exception_info: + await action(123, 456, "supersecrettoken", AttachmentTypes.OPTIMIZED) + + assert str(exception_info.value) == "Optimized file not found" @pytest.mark.anyio async def test_file_not_found(self) -> None: @@ -134,7 +160,7 @@ async def test_file_not_found(self) -> None: ) with pytest.raises(NotFoundException) as exception_info: - await action(123, 456, "supersecrettoken") + await action(123, 456, "supersecrettoken", AttachmentTypes.ORIGINAL) assert str(exception_info.value) == "File not found"