diff --git a/invenio_communities/errors.py b/invenio_communities/errors.py index 3c8d985af..7f5a4f49c 100644 --- a/invenio_communities/errors.py +++ b/invenio_communities/errors.py @@ -12,6 +12,8 @@ from flask_babel import ngettext from invenio_i18n import gettext as _ +from .utils import humanize_byte_size + class CommunityError(Exception): """Base exception for community errors.""" @@ -44,10 +46,15 @@ class LogoSizeLimitError(CommunityError): def __init__(self, limit, file_size): """Initialise error.""" + limit_value, limit_unit = humanize_byte_size(limit) + file_size_value, file_size_unit = humanize_byte_size(file_size) super().__init__( _( - "Logo size limit exceeded. Limit: {limit} bytes Given: {file_size} bytes".format( - limit=ceil(limit), file_size=ceil(file_size) + "Logo size limit exceeded. Limit: {limit_value} {limit_unit} Given: {file_size_value} {file_size_unit}".format( + limit_value=limit_value, + limit_unit=limit_unit, + file_size_value=file_size_value, + file_size_unit=file_size_unit, ) ) ) diff --git a/invenio_communities/utils.py b/invenio_communities/utils.py index 0d4a7dddd..0258d4c80 100644 --- a/invenio_communities/utils.py +++ b/invenio_communities/utils.py @@ -8,6 +8,8 @@ """Utilities.""" +from decimal import ROUND_HALF_UP, Decimal + from flask import session from flask_principal import Identity from invenio_accounts.models import Role @@ -109,3 +111,14 @@ def on_datastore_post_commit(sender, session): users = role.users.all() for user in users: on_user_membership_change(Identity(user.id)) + + +def humanize_byte_size(size): + """Converts bytes to largest unit (e.g., KB, MB, GB).""" + BYTES_PER_UNIT = 1000 + s = Decimal(size) + q = Decimal("0.00") + for unit in ["B", "KB", "MB", "GB", "TB", "PB"]: + if s < BYTES_PER_UNIT: + return s.quantize(q, rounding=ROUND_HALF_UP), unit + s /= BYTES_PER_UNIT diff --git a/tests/communities/test_resources.py b/tests/communities/test_resources.py index 07059cf61..df32263d9 100644 --- a/tests/communities/test_resources.py +++ b/tests/communities/test_resources.py @@ -689,6 +689,9 @@ def test_logo_max_content_length( data=BytesIO(logo_data), ) assert res.status_code == 400 + assert ( + res.json["message"] == "Logo size limit exceeded. Limit: 1.00 MB Given: 4.00 MB" + ) # Update logo with small content logo_data = b"logo"