Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# (c) Stefan Countryman, 2019 

2 

3import sys 

4from time import sleep 

5import ipywidgets as widgets 

6from IPython.display import display 

7from pathlib import Path 

8from llama.utils import LOGDIR 

9 

10# docs at https://ipywidgets.readthedocs.io/en/latest/examples/Output%20Widget.html 

11 

12logs = Path(LOGDIR) 

13CONTINUE = [True] 

14READ_SIZE = 2000 

15 

16 

17def setup_tail_widgets(): 

18 logwidg = widgets.Select( 

19 options=[(x.name, x) for x in logs.iterdir() if x.is_file()], 

20 index=0, 

21 description="Log file:", 

22 disabled=False, 

23 ) 

24 lineswidg = widgets.IntText( 

25 value=10, 

26 description='Num lines:', 

27 disabled=False 

28 ) 

29 follow = widgets.Checkbox( 

30 value=True, 

31 description='Follow output', 

32 disabled=False 

33 ) 

34 submit = widgets.Button( 

35 description='Show log', 

36 disabled=False, 

37 button_style='', # 'success', 'info', 'warning', 'danger' or '' 

38 tooltip='Print the last "Num lines" lines of the selected logfile.', 

39 icon='', 

40 ) 

41 clear = widgets.Button( 

42 description='Clear output', 

43 disabled=False, 

44 button_style='', # 'success', 'info', 'warning', 'danger' or '' 

45 tooltip='Clear the output where logs have been printing.', 

46 icon='', 

47 ) 

48 #stop = widgets.Button( 

49 # description='Stop showing', 

50 # disabled=False, 

51 # button_style='', 

52 # tooltip='Stop printing logs', 

53 # icon='', 

54 #) 

55 output = widgets.Output(layout={'border': '2px solid green'}) 

56 

57 

58 def onclick(button): 

59 """Print the last ``lineswidg.value`` lines of ``logwidg.value`` and then 

60 keep reading more lines and printing them as they become available.""" 

61 CONTINUE[0] = True 

62 prevlines = lineswidg.value + 1 

63 logpath = logwidg.value 

64 with output: 

65 if prevlines < 0: 

66 print("Choose a value greater than 1 for Num lines.") 

67 return 

68 with logpath.open('rb') as f: 

69 # seek back till we find 

70 end = f.seek(0, 2) 

71 if end <= READ_SIZE: 

72 cursor = f.seek(0, 0) 

73 else: 

74 cursor = f.seek(-READ_SIZE, 1) 

75 lines_scanned = 0 

76 while cursor > 0: 

77 buf = f.read(READ_SIZE) 

78 newlines = buf.split(b'\n') 

79 lines_scanned += len(newlines) - 1 

80 if lines_scanned >= prevlines: 

81 cursor += len( 

82 b'\n'.join(newlines[:lines_scanned-prevlines+1]) 

83 ) + 1 

84 break 

85 cursor -= READ_SIZE 

86 f.seek(cursor) 

87 else: 

88 cursor = 0 

89 f.seek(cursor) 

90 try: 

91 if not follow.value: 

92 sys.stdout.write(f.read(end-cursor)) 

93 raise KeyboardInterrupt() 

94 while CONTINUE[0]: 

95 nextline = f.readline() 

96 while nextline and CONTINUE[0]: 

97 sys.stdout.write(nextline) 

98 nextline = f.readline() 

99 sleep(0.3) 

100 except KeyboardInterrupt: 

101 print(f"~~~~~~~~~~~< DONE PRINTING {logpath} >~~~~~~~~~~~") 

102 

103 #def stopclick(button): 

104 # with output: 

105 # print(f"CONTINUE={CONTINUE}") 

106 # print("Setting CONTINUE[0]=False") 

107 # CONTINUE[0] = False 

108 # print(f"New value: CONTINUE={CONTINUE}") 

109 

110 submit.on_click(onclick) 

111 clear.on_click(lambda _x: output.clear_output()) 

112 #stop.on_click(stopclick) 

113 

114 display(logwidg) 

115 display(lineswidg) 

116 display(follow) 

117 display(submit) 

118 display(clear) 

119 #display(stop) 

120 display(output)