Coverage for sparkle/CLI/initialise.py: 21%

77 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-09-27 09:10 +0000

1#!/usr/bin/env python3 

2"""Command to initialise a Sparkle platform.""" 

3import subprocess 

4import argparse 

5import shutil 

6import os 

7from pathlib import Path 

8 

9from sparkle.platform import CommandName 

10from sparkle.CLI.help.argparse_custom import DownloadExamplesArgument 

11from sparkle.CLI.help import snapshot_help as snh 

12from sparkle.platform.settings_objects import Settings 

13from sparkle.structures import PerformanceDataFrame, FeatureDataFrame 

14from sparkle.CLI.help import global_variables as gv 

15 

16 

17def parser_function() -> argparse.ArgumentParser: 

18 """Parse CLI arguments for the initialise command.""" 

19 parser = argparse.ArgumentParser( 

20 description=("Initialise the Sparkle platform in the current directory.")) 

21 parser.add_argument(*DownloadExamplesArgument.names, 

22 **DownloadExamplesArgument.kwargs) 

23 return parser 

24 

25 

26def detect_sparkle_platform_exists(check: callable = all) -> Path: 

27 """Return whether a Sparkle platform is currently active. 

28 

29 The default working directories are checked for existence, for each directory in the 

30 CWD. If any of the parents of the CWD yield true, this path is returned 

31 

32 Args: 

33 check: Method to check if the working directory exists. Defaults to all. 

34 

35 Returns: 

36 Path to the Sparkle platform if it exists, None otherwise. 

37 """ 

38 cwd = Path.cwd() 

39 while str(cwd) != cwd.root: 

40 if check([(cwd / wd).exists() for wd in gv.settings().DEFAULT_working_dirs]): 

41 return cwd 

42 cwd = cwd.parent 

43 return None 

44 

45 

46def check_for_initialise(requirements: list[CommandName] = None)\ 

47 -> None: 

48 """Function to check if initialize command was executed and execute it otherwise. 

49 

50 Args: 

51 argv: List of the arguments from the caller. 

52 requirements: The requirements that have to be executed before the calling 

53 function. 

54 """ 

55 platform_path = detect_sparkle_platform_exists() 

56 if platform_path is None: 

57 print("-----------------------------------------------") 

58 print("No Sparkle platform found; " 

59 + "The platform will now be initialized automatically") 

60 if requirements is not None: 

61 if len(requirements) == 1: 

62 print(f"The command {requirements[0]} has \ 

63 to be executed before executing this command.") 

64 else: 

65 print(f"""The commands {", ".join(requirements)} \ 

66 have to be executed before executing this command.""") 

67 print("-----------------------------------------------") 

68 initialise_sparkle() 

69 elif platform_path != Path.cwd(): 

70 print(f"[WARNING] Sparkle platform found in {platform_path} instead of " 

71 f"{Path.cwd()}. Switching to CWD to {platform_path}") 

72 os.chdir(platform_path) 

73 

74 

75def initialise_sparkle(download_examples: bool = False) -> None: 

76 """Initialize a new Sparkle platform. 

77 

78 Args: 

79 download_examples: Downloads examples from the Sparkle Github. 

80 WARNING: May take a some time to complete due to the large amount of data. 

81 """ 

82 print("Start initialising Sparkle platform ...") 

83 # Check if Settings file exists, otherwise initialise a default one 

84 if not Path(Settings.DEFAULT_settings_path).exists(): 

85 print("Settings file does not exist, initializing default settings ...") 

86 gv.__settings = Settings(Settings.DEFAULT_example_settings_path) 

87 gv.settings().write_settings_ini(Path(Settings.DEFAULT_settings_path)) 

88 

89 gv.settings().DEFAULT_snapshot_dir.mkdir(exist_ok=True) 

90 if detect_sparkle_platform_exists(check=any): 

91 snh.save_current_sparkle_platform() 

92 snh.remove_current_platform() 

93 

94 print("Current Sparkle platform found!") 

95 print("Current Sparkle platform recorded!") 

96 

97 for working_dir in gv.settings().DEFAULT_working_dirs: 

98 working_dir.mkdir(exist_ok=True) 

99 

100 # Initialise the FeatureDataFrame 

101 FeatureDataFrame(gv.settings().DEFAULT_feature_data_path) 

102 

103 # Initialise the Performance DF with the static dimensions 

104 # TODO: We have many sparkle settings values regarding ``number of runs'' 

105 # E.g. configurator, parallel portfolio, and here too. Should we unify this more, or 

106 # just make another setting that does this specifically for performance data? 

107 PerformanceDataFrame(gv.settings().DEFAULT_performance_data_path, 

108 objectives=gv.settings().get_general_sparkle_objectives(), 

109 n_runs=1) 

110 

111 # Check that Runsolver is compiled, otherwise, compile 

112 if not gv.settings().DEFAULT_runsolver_exec.exists(): 

113 print("Runsolver does not exist, trying to compile...") 

114 if not (gv.settings().DEFAULT_runsolver_dir / "Makefile").exists(): 

115 print("WARNING: Runsolver executable doesn't exist and cannot find makefile." 

116 " Please verify the contents of the directory: " 

117 f"{gv.settings().DEFAULT_runsolver_dir}") 

118 else: 

119 compile_runsolver =\ 

120 subprocess.run(["make"], 

121 cwd=gv.settings().DEFAULT_runsolver_dir, 

122 capture_output=True) 

123 if compile_runsolver.returncode != 0: 

124 print("WARNING: Compilation of Runsolver failed with the following msg:" 

125 f"[{compile_runsolver.returncode}] " 

126 f"{compile_runsolver.stderr.decode()}") 

127 else: 

128 print("Runsolver compiled successfully!") 

129 # Check that java is available 

130 if shutil.which("java") is None: 

131 # NOTE: An automatic resolution of Java at this point would be good 

132 # However, loading modules from Python has thusfar not been successfull. 

133 print("Could not find Java as an executable!") 

134 

135 if download_examples: 

136 # Download Sparkle examples from Github 

137 # NOTE: Needs to be thoroughly tested after Pip install is working 

138 print("Downloading examples ...") 

139 curl = subprocess.Popen( 

140 ["curl", "https://codeload.github.com/ADA-research/Sparkle/tar.gz/main"], 

141 stdout=subprocess.PIPE) 

142 outpath = Path("outfile.tar.gz") 

143 with curl.stdout, outpath.open("wb") as outfile: 

144 tar = subprocess.Popen(["tar", "-xz", "--strip=1", "Sparkle-main/Examples"], 

145 stdin=curl.stdout, stdout=outfile) 

146 curl.wait() # Wait for the download to complete 

147 tar.wait() # Wait for the extraction to complete 

148 outpath.unlink(missing_ok=True) 

149 

150 print("New Sparkle platform initialised!") 

151 

152 

153if __name__ == "__main__": 

154 # Define command line arguments 

155 parser = parser_function() 

156 # Process command line arguments 

157 args = parser.parse_args() 

158 download = False if args.download_examples is None else args.download_examples 

159 initialise_sparkle(download_examples=download)