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.
This commit is contained in:
Goffi 2021-05-05 15:37:33 +02:00
commit 4e36667134
3 changed files with 88 additions and 12 deletions

View file

@ -29,6 +29,7 @@ from sat.core import exceptions
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 @@ class FilePlugin:
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),

View file

@ -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 @@ class OrderedSet(collections.abc.MutableSet):
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}"

View file

@ -30,6 +30,7 @@ from sat_frontends.jp.constants import Const as C
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 @@ class ShareList(base.CommandBase):
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"""