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
6.. versionadded:: 1.1
7"""
8from __future__ import print_function
10import os
11import sys
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
19if sys.version_info[0] == 2:
20 FileNotFoundError = Exception
23def distribution_checkings(python_path, tools_path, fLOG=print, skip_import=False, module_list=None):
24 """
25 checks a distribution was properly executed
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
33 The function raises @see cl WinInstallDistributionError if an issue is detected.
35 If *python_path* is None, it is replace by ``os.path.dirname(sys.executable)``.
37 .. versionadded:: 1.1
38 """
39 exceptions = []
40 files_to_check = ["jupyter-console.exe", "jupyter-qtconsole.exe",
41 "jupyter-notebook.exe", "jupyter.exe"]
43 if python_path is None:
44 python_path = os.path.dirname(sys.executable)
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
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
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))
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)
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
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)
129 if module_list is None:
130 module_list = small_set()
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]
139 def noLOG(*l, **p):
140 pass
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
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
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
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():
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
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