Coverage for sparkle/CLI/help/logging.py: 100%

45 statements  

« prev     ^ index     » next       coverage.py v7.6.4, created at 2024-11-05 14:48 +0000

1#!/usr/bin/env python3 

2# -*- coding: UTF-8 -*- 

3"""Helper functions to log which output was created by Sparkle where.""" 

4from __future__ import annotations 

5 

6import time 

7from pathlib import Path 

8from pathlib import PurePath 

9 

10from runrunner.logger import Log as RunRunnerLog 

11 

12from sparkle.CLI.help import global_variables as gv 

13 

14 

15# Keep track of which command called Sparkle 

16global caller 

17caller: str = "unknown" 

18 

19# Current caller file path 

20global caller_log_path 

21caller_log_path: str | PurePath = "not set" 

22 

23# Root output directory for the calling command in the form of 

24# Output/<timestamp>_<command_name>/ 

25global caller_out_dir 

26caller_out_dir: Path = Path(".") 

27 

28# Log directory for the calling command in the form of 

29# Output/<timestamp>_<command_name>/Log/ 

30global caller_log_dir 

31caller_log_dir: Path = Path(".") 

32 

33 

34def _update_caller(argv: list[str]) -> None: 

35 """Update which command is currently active. 

36 

37 Args: 

38 argv: List containing the command line arguments derived from sys.argv. 

39 

40 """ 

41 global caller 

42 caller = Path(argv[0]).stem 

43 

44 

45def _update_caller_file_path(timestamp: str) -> None: 

46 """Create a new file path for the caller with the given timestamp. 

47 

48 Args: 

49 timestamp: String representation of the time. 

50 

51 """ 

52 caller_file = caller + "_main_log.txt" 

53 caller_dir = Path(timestamp + "_" + caller) 

54 log_dir = gv.settings().DEFAULT_log_output 

55 # Set caller directory for other Sparkle functions to use 

56 global caller_out_dir 

57 caller_out_dir = Path(caller_dir) 

58 global caller_log_path 

59 caller_log_path = PurePath(log_dir / caller_out_dir / caller_file) 

60 global caller_log_dir 

61 caller_log_dir = log_dir / caller_out_dir 

62 

63 # Create needed directories if they don't exist 

64 caller_dir = Path(caller_log_path).parents[0] 

65 caller_dir.mkdir(parents=True, exist_ok=True) 

66 caller_log_dir.mkdir(parents=True, exist_ok=True) 

67 

68 # If the caller output file does not exist yet, write the header 

69 if not Path(caller_log_path).is_file(): 

70 output_header = "\t Timestamp\t\t\t\t\t\t\t Path\t\t\t\t\t\t\t Description\n" 

71 with Path(caller_log_path).open("a") as output_file: 

72 output_file.write(output_header) 

73 

74 

75def add_output(output_path: str, description: str) -> None: 

76 """Add output location and description to the log of the current command. 

77 

78 Args: 

79 output_path: The file path of where output is written to. 

80 description: A short description of what kind of output is written to this file. 

81 

82 """ 

83 # Prepare logging information 

84 timestamp = time.strftime("%Y-%m-%d-%H:%M:%S", time.localtime(time.time())) 

85 output_str = f"{timestamp}\t{output_path}\t{description}\n" 

86 # Write output path and description to caller file 

87 with Path(caller_log_path).open("a") as output_file: 

88 output_file.write(output_str) 

89 

90 

91def log_command(argv: list[str]) -> None: 

92 """Write to file which command was executed. 

93 

94 Includes information on when it was executed, with which arguments, and 

95 where details about it's output are stored (if any). 

96 

97 Args: 

98 argv: List containing the command line arguments derived from sys.argv. 

99 

100 """ 

101 # Determine caller 

102 _update_caller(argv) 

103 

104 # Prepare logging information 

105 timestamp = time.strftime("%Y-%m-%d-%H:%M:%S", time.localtime(time.time())) 

106 _update_caller_file_path(timestamp) 

107 output_file = caller_log_path 

108 args = " ".join(argv[0:]) 

109 log_str = timestamp + " " + args + " " + str(output_file) + "\n" 

110 

111 # If the log file does not exist yet, write the header 

112 log_path = gv.settings().DEFAULT_output / "sparkle.log" 

113 if not log_path.is_file(): 

114 log_header = "\t Timestamp\t\t\t\t\t\t\t Command\t\t\t\t\t\t\t Output details\n" 

115 log_str = log_header + log_str 

116 

117 # Write to log file 

118 with log_path.open("a") as log_file: 

119 log_file.write(log_str) 

120 

121 # Pipe RunRunner log to the caller log 

122 RunRunnerLog.set_log_file(caller_log_path)