Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/rich/live_render.py: 31%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

52 statements  

1from typing import Literal, Optional, Tuple 

2 

3from ._loop import loop_last 

4from .console import Console, ConsoleOptions, RenderableType, RenderResult 

5from .control import Control 

6from .segment import ControlType, Segment 

7from .style import StyleType 

8from .text import Text 

9 

10VerticalOverflowMethod = Literal["crop", "ellipsis", "visible"] 

11 

12 

13class LiveRender: 

14 """Creates a renderable that may be updated. 

15 

16 Args: 

17 renderable (RenderableType): Any renderable object. 

18 style (StyleType, optional): An optional style to apply to the renderable. Defaults to "". 

19 """ 

20 

21 def __init__( 

22 self, 

23 renderable: RenderableType, 

24 style: StyleType = "", 

25 vertical_overflow: VerticalOverflowMethod = "ellipsis", 

26 ) -> None: 

27 self.renderable = renderable 

28 self.style = style 

29 self.vertical_overflow = vertical_overflow 

30 self._shape: Optional[Tuple[int, int]] = None 

31 

32 @property 

33 def last_render_height(self) -> int: 

34 """The number of lines in the last render (may be 0 if nothing was rendered). 

35 

36 Returns: 

37 Height in lines 

38 """ 

39 if self._shape is None: 

40 return 0 

41 return self._shape[1] 

42 

43 def set_renderable(self, renderable: RenderableType) -> None: 

44 """Set a new renderable. 

45 

46 Args: 

47 renderable (RenderableType): Any renderable object, including str. 

48 """ 

49 self.renderable = renderable 

50 

51 def position_cursor(self) -> Control: 

52 """Get control codes to move cursor to beginning of live render. 

53 

54 Returns: 

55 Control: A control instance that may be printed. 

56 """ 

57 if self._shape is not None: 

58 _, height = self._shape 

59 return Control( 

60 ControlType.CARRIAGE_RETURN, 

61 (ControlType.ERASE_IN_LINE, 2), 

62 *( 

63 ( 

64 (ControlType.CURSOR_UP, 1), 

65 (ControlType.ERASE_IN_LINE, 2), 

66 ) 

67 * (height - 1) 

68 ) 

69 ) 

70 return Control() 

71 

72 def restore_cursor(self) -> Control: 

73 """Get control codes to clear the render and restore the cursor to its previous position. 

74 

75 Returns: 

76 Control: A Control instance that may be printed. 

77 """ 

78 if self._shape is not None: 

79 _, height = self._shape 

80 return Control( 

81 ControlType.CARRIAGE_RETURN, 

82 *((ControlType.CURSOR_UP, 1), (ControlType.ERASE_IN_LINE, 2)) * height 

83 ) 

84 return Control() 

85 

86 def __rich_console__( 

87 self, console: Console, options: ConsoleOptions 

88 ) -> RenderResult: 

89 renderable = self.renderable 

90 style = console.get_style(self.style) 

91 lines = console.render_lines(renderable, options, style=style, pad=False) 

92 shape = Segment.get_shape(lines) 

93 

94 _, height = shape 

95 if height > options.size.height: 

96 if self.vertical_overflow == "crop": 

97 lines = lines[: options.size.height] 

98 shape = Segment.get_shape(lines) 

99 elif self.vertical_overflow == "ellipsis": 

100 lines = lines[: (options.size.height - 1)] 

101 overflow_text = Text( 

102 "...", 

103 overflow="crop", 

104 justify="center", 

105 end="", 

106 style="live.ellipsis", 

107 ) 

108 lines.append(list(console.render(overflow_text))) 

109 shape = Segment.get_shape(lines) 

110 self._shape = shape 

111 

112 new_line = Segment.line() 

113 for last, line in loop_last(lines): 

114 yield from line 

115 if not last: 

116 yield new_line