Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pip/_vendor/rich/palette.py: 35%
34 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:48 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:48 +0000
1from math import sqrt
2from functools import lru_cache
3from typing import Sequence, Tuple, TYPE_CHECKING
5from .color_triplet import ColorTriplet
7if TYPE_CHECKING:
8 from pip._vendor.rich.table import Table
11class Palette:
12 """A palette of available colors."""
14 def __init__(self, colors: Sequence[Tuple[int, int, int]]):
15 self._colors = colors
17 def __getitem__(self, number: int) -> ColorTriplet:
18 return ColorTriplet(*self._colors[number])
20 def __rich__(self) -> "Table":
21 from pip._vendor.rich.color import Color
22 from pip._vendor.rich.style import Style
23 from pip._vendor.rich.text import Text
24 from pip._vendor.rich.table import Table
26 table = Table(
27 "index",
28 "RGB",
29 "Color",
30 title="Palette",
31 caption=f"{len(self._colors)} colors",
32 highlight=True,
33 caption_justify="right",
34 )
35 for index, color in enumerate(self._colors):
36 table.add_row(
37 str(index),
38 repr(color),
39 Text(" " * 16, style=Style(bgcolor=Color.from_rgb(*color))),
40 )
41 return table
43 # This is somewhat inefficient and needs caching
44 @lru_cache(maxsize=1024)
45 def match(self, color: Tuple[int, int, int]) -> int:
46 """Find a color from a palette that most closely matches a given color.
48 Args:
49 color (Tuple[int, int, int]): RGB components in range 0 > 255.
51 Returns:
52 int: Index of closes matching color.
53 """
54 red1, green1, blue1 = color
55 _sqrt = sqrt
56 get_color = self._colors.__getitem__
58 def get_color_distance(index: int) -> float:
59 """Get the distance to a color."""
60 red2, green2, blue2 = get_color(index)
61 red_mean = (red1 + red2) // 2
62 red = red1 - red2
63 green = green1 - green2
64 blue = blue1 - blue2
65 return _sqrt(
66 (((512 + red_mean) * red * red) >> 8)
67 + 4 * green * green
68 + (((767 - red_mean) * blue * blue) >> 8)
69 )
71 min_index = min(range(len(self._colors)), key=get_color_distance)
72 return min_index
75if __name__ == "__main__": # pragma: no cover
76 import colorsys
77 from typing import Iterable
78 from pip._vendor.rich.color import Color
79 from pip._vendor.rich.console import Console, ConsoleOptions
80 from pip._vendor.rich.segment import Segment
81 from pip._vendor.rich.style import Style
83 class ColorBox:
84 def __rich_console__(
85 self, console: Console, options: ConsoleOptions
86 ) -> Iterable[Segment]:
87 height = console.size.height - 3
88 for y in range(0, height):
89 for x in range(options.max_width):
90 h = x / options.max_width
91 l = y / (height + 1)
92 r1, g1, b1 = colorsys.hls_to_rgb(h, l, 1.0)
93 r2, g2, b2 = colorsys.hls_to_rgb(h, l + (1 / height / 2), 1.0)
94 bgcolor = Color.from_rgb(r1 * 255, g1 * 255, b1 * 255)
95 color = Color.from_rgb(r2 * 255, g2 * 255, b2 * 255)
96 yield Segment("▄", Style(color=color, bgcolor=bgcolor))
97 yield Segment.line()
99 console = Console()
100 console.print(ColorBox())