From acb1a5e51e235d3a303a2b1ce29eb9f87fbf3958 Mon Sep 17 00:00:00 2001 From: zhengxie Date: Tue, 23 Feb 2016 17:20:02 +0800 Subject: [PATCH] Use GB instead of GiB in filesizeformat and quota calculation --- seahub/api2/views.py | 3 +- seahub/base/templatetags/seahub_tags.py | 41 ++++++++++++++++++- .../templates/snippets/space_and_traffic.html | 6 +-- .../templates/sysadmin/org_admin_table.html | 2 +- .../templates/sysadmin/sys_org_info_base.html | 3 +- .../templates/sysadmin/sys_org_info_user.html | 5 +-- .../sys_user_admin_ldap_imported.html | 7 +--- .../sysadmin/sys_useradmin_ldap.html | 7 +--- .../templates/sysadmin/useradmin_table.html | 4 +- seahub/templates/sysadmin/userinfo.html | 4 +- seahub/utils/file_size.py | 24 +++++++++++ seahub/utils/html.py | 8 ++++ seahub/views/sysadmin.py | 9 ++-- .../base/templatetags/test_seahub_tags.py | 11 ++++- tests/seahub/utils/test_file_size.py | 20 +++++++++ 15 files changed, 121 insertions(+), 33 deletions(-) create mode 100644 seahub/utils/file_size.py create mode 100644 seahub/utils/html.py create mode 100644 tests/seahub/utils/test_file_size.py diff --git a/seahub/api2/views.py b/seahub/api2/views.py index ad8bdf1a1f..454407db82 100644 --- a/seahub/api2/views.py +++ b/seahub/api2/views.py @@ -75,6 +75,7 @@ from seahub.utils import gen_file_get_url, gen_token, gen_file_upload_url, \ from seahub.utils.repo import get_sub_repo_abbrev_origin_path from seahub.utils.star import star_file, unstar_file from seahub.utils.file_types import IMAGE, DOCUMENT +from seahub.utils.file_size import get_file_size_unit from seahub.utils.timeutils import utc_to_local from seahub.views import validate_owner, is_registered_user, check_file_lock, \ group_events_data, get_diff, create_default_library, get_owned_repo_list, \ @@ -4585,7 +4586,7 @@ class OrganizationView(APIView): OrgMemberQuota.objects.set_quota(new_org.org_id, member_limit) # set quota - quota = quota_mb * (1 << 20) + quota = quota_mb * get_file_size_unit('MB') seafserv_threaded_rpc.set_org_quota(new_org.org_id, quota) return Response('success', status=status.HTTP_201_CREATED) diff --git a/seahub/base/templatetags/seahub_tags.py b/seahub/base/templatetags/seahub_tags.py index 0a76de8174..1ec1e3a856 100644 --- a/seahub/base/templatetags/seahub_tags.py +++ b/seahub/base/templatetags/seahub_tags.py @@ -7,10 +7,10 @@ import time from django import template from django.core.cache import cache from django.utils.safestring import mark_safe -from django.utils import translation +from django.utils import translation, formats from django.utils.dateformat import DateFormat from django.utils.translation import ugettext as _ -from django.utils.translation import ungettext +from django.utils.translation import ugettext, ungettext from django.utils.translation import pgettext from django.utils.html import escape @@ -22,6 +22,8 @@ from seahub.cconvert import CConvert from seahub.po import TRANSLATION_MAP from seahub.shortcuts import get_first_object_or_none from seahub.utils import normalize_cache_key, CMMT_DESC_PATT +from seahub.utils.html import avoid_wrapping +from seahub.utils.file_size import get_file_size_unit register = template.Library() @@ -468,3 +470,38 @@ def trim(value, length): @register.filter(name='strip_slash') def strip_slash(value): return value.strip('/') + +@register.filter(is_safe=True) +def seahub_filesizeformat(bytes): + """ + Formats the value like a 'human-readable' file size (i.e. 13 KB, 4.1 MB, + 102 bytes, etc). + """ + try: + bytes = float(bytes) + except (TypeError, ValueError, UnicodeDecodeError): + value = ungettext("%(size)d byte", "%(size)d bytes", 0) % {'size': 0} + return avoid_wrapping(value) + + filesize_number_format = lambda value: formats.number_format(round(value, 1), 1) + + KB = get_file_size_unit('KB') + MB = get_file_size_unit('MB') + GB = get_file_size_unit('GB') + TB = get_file_size_unit('TB') + PB = get_file_size_unit('PB') + + if bytes < KB: + value = ungettext("%(size)d byte", "%(size)d bytes", bytes) % {'size': bytes} + elif bytes < MB: + value = ugettext("%s KB") % filesize_number_format(bytes / KB) + elif bytes < GB: + value = ugettext("%s MB") % filesize_number_format(bytes / MB) + elif bytes < TB: + value = ugettext("%s GB") % filesize_number_format(bytes / GB) + elif bytes < PB: + value = ugettext("%s TB") % filesize_number_format(bytes / TB) + else: + value = ugettext("%s PB") % filesize_number_format(bytes / PB) + + return avoid_wrapping(value) diff --git a/seahub/templates/snippets/space_and_traffic.html b/seahub/templates/snippets/space_and_traffic.html index 0d0a6d949f..e0b15f4b8e 100644 --- a/seahub/templates/snippets/space_and_traffic.html +++ b/seahub/templates/snippets/space_and_traffic.html @@ -1,10 +1,10 @@ -{% load i18n %} +{% load seahub_tags i18n %}
-

{% trans "Used:" %} {{ space_usage|filesizeformat }} {% if space_quota > 0 %}/ {{ space_quota|filesizeformat }} {% endif %}

+

{% trans "Used:" %} {{ space_usage|seahub_filesizeformat }} {% if space_quota > 0 %}/ {{ space_quota|seahub_filesizeformat }} {% endif %}

{% if not org %} {% if CALC_SHARE_USAGE %} -

{% trans "Sharing:" %} {{ share_usage|filesizeformat }} {% if share_quota > 0 %}/ {{ share_quota|filesizeformat }} {% endif %}

+

{% trans "Sharing:" %} {{ share_usage|seahub_filesizeformat }} {% if share_quota > 0 %}/ {{ share_quota|seahub_filesizeformat }} {% endif %}

{% endif %} {% endif %} diff --git a/seahub/templates/sysadmin/org_admin_table.html b/seahub/templates/sysadmin/org_admin_table.html index 74aaa0ace9..33945fa148 100644 --- a/seahub/templates/sysadmin/org_admin_table.html +++ b/seahub/templates/sysadmin/org_admin_table.html @@ -17,7 +17,7 @@ {{ org.creator }} - {{ org.quota_usage|filesizeformat }} {% if org.total_quota > 0 %} / {{ org.total_quota|filesizeformat }} {% endif %} + {{ org.quota_usage|seahub_filesizeformat }} {% if org.total_quota > 0 %} / {{ org.total_quota|seahub_filesizeformat }} {% endif %} {{ org.ctime|tsstr_sec }}
{% if org.expiration %}{{ org.expiration|date:'Y-m-d H:i:s' }}{% else %}--{% endif %} diff --git a/seahub/templates/sysadmin/sys_org_info_base.html b/seahub/templates/sysadmin/sys_org_info_base.html index 76d9e4bdf3..04d926a502 100644 --- a/seahub/templates/sysadmin/sys_org_info_base.html +++ b/seahub/templates/sysadmin/sys_org_info_base.html @@ -1,6 +1,5 @@ {% extends "admin_base.html" %} {% load i18n seahub_tags %} -{% load url from future %} {% block nav_orgadmin_class %}class="cur"{% endblock %} @@ -25,7 +24,7 @@

{% trans "Space Used" %}

-

{{ quota_usage|filesizeformat }} {% if total_quota > 0 %}/ {{ total_quota|filesizeformat }} {% endif %}

+

{{ quota_usage|seahub_filesizeformat }} {% if total_quota > 0 %}/ {{ total_quota|seahub_filesizeformat }} {% endif %}

{% trans "Set Quota" %}
{% csrf_token %} diff --git a/seahub/templates/sysadmin/sys_org_info_user.html b/seahub/templates/sysadmin/sys_org_info_user.html index 296158864f..7878802861 100644 --- a/seahub/templates/sysadmin/sys_org_info_user.html +++ b/seahub/templates/sysadmin/sys_org_info_user.html @@ -1,6 +1,5 @@ {% extends "sysadmin/sys_org_info_base.html" %} {% load i18n seahub_tags %} -{% load url from future %} {% block right_panel %}
@@ -40,9 +39,9 @@ {% if CALC_SHARE_USAGE %} - {{ user.self_usage|filesizeformat }} + {{ user.share_usage|filesizeformat }} {% if user.quota > 0 %} / {{ user.quota|filesizeformat }} {% endif %} + {{ user.self_usage|seahub_filesizeformat }} + {{ user.share_usage|seahub_filesizeformat }} {% if user.quota > 0 %} / {{ user.quota|seahub_filesizeformat }} {% endif %} {% else %} - {{ user.self_usage|filesizeformat }} {% if user.quota > 0 %} / {{ user.quota|filesizeformat }} {% endif %} + {{ user.self_usage|seahub_filesizeformat }} {% if user.quota > 0 %} / {{ user.quota|seahub_filesizeformat }} {% endif %} {% endif %} diff --git a/seahub/templates/sysadmin/sys_user_admin_ldap_imported.html b/seahub/templates/sysadmin/sys_user_admin_ldap_imported.html index 84055a286d..3b9801553e 100644 --- a/seahub/templates/sysadmin/sys_user_admin_ldap_imported.html +++ b/seahub/templates/sysadmin/sys_user_admin_ldap_imported.html @@ -49,12 +49,7 @@ -

{{ user.space_usage|filesizeformat }} {% if user.space_quota > 0 %} / {{ user.space_quota|filesizeformat }} {% endif %}

- {% if not user.org %} - {% if CALC_SHARE_USAGE %} -

{{ user.share_usage|filesizeformat }} {% if user.share_quota > 0 %} / {{ user.share_quota|filesizeformat }} {% endif %}

- {% endif %} - {% endif %} +

{{ user.space_usage|seahub_filesizeformat }} {% if user.space_quota > 0 %} / {{ user.space_quota|seahub_filesizeformat }} {% endif %}

{% if user.last_login %}{{user.last_login|translate_seahub_time}} {% else %} -- {% endif %} diff --git a/seahub/templates/sysadmin/sys_useradmin_ldap.html b/seahub/templates/sysadmin/sys_useradmin_ldap.html index 33ef91e224..2a49d5f0ca 100644 --- a/seahub/templates/sysadmin/sys_useradmin_ldap.html +++ b/seahub/templates/sysadmin/sys_useradmin_ldap.html @@ -32,12 +32,7 @@ -- / {% if user.last_login %}{{user.last_login|translate_seahub_time}} {% else %} -- {% endif %} -

{{ user.space_usage|filesizeformat }} {% if user.space_quota > 0 %} / {{ user.space_quota|filesizeformat }} {% endif %}

- {% if not user.org %} - {% if CALC_SHARE_USAGE %} -

{{ user.share_usage|filesizeformat }} {% if user.share_quota > 0 %} / {{ user.share_quota|filesizeformat }} {% endif %}

- {% endif %} - {% endif %} +

{{ user.space_usage|seahub_filesizeformat }} {% if user.space_quota > 0 %} / {{ user.space_quota|seahub_filesizeformat }} {% endif %}

{% endfor %} diff --git a/seahub/templates/sysadmin/useradmin_table.html b/seahub/templates/sysadmin/useradmin_table.html index 8d7c376906..0b661198b0 100644 --- a/seahub/templates/sysadmin/useradmin_table.html +++ b/seahub/templates/sysadmin/useradmin_table.html @@ -62,10 +62,10 @@ {% endif %} -

{{ user.space_usage|filesizeformat }} {% if user.space_quota > 0 %} / {{ user.space_quota|filesizeformat }} {% endif %}

+

{{ user.space_usage|seahub_filesizeformat }} {% if user.space_quota > 0 %} / {{ user.space_quota|seahub_filesizeformat }} {% endif %}

{% if not user.org %} {% if CALC_SHARE_USAGE %} -

{{ user.share_usage|filesizeformat }} {% if user.share_quota > 0 %} / {{ user.share_quota|filesizeformat }} {% endif %}

+

{{ user.share_usage|seahub_filesizeformat }} {% if user.share_quota > 0 %} / {{ user.share_quota|seahub_filesizeformat }} {% endif %}

{% endif %} {% endif %} diff --git a/seahub/templates/sysadmin/userinfo.html b/seahub/templates/sysadmin/userinfo.html index 935b461e74..b80cc4d2db 100644 --- a/seahub/templates/sysadmin/userinfo.html +++ b/seahub/templates/sysadmin/userinfo.html @@ -43,10 +43,10 @@

{% trans "Space Used" %}

-

{% trans "Used" %}: {{ space_usage|filesizeformat }} {% if space_quota > 0 %} / {{ space_quota|filesizeformat }} {% endif %}

+

{% trans "Used" %}: {{ space_usage|seahub_filesizeformat }} {% if space_quota > 0 %} / {{ space_quota|seahub_filesizeformat }} {% endif %}

{% if CALC_SHARE_USAGE %} -

{% trans "Sharing" %}: {{ share_usage|filesizeformat }} {% if share_quota > 0 %} / {{ share_quota|filesizeformat }} {% endif %}

+

{% trans "Sharing" %}: {{ share_usage|seahub_filesizeformat }} {% if share_quota > 0 %} / {{ share_quota|seahub_filesizeformat }} {% endif %}

{% endif %} {% trans "Set Quota" %} diff --git a/seahub/utils/file_size.py b/seahub/utils/file_size.py new file mode 100644 index 0000000000..406c6f437d --- /dev/null +++ b/seahub/utils/file_size.py @@ -0,0 +1,24 @@ +def get_file_size_unit(unit_type): + """ + File size unit according to https://en.wikipedia.org/wiki/Kibibyte. + """ + table = { + # decimal + 'kb': 10 ** 3, + 'mb': 10 ** 6, + 'gb': 10 ** 9, + 'tb': 10 ** 12, + 'pb': 10 ** 15, + # binary + 'kib': 1 << 10, + 'mib': 1 << 20, + 'gib': 1 << 30, + 'tib': 1 << 40, + 'pib': 1 << 50, + } + + unit_type = unit_type.lower() + if unit_type not in table.keys(): + raise TypeError('Invalid unit type') + + return table.get(unit_type) diff --git a/seahub/utils/html.py b/seahub/utils/html.py new file mode 100644 index 0000000000..0ca7147a76 --- /dev/null +++ b/seahub/utils/html.py @@ -0,0 +1,8 @@ +from __future__ import unicode_literals + +def avoid_wrapping(value): + """ + Avoid text wrapping in the middle of a phrase by adding non-breaking + spaces where there previously were normal spaces. + """ + return value.replace(" ", "\xa0") diff --git a/seahub/views/sysadmin.py b/seahub/views/sysadmin.py index a2e02afe1e..4e2a0ea4de 100644 --- a/seahub/views/sysadmin.py +++ b/seahub/views/sysadmin.py @@ -38,6 +38,7 @@ from seahub.utils import IS_EMAIL_CONFIGURED, string2list, is_valid_username, \ is_pro_version, send_html_email, get_user_traffic_list, get_server_id, \ clear_token, gen_file_get_url, is_org_context, handle_virus_record, \ get_virus_record_by_id, get_virus_record +from seahub.utils.file_size import get_file_size_unit from seahub.utils.rpc import mute_seafile_api from seahub.utils.licenseparse import parse_license from seahub.utils.sysinfo import get_platform_name @@ -966,12 +967,12 @@ def user_set_quota(request, email): if f.is_valid(): email = f.cleaned_data['email'] space_quota_mb = f.cleaned_data['space_quota'] - space_quota = space_quota_mb * (1 << 20) + space_quota = space_quota_mb * get_file_size_unit('MB') share_quota_mb = f.cleaned_data['share_quota'] share_quota = None if share_quota_mb is not None: - share_quota = share_quota_mb * (1 << 20) + share_quota = share_quota_mb * get_file_size_unit('MB') org = ccnet_threaded_rpc.get_orgs_by_user(email) try: @@ -981,7 +982,7 @@ def user_set_quota(request, email): seafile_api.set_user_share_quota(email, share_quota) else: org_id = org[0].org_id - org_quota_mb = seafserv_threaded_rpc.get_org_quota(org_id) / (1 << 20) + org_quota_mb = seafserv_threaded_rpc.get_org_quota(org_id) / get_file_size_unit('MB') if space_quota_mb > org_quota_mb: result['error'] = _(u'Failed to set quota: maximum quota is %d MB' % \ org_quota_mb) @@ -1009,7 +1010,7 @@ def sys_org_set_quota(request, org_id): org_id = int(org_id) quota_mb = int(request.POST.get('quota', 0)) - quota = quota_mb * (1 << 20) + quota = quota_mb * get_file_size_unit('MB') try: seafserv_threaded_rpc.set_org_quota(org_id, quota) diff --git a/tests/seahub/base/templatetags/test_seahub_tags.py b/tests/seahub/base/templatetags/test_seahub_tags.py index f78389b647..e1de35fc3c 100644 --- a/tests/seahub/base/templatetags/test_seahub_tags.py +++ b/tests/seahub/base/templatetags/test_seahub_tags.py @@ -1,6 +1,7 @@ from seahub.test_utils import BaseTestCase -from seahub.base.templatetags.seahub_tags import email2nickname +from seahub.base.templatetags.seahub_tags import email2nickname, \ + seahub_filesizeformat from seahub.profile.models import Profile @@ -30,3 +31,11 @@ class Email2nicknameTest(BaseTestCase): assert Profile.objects.all()[0].nickname == ' foo bar ' assert email2nickname(self.user.username) == 'foo bar' + + +class SeahubFilesizeformatTest(BaseTestCase): + def test_seahub_filesizeformat(self): + assert seahub_filesizeformat(1) == u'1\xa0byte' + assert seahub_filesizeformat(1000) == u'1.0\xa0KB' + assert seahub_filesizeformat(1000000) == u'1.0\xa0MB' + assert seahub_filesizeformat(1000000000) == u'1.0\xa0GB' diff --git a/tests/seahub/utils/test_file_size.py b/tests/seahub/utils/test_file_size.py new file mode 100644 index 0000000000..4c52c690aa --- /dev/null +++ b/tests/seahub/utils/test_file_size.py @@ -0,0 +1,20 @@ +from seahub.test_utils import BaseTestCase +from seahub.utils.file_size import get_file_size_unit + +class GetFileSizeUnitTest(BaseTestCase): + def test_invalid_type(self): + with self.assertRaises(TypeError): + get_file_size_unit('ff') + + def test_valid_type(self): + assert get_file_size_unit('KB') == 1000 ** 1 + assert get_file_size_unit('MB') == 1000 ** 2 + assert get_file_size_unit('GB') == 1000 ** 3 + assert get_file_size_unit('TB') == 1000 ** 4 + assert get_file_size_unit('PB') == 1000 ** 5 + + assert get_file_size_unit('KiB') == 1024 ** 1 + assert get_file_size_unit('MiB') == 1024 ** 2 + assert get_file_size_unit('GiB') == 1024 ** 3 + assert get_file_size_unit('TiB') == 1024 ** 4 + assert get_file_size_unit('PiB') == 1024 ** 5