Coverage for /run/media/veganeco/water/status600.com/pypi/reptilian_climates/modules_series_2/ships/fields/gardens_pip/rich/measure.py: 34%

1 from operator import itemgetter

2 from typing import TYPE_CHECKING, Callable, NamedTuple, Optional, Sequence

3

4 from . import errors

5 from .protocol import is_renderable, rich_cast

6

7 if TYPE_CHECKING:

8 from .console import Console, ConsoleOptions, RenderableType

9

10

11 class Measurement(NamedTuple):

12 """Stores the minimum and maximum widths (in characters) required to render an object."""

13

14 minimum: int

15 """Minimum number of cells required to render."""

16 maximum: int

17 """Maximum number of cells required to render."""

18

19 @property

20 def span(self) -> int:

21 """Get difference between maximum and minimum."""

22 return self.maximum - self.minimum

23

24 def normalize(self) -> "Measurement":

25 """Get measurement that ensures that minimum <= maximum and minimum >= 0

26

27 Returns:

28 Measurement: A normalized measurement.

29 """

30 minimum, maximum = self

31 minimum = min(max(0, minimum), maximum)

32 return Measurement(max(0, minimum), max(0, max(minimum, maximum)))

33

34 def with_maximum(self, width: int) -> "Measurement":

35 """Get a RenderableWith where the widths are <= width.

36

37 Args:

38 width (int): Maximum desired width.

39

40 Returns:

41 Measurement: New Measurement object.

42 """

43 minimum, maximum = self

44 return Measurement(min(minimum, width), min(maximum, width))

45

46 def with_minimum(self, width: int) -> "Measurement":

47 """Get a RenderableWith where the widths are >= width.

48

49 Args:

50 width (int): Minimum desired width.

51

52 Returns:

53 Measurement: New Measurement object.

54 """

55 minimum, maximum = self

56 width = max(0, width)

57 return Measurement(max(minimum, width), max(maximum, width))

58

59 def clamp(

60 self, min_width: Optional[int] = None, max_width: Optional[int] = None

61 ) -> "Measurement":

62 """Clamp a measurement within the specified range.

63

64 Args:

65 min_width (int): Minimum desired width, or ``None`` for no minimum. Defaults to None.

66 max_width (int): Maximum desired width, or ``None`` for no maximum. Defaults to None.

67

68 Returns:

69 Measurement: New Measurement object.

70 """

71 measurement = self

72 if min_width is not None:

73 measurement = measurement.with_minimum(min_width)

74 if max_width is not None:

75 measurement = measurement.with_maximum(max_width)

76 return measurement

77

78 @classmethod

79 def get(

80 cls, console: "Console", options: "ConsoleOptions", renderable: "RenderableType"

81 ) -> "Measurement":

82 """Get a measurement for a renderable.

83

84 Args:

85 console (~rich.console.Console): Console instance.

86 options (~rich.console.ConsoleOptions): Console options.

87 renderable (RenderableType): An object that may be rendered with Rich.

88

89 Raises:

90 errors.NotRenderableError: If the object is not renderable.

91

92 Returns:

93 Measurement: Measurement object containing range of character widths required to render the object.

94 """

95 _max_width = options.max_width

96 if _max_width < 1:

97 return Measurement(0, 0)

98 if isinstance(renderable, str):

99 renderable = console.render_str(

100 renderable, markup=options.markup, highlight=False

101 )

102 renderable = rich_cast(renderable)

103 if is_renderable(renderable):

104 get_console_width: Optional[

105 Callable[["Console", "ConsoleOptions"], "Measurement"]

106 ] = getattr(renderable, "__rich_measure__", None)

107 if get_console_width is not None:

108 render_width = (

109 get_console_width(console, options)

110 .normalize()

111 .with_maximum(_max_width)

112 )

113 if render_width.maximum < 1:

114 return Measurement(0, 0)

115 return render_width.normalize()

116 else:

117 return Measurement(0, _max_width)

118 else:

119 raise errors.NotRenderableError(

120 f"Unable to get render width for {renderable!r}; "

121 "a str, Segment, or object with __rich_console__ method is required"

122 )

123

124

125 def measure_renderables(

126 console: "Console",

127 options: "ConsoleOptions",

128 renderables: Sequence["RenderableType"],

129) -> "Measurement":

130 """Get a measurement that would fit a number of renderables.

131

132 Args:

133 console (~rich.console.Console): Console instance.

134 options (~rich.console.ConsoleOptions): Console options.

135 renderables (Iterable[RenderableType]): One or more renderable objects.

136

137 Returns:

138 Measurement: Measurement object containing range of character widths required to

139 contain all given renderables.

140 """

141 if not renderables:

142 return Measurement(0, 0)

143 get_measurement = Measurement.get

144 measurements = [

145 get_measurement(console, options, renderable) for renderable in renderables

146 ]

147 measured_width = Measurement(

148 max(measurements, key=itemgetter(0)).minimum,

149 max(measurements, key=itemgetter(1)).maximum,

150 )

151 return measured_width