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# -*- coding: utf-8 -*- 

2""" 

3@file 

4@brief Helpers, inspired from `utils.py <https://github.com/winpython/winpython/blob/master/winpython/utils.py>`_ 

5""" 

6from __future__ import print_function 

7 

8import sys 

9import os 

10import os.path as osp 

11import subprocess 

12import tarfile 

13import zipfile 

14import fnmatch 

15# import winreg 

16import glob 

17import shutil 

18from ..installcustom.install_custom_python import unzip7_files 

19 

20from .win_helper import patch_shebang_line 

21 

22if sys.version_info[0] == 2: 

23 FileNotFoundError = Exception 

24 

25 

26def is_program_installed(basename): 

27 """ 

28 Return program absolute path if installed in PATH 

29 Otherwise, return None 

30 

31 @param basename base name 

32 @return boolean 

33 """ 

34 if os.path.exists(basename): 

35 return True 

36 for path in os.environ["PATH"].split(os.pathsep): 

37 abspath = osp.join(path, basename) 

38 if osp.isfile(abspath): 

39 return abspath 

40 

41 

42def extract_msi(fname, targetdir=None, verbose=False, fLOG=print): 

43 """ 

44 Extract .msi installer to a temporary directory (if targetdir 

45 is None). Return the temporary directory path 

46 

47 @param fname local installer (exe) 

48 @param targetdir where to install 

49 @param verbose verbose 

50 @param fLOG logging function 

51 @return targetdir 

52 """ 

53 extract = 'msiexec.exe' 

54 bname = osp.basename(fname) 

55 args = ['/a', '%s' % bname] 

56 if not verbose: 

57 args += ['/quiet', '/qn'] 

58 args += ['TARGETDIR=%s' % targetdir] 

59 cmd = [extract] + args 

60 fLOG("[pymy] RUN: ", cmd) 

61 subprocess.call(cmd, cwd=osp.dirname(fname)) 

62 fLOG('fname=%s' % fname) 

63 fLOG('TARGETDIR=%s' % targetdir) 

64 

65 if "python-3" in fname.lower(): 

66 subprocess.call( 

67 [r'%s\%s' % (targetdir, 'python.exe'), '-m', 'ensurepip'], 

68 cwd=osp.dirname(r'%s\%s' % (targetdir, 'pythons.exe'))) 

69 # We patch ensurepip live (shame) !!!! 

70 # rational: https://github.com/pypa/pip/issues/2328 

71 for fname in glob.glob(r'%s\Scripts\*.exe' % targetdir): 

72 patch_shebang_line(fname) 

73 return targetdir 

74 

75 

76def extract_exe(fname, targetdir=None, verbose=False, fLOG=print, szip="7z.exe"): 

77 """ 

78 Extract *.exe* archive to a temporary directory (if targetdir 

79 is None). Return the temporary directory path 

80 

81 @param fname local installer (exe) 

82 @param targetdir where to install 

83 @param verbose verbose 

84 @param szip path to 7z.exe 

85 @param fLOG logging function 

86 @return targetdir 

87 """ 

88 extract = szip 

89 if not is_program_installed(extract): 

90 pp = os.environ["PATH"].split(";") 

91 raise FileNotFoundError( 

92 "Required program '%s' was not found in PATH:\n %s" % (extract, "\n ".join(pp))) 

93 bname = osp.basename(fname) 

94 args = ['x', '-o%s' % targetdir, '-aos', bname] 

95 if verbose: 

96 retcode = subprocess.call([extract] + args, cwd=osp.dirname(fname)) 

97 else: 

98 p = subprocess.Popen([extract] + args, cwd=osp.dirname(fname), 

99 stdout=subprocess.PIPE) 

100 p.communicate() 

101 p.stdout.close() 

102 retcode = p.returncode 

103 if retcode != 0: 

104 raise RuntimeError("Failed to extract %s (return code: %d),\nCMD: %s\nCMD*: %s\nin %s" 

105 % (fname, retcode, str([extract] + args), " ".join([extract] + args), targetdir)) 

106 return targetdir 

107 

108 

109def extract_archive(fname, targetdir=None, verbose=False, fLOG=print): 

110 """ 

111 Extract .zip, .exe (considered to be a zip archive) or .tar.gz archive 

112 to a temporary directory (if targetdir is None). 

113 Return the temporary directory path 

114 

115 @param fname zip file or exe file 

116 @param targetdir where to install 

117 @param verbose verbose 

118 @param fLOG logging function 

119 @return targetdir 

120 """ 

121 if osp.splitext(fname)[1] in ('.zip', '.exe'): 

122 obj = zipfile.ZipFile(fname, mode="r") 

123 elif osp.splitext(fname)[1] in ('.7z'): 

124 unzip7_files(fname, fLOG=fLOG, dest=targetdir) 

125 return targetdir 

126 elif fname.endswith('.tar.gz'): 

127 obj = tarfile.open(fname, mode='r:gz') 

128 else: 

129 raise RuntimeError("Unsupported archive filename %s" % fname) 

130 obj.extractall(path=targetdir) 

131 return targetdir 

132 

133 

134def clean_msi(folder, pattern, verbose=False, fLOG=print): 

135 """ 

136 clean all files follwing a specific pattern 

137 

138 @param folder folder 

139 @param pattern files to remove 

140 @param verbose display more information 

141 @param fLOG logging function 

142 @return removed files (as operation) 

143 """ 

144 def find(loc, pattern): 

145 exes = [] 

146 for root, dirnames, filenames in os.walk(loc): 

147 for filename in fnmatch.filter(filenames, pattern): 

148 exes.append(os.path.join(root, filename)) 

149 return exes 

150 remove = find(folder, pattern) 

151 operations = [] 

152 for r in remove: 

153 if verbose: 

154 fLOG("[pymy] remove", r) 

155 os.remove(r) 

156 operations.append(("remove", r)) 

157 return operations 

158 

159 

160def extract_copy(fname, targetdir=None, verbose=False, fLOG=print, szip=None): 

161 """ 

162 Copy *.exe* to targetdir 

163 

164 @param fname local installer (exe) 

165 @param targetdir where to install 

166 @param verbose verbose 

167 @param fLOG logging function 

168 @param szip unused 

169 @return targetdir 

170 """ 

171 shutil.copy(fname, targetdir)