ByteSize: an exact, non-negative number of bytes (Effect's ByteSize).
A ByteSize is an int (Effect's branded bigint), so it compares,
hashes, prints and sorts as one; min / max keep the type. Decimal
units (kB, MB, ...) are powers of 1,000 and binary units (KiB,
MiB, ...) powers of 1,024::
size = byte_size.mebibytes(2) # 2097152
byte_size.from_string("1.5 kB") # 1500
byte_size.format(byte_size.bytes(1536)) # "1.5 KiB"Constructors raise ValueError for what is not a whole, non-negative
number of bytes; the from_* parsers give None instead. Arithmetic
that can leave the range (subtract, times, divide) gives
None too.
| Attribute | Type | Description |
|---|---|---|
ByteSize | = NewType('ByteSize', int) | |
zero | = ByteSize(0) | |
kilobytes | = _unit('kB') | |
megabytes | = _unit('MB') | |
gigabytes | = _unit('GB') | |
terabytes | = _unit('TB') | |
petabytes | = _unit('PB') | |
exabytes | = _unit('EB') | |
zettabytes | = _unit('ZB') | |
yottabytes | = _unit('YB') | |
ronnabytes | = _unit('RB') | |
quettabytes | = _unit('QB') | |
kibibytes | = _unit('KiB') | |
mebibytes | = _unit('MiB') | |
gibibytes | = _unit('GiB') | |
tebibytes | = _unit('TiB') | |
pebibytes | = _unit('PiB') | |
exbibytes | = _unit('EiB') | |
zebibytes | = _unit('ZiB') | |
yobibytes | = _unit('YiB') |
Functions#
bytes#
bytes(value) -> ByteSizevalue bytes. Raises ValueError when it is negative.
| Parameter | Type | Description |
|---|---|---|
value | int |
Returns ByteSize
def bytes(value: int) -> ByteSize:
"""``value`` bytes. Raises ``ValueError`` when it is negative."""
if value < 0:
raise _invalid(f"expected a non-negative bigint, received {value}")
return ByteSize(value)from_string_unsafe#
from_string_unsafe(text) -> ByteSizeThe size text spells ("10 MB", "1.5KiB", "3 kilobytes").
Raises ValueError for other syntax, an unknown unit, or a size that
is not a whole number of bytes.
| Parameter | Type | Description |
|---|---|---|
text | str |
Returns ByteSize
def from_string_unsafe(text: str) -> ByteSize:
"""The size ``text`` spells (``"10 MB"``, ``"1.5KiB"``, ``"3 kilobytes"``).
Raises ``ValueError`` for other syntax, an unknown unit, or a size that
is not a whole number of bytes."""
match = _SYNTAX.fullmatch(text)
if match is None:
raise _invalid(f"unsupported syntax {_quote(text)}")
whole, fraction, unit = match.group(1), match.group(2) or "", match.group(3)
factor = _UNITS_BY_NAME.get(unit)
if factor is None:
raise _invalid(f"unsupported unit {_quote(unit)}")
numerator = int(whole + fraction) * factor
scale = 10 ** len(fraction)
if numerator % scale != 0:
raise _invalid(f"{_quote(text)} does not represent an integral number of bytes")
return ByteSize(numerator // scale)from_string#
from_string(text) -> ByteSize | Nonefrom_string_unsafe, with None in place of the error.
| Parameter | Type | Description |
|---|---|---|
text | str |
Returns ByteSize | None
def from_string(text: str) -> ByteSize | None:
"""``from_string_unsafe``, with ``None`` in place of the error."""
try:
return from_string_unsafe(text)
except ValueError:
return Nonefrom_input_unsafe#
from_input_unsafe(value) -> ByteSizeA size from an int, a safe-integer float or a string.
Raises ValueError for anything else or a negative size.
| Parameter | Type | Description |
|---|---|---|
value | Input |
Returns ByteSize
def from_input_unsafe(value: Input) -> ByteSize:
"""A size from an ``int``, a safe-integer ``float`` or a string.
Raises ``ValueError`` for anything else or a negative size."""
if isinstance(value, str):
return from_string_unsafe(value)
if isinstance(value, int):
return bytes(value)
whole = _safe_integer(value)
if whole is None or whole < 0:
raise _invalid(f"expected a non-negative safe integer, received {js_number(value)}")
return ByteSize(whole)from_input#
from_input(value) -> ByteSize | Nonefrom_input_unsafe, with None in place of the error.
| Parameter | Type | Description |
|---|---|---|
value | Input |
Returns ByteSize | None
def from_input(value: Input) -> ByteSize | None:
"""``from_input_unsafe``, with ``None`` in place of the error."""
try:
return from_input_unsafe(value)
except ValueError:
return Noneis_byte_size#
is_byte_size(value) -> TypeIs[ByteSize]value is a non-negative int (not a bool).
| Parameter | Type | Description |
|---|---|---|
value | object |
Returns TypeIs[ByteSize]
def is_byte_size(value: object) -> TypeIs[ByteSize]:
"""``value`` is a non-negative ``int`` (not a ``bool``)."""
return isinstance(value, int) and not isinstance(value, bool) and value >= 0is_zero#
is_zero(size) -> bool| Parameter | Type | Description |
|---|---|---|
size | ByteSize |
Returns bool
def is_zero(size: ByteSize) -> bool:
return size == 0to_unit#
to_unit(size, unit) -> floatsize in units, as a float (to_unit(kibibytes(3), "KiB")
is 3.0).
| Parameter | Type | Description |
|---|---|---|
size | ByteSize | |
unit | Unit |
Returns float
def to_unit(size: ByteSize, unit: Unit) -> float:
"""``size`` in ``unit``s, as a ``float`` (``to_unit(kibibytes(3), "KiB")``
is ``3.0``)."""
return float(size) / float(_FACTORS[unit])sum#
sum(size, that) -> ByteSizesize + that, still a ByteSize.
| Parameter | Type | Description |
|---|---|---|
size | ByteSize | |
that | ByteSize |
Returns ByteSize
def sum(size: ByteSize, that: ByteSize) -> ByteSize:
"""``size + that``, still a ``ByteSize``."""
return ByteSize(size + that)subtract#
subtract(size, that) -> ByteSize | Nonesize - that, or None when that is larger.
| Parameter | Type | Description |
|---|---|---|
size | ByteSize | |
that | ByteSize |
Returns ByteSize | None
def subtract(size: ByteSize, that: ByteSize) -> ByteSize | None:
"""``size - that``, or ``None`` when ``that`` is larger."""
return None if size < that else ByteSize(size - that)subtract_unsafe#
subtract_unsafe(size, that) -> ByteSizesize - that. Raises ValueError when that is larger.
| Parameter | Type | Description |
|---|---|---|
size | ByteSize | |
that | ByteSize |
Returns ByteSize
def subtract_unsafe(size: ByteSize, that: ByteSize) -> ByteSize:
"""``size - that``. Raises ``ValueError`` when ``that`` is larger."""
if size < that:
raise ValueError(f"ByteSize subtraction underflow: {size} - {that}")
return ByteSize(size - that)times#
times(size, multiplier) -> ByteSize | Nonesize * multiplier, or None unless multiplier is a
non-negative whole number.
| Parameter | Type | Description |
|---|---|---|
size | ByteSize | |
multiplier | float |
Returns ByteSize | None
def times(size: ByteSize, multiplier: float) -> ByteSize | None:
"""``size * multiplier``, or ``None`` unless ``multiplier`` is a
non-negative whole number."""
value = _scalar(multiplier, 0)
return None if value is None else ByteSize(size * value)divide#
divide(size, divisor) -> ByteSize | Nonesize // divisor, or None unless divisor is a positive
whole number.
| Parameter | Type | Description |
|---|---|---|
size | ByteSize | |
divisor | float |
Returns ByteSize | None
def divide(size: ByteSize, divisor: float) -> ByteSize | None:
"""``size // divisor``, or ``None`` unless ``divisor`` is a positive
whole number."""
value = _scalar(divisor, 1)
return None if value is None else ByteSize(size // value)format#
format(size, *, precision=2, trailing_zeros=False, system='binary', unit=None) -> strsize as text in the largest unit of system it fills
("1.5 KiB"), or in unit. precision (0 to 20) is the number of
decimals, rounded half up; trailing_zeros keeps zeros after the
point.
| Parameter | Type | Description |
|---|---|---|
size | ByteSize | |
precision | int = 2 | |
trailing_zeros | bool = False | |
system | Literal['binary', 'decimal'] = 'binary' | |
unit | Unit | None = None |
Returns str
def format(
size: ByteSize,
*,
precision: int = 2,
trailing_zeros: bool = False,
system: Literal["binary", "decimal"] = "binary",
unit: Unit | None = None,
) -> str:
"""``size`` as text in the largest unit of ``system`` it fills
(``"1.5 KiB"``), or in ``unit``. ``precision`` (0 to 20) is the number of
decimals, rounded half up; ``trailing_zeros`` keeps zeros after the
point."""
if not 0 <= precision <= 20:
raise ValueError(
f"ByteSize format precision must be an integer from 0 to 20, received {precision}"
)
if unit is not None:
return _format_with(size, unit, precision, trailing_zeros)
if size == 0:
return "0 B"
units = _DECIMAL if system == "decimal" else _BINARY
index = len(units) - 1
while index > 0 and size < units[index][1]:
index -= 1
if index < len(units) - 1:
scale = 10**precision
factor = units[index][1]
rounded = (size * scale * 2 + factor) // (factor * 2)
if rounded >= units[1][1] * scale:
index += 1
return _format_with(size, units[index][0], precision, trailing_zeros)