SUFFIX_TO_BYTES = {
"KI": 1024,
"MI": 1024**2,
"GI": 1024**3,
"TI": 1024**4,
"PI": 1024**5,
"EI": 1024**6,
"K": 1000,
"M": 1000**2,
"G": 1000**3,
"T": 1000**4,
"P": 1000**5,
"E": 1000**6,
}
[docs]class ByteSize:
"""Convert multiples of bytes to various units."""
[docs] def __init__(self, value):
"""
Represents a quantity of bytes.
`value` may be an integer, in which case it is assumed to be bytes.
If value is a string, it is parsed as bytes if no suffix (Mi, M, Gi, G ...)
is found.
>>> values = [128974848, '129e6', '129M', '123Mi' ]
>>> [ByteSize(v).to_unit('M') for v in values]
['128M', '129M', '129M', '128M']
"""
self.value = parse_bytesize(value)
[docs] def to_unit(self, unit=None, as_string=True):
"""unit must be `None` or one of Ki,Mi,Gi,Ti,Pi,Ei,K,M,G,T,P."""
if unit is None:
if as_string:
return str(self.value)
return self.value
unit = unit.upper()
new_value = int(self.value / SUFFIX_TO_BYTES[unit])
if not as_string:
return new_value
return f"{new_value}{unit}"
[docs]def parse_bytesize(value):
if isinstance(value, int) or isinstance(value, float):
# Assume bytes
return value
value = value.upper()
found_suffix = None
for suffix in SUFFIX_TO_BYTES:
if value.endswith(suffix):
found_suffix = suffix
break
if found_suffix:
value = value[: -len(found_suffix)]
try:
value = int(value)
except ValueError:
try:
value = float(value)
except ValueError:
raise ValueError(f"{value} is not a valid integer or float value")
if found_suffix:
value = value * SUFFIX_TO_BYTES[found_suffix]
return value