File: _utils.py

package info (click to toggle)
textual-image 0.8.5-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 2,468 kB
  • sloc: python: 1,851; makefile: 2
file content (59 lines) | stat: -rw-r--r-- 1,410 bytes parent folder | download
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