From 9e7b95d12a245bbfe0ecb7cf23e2a6aa0daa13cf Mon Sep 17 00:00:00 2001 From: Jacques Fize <4259846+jacquesfize@users.noreply.github.com> Date: Fri, 20 Dec 2024 17:10:15 +0100 Subject: [PATCH] feat(media): enable thumbnail generation with only the width or height parameter (#594) * fix(thumbnail, generation): now can use the thumbnail generation with only the width GET arg * feat(media, thumbnail): now route can be called with either height params or width * feat(test): increase backend test on the thumbnail generation route * update changelog + default value of height and width --- apptax/taxonomie/filemanager.py | 9 ++++++- apptax/taxonomie/routestmedias.py | 21 +++++++++++++--- apptax/tests/test_media.py | 42 +++++++++++++++++++++++++++---- docs/changelog.md | 3 ++- 4 files changed, 65 insertions(+), 10 deletions(-) diff --git a/apptax/taxonomie/filemanager.py b/apptax/taxonomie/filemanager.py index a04e7c8a..be12a347 100644 --- a/apptax/taxonomie/filemanager.py +++ b/apptax/taxonomie/filemanager.py @@ -94,10 +94,17 @@ def create_thumb(self, media, size, force=False, regenerate=False): # Get Image try: - img = self._get_image_object(media) + img: Image = self._get_image_object(media) except TaxhubError as e: return None + # If width only was given in the parameter (height <=> size[1] < 0) + if size[1] < 0: + size[1] = img.width / size[0] * img.height + # Same with height + if size[0] < 0: + size[0] = img.height / size[1] * img.width + # Création du thumbnail resizeImg = resize_thumbnail(img, (size[0], size[1], force)) # Sauvegarde de l'image diff --git a/apptax/taxonomie/routestmedias.py b/apptax/taxonomie/routestmedias.py index f8ae7bfb..b3bc5a6d 100644 --- a/apptax/taxonomie/routestmedias.py +++ b/apptax/taxonomie/routestmedias.py @@ -3,6 +3,7 @@ from pathlib import Path import os from flask import json, Blueprint, request, current_app, send_file, abort +from werkzeug.exceptions import Forbidden from .models import TMedias, BibTypesMedia @@ -10,6 +11,7 @@ from .filemanager import FILEMANAGER +DEFAULT_THUMBNAIL_SIZE = (300, 400) adresses = Blueprint("t_media", __name__) logger = logging.getLogger() @@ -84,9 +86,22 @@ def getThumbnail_tmedias(id_media): ) params = request.args - size = (300, 400) - if ("h" in params) or ("w" in params): - size = (int(params.get("h", -1)), int(params.get("w", -1))) + + size = DEFAULT_THUMBNAIL_SIZE + + height_params: str = params.get("h", None) + width_params: str = params.get("w", None) + + if (width_params and not width_params.isdigit()) or ( + height_params and not height_params.isdigit() + ): + raise Forbidden("Valeur de la hauteur ou largeur incorrecte: Un entier est attendu") + + if width_params: + size = (int(width_params), size[1]) + + if height_params: + size = (size[0], int(height_params)) force = False if ("force" in params) and (params.get("force") == "true"): diff --git a/apptax/tests/test_media.py b/apptax/tests/test_media.py index 69fb287a..907ff323 100644 --- a/apptax/tests/test_media.py +++ b/apptax/tests/test_media.py @@ -1,8 +1,9 @@ import json import os +from apptax.taxonomie.models import BibTypesMedia, TMedias import pytest -from flask import url_for, current_app +from flask import url_for, current_app, Response from apptax.database import db @@ -39,6 +40,21 @@ def user(): return u +@pytest.fixture +def media(): + test_dir_absolute_path = os.path.dirname(os.path.abspath(__file__)) + with db.session.begin_nested(): + media = TMedias( + titre="test", + chemin=os.path.join(test_dir_absolute_path, "assets", "coccinelle.jpg"), + is_public=True, + types=BibTypesMedia.query.first(), + ) + db.session.add(media) + db.session.commit() + return media + + @pytest.mark.usefixtures("client_class", "temporary_transaction") class TestAPIMedia: @@ -117,8 +133,24 @@ def test_get_tmedias(self): # id_media = json.loads(response.data)["id_media"] # self.get_thumbnail(id_media) - def get_thumbnail(self, id_media): - response = self.client.get( - url_for("t_media.getThumbnail_tmedias", id_media=id_media), + @pytest.mark.parametrize( + "get_params,expected_status_code", + [ + ({}, 200), + (dict(w=100), 200), + (dict(h=100), 200), + (dict(w=100, h=100), 200), + (dict(w=100, h=-1), 403), + (dict(w="a", h="b"), 403), + (dict(h="b"), 403), + ], + ) + def test_get_thumbnail(self, media, get_params, expected_status_code): + id_media = media.id_media + + response: Response = self.client.get( + url_for( + "t_media.getThumbnail_tmedias", id_media=id_media, **get_params, regenerate="true" + ), ) - assert response.status_code == 200 + assert response.status_code == expected_status_code diff --git a/docs/changelog.md b/docs/changelog.md index e58c7686..73e0c312 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -5,7 +5,8 @@ **🚀 Nouveautés** -- La limite du nombre de caractères du champs `source` des médias est levée (#592 par @jacquesfize, @amandine-sahl) +- La limite du nombre de caractères dans la colonne `source` des médias est levée (#595 par @jacquesfize,@amandine-sahl) +- Ajout de la possibilité sur la route `/thumbnail/` d'indiquer seulement la hauteur ou la largeur de la minitiature souhaitée (#594 par @jacquesfize) 2.1.0 (2024-12-06) ------------------