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 56 57 58 59
|
"""Utility functions."""
import io
import os
from typing import Any, Iterable, Iterator, TypeVar
T = TypeVar("T")
def grouped(iterable: Iterable[T], n: int) -> Iterator[Iterable[T]]:
"""Groups values of an iterable into equally sized groups.
The values of iterable are collected into groups of size `n`.
An iterator over the resulting groups is returned.
Example:
Grouping a list of integers::
>>> list(grouped([1, 2, 3, 4, 5, 6], 2))
[(1, 2), (3, 4), (5, 6)]
Args:
iterable: Iterable over the values to group
n: Size of each group
Returns:
An iterator over the groups
"""
return zip(*([iter(iterable)] * n), strict=True)
N = TypeVar("N", bound=int | float)
def clamp(n: N, minimum: N, maximum: N) -> N:
"""Constrains a value to lie between two further values.
Args:
n: The value to constrain.
minimum: The manimum value n may have.
maximum: The maximum value n may have.
Returns:
The constrained value.
"""
return max(min(n, maximum), minimum)
StrOrBytesPath = str | bytes | os.PathLike[str] | os.PathLike[bytes]
def is_non_seekable_stream(stream: Any) -> bool:
if not isinstance(stream, io.IOBase) or not hasattr(stream, "seekable"):
return False
try:
return not stream.seekable()
except Exception:
return False
|