1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
from typing import Literal, Union
UNITS = {
"m": 0.001,
"Ki": 1024,
"Mi": 1024**2,
"Gi": 1024**3,
"Ti": 1024**4,
"Pi": 1024**5,
"Ei": 1024**6,
"k": 1e3,
"M": 1e6,
"G": 1e9,
"T": 1e12,
"P": 1e15,
"E": 1e18,
}
def parse(x: str, /) -> Union[float, int]:
"""Converts a string to an integer with respect of units."""
for unit, multiplier in UNITS.items():
if x.endswith(unit):
return float(x[: -len(unit)]) * multiplier
if "." in x:
return float(x)
return int(x)
def get_base(x: str, /) -> Literal[1024, 1000]:
"""Returns the base of the unit."""
for unit, multiplier in UNITS.items():
if x.endswith(unit):
return 1024 if unit in ["Ki", "Mi", "Gi", "Ti", "Pi", "Ei"] else 1000
return 1000 if "." in x else 1024
def format(x: Union[float, int], /, *, base: Literal[1024, 1000] = 1024) -> str:
"""Converts an integer to a string with respect of units."""
if x < 1:
return f"{int(x*1000)}m"
if x < base:
return str(x)
units = ["", "K", "M", "G", "T", "P", "E"]
binary_units = ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei"]
x = int(x)
for i, unit in enumerate(binary_units if base == 1024 else units):
if x < base ** (i + 1) or i == len(units) - 1 or x / base ** (i + 1) < 10:
return f"{x/base**i:.0f}{unit}"
return f"{x/6**i:.0f}{unit}"
|