204 try: |
207 try: |
205 # Install the files |
208 # Install the files |
206 # copy the various parts of eric debug clients |
209 # copy the various parts of eric debug clients |
207 copyTree( |
210 copyTree( |
208 os.path.join(eric7SourceDir, "DebugClients"), |
211 os.path.join(eric7SourceDir, "DebugClients"), |
209 targetDir, |
212 os.path.join(targetDir, "DebugClients"), |
210 ["*.py", "*.pyc", "*.pyo", "*.pyw"], |
213 ["*.py", "*.pyc", "*.pyo", "*.pyw"], |
211 excludePatterns=["eric7config.py*"], |
214 excludePatterns=["eric7config.py*"], |
212 ) |
215 ) |
213 |
216 |
|
217 # copy the top level package file |
|
218 shutilCopy(os.path.join(eric7SourceDir, "__init__.py"), targetDir) |
|
219 |
214 # copy the license file |
220 # copy the license file |
215 shutilCopy(os.path.join(sourceDir, "docs", "LICENSE.txt"), targetDir) |
221 shutilCopy(os.path.join(sourceDir, "docs", "LICENSE.txt"), targetDir) |
216 |
222 |
217 except OSError as msg: |
223 except OSError as msg: |
218 sys.stderr.write("Error: {0}\nTry install with admin rights.\n".format(msg)) |
224 sys.stderr.write("\nError: {0}\nTry install with admin rights.\n".format(msg)) |
219 return 7 |
225 return 7 |
220 |
226 |
221 return 0 |
227 return 0 |
|
228 |
|
229 |
|
230 def pipInstall(packageName, message, force=True): |
|
231 """ |
|
232 Install the given package via pip. |
|
233 |
|
234 @param packageName name of the package to be installed |
|
235 @type str |
|
236 @param message message to be shown to the user |
|
237 @type str |
|
238 @param force flag indicating to perform the installation |
|
239 without asking the user |
|
240 @type bool |
|
241 @return flag indicating a successful installation |
|
242 @rtype bool |
|
243 """ |
|
244 ok = False |
|
245 if force: |
|
246 answer = "y" |
|
247 else: |
|
248 print( |
|
249 "{0}\nShall '{1}' be installed using pip? (Y/n)".format( |
|
250 message, packageName |
|
251 ), |
|
252 end=" ", |
|
253 ) |
|
254 answer = input() # secok |
|
255 if answer in ("", "Y", "y"): |
|
256 exitCode = subprocess.run( # secok |
|
257 [ |
|
258 sys.executable, |
|
259 "-m", |
|
260 "pip", |
|
261 "install", |
|
262 "--prefer-binary", |
|
263 "--upgrade", |
|
264 packageName, |
|
265 ] |
|
266 ).returncode |
|
267 ok = exitCode == 0 |
|
268 |
|
269 return ok |
|
270 |
|
271 |
|
272 def isPipOutdated(): |
|
273 """ |
|
274 Check, if pip is outdated. |
|
275 |
|
276 @return flag indicating an outdated pip |
|
277 @rtype bool |
|
278 """ |
|
279 try: |
|
280 pipOut = ( |
|
281 subprocess.run( # secok |
|
282 [sys.executable, "-m", "pip", "list", "--outdated", "--format=json"], |
|
283 check=True, |
|
284 capture_output=True, |
|
285 text=True, |
|
286 ) |
|
287 .stdout.strip() |
|
288 .splitlines()[0] |
|
289 ) |
|
290 # only the first line contains the JSON data |
|
291 except (OSError, subprocess.CalledProcessError): |
|
292 pipOut = "[]" # default empty list |
|
293 try: |
|
294 jsonList = json.loads(pipOut) |
|
295 except Exception: |
|
296 jsonList = [] |
|
297 for package in jsonList: |
|
298 if isinstance(package, dict) and package["name"] == "pip": |
|
299 print( |
|
300 "'pip' is outdated (installed {0}, available {1})".format( |
|
301 package["version"], package["latest_version"] |
|
302 ) |
|
303 ) |
|
304 return True |
|
305 |
|
306 return False |
|
307 |
|
308 |
|
309 def updatePip(): |
|
310 """ |
|
311 Update the installed pip package. |
|
312 """ |
|
313 global yes2All |
|
314 |
|
315 if yes2All: |
|
316 answer = "y" |
|
317 else: |
|
318 print("Shall 'pip' be updated (recommended)? (Y/n)", end=" ") |
|
319 answer = input() # secok |
|
320 if answer in ("", "Y", "y"): |
|
321 subprocess.run( # secok |
|
322 [sys.executable, "-m", "pip", "install", "--upgrade", "pip"] |
|
323 ) |
|
324 |
|
325 |
|
326 def doDependancyChecks(): |
|
327 """ |
|
328 Perform some dependency checks. |
|
329 """ |
|
330 try: |
|
331 isSudo = os.getuid() == 0 and sys.platform != "darwin" |
|
332 # disregard sudo installs on macOS |
|
333 except AttributeError: |
|
334 isSudo = False |
|
335 |
|
336 print("Checking dependencies") |
|
337 |
|
338 # update pip first even if we don't need to install anything |
|
339 if not isSudo and isPipOutdated(): |
|
340 updatePip() |
|
341 print("\n") |
|
342 |
|
343 # perform dependency checks |
|
344 if sys.version_info < (3, 7, 0) or sys.version_info >= (3, 12, 0): |
|
345 print("Sorry, you must have Python 3.7.0 or higher, but less 3.12.0.") |
|
346 print("Yours is {0}.".format(".".join(str(v) for v in sys.version_info[:3]))) |
|
347 exit(5) |
|
348 |
|
349 requiredModulesList = { |
|
350 # key is pip project name |
|
351 # value is tuple of package name, pip install constraint |
|
352 "coverage": ("coverage", ">=6.5.0"), |
|
353 } |
|
354 |
|
355 # check required modules |
|
356 print("Required Packages") |
|
357 print("-----------------") |
|
358 requiredMissing = False |
|
359 for requiredPackage in sorted(requiredModulesList): |
|
360 try: |
|
361 importlib.import_module(requiredModulesList[requiredPackage][0]) |
|
362 print("Found", requiredPackage) |
|
363 except ImportError as err: |
|
364 if isSudo: |
|
365 print("Required '{0}' could not be detected.".format(requiredPackage)) |
|
366 requiredMissing = True |
|
367 else: |
|
368 pipInstall( |
|
369 requiredPackage + requiredModulesList[requiredPackage][1], |
|
370 "Required '{0}' could not be detected.{1}".format( |
|
371 requiredPackage, "\nError: {0}".format(err) |
|
372 ), |
|
373 force=True, |
|
374 ) |
|
375 if requiredMissing: |
|
376 print("Some required packages are missing and could not be installed.") |
|
377 print("Install them manually.") |
|
378 |
|
379 print() |
|
380 print("All dependencies ok.") |
|
381 print() |
222 |
382 |
223 |
383 |
224 def main(argv): |
384 def main(argv): |
225 """ |
385 """ |
226 The main function of the script. |
386 The main function of the script. |
275 else os.path.join(sourceDir, "src", "eric7") |
438 else os.path.join(sourceDir, "src", "eric7") |
276 ) |
439 ) |
277 |
440 |
278 # cleanup source if installing from source |
441 # cleanup source if installing from source |
279 if installFromSource: |
442 if installFromSource: |
280 print("Cleaning up source ...") |
443 print("Cleaning up source ...", end="") |
281 cleanupSource(os.path.join(eric7SourceDir, "DebugClients")) |
444 cleanupSource(os.path.join(eric7SourceDir, "DebugClients")) |
282 print() |
445 print(" Done") |
283 |
446 |
284 # cleanup old installation |
447 # cleanup old installation |
285 try: |
448 try: |
286 if doCleanup: |
449 if doCleanup: |
287 print("Cleaning up old installation ...") |
450 print("Cleaning up old installation ...", end="") |
288 if distDir: |
451 if distDir: |
289 shutil.rmtree(distDir, True) |
452 shutil.rmtree(distDir, True) |
290 else: |
453 else: |
291 cleanUp() |
454 cleanUp() |
|
455 print(" Done") |
292 except OSError as msg: |
456 except OSError as msg: |
293 sys.stderr.write("Error: {0}\nTry install as root.\n".format(msg)) |
457 sys.stderr.write("Error: {0}\nTry install as root.\n".format(msg)) |
294 exit(7) |
458 exit(7) |
295 |
459 |
296 if doCompile: |
460 if doCompile: |
297 print("\nCompiling source files ...") |
461 print("Compiling source files ...", end="") |
298 skipRe = re.compile(r"DebugClients[\\/]Python[\\/]") |
462 skipRe = re.compile(r"DebugClients[\\/]Python[\\/]") |
299 sys.stdout = io.StringIO() |
463 sys.stdout = io.StringIO() |
300 if distDir: |
464 if distDir: |
301 compileall.compile_dir( |
465 compileall.compile_dir( |
302 os.path.join(eric7SourceDir, "DebugClients"), |
466 os.path.join(eric7SourceDir, "DebugClients"), |