diff --git a/src/humanize/filesize.py b/src/humanize/filesize.py index 13e5edd..977b01e 100644 --- a/src/humanize/filesize.py +++ b/src/humanize/filesize.py @@ -4,96 +4,75 @@ from math import log -suffixes = { +from humanize.i18n import gettext as _ + +_SUFFIXES = { "decimal": ( - " kB", - " MB", - " GB", - " TB", - " PB", - " EB", - " ZB", - " YB", - " RB", - " QB", + _(" kB"), + _(" MB"), + _(" GB"), + _(" TB"), + _(" PB"), + _(" EB"), + _(" ZB"), + _(" YB"), + _(" RB"), + _(" QB"), ), "binary": ( - " KiB", - " MiB", - " GiB", - " TiB", - " PiB", - " EiB", - " ZiB", - " YiB", - " RiB", - " QiB", + _(" KiB"), + _(" MiB"), + _(" GiB"), + _(" TiB"), + _(" PiB"), + _(" EiB"), + _(" ZiB"), + _(" YiB"), + _(" RiB"), + _(" QiB"), ), - "gnu": "KMGTPEZYRQ", } def naturalsize( value: float | str, binary: bool = False, - gnu: bool = False, format: str = "%.1f", ) -> str: - """Format a number of bytes like a human-readable filesize (e.g. 10 kB). - - By default, decimal suffixes (kB, MB) are used. - - Non-GNU modes are compatible with jinja2's `filesizeformat` filter. + """Format a number of bytes like a human-readable file size. Examples: - ```pycon - >>> naturalsize(3000000) - '3.0 MB' - >>> naturalsize(300, False, True) - '300B' - >>> naturalsize(3000, False, True) - '2.9K' - >>> naturalsize(3000, False, True, "%.3f") - '2.930K' - >>> naturalsize(3000, True) - '2.9 KiB' - >>> naturalsize(10**28) - '10.0 RB' - >>> naturalsize(10**34 * 3) - '30000.0 QB' - >>> naturalsize(-4096, True) - '-4.0 KiB' + >>> naturalsize(42) + '42 Bytes' + >>> naturalsize(42000) + '42.0 kB' + >>> naturalsize(42000000) + '42.0 MB' - ``` + When a locale is activated via ``humanize.i18n.activate()``, + the unit suffixes will be translated accordingly. - Args: - value (int, float, str): Integer to convert. - binary (bool): If `True`, uses binary suffixes (KiB, MiB) with base - 210 instead of 103. - gnu (bool): If `True`, the binary argument is ignored and GNU-style - (`ls -sh` style) prefixes are used (K, M) with the 2**10 definition. - format (str): Custom formatter. - - Returns: - str: Human readable representation of a filesize. + :param value: The number of bytes. + :param binary: Use binary (powers of 1024) units instead of decimal. + :param format: Numeric format string. + :return: Human-readable file size. """ - if gnu: - suffix = suffixes["gnu"] - elif binary: - suffix = suffixes["binary"] - else: - suffix = suffixes["decimal"] + try: + bytes_value = float(value) + except (TypeError, ValueError): + return str(value) + + if bytes_value == 1: + return _("1 Byte") + if bytes_value < 1024: + return _("%d Bytes") % bytes_value - base = 1024 if (gnu or binary) else 1000 - bytes_ = float(value) - abs_bytes = abs(bytes_) + base = 1024 if binary else 1000 + exp = int(log(bytes_value, base)) + exp = min(exp, len(_SUFFIXES["binary"]) if binary else len(_SUFFIXES["decimal"])) - if abs_bytes == 1 and not gnu: - return f"{int(bytes_)} Byte" + value = bytes_value / base**exp - if abs_bytes < base: - return f"{int(bytes_)}B" if gnu else f"{int(bytes_)} Bytes" + suffix = _SUFFIXES["binary"][exp - 1] if binary else _SUFFIXES["decimal"][exp - 1] - exp = int(min(log(abs_bytes, base), len(suffix))) - ret: str = format % (bytes_ / (base**exp)) + suffix[exp - 1] - return ret + return (format % value) + suffix diff --git a/src/humanize/locale/fr_FR/LC_MESSAGES/humanize.po b/src/humanize/locale/fr_FR/LC_MESSAGES/humanize.po index 6aae582..d0a07fb 100644 --- a/src/humanize/locale/fr_FR/LC_MESSAGES/humanize.po +++ b/src/humanize/locale/fr_FR/LC_MESSAGES/humanize.po @@ -363,3 +363,34 @@ msgstr "hier" #, python-format msgid "%s and %s" msgstr "%s et %s" + +# --- filesize units (naturalsize) --- +msgid "Byte" +msgstr "octet" + +msgid "Bytes" +msgstr "octets" + +msgid "kB" +msgstr "Ko" + +msgid "MB" +msgstr "Mo" + +msgid "GB" +msgstr "Go" + +msgid "TB" +msgstr "To" + +msgid "PB" +msgstr "Po" + +msgid "EB" +msgstr "Eo" + +msgid "ZB" +msgstr "Zo" + +msgid "YB" +msgstr "Yo"