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 Run some checkings about the distribution 

5 

6.. versionadded:: 1.1 

7""" 

8from __future__ import print_function 

9 

10import os 

11import sys 

12 

13from .win_exception import WinInstallDistributionError 

14from ..packaged.automate_install import find_module_install 

15from ..installhelper.install_venv_helper import run_cmd_path 

16from ..packaged import small_set 

17from ..installhelper.module_install import ModuleInstall, run_cmd 

18 

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

20 FileNotFoundError = Exception 

21 

22 

23def distribution_checkings(python_path, tools_path, fLOG=print, skip_import=False, module_list=None): 

24 """ 

25 checks a distribution was properly executed 

26 

27 @param python_path path for python 

28 @param tools_path path for tools 

29 @param fLOG logging function 

30 @param skip_import skip the validation of every installed module (for unit test purposes) 

31 @param module_list module list to check 

32 

33 The function raises @see cl WinInstallDistributionError if an issue is detected. 

34 

35 If *python_path* is None, it is replace by ``os.path.dirname(sys.executable)``. 

36 

37 .. versionadded:: 1.1 

38 """ 

39 exceptions = [] 

40 files_to_check = ["jupyter-console.exe", "jupyter-qtconsole.exe", 

41 "jupyter-notebook.exe", "jupyter.exe"] 

42 

43 if python_path is None: 

44 python_path = os.path.dirname(sys.executable) 

45 

46 # on Python 3.5, pip does not always exist 

47 # in a virtual environment (probable bug) 

48 pip = os.path.join(python_path, "pip.exe") 

49 pep8 = os.path.join(python_path, "pep8.exe") 

50 if not os.path.exists(pip) and not os.path.exists(pep8): 

51 scripts = os.path.join(python_path, "Scripts") 

52 files_to_check.extend( 

53 [("spyder.bat", 'spyder.exe'), "autopep8.exe"]) 

54 if sys.version_info[:2] != (3, 5): 

55 files_to_check.append("pip.exe") 

56 else: 

57 scripts = python_path 

58 

59 ###################################### 

60 # check Jupyter, numpy, works properly 

61 ###################################### 

62 if sys.platform.startswith("win"): 

63 new_files_to_check = [] 

64 for file in files_to_check: 

65 if isinstance(file, tuple): 

66 fs = [os.path.join(scripts, f) for f in file] 

67 ft = [f for f in fs if os.path.exists(f)] 

68 if len(ft) > 0: 

69 new_files_to_check.append(os.path.split(ft[0])[-1]) 

70 else: 

71 try: 

72 raise FileNotFoundError(fs) 

73 except Exception as e: 

74 exceptions.append(e) 

75 else: 

76 f = os.path.join(scripts, file) 

77 if not os.path.exists(f): 

78 try: 

79 raise FileNotFoundError(f) 

80 except Exception as e: 

81 exceptions.append(e) 

82 else: 

83 new_files_to_check.append(file) 

84 files_to_check = new_files_to_check 

85 

86 ################################ 

87 # check that module can be imported 

88 ################################ 

89 if not skip_import: 

90 res = import_every_module( 

91 python_path, module_list, only_installed=True, fLOG=fLOG) 

92 mes = [] 

93 for r in res: 

94 if not r[0]: 

95 m = "------\nFAILED {0}\nOUT\n{1}\nERR--E\n{2}".format( 

96 r[1].name, r[2], r[3]) 

97 mes.append(m) 

98 if len(mes) > 0: 

99 raise WinInstallDistributionError( 

100 "cannot import modules\n" + "\n".join(mes)) 

101 

102 ######## 

103 # final 

104 ######## 

105 if len(exceptions) > 0: 

106 typstr = str # unicode# 

107 errors = "\n----\n".join("{0}\n{1}".format(type(_), typstr(_)) 

108 for _ in exceptions) 

109 raise WinInstallDistributionError("\n" + errors) 

110 

111 

112def import_every_module(python_path, module_list, only_installed=True, fLOG=print, start=0, end=-1): 

113 """ 

114 import every module in *module_list* assuming they are defined 

115 by @see cl ModuleInstall or a string 

116 

117 @param python_path python path 

118 @param module_list module list, if None, consider the largest list 

119 @param only_installed True to check only installed module in the list, False to test them without checking they were installed 

120 @param start start the list at *start* 

121 @param end end the list at *end* or -1 for all 

122 @return list of tuple (success, failing modules, output, error) 

123 """ 

124 if python_path is None: 

125 python_path = os.path.dirname(sys.executable) 

126 if os.path.isfile(python_path): 

127 python_path = os.path.dirname(python_path) 

128 

129 if module_list is None: 

130 module_list = small_set() 

131 

132 def tomod(m): 

133 if isinstance(m, ModuleInstall): 

134 return m 

135 else: 

136 return find_module_install(m) 

137 module_list = [tomod(m) for m in module_list] 

138 

139 def noLOG(*l, **p): 

140 pass 

141 

142 def is_errored_line(line): 

143 if ".py" in line: 

144 if "UserWarning:" in line: 

145 return False 

146 if "FutureWarning:" in line: 

147 return False 

148 return True 

149 return False 

150 

151 def analyze_error_success(mod, err): 

152 if err is None or len(err) == 0: 

153 return True 

154 if "ImportError" in err: 

155 return False 

156 if "ShimWarning" in err: 

157 return True 

158 if "kivy" in mod.name.lower(): 

159 if "error" not in err.lower(): 

160 return True 

161 

162 if err is not None: 

163 lines = err.split("\n") 

164 for line in lines: 

165 if ".py" in line: 

166 res = is_errored_line(lines) 

167 if res: 

168 return False 

169 else: 

170 continue 

171 return True 

172 return False 

173 

174 res = [] 

175 for i, m in enumerate(module_list): 

176 if i < start: 

177 continue 

178 if end != -1 and i >= end: 

179 fLOG("[pymy] {0}/{1}: end".format(i, len(module_list) - start)) 

180 break 

181 if m.is_installed_version(): 

182 

183 if m.name in ["libpython", "tutormagic", "pymyinstall", "distribute"]: 

184 # nothing to import or failure 

185 fLOG("[pymy] {0}/{1}: skipped".format(i, 

186 len(module_list) - start), m) 

187 continue 

188 elif m.mname == "theano": 

189 # we need to check that TDM-GCC is installed 

190 cmd = "g++ --help" 

191 out, err = run_cmd(cmd, wait=True, fLOG=fLOG) 

192 if err is not None and len(err) > 0: 

193 fLOG("[pymy] {0}/{1}: failed (g++)".format(i, 

194 len(module_list) - start), m) 

195 res.append((False, m, out, err)) 

196 continue 

197 if "Usage: g++ [options] file..." not in out: 

198 fLOG("[pymy] {0}/{1}: failed (g++)".format(i, 

199 len(module_list) - start), m) 

200 res.append((False, m, out, err)) 

201 continue 

202 

203 sc = "import " + m.ImportName 

204 if m.name == "cvxopt": 

205 # see 

206 # http://stackoverflow.com/questions/14778178/import-cvxopt-base-the-specified-module-could-not-be-found 

207 sc += "import numpy;" + sc 

208 if m.name == "scipy": 

209 # see 

210 # http://stackoverflow.com/questions/14778178/import-cvxopt-base-the-specified-module-could-not-be-found 

211 sc += sc + ";import scipy.stats" 

212 out, err = run_cmd_path( 

213 python_path, sc, fLOG=fLOG, communicate=True, timeout=40) 

214 suc = analyze_error_success(m, err) 

215 nextm = module_list[i + 1] if i + 1 < len(module_list) else "" 

216 if suc: 

217 fLOG("[pymy] {0}/{1}: success".format(i, 

218 len(module_list) - start), m, "-->", nextm) 

219 else: 

220 fLOG("[pymy] {0}/{1}: failed ".format(i, 

221 len(module_list) - start), m, "-->", nextm) 

222 if m.name == "paramiko": 

223 err = "You might have to install manually pycrypto.\n" + \ 

224 "Please read http://www.xavierdupre.fr/app/pymyinstall/helpsphinx//blog/2016/2016-02-27_pycrypto_paramiko.html" + \ 

225 err 

226 err = [(" - ERR--F: " if is_errored_line(line) 

227 else " - OK: ") + line.rstrip("\n\r") for line in err.split("\n")] 

228 err = "\n".join(err) 

229 res.append((suc, m, out, err)) 

230 return res