about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_ratio.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/pip/_vendor/rich/_ratio.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/pip/_vendor/rich/_ratio.py')
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/rich/_ratio.py159
1 files changed, 159 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_ratio.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_ratio.py
new file mode 100644
index 00000000..95267b0c
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/_ratio.py
@@ -0,0 +1,159 @@
+import sys
+from fractions import Fraction
+from math import ceil
+from typing import cast, List, Optional, Sequence
+
+if sys.version_info >= (3, 8):
+    from typing import Protocol
+else:
+    from pip._vendor.typing_extensions import Protocol  # pragma: no cover
+
+
+class Edge(Protocol):
+    """Any object that defines an edge (such as Layout)."""
+
+    size: Optional[int] = None
+    ratio: int = 1
+    minimum_size: int = 1
+
+
+def ratio_resolve(total: int, edges: Sequence[Edge]) -> List[int]:
+    """Divide total space to satisfy size, ratio, and minimum_size, constraints.
+
+    The returned list of integers should add up to total in most cases, unless it is
+    impossible to satisfy all the constraints. For instance, if there are two edges
+    with a minimum size of 20 each and `total` is 30 then the returned list will be
+    greater than total. In practice, this would mean that a Layout object would
+    clip the rows that would overflow the screen height.
+
+    Args:
+        total (int): Total number of characters.
+        edges (List[Edge]): Edges within total space.
+
+    Returns:
+        List[int]: Number of characters for each edge.
+    """
+    # Size of edge or None for yet to be determined
+    sizes = [(edge.size or None) for edge in edges]
+
+    _Fraction = Fraction
+
+    # While any edges haven't been calculated
+    while None in sizes:
+        # Get flexible edges and index to map these back on to sizes list
+        flexible_edges = [
+            (index, edge)
+            for index, (size, edge) in enumerate(zip(sizes, edges))
+            if size is None
+        ]
+        # Remaining space in total
+        remaining = total - sum(size or 0 for size in sizes)
+        if remaining <= 0:
+            # No room for flexible edges
+            return [
+                ((edge.minimum_size or 1) if size is None else size)
+                for size, edge in zip(sizes, edges)
+            ]
+        # Calculate number of characters in a ratio portion
+        portion = _Fraction(
+            remaining, sum((edge.ratio or 1) for _, edge in flexible_edges)
+        )
+
+        # If any edges will be less than their minimum, replace size with the minimum
+        for index, edge in flexible_edges:
+            if portion * edge.ratio <= edge.minimum_size:
+                sizes[index] = edge.minimum_size
+                # New fixed size will invalidate calculations, so we need to repeat the process
+                break
+        else:
+            # Distribute flexible space and compensate for rounding error
+            # Since edge sizes can only be integers we need to add the remainder
+            # to the following line
+            remainder = _Fraction(0)
+            for index, edge in flexible_edges:
+                size, remainder = divmod(portion * edge.ratio + remainder, 1)
+                sizes[index] = size
+            break
+    # Sizes now contains integers only
+    return cast(List[int], sizes)
+
+
+def ratio_reduce(
+    total: int, ratios: List[int], maximums: List[int], values: List[int]
+) -> List[int]:
+    """Divide an integer total in to parts based on ratios.
+
+    Args:
+        total (int): The total to divide.
+        ratios (List[int]): A list of integer ratios.
+        maximums (List[int]): List of maximums values for each slot.
+        values (List[int]): List of values
+
+    Returns:
+        List[int]: A list of integers guaranteed to sum to total.
+    """
+    ratios = [ratio if _max else 0 for ratio, _max in zip(ratios, maximums)]
+    total_ratio = sum(ratios)
+    if not total_ratio:
+        return values[:]
+    total_remaining = total
+    result: List[int] = []
+    append = result.append
+    for ratio, maximum, value in zip(ratios, maximums, values):
+        if ratio and total_ratio > 0:
+            distributed = min(maximum, round(ratio * total_remaining / total_ratio))
+            append(value - distributed)
+            total_remaining -= distributed
+            total_ratio -= ratio
+        else:
+            append(value)
+    return result
+
+
+def ratio_distribute(
+    total: int, ratios: List[int], minimums: Optional[List[int]] = None
+) -> List[int]:
+    """Distribute an integer total in to parts based on ratios.
+
+    Args:
+        total (int): The total to divide.
+        ratios (List[int]): A list of integer ratios.
+        minimums (List[int]): List of minimum values for each slot.
+
+    Returns:
+        List[int]: A list of integers guaranteed to sum to total.
+    """
+    if minimums:
+        ratios = [ratio if _min else 0 for ratio, _min in zip(ratios, minimums)]
+    total_ratio = sum(ratios)
+    assert total_ratio > 0, "Sum of ratios must be > 0"
+
+    total_remaining = total
+    distributed_total: List[int] = []
+    append = distributed_total.append
+    if minimums is None:
+        _minimums = [0] * len(ratios)
+    else:
+        _minimums = minimums
+    for ratio, minimum in zip(ratios, _minimums):
+        if total_ratio > 0:
+            distributed = max(minimum, ceil(ratio * total_remaining / total_ratio))
+        else:
+            distributed = total_remaining
+        append(distributed)
+        total_ratio -= ratio
+        total_remaining -= distributed
+    return distributed_total
+
+
+if __name__ == "__main__":
+    from dataclasses import dataclass
+
+    @dataclass
+    class E:
+        size: Optional[int] = None
+        ratio: int = 1
+        minimum_size: int = 1
+
+    resolved = ratio_resolve(110, [E(None, 1, 1), E(None, 1, 1), E(None, 1, 1)])
+    print(sum(resolved))