Coverage for pesummary/_version_helper.py: 68.2%

107 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-05-02 08:42 +0000

1# Licensed under an MIT style license -- see LICENSE.md 

2 

3import json 

4import os 

5import shutil 

6import subprocess 

7import sys 

8from pathlib import Path 

9 

10__author__ = ["Charlie Hoy <charlie.hoy@ligo.org>"] 

11 

12CONDA_EXE = os.getenv("CONDA_EXE", shutil.which("conda")) or "conda" 

13 

14 

15class GitDummy(object): 

16 def __getattr__(self, attr): 

17 return "" 

18 

19 

20class GitInformation(object): 

21 """Helper class to handle the git information 

22 """ 

23 def __init__(self, directory=None): 

24 if directory is None and not os.path.isdir(".git"): 

25 raise TypeError( 

26 "Not a git repository. Unable to get git information" 

27 ) 

28 elif directory is None: 

29 directory = "." 

30 cwd = os.getcwd() 

31 os.chdir(directory) 

32 self.last_commit_info = self.get_last_commit_info() 

33 self.last_version = self.get_last_version() 

34 self.hash = self.last_commit_info[0] 

35 self.author = self.last_commit_info[1] 

36 self.status = self.get_status() 

37 self.builder = self.get_build_name() 

38 self.build_date = self.get_build_date() 

39 os.chdir(cwd) 

40 

41 def call(self, arguments): 

42 """Launch a subprocess to run the bash command 

43 

44 Parameters 

45 ---------- 

46 arguments: list 

47 list of bash commands 

48 """ 

49 return subprocess.check_output(arguments) 

50 

51 def get_build_name(self): 

52 """Return the username and email of the current builder 

53 """ 

54 try: 

55 name = self.call(["git", "config", "user.name"]) 

56 email = self.call(["git", "config", "user.email"]) 

57 name = name.strip() 

58 email = email.strip() 

59 return "%s <%s>" % (name.decode("utf-8"), email.decode("utf-8")) 

60 except Exception: 

61 return "" 

62 

63 def get_build_date(self): 

64 """Return the current datetime 

65 """ 

66 import time 

67 return time.strftime('%Y-%m-%d %H:%M:%S +0000', time.gmtime()) 

68 

69 def get_last_commit_info(self): 

70 """Return the details of the last git commit 

71 """ 

72 try: 

73 string = self.call( 

74 ["git", "log", "-1", "--pretty=format:%h,%an,%ae"]) 

75 string = string.decode("utf-8").split(",") 

76 hash, username, email = string 

77 author = "%s <%s>" % (username, email) 

78 return hash, author 

79 except Exception: 

80 return "" 

81 

82 def get_status(self): 

83 """Return the state of the git repository 

84 """ 

85 git_diff = self.call(["git", "diff", "."]).decode("utf-8") 

86 if git_diff: 

87 return "UNCLEAN: Modified working tree" 

88 return "CLEAN: All modifications committed" 

89 

90 def get_last_version(self): 

91 """Return the last stable version 

92 """ 

93 try: 

94 tag = self.call(["git", "describe", "--tags", "--abbrev=0"]).decode( 

95 "utf-8" 

96 ).strip("\n") 

97 if tag[0] != "v": 

98 return tag 

99 return tag[1:] 

100 except Exception: 

101 return "Not found" 

102 

103 

104class PackageInformation(GitInformation): 

105 """Helper class to handle package versions 

106 """ 

107 def __init__(self): 

108 self.package_info = self.get_package_info() 

109 self.package_dir = self.get_package_dir() 

110 

111 def get_package_info(self): 

112 """Return the package information 

113 """ 

114 if (Path(sys.prefix) / "conda-meta").is_dir(): 

115 self.package_manager = "conda" 

116 raw = self.call([ 

117 CONDA_EXE, 

118 "list", 

119 "--json", 

120 "--prefix", sys.prefix, 

121 ]) 

122 else: 

123 self.package_manager = "pypi" 

124 raw = self.call([ 

125 sys.executable, 

126 "-m", "pip", 

127 "list", "installed", 

128 "--format", "json", 

129 ]) 

130 return json.loads(raw.decode('utf-8')) 

131 

132 def get_package_dir(self): 

133 """Return the package directory 

134 """ 

135 return sys.prefix 

136 

137 

138def make_version_file( 

139 version_file=None, return_string=False, version=None, add_install_path=False 

140): 

141 """Write a version file 

142 

143 Parameters 

144 ---------- 

145 version_file: str 

146 the path to the version file you wish to write 

147 return_sting: Bool, optional 

148 if True, return the version file as a string. Default False 

149 """ 

150 from pesummary import __version_string__ 

151 

152 string = __version_string__ 

153 if add_install_path: 

154 string += install_path(return_string=True) 

155 if not return_string and version_file is None: 

156 raise ValueError("Please provide a version file") 

157 elif not return_string: 

158 with open(version_file, "w") as f: 

159 f.write(string) 

160 return version_file 

161 return string 

162 

163 

164def install_path(return_string=False): 

165 """Return the install path of a package 

166 """ 

167 packages = PackageInformation() 

168 install_path = packages.package_dir 

169 string = "# Install information\n\ninstall_path = %s\n" % ( 

170 install_path 

171 ) 

172 if return_string: 

173 return string 

174 return packages.package_dir 

175 

176 

177def get_version_information(short=False): 

178 """Grab the version from the .version file 

179 

180 Parameters 

181 ---------- 

182 short: Bool 

183 If True, only return the version. If False, return git hash 

184 """ 

185 try: 

186 from ._version import version 

187 except ModuleNotFoundError: 

188 try: 

189 # in build 

190 import setuptools_scm 

191 version = setuptools_scm.get_version() 

192 except ImportError: 

193 version = "" 

194 

195 if short: 

196 return version.split("+")[0] 

197 return version