# HG changeset patch # User Goffi # Date 1620221853 -7200 # Node ID 5843794739257eaeb622e63744554d6cd5177a9d # Parent 30779935c0aaaed49806ba47f3e8acd774c7962c tools (common/utils): new methods to parse and generate file size with symbols: - `parseSize` lets parse a size which can be either a int, or a string with a symbol like `Mio` - `getSizeMultiplier` returns a tuple of size with it's multiplier symbol - `getHumanSize` returns a string with size and adapted multiplier. diff -r 30779935c0aa -r 584379473925 sat/plugins/plugin_misc_file.py --- a/sat/plugins/plugin_misc_file.py Wed May 05 15:37:21 2021 +0200 +++ b/sat/plugins/plugin_misc_file.py Wed May 05 15:37:33 2021 +0200 @@ -29,6 +29,7 @@ from sat.tools import xml_tools from sat.tools import stream from sat.tools import utils +from sat.tools.common import utils as common_utils log = getLogger(__name__) @@ -321,9 +322,7 @@ assert filename and not "/" in filename assert PROGRESS_ID_KEY in file_data # human readable size - file_data["size_human"] = "{:.6n} Mio".format( - float(file_data["size"]) / (1024 ** 2) - ) + file_data["size_human"] = common_utils.getHumanSize(file_data["size"]) d = xml_tools.deferDialog( self.host, _(CONFIRM).format(peer=peer_jid.full(), **file_data), diff -r 30779935c0aa -r 584379473925 sat/tools/common/utils.py --- a/sat/tools/common/utils.py Wed May 05 15:37:21 2021 +0200 +++ b/sat/tools/common/utils.py Wed May 05 15:37:33 2021 +0200 @@ -19,6 +19,42 @@ """Misc utils for both backend and frontends""" import collections.abc +size_units = { + "b": 1, + "kb": 1000, + "mb": 1000**2, + "gb": 1000**3, + "tb": 1000**4, + "pb": 1000**5, + "eb": 1000**6, + "zb": 1000**7, + "yb": 1000**8, + "o": 1, + "ko": 1000, + "mo": 1000**2, + "go": 1000**3, + "to": 1000**4, + "po": 1000**5, + "eo": 1000**6, + "zo": 1000**7, + "yo": 1000**8, + "kib": 1024, + "mib": 1024**2, + "gib": 1024**3, + "tib": 1024**4, + "pib": 1024**5, + "eib": 1024**6, + "zib": 1024**7, + "yib": 1024**8, + "kio": 1024, + "mio": 1024**2, + "gio": 1024**3, + "tio": 1024**4, + "pio": 1024**5, + "eio": 1024**6, + "zio": 1024**7, + "yio": 1024**8, +} def per_luminance(red, green, blue): @@ -73,3 +109,51 @@ def update(self, items): self._dict.update({i: None for i in items}) + + +def parseSize(size): + """Parse a file size with optional multiple symbole""" + try: + return int(size) + except ValueError: + number = [] + symbol = [] + try: + for c in size: + if c == " ": + continue + if c.isdigit(): + number.append(c) + elif c.isalpha(): + symbol.append(c) + else: + raise ValueError("unexpected char in size: {c!r} (size: {size!r})") + number = int("".join(number)) + symbol = "".join(symbol) + if symbol: + try: + multiplier = size_units[symbol.lower()] + except KeyError: + raise ValueError( + "unknown size multiplier symbole: {symbol!r} (size: {size!r})") + else: + return number * multiplier + return number + except Exception as e: + raise ValueError(f"invalid size: {e}") + + +def getSizeMultiplier(size, suffix="o"): + """Get multiplier of a file size""" + size = int(size) + #  cf. https://stackoverflow.com/a/1094933 (thanks) + for unit in ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]: + if abs(size) < 1024.0: + return size, f"{unit}{suffix}" + size /= 1024.0 + return size, f"Yi{suffix}" + + +def getHumanSize(size, suffix="o", sep=" "): + size, symbol = getSizeMultiplier(size, suffix) + return f"{size:.2f}{sep}{symbol}" diff -r 30779935c0aa -r 584379473925 sat_frontends/jp/cmd_file.py --- a/sat_frontends/jp/cmd_file.py Wed May 05 15:37:21 2021 +0200 +++ b/sat_frontends/jp/cmd_file.py Wed May 05 15:37:33 2021 +0200 @@ -30,6 +30,7 @@ from sat_frontends.jp import common from sat_frontends.tools import jid from sat.tools.common.ansi import ANSI as A +from sat.tools.common import utils from urllib.parse import urlparse from pathlib import Path import tempfile @@ -864,15 +865,7 @@ def _size_filter(self, size, row): if not size: return "" - size = int(size) - #  cf. https://stackoverflow.com/a/1094933 (thanks) - suffix = "o" - for unit in ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]: - if abs(size) < 1024.0: - return A.color(A.BOLD, "{:.2f}".format(size), unit, suffix) - size /= 1024.0 - - return A.color(A.BOLD, "{:.2f}".format(size), "Yi", suffix) + return A.color(A.BOLD, utils.getHumanSize(size)) def default_output(self, files_data): """display files a way similar to ls"""