scripts/install.py

changeset 7220
5cf645f6daab
parent 7210
8fe313d039e6
parent 7211
1c97f3142fa8
child 7227
5ba312e6599a
equal deleted inserted replaced
7218:eaf2cf171f3a 7220:5cf645f6daab
8 """ 8 """
9 Installation script for the eric6 IDE and all eric6 related tools. 9 Installation script for the eric6 IDE and all eric6 related tools.
10 """ 10 """
11 11
12 from __future__ import unicode_literals, print_function 12 from __future__ import unicode_literals, print_function
13 try:
14 # Python2 only
15 import cStringIO as io
16 try:
17 from PyQt5 import sip
18 except ImportError:
19 import sip
20 sip.setapi('QString', 2)
21 sip.setapi('QVariant', 2)
22 sip.setapi('QTextStream', 2)
23 input = raw_input # __IGNORE_WARNING__
24 except (ImportError):
25 import io # __IGNORE_WARNING__
26 13
27 import sys 14 import sys
28 import os 15 import os
29 import re 16 import re
30 import compileall 17 import compileall
31 import py_compile 18 import py_compile
32 import glob 19 import glob
33 import shutil 20 import shutil
34 import fnmatch 21 import fnmatch
35 import codecs
36 import subprocess 22 import subprocess
37 import time 23 import time
24 import io
38 25
39 # Define the globals. 26 # Define the globals.
40 progName = None 27 progName = None
41 currDir = os.getcwd() 28 currDir = os.getcwd()
42 modDir = None 29 modDir = None
48 installApis = True 35 installApis = True
49 doCleanup = True 36 doCleanup = True
50 doCleanDesktopLinks = False 37 doCleanDesktopLinks = False
51 forceCleanDesktopLinks = False 38 forceCleanDesktopLinks = False
52 doCompile = True 39 doCompile = True
53 includePythonVariant = False
54 cfg = {} 40 cfg = {}
55 progLanguages = ["Python", "Ruby", "QSS"] 41 progLanguages = ["Python", "Ruby", "QSS"]
56 sourceDir = "eric" 42 sourceDir = "eric"
57 eric6SourceDir = os.path.join(sourceDir, "eric6") 43 eric6SourceDir = os.path.join(sourceDir, "eric6")
58 configName = 'eric6config.py' 44 configName = 'eric6config.py'
61 defaultMacPythonExe = "{0}/Resources/Python.app/Contents/MacOS/Python".format( 47 defaultMacPythonExe = "{0}/Resources/Python.app/Contents/MacOS/Python".format(
62 sys.exec_prefix) 48 sys.exec_prefix)
63 macAppBundleName = defaultMacAppBundleName 49 macAppBundleName = defaultMacAppBundleName
64 macAppBundlePath = defaultMacAppBundlePath 50 macAppBundlePath = defaultMacAppBundlePath
65 macPythonExe = defaultMacPythonExe 51 macPythonExe = defaultMacPythonExe
66 pyqtVariant = ""
67 pyqtOverride = False
68 52
69 # Define blacklisted versions of the prerequisites 53 # Define blacklisted versions of the prerequisites
70 BlackLists = { 54 BlackLists = {
71 "sip": [], 55 "sip": [],
72 "PyQt4": [],
73 "PyQt5": [], 56 "PyQt5": [],
74 "QScintilla2": [], 57 "QScintilla2": [],
75 } 58 }
76 PlatformsBlackLists = { 59 PlatformsBlackLists = {
77 "windows": { 60 "windows": {
78 "sip": [], 61 "sip": [],
79 "PyQt4": [],
80 "PyQt5": [], 62 "PyQt5": [],
81 "QScintilla2": [], 63 "QScintilla2": [],
82 }, 64 },
83 65
84 "linux": { 66 "linux": {
85 "sip": [], 67 "sip": [],
86 "PyQt4": [],
87 "PyQt5": [], 68 "PyQt5": [],
88 "QScintilla2": [], 69 "QScintilla2": [],
89 }, 70 },
90 71
91 "mac": { 72 "mac": {
92 "sip": [], 73 "sip": [],
93 "PyQt4": [],
94 "PyQt5": [], 74 "PyQt5": [],
95 "QScintilla2": [], 75 "QScintilla2": [],
96 }, 76 },
97 } 77 }
98 78
99 # Define file name markers for Python variants
100 PythonMarkers = {
101 2: "_py2",
102 3: "_py3",
103 }
104 # Define a mapping of markers to full text
105 PythonTextMarkers = {
106 "_py2": "Python 2",
107 "_py3": "Python 3",
108 }
109
110 79
111 def exit(rcode=0): 80 def exit(rcode=0):
112 """ 81 """
113 Exit the install script. 82 Exit the install script.
114 83
117 global currDir 86 global currDir
118 87
119 print() 88 print()
120 89
121 if sys.platform.startswith(("win", "cygwin")): 90 if sys.platform.startswith(("win", "cygwin")):
122 # different meaning of input between Py2 and Py3
123 try: 91 try:
124 input("Press enter to continue...") 92 input("Press enter to continue...")
125 except (EOFError, SyntaxError): 93 except (EOFError, SyntaxError):
126 pass 94 pass
127 95
136 104
137 @param rcode the return code passed back to the calling process. 105 @param rcode the return code passed back to the calling process.
138 """ 106 """
139 global progName, modDir, distDir, apisDir 107 global progName, modDir, distDir, apisDir
140 global macAppBundleName, macAppBundlePath, macPythonExe 108 global macAppBundleName, macAppBundlePath, macPythonExe
141 global pyqtVariant
142 109
143 print() 110 print()
144 print("Usage:") 111 print("Usage:")
145 if sys.platform == "darwin": 112 if sys.platform == "darwin":
146 print(" {0} [-chxyz] [-a dir] [-b dir] [-d dir] [-f file] [-i dir]" 113 print(" {0} [-chxyz] [-a dir] [-b dir] [-d dir] [-f file] [-i dir]"
147 " [-m name] [-n path] [-p python] [--no-apis] [--pyqt=version]" 114 " [-m name] [-n path] [-p python] [--no-apis]"
148 .format(progName)) 115 .format(progName))
149 elif sys.platform.startswith(("win", "cygwin")): 116 elif sys.platform.startswith(("win", "cygwin")):
150 print(" {0} [-chxyz] [-a dir] [-b dir] [-d dir] [-f file]" 117 print(" {0} [-chxyz] [-a dir] [-b dir] [-d dir] [-f file]"
151 " [--clean-desktop] [--no-apis] [--pyqt=version]" 118 " [--clean-desktop] [--no-apis]"
152 .format(progName)) 119 .format(progName))
153 else: 120 else:
154 print(" {0} [-chxyz] [-a dir] [-b dir] [-d dir] [-f file] [-i dir]" 121 print(" {0} [-chxyz] [-a dir] [-b dir] [-d dir] [-f file] [-i dir]"
155 " [--no-apis] [--pyqt=version]" 122 " [--no-apis]"
156 .format(progName)) 123 .format(progName))
157 print("where:") 124 print("where:")
158 print(" -h, --help display this help message") 125 print(" -h, --help display this help message")
159 print(" -a dir where the API files will be installed") 126 print(" -a dir where the API files will be installed")
160 if apisDir: 127 if apisDir:
182 print(" -c don't cleanup old installation first") 149 print(" -c don't cleanup old installation first")
183 if sys.platform.startswith(("win", "cygwin")): 150 if sys.platform.startswith(("win", "cygwin")):
184 (" --clean-desktop delete desktop links before installation") 151 (" --clean-desktop delete desktop links before installation")
185 print(" -x don't perform dependency checks (use on your own" 152 print(" -x don't perform dependency checks (use on your own"
186 " risk)") 153 " risk)")
187 print(" -y add the Python variant to the executable names")
188 print(" -z don't compile the installed python files") 154 print(" -z don't compile the installed python files")
189 print(" --pyqt=version version of PyQt to be used (one of 4 or 5)")
190 if pyqtVariant:
191 print(" (default: {0})".format(pyqtVariant[-1]))
192 else:
193 print(" (no PyQt variant found)")
194 print() 155 print()
195 print("The file given to the -f option must be valid Python code" 156 print("The file given to the -f option must be valid Python code"
196 " defining a") 157 " defining a")
197 print("dictionary called 'cfg' with the keys 'ericDir', 'ericPixDir'," 158 print("dictionary called 'cfg' with the keys 'ericDir', 'ericPixDir',"
198 " 'ericIconDir',") 159 " 'ericIconDir',")
204 " parts of eric6.") 165 " parts of eric6.")
205 166
206 exit(rcode) 167 exit(rcode)
207 168
208 169
209 def determinePyQtVariant():
210 """
211 Module function to determine the PyQt variant to be used.
212 """
213 global pyqtVariant, pyqtOverride
214
215 pyqtVariant = ""
216 # need to handle the --pyqt= option here
217 if "--pyqt=4" in sys.argv:
218 pyqtVariant = "PyQt4"
219 pyqtOverride = True
220 elif "--pyqt=5" in sys.argv:
221 pyqtVariant = "PyQt5"
222 pyqtOverride = True
223 else:
224 try:
225 import PyQt5 # __IGNORE_WARNING__
226 pyqtVariant = "PyQt5"
227 del sys.modules["PyQt5"]
228 except ImportError:
229 try:
230 import PyQt4 # __IGNORE_WARNING__
231 pyqtVariant = "PyQt4"
232 del sys.modules["PyQt4"]
233 except ImportError:
234 # default to PyQt5, installation will be asked for
235 pyqtVariant = "PyQt5"
236
237
238 def initGlobals(): 170 def initGlobals():
239 """ 171 """
240 Module function to set the values of globals that need more than a 172 Module function to set the values of globals that need more than a
241 simple assignment. 173 simple assignment.
242 """ 174 """
243 global platBinDir, modDir, pyModDir, apisDir, pyqtVariant, platBinDirOld 175 global platBinDir, modDir, pyModDir, apisDir, platBinDirOld
244 176
245 try: 177 try:
246 import distutils.sysconfig 178 import distutils.sysconfig
247 except ImportError: 179 except ImportError:
248 print("Please install the 'distutils' package first.") 180 print("Please install the 'distutils' package first.")
269 platBinDirOld = "/usr/local/bin" 201 platBinDirOld = "/usr/local/bin"
270 202
271 modDir = distutils.sysconfig.get_python_lib(True) 203 modDir = distutils.sysconfig.get_python_lib(True)
272 pyModDir = modDir 204 pyModDir = modDir
273 205
274 pyqtDataDir = os.path.join(modDir, pyqtVariant) 206 pyqtDataDir = os.path.join(modDir, "PyQt5")
275 if os.path.exists(os.path.join(pyqtDataDir, "qsci")): 207 if os.path.exists(os.path.join(pyqtDataDir, "qsci")):
276 # it's the installer 208 # it's the installer
277 qtDataDir = pyqtDataDir 209 qtDataDir = pyqtDataDir
278 elif os.path.exists(os.path.join(pyqtDataDir, "Qt", "qsci")): 210 elif os.path.exists(os.path.join(pyqtDataDir, "Qt", "qsci")):
279 # it's the wheel 211 # it's the wheel
280 qtDataDir = os.path.join(pyqtDataDir, "Qt") 212 qtDataDir = os.path.join(pyqtDataDir, "Qt")
281 else: 213 else:
282 # determine dynamically 214 # determine dynamically
283 try: 215 try:
284 if pyqtVariant == "PyQt4": 216 from PyQt5.QtCore import QLibraryInfo
285 from PyQt4.QtCore import QLibraryInfo
286 else:
287 from PyQt5.QtCore import QLibraryInfo
288 qtDataDir = QLibraryInfo.location(QLibraryInfo.DataPath) 217 qtDataDir = QLibraryInfo.location(QLibraryInfo.DataPath)
289 except ImportError: 218 except ImportError:
290 qtDataDir = None 219 qtDataDir = None
291 if qtDataDir: 220 if qtDataDir:
292 apisDir = os.path.join(qtDataDir, "qsci", "api") 221 apisDir = os.path.join(qtDataDir, "qsci", "api")
300 229
301 @param name the name of the file. 230 @param name the name of the file.
302 @param text the contents to copy to the file. 231 @param text the contents to copy to the file.
303 """ 232 """
304 f = open(name, "w") 233 f = open(name, "w")
305 if sys.version_info[0] == 2:
306 text = codecs.encode(text, "utf-8")
307 f.write(text) 234 f.write(text)
308 f.close() 235 f.close()
309 236
310 237
311 def copyDesktopFile(src, dst, marker): 238 def copyDesktopFile(src, dst):
312 """ 239 """
313 Modify a desktop file and write it to its destination. 240 Modify a desktop file and write it to its destination.
314 241
315 @param src source file name (string) 242 @param src source file name (string)
316 @param dst destination file name (string) 243 @param dst destination file name (string)
317 @param marker marker to be used (string)
318 """ 244 """
319 global cfg, platBinDir 245 global cfg, platBinDir
320 246
321 if sys.version_info[0] == 2: 247 f = open(src, "r", encoding="utf-8")
322 f = codecs.open(src, "r", "utf-8")
323 else:
324 f = open(src, "r", encoding="utf-8")
325 text = f.read() 248 text = f.read()
326 f.close() 249 f.close()
327 250
328 text = text.replace("@BINDIR@", platBinDir) 251 text = text.replace("@BINDIR@", platBinDir)
329 text = text.replace("@MARKER@", marker) 252 text = text.replace("@MARKER@", "")
330 if marker: 253 text = text.replace("@PY_MARKER@", "")
331 t_marker = " ({0})".format(PythonTextMarkers[marker]) 254
332 else: 255 f = open(dst, "w", encoding="utf-8")
333 t_marker = ""
334 text = text.replace("@PY_MARKER@", t_marker)
335
336 if sys.version_info[0] == 2:
337 f = codecs.open(dst, "w", "utf-8")
338 else:
339 f = open(dst, "w", encoding="utf-8")
340 f.write(text) 256 f.write(text)
341 f.close() 257 f.close()
342 os.chmod(dst, 0o644) 258 os.chmod(dst, 0o644)
343 259
344 260
345 def copyAppStreamFile(src, dst, marker): 261 def copyAppStreamFile(src, dst):
346 """ 262 """
347 Modify an appstream file and write it to its destination. 263 Modify an appstream file and write it to its destination.
348 264
349 @param src source file name (string) 265 @param src source file name (string)
350 @param dst destination file name (string) 266 @param dst destination file name (string)
351 @param marker marker to be used (string)
352 """ 267 """
353 if os.path.exists(os.path.join("eric", "eric6", "UI", "Info.py")): 268 if os.path.exists(os.path.join("eric", "eric6", "UI", "Info.py")):
354 # Installing from archive 269 # Installing from archive
355 from eric.eric6.UI.Info import Version 270 from eric.eric6.UI.Info import Version
356 elif os.path.exists(os.path.join("eric6", "UI", "Info.py")): 271 elif os.path.exists(os.path.join("eric6", "UI", "Info.py")):
357 # Installing from source tree 272 # Installing from source tree
358 from eric6.UI.Info import Version 273 from eric6.UI.Info import Version
359 else: 274 else:
360 Version = "Unknown" 275 Version = "Unknown"
361 276
362 if sys.version_info[0] == 2: 277 f = open(src, "r", encoding="utf-8")
363 f = codecs.open(src, "r", "utf-8")
364 else:
365 f = open(src, "r", encoding="utf-8")
366 text = f.read() 278 text = f.read()
367 f.close() 279 f.close()
368 280
369 text = text.replace("@MARKER@", marker)\ 281 text = text.replace("@MARKER@", "")\
370 .replace("@VERSION@", Version.split(None, 1)[0])\ 282 .replace("@VERSION@", Version.split(None, 1)[0])\
371 .replace("@DATE@", time.strftime("%Y-%m-%d")) 283 .replace("@DATE@", time.strftime("%Y-%m-%d"))
372 284
373 if sys.version_info[0] == 2: 285 f = open(dst, "w", encoding="utf-8")
374 f = codecs.open(dst, "w", "utf-8")
375 else:
376 f = open(dst, "w", encoding="utf-8")
377 f.write(text) 286 f.write(text)
378 f.close() 287 f.close()
379 os.chmod(dst, 0o644) 288 os.chmod(dst, 0o644)
380 289
381 290
406 @param saveDir directory to save the file into (string) 315 @param saveDir directory to save the file into (string)
407 @param isGuiScript flag indicating a wrapper script for a GUI 316 @param isGuiScript flag indicating a wrapper script for a GUI
408 application (boolean) 317 application (boolean)
409 @return the platform specific name of the wrapper (string) 318 @return the platform specific name of the wrapper (string)
410 """ 319 """
411 global includePythonVariant, pyqtVariant, pyqtOverride
412
413 if includePythonVariant:
414 marker = PythonMarkers[sys.version_info.major]
415 else:
416 marker = ""
417
418 if pyqtOverride and pyqtVariant == "PyQt4":
419 pyqt4opt = " --pyqt4"
420 else:
421 pyqt4opt = ""
422
423 # all kinds of Windows systems 320 # all kinds of Windows systems
424 if sys.platform.startswith(("win", "cygwin")): 321 if sys.platform.startswith(("win", "cygwin")):
425 wname = wfile + marker + ".cmd" 322 wname = wfile + ".cmd"
426 if isGuiScript: 323 if isGuiScript:
427 wrapper = \ 324 wrapper = \
428 '''@echo off\n''' \ 325 '''@echo off\n''' \
429 '''start "" "{2}\\pythonw.exe"''' \ 326 '''start "" "{2}\\pythonw.exe"''' \
430 ''' "{0}\\{1}.pyw"{3}''' \ 327 ''' "{0}\\{1}.pyw"''' \
431 ''' %1 %2 %3 %4 %5 %6 %7 %8 %9\n'''.format( 328 ''' %1 %2 %3 %4 %5 %6 %7 %8 %9\n'''.format(
432 pydir, wfile, sys.exec_prefix, pyqt4opt) 329 pydir, wfile, sys.exec_prefix)
433 else: 330 else:
434 wrapper = \ 331 wrapper = \
435 '''@"{0}\\python" "{1}\\{2}.py"{3}''' \ 332 '''@"{0}\\python" "{1}\\{2}.py"''' \
436 ''' %1 %2 %3 %4 %5 %6 %7 %8 %9\n'''.format( 333 ''' %1 %2 %3 %4 %5 %6 %7 %8 %9\n'''.format(
437 sys.exec_prefix, pydir, wfile, pyqt4opt) 334 sys.exec_prefix, pydir, wfile)
438 335
439 # Mac OS X 336 # Mac OS X
440 elif sys.platform == "darwin": 337 elif sys.platform == "darwin":
441 major = sys.version_info.major 338 major = sys.version_info.major
442 pyexec = "{0}/bin/pythonw{1}".format(sys.exec_prefix, major) 339 pyexec = "{0}/bin/pythonw{1}".format(sys.exec_prefix, major)
443 if not os.path.exists(pyexec): 340 if not os.path.exists(pyexec):
444 pyexec = "{0}/bin/python{1}".format(sys.exec_prefix, major) 341 pyexec = "{0}/bin/python{1}".format(sys.exec_prefix, major)
445 wname = wfile + marker 342 wname = wfile
446 wrapper = ('''#!/bin/sh\n''' 343 wrapper = ('''#!/bin/sh\n'''
447 '''\n''' 344 '''\n'''
448 '''exec "{0}" "{1}/{2}.py"{3} "$@"\n''' 345 '''exec "{0}" "{1}/{2}.py" "$@"\n'''
449 .format(pyexec, pydir, wfile, pyqt4opt)) 346 .format(pyexec, pydir, wfile))
450 347
451 # *nix systems 348 # *nix systems
452 else: 349 else:
453 wname = wfile + marker 350 wname = wfile
454 wrapper = ('''#!/bin/sh\n''' 351 wrapper = ('''#!/bin/sh\n'''
455 '''\n''' 352 '''\n'''
456 '''exec "{0}" "{1}/{2}.py"{3} "$@"\n''' 353 '''exec "{0}" "{1}/{2}.py" "$@"\n'''
457 .format(sys.executable, pydir, wfile, pyqt4opt)) 354 .format(sys.executable, pydir, wfile))
458 355
459 wname = os.path.join(saveDir, wname) 356 wname = os.path.join(saveDir, wname)
460 copyToFile(wname, wrapper) 357 copyToFile(wname, wrapper)
461 os.chmod(wname, 0o755) 358 os.chmod(wname, 0o755)
462 359
572 469
573 def cleanUp(): 470 def cleanUp():
574 """ 471 """
575 Uninstall the old eric files. 472 Uninstall the old eric files.
576 """ 473 """
577 global platBinDir, platBinDirOld, includePythonVariant 474 global platBinDir, platBinDirOld
578 475
579 try: 476 try:
580 from eric6config import getConfig 477 from eric6config import getConfig
581 except ImportError: 478 except ImportError:
582 # eric6 wasn't installed previously 479 # eric6 wasn't installed previously
603 "eric6_trpreviewer", "eric6_uipreviewer", 500 "eric6_trpreviewer", "eric6_uipreviewer",
604 "eric6_unittest", "eric6", 501 "eric6_unittest", "eric6",
605 "eric6_tray", "eric6_editor", 502 "eric6_tray", "eric6_editor",
606 "eric6_plugininstall", "eric6_pluginuninstall", 503 "eric6_plugininstall", "eric6_pluginuninstall",
607 "eric6_pluginrepository", "eric6_sqlbrowser", 504 "eric6_pluginrepository", "eric6_sqlbrowser",
608 "eric6_webbrowser", "eric6_iconeditor", 505 "eric6_iconeditor", "eric6_snap", "eric6_hexeditor",
609 "eric6_snap", "eric6_hexeditor", "eric6_browser", 506 "eric6_browser", "eric6_shell",
610 "eric6_shell", 507 # from Python2 era
508 "eric6_webbrowser",
611 ] 509 ]
612 if includePythonVariant:
613 marker = PythonMarkers[sys.version_info.major]
614 rem_wnames = [n + marker for n in rem_wnames]
615 510
616 try: 511 try:
617 dirs = [platBinDir, getConfig('bindir')] 512 dirs = [platBinDir, getConfig('bindir')]
618 if platBinDirOld: 513 if platBinDirOld:
619 dirs.append(platBinDirOld) 514 dirs.append(platBinDirOld)
678 if os.getuid() == 0: 573 if os.getuid() == 0:
679 for name in ["/usr/share/pixmaps/eric.png", 574 for name in ["/usr/share/pixmaps/eric.png",
680 "/usr/share/pixmaps/ericWeb.png"]: 575 "/usr/share/pixmaps/ericWeb.png"]:
681 if os.path.exists(name): 576 if os.path.exists(name):
682 os.remove(name) 577 os.remove(name)
683 if includePythonVariant:
684 marker = PythonMarkers[sys.version_info.major]
685 else:
686 marker = ""
687 for name in [ 578 for name in [
688 "/usr/share/applications/eric6" + marker + ".desktop", 579 "/usr/share/applications/eric6.desktop",
689 "/usr/share/appdata/eric6" + marker + ".appdata.xml", 580 "/usr/share/appdata/eric6.appdata.xml",
690 "/usr/share/metainfo/eric6" + marker + ".appdata.xml", 581 "/usr/share/metainfo/eric6.appdata.xml",
691 "/usr/share/applications/eric6_webbrowser" + marker + 582 "/usr/share/applications/eric6_browser.desktop",
692 ".desktop", 583 "/usr/share/pixmaps/eric.png",
693 "/usr/share/applications/eric6_browser" + marker + 584 "/usr/share/pixmaps/ericWeb.png",
694 ".desktop", 585 # from Python2 era
695 "/usr/share/pixmaps/eric" + marker + ".png", 586 "/usr/share/applications/eric6_webbrowser.desktop",
696 "/usr/share/pixmaps/ericWeb" + marker + ".png",
697 ]: 587 ]:
698 if os.path.exists(name): 588 if os.path.exists(name):
699 os.remove(name) 589 os.remove(name)
700 elif os.getuid() >= 1000: 590 elif os.getuid() >= 1000:
701 # it is assumed that user ids start at 1000 591 # it is assumed that user ids start at 1000
702 for name in ["~/.local/share/pixmaps/eric.png", 592 for name in ["~/.local/share/pixmaps/eric.png",
703 "~/.local/share/pixmaps/ericWeb.png"]: 593 "~/.local/share/pixmaps/ericWeb.png"]:
704 path = os.path.expanduser(name) 594 path = os.path.expanduser(name)
705 if os.path.exists(path): 595 if os.path.exists(path):
706 os.remove(path) 596 os.remove(path)
707 if includePythonVariant:
708 marker = PythonMarkers[sys.version_info.major]
709 else:
710 marker = ""
711 for name in [ 597 for name in [
712 "~/.local/share/applications/eric6" + marker + ".desktop", 598 "~/.local/share/applications/eric6.desktop",
713 "~/.local/share/appdata/eric6" + marker + ".appdata.xml", 599 "~/.local/share/appdata/eric6.appdata.xml",
714 "~/.local/share/metainfo/eric6" + marker + ".appdata.xml", 600 "~/.local/share/metainfo/eric6.appdata.xml",
715 "~/.local/share/applications/eric6_webbrowser" + marker + 601 "~/.local/share/applications/eric6_browser.desktop",
716 ".desktop", 602 "~/.local/share/pixmaps/eric.png",
717 "~/.local/share/applications/eric6_browser" + marker + 603 "~/.local/share/pixmaps/ericWeb.png",
718 ".desktop", 604 # from Python2 era
719 "~/.local/share/pixmaps/eric" + marker + ".png", 605 "/usr/share/applications/eric6_webbrowser.desktop",
720 "~/.local/share/pixmaps/ericWeb" + marker + ".png",
721 ]: 606 ]:
722 path = os.path.expanduser(name) 607 path = os.path.expanduser(name)
723 if os.path.exists(path): 608 if os.path.exists(path):
724 os.remove(path) 609 os.remove(path)
725 610
807 Actually perform the installation steps. 692 Actually perform the installation steps.
808 693
809 @return result code (integer) 694 @return result code (integer)
810 """ 695 """
811 global distDir, doCleanup, cfg, progLanguages, sourceDir, configName 696 global distDir, doCleanup, cfg, progLanguages, sourceDir, configName
812 global includePythonVariant, installApis 697 global installApis
813 698
814 # Create the platform specific wrappers. 699 # Create the platform specific wrappers.
815 scriptsDir = "install_scripts" 700 scriptsDir = "install_scripts"
816 if not os.path.isdir(scriptsDir): 701 if not os.path.isdir(scriptsDir):
817 os.mkdir(scriptsDir) 702 os.mkdir(scriptsDir)
822 "eric6_editor", "eric6_hexeditor", "eric6_iconeditor", 707 "eric6_editor", "eric6_hexeditor", "eric6_iconeditor",
823 "eric6_plugininstall", "eric6_pluginrepository", 708 "eric6_plugininstall", "eric6_pluginrepository",
824 "eric6_pluginuninstall", "eric6_qregexp", 709 "eric6_pluginuninstall", "eric6_qregexp",
825 "eric6_qregularexpression", "eric6_re", "eric6_snap", 710 "eric6_qregularexpression", "eric6_re", "eric6_snap",
826 "eric6_sqlbrowser", "eric6_tray", "eric6_trpreviewer", 711 "eric6_sqlbrowser", "eric6_tray", "eric6_trpreviewer",
827 "eric6_uipreviewer", "eric6_unittest", "eric6_webbrowser", 712 "eric6_uipreviewer", "eric6_unittest", "eric6_browser",
828 "eric6_browser", "eric6_shell", "eric6"]: 713 "eric6_shell", "eric6"]:
829 wnames.append(createPyWrapper(cfg['ericDir'], name, scriptsDir)) 714 wnames.append(createPyWrapper(cfg['ericDir'], name, scriptsDir))
830 715
831 # set install prefix, if not None 716 # set install prefix, if not None
832 if distDir: 717 if distDir:
833 for key in list(cfg.keys()): 718 for key in list(cfg.keys()):
1014 899
1015 def createLinuxSpecifics(): 900 def createLinuxSpecifics():
1016 """ 901 """
1017 Install Linux specific files. 902 Install Linux specific files.
1018 """ 903 """
1019 global distDir, sourceDir, includePythonVariant 904 global distDir, sourceDir
1020 905
1021 if includePythonVariant:
1022 marker = PythonMarkers[sys.version_info.major]
1023 else:
1024 marker = ""
1025
1026 if distDir: 906 if distDir:
1027 dst = os.path.normpath(os.path.join(distDir, "usr/share/pixmaps")) 907 dst = os.path.normpath(os.path.join(distDir, "usr/share/pixmaps"))
1028 if not os.path.exists(dst): 908 if not os.path.exists(dst):
1029 os.makedirs(dst) 909 os.makedirs(dst)
1030 shutilCopy( 910 shutilCopy(
1031 os.path.join(eric6SourceDir, "icons", "default", "eric.png"), 911 os.path.join(eric6SourceDir, "icons", "default", "eric.png"),
1032 os.path.join(dst, "eric" + marker + ".png")) 912 os.path.join(dst, "eric.png"))
1033 shutilCopy( 913 shutilCopy(
1034 os.path.join(eric6SourceDir, "icons", "default", "ericWeb48.png"), 914 os.path.join(eric6SourceDir, "icons", "default", "ericWeb48.png"),
1035 os.path.join(dst, "ericWeb" + marker + ".png")) 915 os.path.join(dst, "ericWeb.png"))
1036 dst = os.path.normpath( 916 dst = os.path.normpath(
1037 os.path.join(distDir, "usr/share/applications")) 917 os.path.join(distDir, "usr/share/applications"))
1038 if not os.path.exists(dst): 918 if not os.path.exists(dst):
1039 os.makedirs(dst) 919 os.makedirs(dst)
1040 copyDesktopFile(os.path.join(sourceDir, "linux", "eric6.desktop.in"), 920 copyDesktopFile(os.path.join(sourceDir, "linux", "eric6.desktop.in"),
1041 os.path.join(dst, "eric6" + marker + ".desktop"), 921 os.path.join(dst, "eric6.desktop"))
1042 marker)
1043 copyDesktopFile(
1044 os.path.join(sourceDir, "linux", "eric6_webbrowser.desktop.in"),
1045 os.path.join(dst, "eric6_webbrowser" + marker + ".desktop"),
1046 marker)
1047 copyDesktopFile( 922 copyDesktopFile(
1048 os.path.join(sourceDir, "linux", "eric6_browser.desktop.in"), 923 os.path.join(sourceDir, "linux", "eric6_browser.desktop.in"),
1049 os.path.join(dst, "eric6_browser" + marker + ".desktop"), 924 os.path.join(dst, "eric6_browser.desktop"))
1050 marker)
1051 dst = os.path.normpath( 925 dst = os.path.normpath(
1052 os.path.join(distDir, "usr/share/metainfo")) 926 os.path.join(distDir, "usr/share/metainfo"))
1053 if not os.path.exists(dst): 927 if not os.path.exists(dst):
1054 os.makedirs(dst) 928 os.makedirs(dst)
1055 copyAppStreamFile( 929 copyAppStreamFile(
1056 os.path.join(sourceDir, "linux", "eric6.appdata.xml.in"), 930 os.path.join(sourceDir, "linux", "eric6.appdata.xml.in"),
1057 os.path.join(dst, "eric6" + marker + ".appdata.xml"), 931 os.path.join(dst, "eric6.appdata.xml"))
1058 marker)
1059 elif os.getuid() == 0: 932 elif os.getuid() == 0:
1060 shutilCopy(os.path.join( 933 shutilCopy(os.path.join(
1061 eric6SourceDir, "icons", "default", "eric.png"), 934 eric6SourceDir, "icons", "default", "eric.png"),
1062 "/usr/share/pixmaps/eric" + marker + ".png") 935 "/usr/share/pixmaps/eric.png")
1063 copyDesktopFile( 936 copyDesktopFile(
1064 os.path.join(sourceDir, "linux", "eric6.desktop.in"), 937 os.path.join(sourceDir, "linux", "eric6.desktop.in"),
1065 "/usr/share/applications/eric6" + marker + ".desktop", 938 "/usr/share/applications/eric6.desktop")
1066 marker)
1067 if os.path.exists("/usr/share/metainfo"): 939 if os.path.exists("/usr/share/metainfo"):
1068 copyAppStreamFile( 940 copyAppStreamFile(
1069 os.path.join(sourceDir, "linux", "eric6.appdata.xml.in"), 941 os.path.join(sourceDir, "linux", "eric6.appdata.xml.in"),
1070 "/usr/share/metainfo/eric6" + marker + ".appdata.xml", 942 "/usr/share/metainfo/eric6.appdata.xml")
1071 marker)
1072 elif os.path.exists("/usr/share/appdata"): 943 elif os.path.exists("/usr/share/appdata"):
1073 copyAppStreamFile( 944 copyAppStreamFile(
1074 os.path.join(sourceDir, "linux", "eric6.appdata.xml.in"), 945 os.path.join(sourceDir, "linux", "eric6.appdata.xml.in"),
1075 "/usr/share/appdata/eric6" + marker + ".appdata.xml", 946 "/usr/share/appdata/eric6.appdata.xml")
1076 marker)
1077 shutilCopy(os.path.join( 947 shutilCopy(os.path.join(
1078 eric6SourceDir, "icons", "default", "ericWeb48.png"), 948 eric6SourceDir, "icons", "default", "ericWeb48.png"),
1079 "/usr/share/pixmaps/ericWeb" + marker + ".png") 949 "/usr/share/pixmaps/ericWeb.png")
1080 copyDesktopFile(
1081 os.path.join(sourceDir, "linux", "eric6_webbrowser.desktop.in"),
1082 "/usr/share/applications/eric6_webbrowser" + marker +
1083 ".desktop",
1084 marker)
1085 copyDesktopFile( 950 copyDesktopFile(
1086 os.path.join(sourceDir, "linux", "eric6_browser.desktop.in"), 951 os.path.join(sourceDir, "linux", "eric6_browser.desktop.in"),
1087 "/usr/share/applications/eric6_browser" + marker + 952 "/usr/share/applications/eric6_browser.desktop")
1088 ".desktop",
1089 marker)
1090 elif os.getuid() >= 1000: 953 elif os.getuid() >= 1000:
1091 # it is assumed, that user ids start at 1000 954 # it is assumed, that user ids start at 1000
1092 localPath = os.path.join(os.path.expanduser("~"), 955 localPath = os.path.join(os.path.expanduser("~"),
1093 ".local", "share") 956 ".local", "share")
1094 # create directories first 957 # create directories first
1098 if not os.path.isdir(directory): 961 if not os.path.isdir(directory):
1099 os.makedirs(directory) 962 os.makedirs(directory)
1100 # now copy the files 963 # now copy the files
1101 shutilCopy( 964 shutilCopy(
1102 os.path.join(eric6SourceDir, "icons", "default", "eric.png"), 965 os.path.join(eric6SourceDir, "icons", "default", "eric.png"),
1103 os.path.join(localPath, "pixmaps", "eric" + marker + ".png")) 966 os.path.join(localPath, "pixmaps", "eric.png"))
1104 copyDesktopFile( 967 copyDesktopFile(
1105 os.path.join(sourceDir, "linux", "eric6.desktop.in"), 968 os.path.join(sourceDir, "linux", "eric6.desktop.in"),
1106 os.path.join(localPath, "applications", 969 os.path.join(localPath, "applications", "eric6.desktop"))
1107 "eric6" + marker + ".desktop"),
1108 marker)
1109 copyAppStreamFile( 970 copyAppStreamFile(
1110 os.path.join(sourceDir, "linux", "eric6.appdata.xml.in"), 971 os.path.join(sourceDir, "linux", "eric6.appdata.xml.in"),
1111 os.path.join(localPath, "metainfo", 972 os.path.join(localPath, "metainfo", "eric6.appdata.xml"))
1112 "eric6" + marker + ".appdata.xml"),
1113 marker)
1114 copyAppStreamFile( 973 copyAppStreamFile(
1115 os.path.join(sourceDir, "linux", "eric6.appdata.xml.in"), 974 os.path.join(sourceDir, "linux", "eric6.appdata.xml.in"),
1116 os.path.join(localPath, "appdata", 975 os.path.join(localPath, "appdata", "eric6.appdata.xml"))
1117 "eric6" + marker + ".appdata.xml"),
1118 marker)
1119 shutilCopy( 976 shutilCopy(
1120 os.path.join(eric6SourceDir, "icons", "default", "ericWeb48.png"), 977 os.path.join(eric6SourceDir, "icons", "default", "ericWeb48.png"),
1121 os.path.join(localPath, "pixmaps", 978 os.path.join(localPath, "pixmaps", "ericWeb.png"))
1122 "ericWeb" + marker + ".png"))
1123 copyDesktopFile(
1124 os.path.join(sourceDir, "linux", "eric6_webbrowser.desktop.in"),
1125 os.path.join(localPath, "applications",
1126 "eric6_webbrowser" + marker + ".desktop"),
1127 marker)
1128 copyDesktopFile( 979 copyDesktopFile(
1129 os.path.join(sourceDir, "linux", "eric6_browser.desktop.in"), 980 os.path.join(sourceDir, "linux", "eric6_browser.desktop.in"),
1130 os.path.join(localPath, "applications", 981 os.path.join(localPath, "applications", "eric6_browser.desktop"))
1131 "eric6_browser" + marker + ".desktop"),
1132 marker)
1133 982
1134 983
1135 def createWindowsLinks(): 984 def createWindowsLinks():
1136 """ 985 """
1137 Create Desktop and Start Menu links. 986 Create Desktop and Start Menu links.
1150 args = [ 999 args = [
1151 sys.executable, 1000 sys.executable,
1152 os.path.join(os.path.dirname(__file__), 1001 os.path.join(os.path.dirname(__file__),
1153 "create_windows_links.py"), 1002 "create_windows_links.py"),
1154 ] 1003 ]
1155 if includePythonVariant:
1156 args.append("-y")
1157 subprocess.call(args) 1004 subprocess.call(args)
1158 else: 1005 else:
1159 print( 1006 print(
1160 "\nThe Python package 'pywin32' is not installed. Desktop and" 1007 "\nThe Python package 'pywin32' is not installed. Desktop and"
1161 " Start Menu entries will not be created." 1008 " Start Menu entries will not be created."
1197 1044
1198 @param pydir the name of the directory where the Python script will 1045 @param pydir the name of the directory where the Python script will
1199 eventually be installed 1046 eventually be installed
1200 @type str 1047 @type str
1201 """ 1048 """
1202 global cfg, macAppBundleName, macPythonExe, macAppBundlePath, pyqtVariant 1049 global cfg, macAppBundleName, macPythonExe, macAppBundlePath
1203 1050
1204 directories = { 1051 directories = {
1205 "contents": "{0}/{1}/Contents/".format( 1052 "contents": "{0}/{1}/Contents/".format(
1206 macAppBundlePath, macAppBundleName), 1053 macAppBundlePath, macAppBundleName),
1207 "exe": "{0}/{1}/Contents/MacOS".format( 1054 "exe": "{0}/{1}/Contents/MacOS".format(
1222 wname = os.path.join(directories["exe"], "eric6") 1069 wname = os.path.join(directories["exe"], "eric6")
1223 1070
1224 # determine entry for DYLD_FRAMEWORK_PATH 1071 # determine entry for DYLD_FRAMEWORK_PATH
1225 dyldLine = "" 1072 dyldLine = ""
1226 try: 1073 try:
1227 if pyqtVariant == "PyQt4": 1074 from PyQt5.QtCore import QLibraryInfo
1228 from PyQt4.QtCore import QLibraryInfo
1229 else:
1230 from PyQt5.QtCore import QLibraryInfo
1231 qtLibraryDir = QLibraryInfo.location(QLibraryInfo.LibrariesPath) 1075 qtLibraryDir = QLibraryInfo.location(QLibraryInfo.LibrariesPath)
1232 except ImportError: 1076 except ImportError:
1233 qtLibraryDir = "" 1077 qtLibraryDir = ""
1234 if qtLibraryDir: 1078 if qtLibraryDir:
1235 dyldLine = "DYLD_FRAMEWORK_PATH={0}\n".format(qtLibraryDir) 1079 dyldLine = "DYLD_FRAMEWORK_PATH={0}\n".format(qtLibraryDir)
1435 @rtype bool 1279 @rtype bool
1436 """ 1280 """
1437 ok = False 1281 ok = False
1438 print("{0}\n\nShall '{1}' be installed using pip? (Y/n)" 1282 print("{0}\n\nShall '{1}' be installed using pip? (Y/n)"
1439 .format(message, packageName), end=" ") 1283 .format(message, packageName), end=" ")
1440 if sys.version_info[0] == 2: 1284 answer = input()
1441 answer = raw_input() # __IGNORE_WARNING__
1442 else:
1443 answer = input()
1444 if answer in ("", "Y", "y"): 1285 if answer in ("", "Y", "y"):
1445 exitCode = subprocess.call( 1286 exitCode = subprocess.call(
1446 [sys.executable, "-m", "pip", "install", packageName]) 1287 [sys.executable, "-m", "pip", "install", packageName])
1447 ok = (exitCode == 0) 1288 ok = (exitCode == 0)
1448 1289
1455 """ 1296 """
1456 print('Checking dependencies') 1297 print('Checking dependencies')
1457 1298
1458 # perform dependency checks 1299 # perform dependency checks
1459 print("Python Version: {0:d}.{1:d}.{2:d}".format(*sys.version_info[:3])) 1300 print("Python Version: {0:d}.{1:d}.{2:d}".format(*sys.version_info[:3]))
1460 if sys.version_info < (2, 7, 10): 1301 if sys.version_info < (3, 5, 0):
1461 print('Sorry, you must have Python 2.7.10 or higher or '
1462 'Python 3.5.0 or higher.')
1463 exit(5)
1464 elif sys.version_info < (3, 5, 0) and sys.version_info[0] == 3:
1465 print('Sorry, you must have Python 3.5.0 or higher.') 1302 print('Sorry, you must have Python 3.5.0 or higher.')
1466 exit(5) 1303 exit(5)
1467 if sys.version_info[0] > 3: 1304 if sys.version_info[0] > 3:
1468 print('Sorry, eric6 requires Python 3 or Python 2 for running.') 1305 print('Sorry, eric6 requires Python 3 for running.')
1469 exit(5) 1306 exit(5)
1470 1307
1471 try: 1308 try:
1472 import xml.etree # __IGNORE_WARNING__ 1309 import xml.etree # __IGNORE_WARNING__
1473 except ImportError: 1310 except ImportError:
1474 print('Your Python installation is missing the XML module.') 1311 print('Your Python installation is missing the XML module.')
1475 print('Please install it and try again.') 1312 print('Please install it and try again.')
1476 exit(5) 1313 exit(5)
1477 1314
1478 if pyqtVariant == "PyQt4": 1315 try:
1479 try: 1316 from PyQt5.QtCore import qVersion
1480 from PyQt4.QtCore import qVersion 1317 except ImportError as msg:
1481 except ImportError as msg: 1318 installed = pipInstall(
1482 print('Sorry, please install PyQt4.') 1319 "PyQt5",
1483 print('Error: {0}'.format(msg)) 1320 "PyQt5 could not be detected.\nError: {0}".format(msg)
1484 exit(1) 1321 )
1485 print("Found PyQt4") 1322 if installed:
1486 else: 1323 # try to import it again
1487 try: 1324 try:
1488 from PyQt5.QtCore import qVersion 1325 from PyQt5.QtCore import qVersion
1489 except ImportError as msg: 1326 except ImportError as msg:
1490 if sys.version_info[0] == 2:
1491 # no PyQt5 wheels available for Python 2
1492 installed = False
1493 else:
1494 installed = pipInstall(
1495 "PyQt5",
1496 "PyQt5 could not be detected.\nError: {0}".format(msg)
1497 )
1498 if installed:
1499 # try to import it again
1500 try:
1501 from PyQt5.QtCore import qVersion
1502 except ImportError as msg:
1503 print('Sorry, please install PyQt5.')
1504 print('Error: {0}'.format(msg))
1505 exit(1)
1506 else:
1507 print('Sorry, please install PyQt5.') 1327 print('Sorry, please install PyQt5.')
1508 print('Error: {0}'.format(msg)) 1328 print('Error: {0}'.format(msg))
1509 exit(1) 1329 exit(1)
1510 print("Found PyQt5")
1511
1512 try:
1513 if pyqtVariant == "PyQt4":
1514 pyuic = "pyuic4"
1515 from PyQt4 import uic # __IGNORE_WARNING__
1516 else: 1330 else:
1517 pyuic = "pyuic5" 1331 print('Sorry, please install PyQt5.')
1518 from PyQt5 import uic # __IGNORE_WARNING__ 1332 print('Error: {0}'.format(msg))
1333 exit(1)
1334 print("Found PyQt5")
1335
1336 try:
1337 pyuic = "pyuic5"
1338 from PyQt5 import uic # __IGNORE_WARNING__
1519 except ImportError as msg: 1339 except ImportError as msg:
1520 print("Sorry, {0} is not installed.".format(pyuic)) 1340 print("Sorry, {0} is not installed.".format(pyuic))
1521 print('Error: {0}'.format(msg)) 1341 print('Error: {0}'.format(msg))
1522 exit(1) 1342 exit(1)
1523 print("Found {0}".format(pyuic)) 1343 print("Found {0}".format(pyuic))
1524 1344
1525 if pyqtVariant != "PyQt4": 1345 try:
1526 try: 1346 from PyQt5 import QtWebEngineWidgets # __IGNORE_WARNING__
1527 from PyQt5 import QtWebEngineWidgets # __IGNORE_WARNING__ 1347 except ImportError as msg:
1528 except ImportError as msg: 1348 from PyQt5.QtCore import PYQT_VERSION
1529 from PyQt5.QtCore import PYQT_VERSION 1349 if PYQT_VERSION >= 0x050c00:
1530 if PYQT_VERSION >= 0x50c00: 1350 # PyQt 5.12 separated QtWebEngine into a separate wheel
1531 # PyQt 5.12 separated QtWebEngine into a separate wheel
1532 installed = pipInstall(
1533 "PyQtWebEngine",
1534 "PyQtWebEngine could not be detected.\nError: {0}"
1535 .format(msg)
1536 )
1537
1538 try:
1539 from PyQt5 import QtChart # __IGNORE_WARNING__
1540 except ImportError as msg:
1541 installed = pipInstall( 1351 installed = pipInstall(
1542 "PyQtChart", 1352 "PyQtWebEngine",
1543 "PyQtChart could not be detected.\nError: {0}" 1353 "PyQtWebEngine could not be detected.\nError: {0}"
1544 .format(msg) 1354 .format(msg)
1545 ) 1355 )
1546 1356
1547 try: 1357 try:
1548 if pyqtVariant == "PyQt4": 1358 from PyQt5 import QtChart # __IGNORE_WARNING__
1549 from PyQt4 import Qsci # __IGNORE_WARNING__ 1359 except ImportError as msg:
1360 installed = pipInstall(
1361 "PyQtChart",
1362 "PyQtChart could not be detected.\nError: {0}"
1363 .format(msg)
1364 )
1365
1366 try:
1367 from PyQt5 import Qsci # __IGNORE_WARNING__
1368 except ImportError as msg:
1369 installed = pipInstall(
1370 "QScintilla",
1371 "QScintilla could not be detected.\nError: {0}".format(msg)
1372 )
1373 if installed:
1374 # try to import it again
1375 try:
1376 from PyQt5 import Qsci # __IGNORE_WARNING__
1377 message = None
1378 except ImportError as msg:
1379 message = str(msg)
1550 else: 1380 else:
1551 from PyQt5 import Qsci # __IGNORE_WARNING__ 1381 message = "QScintilla could not be installed."
1552 except ImportError as msg:
1553 if pyqtVariant == "PyQt4":
1554 message = str(msg)
1555 else:
1556 installed = pipInstall(
1557 "QScintilla",
1558 "QScintilla could not be detected.\nError: {0}".format(msg)
1559 )
1560 if installed:
1561 # try to import it again
1562 try:
1563 from PyQt5 import Qsci # __IGNORE_WARNING__
1564 message = None
1565 except ImportError as msg:
1566 message = str(msg)
1567 else:
1568 message = "QScintilla could not be installed."
1569 if message: 1382 if message:
1570 print("Sorry, please install QScintilla2 and") 1383 print("Sorry, please install QScintilla2 and")
1571 print("its PyQt5/PyQt4 wrapper.") 1384 print("its PyQt5 wrapper.")
1572 print('Error: {0}'.format(message)) 1385 print('Error: {0}'.format(message))
1573 exit(1) 1386 exit(1)
1574 print("Found QScintilla2") 1387 print("Found QScintilla2")
1575 1388
1576 if pyqtVariant == "PyQt4": 1389 impModulesList = [
1577 impModulesList = [ 1390 "PyQt5.QtGui", "PyQt5.QtNetwork", "PyQt5.QtPrintSupport",
1578 "PyQt4.QtGui", "PyQt4.QtNetwork", "PyQt4.QtSql", 1391 "PyQt5.QtSql", "PyQt5.QtSvg", "PyQt5.QtWidgets",
1579 "PyQt4.QtSvg", "PyQt4.QtWebKit", 1392 ]
1580 ] 1393 altModulesList = [
1581 altModulesList = [] 1394 # Tuple with alternatives, flag indicating it's ok to not be
1582 else: 1395 # available (e.g. for 32-Bit Windows)
1583 impModulesList = [ 1396 (("PyQt5.QtWebEngineWidgets", ), sys.maxsize <= 2**32),
1584 "PyQt5.QtGui", "PyQt5.QtNetwork", "PyQt5.QtPrintSupport", 1397 ]
1585 "PyQt5.QtSql", "PyQt5.QtSvg", "PyQt5.QtWidgets",
1586 ]
1587 altModulesList = [
1588 # Tuple with alternatives, flag indicating it's ok to not be
1589 # available (e.g. for 32-Bit Windows)
1590 (("PyQt5.QtWebEngineWidgets", "PyQt5.QtWebKitWidgets"),
1591 sys.maxsize <= 2**32),
1592 ]
1593 # check mandatory modules 1398 # check mandatory modules
1594 modulesOK = True 1399 modulesOK = True
1595 for impModule in impModulesList: 1400 for impModule in impModulesList:
1596 name = impModule.split(".")[1] 1401 name = impModule.split(".")[1]
1597 try: 1402 try:
1634 1439
1635 # check version of Qt 1440 # check version of Qt
1636 qtMajor = int(qVersion().split('.')[0]) 1441 qtMajor = int(qVersion().split('.')[0])
1637 qtMinor = int(qVersion().split('.')[1]) 1442 qtMinor = int(qVersion().split('.')[1])
1638 print("Qt Version: {0}".format(qVersion().strip())) 1443 print("Qt Version: {0}".format(qVersion().strip()))
1639 if qtMajor < 4 or \ 1444 if qtMajor == 5 and qtMinor < 9:
1640 (qtMajor == 4 and qtMinor < 8) or \ 1445 print('Sorry, you must have Qt version 5.9.0 or better.')
1641 (qtMajor == 5 and qtMinor < 9):
1642 print('Sorry, you must have Qt version 4.8.0 or better or')
1643 print('5.9.0 or better.')
1644 exit(2) 1446 exit(2)
1645 1447
1646 # check version of sip 1448 # check version of sip
1647 try: 1449 try:
1648 try: 1450 try:
1674 exit(3) 1476 exit(3)
1675 except (ImportError, AttributeError): 1477 except (ImportError, AttributeError):
1676 pass 1478 pass
1677 1479
1678 # check version of PyQt 1480 # check version of PyQt
1679 if pyqtVariant == "PyQt4": 1481 from PyQt5.QtCore import PYQT_VERSION_STR
1680 from PyQt4.QtCore import PYQT_VERSION_STR
1681 else:
1682 from PyQt5.QtCore import PYQT_VERSION_STR
1683 pyqtVersion = PYQT_VERSION_STR 1482 pyqtVersion = PYQT_VERSION_STR
1684 print("PyQt Version:", pyqtVersion.strip()) 1483 print("PyQt Version:", pyqtVersion.strip())
1685 # always assume, that snapshots or dev versions are new enough 1484 # always assume, that snapshots or dev versions are new enough
1686 if "snapshot" not in pyqtVersion and "dev" not in pyqtVersion: 1485 if "snapshot" not in pyqtVersion and "dev" not in pyqtVersion:
1687 while pyqtVersion.count('.') < 2: 1486 while pyqtVersion.count('.') < 2:
1688 pyqtVersion += '.0' 1487 pyqtVersion += '.0'
1689 (major, minor, pat) = pyqtVersion.split('.') 1488 (major, minor, pat) = pyqtVersion.split('.')
1690 major = int(major) 1489 major = int(major)
1691 minor = int(minor) 1490 minor = int(minor)
1692 pat = int(pat) 1491 pat = int(pat)
1693 if major < 4 or \ 1492 if major == 5 and minor < 9:
1694 (major == 4 and minor < 10) or \ 1493 print('Sorry, you must have PyQt 5.9.0 or better or'
1695 (major == 5 and minor < 9):
1696 print('Sorry, you must have PyQt 4.10.0 or better or')
1697 print('PyQt 5.9.0 or better or'
1698 ' a recent snapshot release.') 1494 ' a recent snapshot release.')
1699 exit(4) 1495 exit(4)
1700 # check for blacklisted versions 1496 # check for blacklisted versions
1701 for vers in BlackLists[pyqtVariant] + PlatformBlackLists[pyqtVariant]: 1497 for vers in BlackLists["PyQt5"] + PlatformBlackLists["PyQt5"]:
1702 if vers == pyqtVersion: 1498 if vers == pyqtVersion:
1703 print('Sorry, PyQt version {0} is not compatible with eric6.' 1499 print('Sorry, PyQt version {0} is not compatible with eric6.'
1704 .format(vers)) 1500 .format(vers))
1705 print('Please install another version.') 1501 print('Please install another version.')
1706 exit(4) 1502 exit(4)
1707 1503
1708 # check version of QScintilla 1504 # check version of QScintilla
1709 if pyqtVariant == "PyQt4": 1505 from PyQt5.Qsci import QSCINTILLA_VERSION_STR
1710 from PyQt4.Qsci import QSCINTILLA_VERSION_STR
1711 else:
1712 from PyQt5.Qsci import QSCINTILLA_VERSION_STR
1713 scintillaVersion = QSCINTILLA_VERSION_STR 1506 scintillaVersion = QSCINTILLA_VERSION_STR
1714 print("QScintilla Version:", QSCINTILLA_VERSION_STR.strip()) 1507 print("QScintilla Version:", QSCINTILLA_VERSION_STR.strip())
1715 # always assume, that snapshots or dev versions are new enough 1508 # always assume, that snapshots or dev versions are new enough
1716 if "snapshot" not in scintillaVersion and "dev" not in scintillaVersion: 1509 if "snapshot" not in scintillaVersion and "dev" not in scintillaVersion:
1717 while scintillaVersion.count('.') < 2: 1510 while scintillaVersion.count('.') < 2:
1752 1545
1753 def compileUiFiles(): 1546 def compileUiFiles():
1754 """ 1547 """
1755 Compile the .ui files to Python sources. 1548 Compile the .ui files to Python sources.
1756 """ 1549 """
1757 if pyqtVariant == "PyQt4": 1550 from PyQt5.uic import compileUiDir
1758 from PyQt4.uic import compileUiDir
1759 else:
1760 from PyQt5.uic import compileUiDir
1761 compileUiDir(eric6SourceDir, True, __pyName) 1551 compileUiDir(eric6SourceDir, True, __pyName)
1762 1552
1763 1553
1764 def prepareInfoFile(fileName): 1554 def prepareInfoFile(fileName):
1765 """ 1555 """
1774 os.rename(fileName, fileName + ".orig") 1564 os.rename(fileName, fileName + ".orig")
1775 except EnvironmentError: 1565 except EnvironmentError:
1776 pass 1566 pass
1777 try: 1567 try:
1778 hgOut = subprocess.check_output(["hg", "identify", "-i"]) 1568 hgOut = subprocess.check_output(["hg", "identify", "-i"])
1779 if sys.version_info[0] == 3: 1569 hgOut = hgOut.decode()
1780 hgOut = hgOut.decode()
1781 except (OSError, subprocess.CalledProcessError): 1570 except (OSError, subprocess.CalledProcessError):
1782 hgOut = "" 1571 hgOut = ""
1783 if hgOut: 1572 if hgOut:
1784 hgOut = hgOut.strip() 1573 hgOut = hgOut.strip()
1785 if hgOut.endswith("+"): 1574 if hgOut.endswith("+"):
1786 hgOut = hgOut[:-1] 1575 hgOut = hgOut[:-1]
1787 if sys.version_info[0] == 2: 1576 f = open(fileName + ".orig", "r", encoding="utf-8")
1788 f = codecs.open(fileName + ".orig", "r", "utf-8")
1789 else:
1790 f = open(fileName + ".orig", "r", encoding="utf-8")
1791 text = f.read() 1577 text = f.read()
1792 f.close() 1578 f.close()
1793 text = text.replace("@@REVISION@@", hgOut)\ 1579 text = text.replace("@@REVISION@@", hgOut)\
1794 .replace("@@VERSION@@", "rev_" + hgOut) 1580 .replace("@@VERSION@@", "rev_" + hgOut)
1795 copyToFile(fileName, text) 1581 copyToFile(fileName, text)
1807 @type str 1593 @type str
1808 @return value of requested registry variable 1594 @return value of requested registry variable
1809 @rtype any 1595 @rtype any
1810 """ 1596 """
1811 try: 1597 try:
1812 import _winreg as winreg 1598 import winreg
1813 except ImportError: 1599 except ImportError:
1814 try: 1600 return None
1815 import winreg
1816 except ImportError:
1817 return None
1818 1601
1819 try: 1602 try:
1820 registryKey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, path, 0, 1603 registryKey = winreg.OpenKey(winreg.HKEY_CURRENT_USER, path, 0,
1821 winreg.KEY_READ) 1604 winreg.KEY_READ)
1822 value, _ = winreg.QueryValueEx(registryKey, name) 1605 value, _ = winreg.QueryValueEx(registryKey, name)
1868 1651
1869 @return list of tuples containing the desktop link name, 1652 @return list of tuples containing the desktop link name,
1870 the link target and the icon target 1653 the link target and the icon target
1871 @rtype list of tuples of (str, str, str) 1654 @rtype list of tuples of (str, str, str)
1872 """ 1655 """
1873 global cfg, includePythonVariant 1656 global cfg
1874
1875 if includePythonVariant:
1876 marker = PythonMarkers[sys.version_info.major]
1877 else:
1878 marker = ""
1879 1657
1880 majorVersion, minorVersion = sys.version_info[:2] 1658 majorVersion, minorVersion = sys.version_info[:2]
1881 entriesTemplates = [ 1659 entriesTemplates = [
1882 ("eric6 (Python {0}.{1}).lnk", 1660 ("eric6 (Python {0}.{1}).lnk",
1883 os.path.join(cfg["bindir"], "eric6" + marker + ".cmd"), 1661 os.path.join(cfg["bindir"], "eric6.cmd"),
1884 os.path.join(cfg["ericPixDir"], "eric6.ico")), 1662 os.path.join(cfg["ericPixDir"], "eric6.ico")),
1663 ("eric6 Browser (Python {0}.{1}).lnk",
1664 os.path.join(cfg["bindir"], "eric6_browse.cmd"),
1665 os.path.join(cfg["ericPixDir"], "ericWeb48.ico")),
1885 ] 1666 ]
1886 if sys.version_info.major == 2:
1887 entriesTemplates.append((
1888 "eric6 Browser (Python {0}.{1}).lnk",
1889 os.path.join(cfg["bindir"], "eric6_webbrowser" + marker + ".cmd"),
1890 os.path.join(cfg["ericPixDir"], "ericWeb48.ico")
1891 ))
1892 else:
1893 entriesTemplates.append((
1894 "eric6 Browser (Python {0}.{1}).lnk",
1895 os.path.join(cfg["bindir"], "eric6_browser" + marker + ".cmd"),
1896 os.path.join(cfg["ericPixDir"], "ericWeb48.ico")
1897 ))
1898 1667
1899 return [ 1668 return [
1900 (e[0].format(majorVersion, minorVersion), e[1], e[2]) 1669 (e[0].format(majorVersion, minorVersion), e[1], e[2])
1901 for e in entriesTemplates 1670 for e in entriesTemplates
1902 ] 1671 ]
1922 """ 1691 """
1923 import getopt 1692 import getopt
1924 1693
1925 # Parse the command line. 1694 # Parse the command line.
1926 global progName, modDir, doCleanup, doCompile, distDir, cfg, apisDir 1695 global progName, modDir, doCleanup, doCompile, distDir, cfg, apisDir
1927 global sourceDir, eric6SourceDir, configName, includePythonVariant 1696 global sourceDir, eric6SourceDir, configName
1928 global macAppBundlePath, macAppBundleName, macPythonExe 1697 global macAppBundlePath, macAppBundleName, macPythonExe
1929 global pyqtVariant, pyqtOverride, installApis, doCleanDesktopLinks 1698 global installApis, doCleanDesktopLinks
1930 1699
1931 if sys.version_info < (2, 7, 0) or sys.version_info > (3, 9, 9): 1700 if sys.version_info < (3, 5, 0) or sys.version_info > (3, 99, 99):
1932 print('Sorry, eric6 requires at least Python 2.7 or ' 1701 print('Sorry, eric6 requires at least Python 3.5 for running.')
1933 'Python 3 for running.')
1934 exit(5) 1702 exit(5)
1935 1703
1936 progName = os.path.basename(argv[0]) 1704 progName = os.path.basename(argv[0])
1937 1705
1938 if os.path.dirname(argv[0]): 1706 if os.path.dirname(argv[0]):
1939 os.chdir(os.path.dirname(argv[0])) 1707 os.chdir(os.path.dirname(argv[0]))
1940 1708
1941 determinePyQtVariant()
1942 initGlobals() 1709 initGlobals()
1943 1710
1944 try: 1711 try:
1945 if sys.platform.startswith(("win", "cygwin")): 1712 if sys.platform.startswith(("win", "cygwin")):
1946 optlist, args = getopt.getopt( 1713 optlist, args = getopt.getopt(
1947 argv[1:], "chxyza:b:d:f:", 1714 argv[1:], "chxza:b:d:f:",
1948 ["help", "pyqt=", "no-apis"]) 1715 ["help", "no-apis"])
1949 elif sys.platform == "darwin": 1716 elif sys.platform == "darwin":
1950 optlist, args = getopt.getopt( 1717 optlist, args = getopt.getopt(
1951 argv[1:], "chxyza:b:d:f:i:m:n:p:", 1718 argv[1:], "chxza:b:d:f:i:m:n:p:",
1952 ["help", "pyqt=", "no-apis"]) 1719 ["help", "no-apis"])
1953 else: 1720 else:
1954 optlist, args = getopt.getopt( 1721 optlist, args = getopt.getopt(
1955 argv[1:], "chxyza:b:d:f:i:", 1722 argv[1:], "chxza:b:d:f:i:",
1956 ["help", "pyqt=", "no-apis"]) 1723 ["help", "no-apis"])
1957 except getopt.GetoptError as err: 1724 except getopt.GetoptError as err:
1958 print(err) 1725 print(err)
1959 usage() 1726 usage()
1960 1727
1961 global platBinDir 1728 global platBinDir
1977 depChecks = False 1744 depChecks = False
1978 elif opt == "-c": 1745 elif opt == "-c":
1979 doCleanup = False 1746 doCleanup = False
1980 elif opt == "-z": 1747 elif opt == "-z":
1981 doCompile = False 1748 doCompile = False
1982 elif opt == "-y":
1983 includePythonVariant = True
1984 elif opt == "-f": 1749 elif opt == "-f":
1985 try: 1750 try:
1986 exec(compile(open(arg).read(), arg, 'exec'), globals()) 1751 exec(compile(open(arg).read(), arg, 'exec'), globals())
1987 if len(cfg) != configLength: 1752 if len(cfg) != configLength:
1988 print("The configuration dictionary in '{0}' is incorrect." 1753 print("The configuration dictionary in '{0}' is incorrect."
1994 macAppBundleName = arg 1759 macAppBundleName = arg
1995 elif opt == "-n": 1760 elif opt == "-n":
1996 macAppBundlePath = arg 1761 macAppBundlePath = arg
1997 elif opt == "-p": 1762 elif opt == "-p":
1998 macPythonExe = arg 1763 macPythonExe = arg
1999 elif opt == "--pyqt":
2000 if arg not in ["4", "5"]:
2001 print("Invalid PyQt version given; should be 4 or 5. Aborting")
2002 exit(6)
2003 pyqtVariant = "PyQt{0}".format(arg)
2004 pyqtOverride = True
2005 elif opt == "--no-apis": 1764 elif opt == "--no-apis":
2006 installApis = False 1765 installApis = False
2007 elif opt == "--clean-desktop": 1766 elif opt == "--clean-desktop":
2008 doCleanDesktopLinks = True 1767 doCleanDesktopLinks = True
2009 1768
2070 # step 2: compile the forms 1829 # step 2: compile the forms
2071 compileUiFiles() 1830 compileUiFiles()
2072 1831
2073 if doCompile: 1832 if doCompile:
2074 print("\nCompiling source files ...") 1833 print("\nCompiling source files ...")
2075 # Hide compile errors (mainly because of Py2/Py3 differences)
2076 skipRe = re.compile(r"DebugClients[\\/]Python[\\/]") 1834 skipRe = re.compile(r"DebugClients[\\/]Python[\\/]")
2077 sys.stdout = io.StringIO() 1835 sys.stdout = io.StringIO()
2078 if distDir: 1836 if distDir:
2079 compileall.compile_dir( 1837 compileall.compile_dir(
2080 eric6SourceDir, 1838 eric6SourceDir,

eric ide

mercurial