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

1from math import sqrt 

2from functools import lru_cache 

3from typing import Sequence, Tuple, TYPE_CHECKING 

4 

5from .color_triplet import ColorTriplet 

6 

7if TYPE_CHECKING: 

8 from pip._vendor.rich.table import Table 

9 

10 

11class Palette: 

12 """A palette of available colors.""" 

13 

14 def __init__(self, colors: Sequence[Tuple[int, int, int]]): 

15 self._colors = colors 

16 

17 def __getitem__(self, number: int) -> ColorTriplet: 

18 return ColorTriplet(*self._colors[number]) 

19 

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 

25 

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 

42 

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. 

47 

48 Args: 

49 color (Tuple[int, int, int]): RGB components in range 0 > 255. 

50 

51 Returns: 

52 int: Index of closes matching color. 

53 """ 

54 red1, green1, blue1 = color 

55 _sqrt = sqrt 

56 get_color = self._colors.__getitem__ 

57 

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 ) 

70 

71 min_index = min(range(len(self._colors)), key=get_color_distance) 

72 return min_index 

73 

74 

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 

82 

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() 

98 

99 console = Console() 

100 console.print(ColorBox())