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: |
13 try: |
|
14 # Python2 only |
14 import cStringIO as io |
15 import cStringIO as io |
15 import sip |
16 import sip |
16 sip.setapi('QString', 2) |
17 sip.setapi('QString', 2) |
17 sip.setapi('QVariant', 2) |
18 sip.setapi('QVariant', 2) |
18 sip.setapi('QTextStream', 2) |
19 sip.setapi('QTextStream', 2) |
|
20 input = raw_input # __IGNORE_WARNING__ |
19 except (ImportError): |
21 except (ImportError): |
20 import io # __IGNORE_WARNING__ |
22 import io # __IGNORE_WARNING__ |
21 |
23 |
22 import sys |
24 import sys |
23 import os |
25 import os |
24 import re |
26 import re |
25 import compileall |
27 import compileall |
238 platBinDirOld = platBinDir |
241 platBinDirOld = platBinDir |
239 platBinDir = os.path.join(platBinDir, "Scripts") |
242 platBinDir = os.path.join(platBinDir, "Scripts") |
240 if not os.path.exists(platBinDir): |
243 if not os.path.exists(platBinDir): |
241 platBinDir = platBinDirOld |
244 platBinDir = platBinDirOld |
242 else: |
245 else: |
243 platBinDir = "/usr/local/bin" |
246 pyBinDir = os.path.normpath(os.path.dirname(sys.executable)) |
|
247 if os.access(pyBinDir, os.W_OK): |
|
248 # install the eric scripts along the python executable |
|
249 platBinDir = pyBinDir |
|
250 else: |
|
251 # install them in the user's bin directory |
|
252 platBinDir = os.path.expanduser("~/bin") |
|
253 if platBinDir != "/usr/local/bin" and \ |
|
254 os.access("/usr/local/bin", os.W_OK): |
|
255 platBinDirOld = "/usr/local/bin" |
244 |
256 |
245 modDir = distutils.sysconfig.get_python_lib(True) |
257 modDir = distutils.sysconfig.get_python_lib(True) |
246 pyModDir = modDir |
258 pyModDir = modDir |
247 |
259 |
248 pyqtDataDir = os.path.join(modDir, pyqtVariant) |
260 pyqtDataDir = os.path.join(modDir, pyqtVariant) |
249 if os.path.exists(os.path.join(pyqtDataDir, "qsci")): |
261 if os.path.exists(os.path.join(pyqtDataDir, "qsci")): |
250 # it's the installer |
262 # it's the installer |
251 qtDataDir = pyqtDataDir |
263 qtDataDir = pyqtDataDir |
252 else: |
264 elif os.path.exists(os.path.join(pyqtDataDir, "Qt", "qsci")): |
|
265 # it's the wheel |
|
266 qtDataDir = os.path.join(pyqtDataDir, "Qt") |
|
267 else: |
|
268 # determine dynamically |
253 try: |
269 try: |
254 if pyqtVariant == "PyQt4": |
270 if pyqtVariant == "PyQt4": |
255 from PyQt4.QtCore import QLibraryInfo |
271 from PyQt4.QtCore import QLibraryInfo |
256 else: |
272 else: |
257 from PyQt5.QtCore import QLibraryInfo |
273 from PyQt5.QtCore import QLibraryInfo |
284 |
300 |
285 @param src source file name (string) |
301 @param src source file name (string) |
286 @param dst destination file name (string) |
302 @param dst destination file name (string) |
287 @param marker marker to be used (string) |
303 @param marker marker to be used (string) |
288 """ |
304 """ |
|
305 global cfg |
|
306 |
289 if sys.version_info[0] == 2: |
307 if sys.version_info[0] == 2: |
290 f = codecs.open(src, "r", "utf-8") |
308 f = codecs.open(src, "r", "utf-8") |
291 else: |
309 else: |
292 f = open(src, "r", encoding="utf-8") |
310 f = open(src, "r", encoding="utf-8") |
293 text = f.read() |
311 text = f.read() |
294 f.close() |
312 f.close() |
295 |
313 |
|
314 text = text.replace("@BINDIR@", cfg['bindir']) |
296 text = text.replace("@MARKER@", marker) |
315 text = text.replace("@MARKER@", marker) |
297 if marker: |
316 if marker: |
298 t_marker = " ({0})".format(PythonTextMarkers[marker]) |
317 t_marker = " ({0})".format(PythonTextMarkers[marker]) |
299 else: |
318 else: |
300 t_marker = "" |
319 t_marker = "" |
542 return |
561 return |
543 |
562 |
544 global pyModDir, progLanguages |
563 global pyModDir, progLanguages |
545 |
564 |
546 # Remove the menu entry for Linux systems |
565 # Remove the menu entry for Linux systems |
547 if sys.platform.startswith("linux") and os.getuid() == 0: |
566 if sys.platform.startswith("linux"): |
548 for name in ["/usr/share/pixmaps/eric.png", |
567 if os.getuid() == 0: |
549 "/usr/share/pixmaps/ericWeb.png"]: |
568 for name in ["/usr/share/pixmaps/eric.png", |
550 if os.path.exists(name): |
569 "/usr/share/pixmaps/ericWeb.png"]: |
551 os.remove(name) |
570 if os.path.exists(name): |
552 if includePythonVariant: |
571 os.remove(name) |
553 marker = PythonMarkers[sys.version_info.major] |
572 if includePythonVariant: |
554 else: |
573 marker = PythonMarkers[sys.version_info.major] |
555 marker = "" |
574 else: |
556 for name in ["/usr/share/applications/eric6" + marker + ".desktop", |
575 marker = "" |
557 "/usr/share/appdata/eric6" + marker + ".appdata.xml", |
576 for name in [ |
558 "/usr/share/metainfo/eric6" + marker + ".appdata.xml", |
577 "/usr/share/applications/eric6" + marker + ".desktop", |
559 "/usr/share/applications/eric6_webbrowser" + marker + |
578 "/usr/share/appdata/eric6" + marker + ".appdata.xml", |
560 ".desktop", |
579 "/usr/share/metainfo/eric6" + marker + ".appdata.xml", |
561 "/usr/share/applications/eric6_browser" + marker + |
580 "/usr/share/applications/eric6_webbrowser" + marker + |
562 ".desktop", |
581 ".desktop", |
563 ]: |
582 "/usr/share/applications/eric6_browser" + marker + |
564 if os.path.exists(name): |
583 ".desktop", |
565 os.remove(name) |
584 "/usr/share/pixmaps/eric" + marker + ".png", |
|
585 "/usr/share/pixmaps/ericWeb" + marker + ".png", |
|
586 ]: |
|
587 if os.path.exists(name): |
|
588 os.remove(name) |
|
589 elif os.getuid() >= 1000: |
|
590 # it is assumed that user ids start at 1000 |
|
591 for name in ["~/.local/share/pixmaps/eric.png", |
|
592 "~/.local/share/pixmaps/ericWeb.png"]: |
|
593 path = os.path.expanduser(name) |
|
594 if os.path.exists(path): |
|
595 os.remove(path) |
|
596 if includePythonVariant: |
|
597 marker = PythonMarkers[sys.version_info.major] |
|
598 else: |
|
599 marker = "" |
|
600 for name in [ |
|
601 "~/.local/share/applications/eric6" + marker + ".desktop", |
|
602 "~/.local/share/appdata/eric6" + marker + ".appdata.xml", |
|
603 "~/.local/share/metainfo/eric6" + marker + ".appdata.xml", |
|
604 "~/.local/share/applications/eric6_webbrowser" + marker + |
|
605 ".desktop", |
|
606 "~/.local/share/applications/eric6_browser" + marker + |
|
607 ".desktop", |
|
608 "~/.local/share/pixmaps/eric" + marker + ".png", |
|
609 "~/.local/share/pixmaps/ericWeb" + marker + ".png", |
|
610 ]: |
|
611 path = os.path.expanduser(name) |
|
612 if os.path.exists(path): |
|
613 os.remove(path) |
566 |
614 |
567 # Remove the wrapper scripts |
615 # Remove the wrapper scripts |
568 rem_wnames = [ |
616 rem_wnames = [ |
569 "eric6_api", "eric6_compare", |
617 "eric6_api", "eric6_compare", |
570 "eric6_configure", "eric6_diff", |
618 "eric6_configure", "eric6_diff", |
593 if os.path.exists(rwname): |
641 if os.path.exists(rwname): |
594 os.remove(rwname) |
642 os.remove(rwname) |
595 |
643 |
596 # Cleanup our config file(s) |
644 # Cleanup our config file(s) |
597 for name in ['eric6config.py', 'eric6config.pyc', 'eric6.pth']: |
645 for name in ['eric6config.py', 'eric6config.pyc', 'eric6.pth']: |
598 e5cfile = os.path.join(pyModDir, name) |
646 e6cfile = os.path.join(pyModDir, name) |
599 if os.path.exists(e5cfile): |
647 if os.path.exists(e6cfile): |
600 os.remove(e5cfile) |
648 os.remove(e6cfile) |
601 e5cfile = os.path.join(pyModDir, "__pycache__", name) |
649 e5cfile = os.path.join(pyModDir, "__pycache__", name) |
602 path, ext = os.path.splitext(e5cfile) |
650 path, ext = os.path.splitext(e5cfile) |
603 for f in glob.glob("{0}.*{1}".format(path, ext)): |
651 for f in glob.glob("{0}.*{1}".format(path, ext)): |
604 os.remove(f) |
652 os.remove(f) |
605 |
653 |
805 |
853 |
806 # install the API file |
854 # install the API file |
807 if installApis: |
855 if installApis: |
808 for progLanguage in progLanguages: |
856 for progLanguage in progLanguages: |
809 apidir = os.path.join(cfg['apidir'], progLanguage.lower()) |
857 apidir = os.path.join(cfg['apidir'], progLanguage.lower()) |
|
858 print("Installing {0} API files to '{1}'.".format( |
|
859 progLanguage, apidir)) |
810 if not os.path.exists(apidir): |
860 if not os.path.exists(apidir): |
811 os.makedirs(apidir) |
861 os.makedirs(apidir) |
812 for apiName in glob.glob(os.path.join(sourceDir, "APIs", |
862 for apiName in glob.glob(os.path.join(sourceDir, "APIs", |
813 progLanguage, "*.api")): |
863 progLanguage, "*.api")): |
814 try: |
864 try: |
815 shutilCopy(apiName, apidir) |
865 shutilCopy(apiName, apidir) |
816 except EnvironmentError: |
866 except EnvironmentError: |
817 print("Could not install '{0}'.".format(apiName)) |
867 print("Could not install '{0}' (no permission)." |
|
868 .format(apiName)) |
818 for apiName in glob.glob(os.path.join(sourceDir, "APIs", |
869 for apiName in glob.glob(os.path.join(sourceDir, "APIs", |
819 progLanguage, "*.bas")): |
870 progLanguage, "*.bas")): |
820 try: |
871 try: |
821 shutilCopy(apiName, apidir) |
872 shutilCopy(apiName, apidir) |
822 except EnvironmentError: |
873 except EnvironmentError: |
823 print("Could not install '{0}'.".format(apiName)) |
874 print("Could not install '{0}' (no permission)." |
|
875 .format(apiName)) |
824 if progLanguage == "Python": |
876 if progLanguage == "Python": |
825 # copy Python3 API files to the same destination |
877 # copy Python3 API files to the same destination |
826 for apiName in glob.glob(os.path.join(sourceDir, "APIs", |
878 for apiName in glob.glob(os.path.join(sourceDir, "APIs", |
827 "Python3", "*.api")): |
879 "Python3", "*.api")): |
828 try: |
880 try: |
829 shutilCopy(apiName, apidir) |
881 shutilCopy(apiName, apidir) |
830 except EnvironmentError: |
882 except EnvironmentError: |
831 print("Could not install '{0}'.".format(apiName)) |
883 print("Could not install '{0}' (no permission)." |
|
884 .format(apiName)) |
832 for apiName in glob.glob(os.path.join(sourceDir, "APIs", |
885 for apiName in glob.glob(os.path.join(sourceDir, "APIs", |
833 "Python3", "*.bas")): |
886 "Python3", "*.bas")): |
834 if os.path.exists(os.path.join( |
887 if os.path.exists(os.path.join( |
835 apidir, os.path.basename( |
888 apidir, os.path.basename( |
836 apiName.replace(".bas", ".api")))): |
889 apiName.replace(".bas", ".api")))): |
837 try: |
890 try: |
838 shutilCopy(apiName, apidir) |
891 shutilCopy(apiName, apidir) |
839 except EnvironmentError: |
892 except EnvironmentError: |
840 print("Could not install '{0}'.".format(apiName)) |
893 print("Could not install '{0}' (no permission)." |
|
894 .format(apiName)) |
841 |
895 |
842 # create menu entry for Linux systems |
896 # create menu entry for Linux systems |
843 if sys.platform.startswith("linux"): |
897 if sys.platform.startswith("linux"): |
844 if includePythonVariant: |
898 if includePythonVariant: |
845 marker = PythonMarkers[sys.version_info.major] |
899 marker = PythonMarkers[sys.version_info.major] |
908 copyDesktopFile( |
962 copyDesktopFile( |
909 os.path.join(sourceDir, "eric6_browser.desktop"), |
963 os.path.join(sourceDir, "eric6_browser.desktop"), |
910 "/usr/share/applications/eric6_browser" + marker + |
964 "/usr/share/applications/eric6_browser" + marker + |
911 ".desktop", |
965 ".desktop", |
912 marker) |
966 marker) |
|
967 elif os.getuid() >= 1000: |
|
968 # it is assumed, that user ids start at 1000 |
|
969 localPath = os.path.join(os.path.expanduser("~"), |
|
970 ".local", "share") |
|
971 # create directories first |
|
972 for directory in [os.path.join(localPath, name) |
|
973 for name in ("pixmaps", "applications", |
|
974 "metainfo", "appdata")]: |
|
975 if not os.path.isdir(directory): |
|
976 os.makedirs(directory) |
|
977 # now copy the files |
|
978 shutilCopy( |
|
979 os.path.join(sourceDir, "icons", "default", "eric.png"), |
|
980 os.path.join(localPath, "pixmaps", "eric" + marker + ".png")) |
|
981 copyDesktopFile( |
|
982 os.path.join(sourceDir, "eric6.desktop"), |
|
983 os.path.join(localPath, "applications", |
|
984 "eric6" + marker + ".desktop"), |
|
985 marker) |
|
986 copyAppStreamFile( |
|
987 os.path.join(sourceDir, "eric6.appdata.xml"), |
|
988 os.path.join(localPath, "metainfo", |
|
989 "eric6" + marker + ".appdata.xml"), |
|
990 marker) |
|
991 copyAppStreamFile( |
|
992 os.path.join(sourceDir, "eric6.appdata.xml"), |
|
993 os.path.join(localPath, "appdata", |
|
994 "eric6" + marker + ".appdata.xml"), |
|
995 marker) |
|
996 shutilCopy( |
|
997 os.path.join(sourceDir, "icons", "default", "ericWeb48.png"), |
|
998 os.path.join(localPath, "pixmaps", |
|
999 "ericWeb" + marker + ".png")) |
|
1000 copyDesktopFile( |
|
1001 os.path.join(sourceDir, "eric6_webbrowser.desktop"), |
|
1002 os.path.join(localPath, "applications", |
|
1003 "eric6_webbrowser" + marker + ".desktop"), |
|
1004 marker) |
|
1005 copyDesktopFile( |
|
1006 os.path.join(sourceDir, "eric6_browser.desktop"), |
|
1007 os.path.join(localPath, "applications", |
|
1008 "eric6_browser" + marker + ".desktop"), |
|
1009 marker) |
913 |
1010 |
914 # Create a Mac application bundle |
1011 # Create a Mac application bundle |
915 if sys.platform == "darwin": |
1012 if sys.platform == "darwin": |
916 createMacAppBundle(cfg['ericDir']) |
1013 createMacAppBundle(cfg['ericDir']) |
917 |
1014 |
1124 macAppBundlePath, macAppBundleName, |
1221 macAppBundlePath, macAppBundleName, |
1125 ) |
1222 ) |
1126 copyToFile(fn, config) |
1223 copyToFile(fn, config) |
1127 |
1224 |
1128 |
1225 |
|
1226 def pipInstall(packageName, message): |
|
1227 """ |
|
1228 Install the given package via pip. |
|
1229 |
|
1230 @param packageName name of the package to be installed |
|
1231 @type str |
|
1232 @param message message to be shown to the user |
|
1233 @type str |
|
1234 @return flag indicating a successful installation |
|
1235 @rtype bool |
|
1236 """ |
|
1237 ok = False |
|
1238 print(message, "\n") |
|
1239 answer = input("Shall '{0}' be installed using pip? (Y/n) " |
|
1240 .format(packageName)) |
|
1241 if answer in ("", "Y", "y"): |
|
1242 exitCode = subprocess.call( |
|
1243 [sys.executable, "-m", "pip", "install", packageName]) |
|
1244 ok = (exitCode == 0) |
|
1245 |
|
1246 return ok |
|
1247 |
|
1248 |
1129 def doDependancyChecks(): |
1249 def doDependancyChecks(): |
1130 """ |
1250 """ |
1131 Perform some dependency checks. |
1251 Perform some dependency checks. |
1132 """ |
1252 """ |
1133 print('Checking dependencies') |
1253 print('Checking dependencies') |
1162 print("Found PyQt4") |
1282 print("Found PyQt4") |
1163 else: |
1283 else: |
1164 try: |
1284 try: |
1165 from PyQt5.QtCore import qVersion |
1285 from PyQt5.QtCore import qVersion |
1166 except ImportError as msg: |
1286 except ImportError as msg: |
1167 print('Sorry, please install PyQt5.') |
1287 installed = pipInstall( |
1168 print('Error: {0}'.format(msg)) |
1288 "PyQt5", |
1169 exit(1) |
1289 "PyQt5 could not be detected.\nError: {0}".format(msg) |
|
1290 ) |
|
1291 if installed: |
|
1292 # try to import it again |
|
1293 try: |
|
1294 from PyQt5.QtCore import qVersion |
|
1295 except ImportError as msg: |
|
1296 print('Sorry, please install PyQt5.') |
|
1297 print('Error: {0}'.format(msg)) |
|
1298 exit(1) |
|
1299 else: |
|
1300 exit(1) |
1170 print("Found PyQt5") |
1301 print("Found PyQt5") |
1171 |
1302 |
1172 try: |
1303 try: |
1173 if pyqtVariant == "PyQt4": |
1304 if pyqtVariant == "PyQt4": |
1174 pyuic = "pyuic4" |
1305 pyuic = "pyuic4" |
1186 if pyqtVariant == "PyQt4": |
1317 if pyqtVariant == "PyQt4": |
1187 from PyQt4 import Qsci # __IGNORE_WARNING__ |
1318 from PyQt4 import Qsci # __IGNORE_WARNING__ |
1188 else: |
1319 else: |
1189 from PyQt5 import Qsci # __IGNORE_WARNING__ |
1320 from PyQt5 import Qsci # __IGNORE_WARNING__ |
1190 except ImportError as msg: |
1321 except ImportError as msg: |
1191 print("Sorry, please install QScintilla2 and") |
1322 if pyqtVariant == "PyQt4": |
1192 print("its PyQt5/PyQt4 wrapper.") |
1323 message = str(msg) |
1193 print('Error: {0}'.format(msg)) |
1324 else: |
1194 exit(1) |
1325 installed = pipInstall( |
|
1326 "QScintilla", |
|
1327 "QScintilla could not be detected.\nError: {0}".format(msg) |
|
1328 ) |
|
1329 if installed: |
|
1330 # try to import it again |
|
1331 try: |
|
1332 from PyQt5 import Qsci # __IGNORE_WARNING__ |
|
1333 message = None |
|
1334 except ImportError as msg: |
|
1335 message = str(msg) |
|
1336 if message: |
|
1337 print("Sorry, please install QScintilla2 and") |
|
1338 print("its PyQt5/PyQt4 wrapper.") |
|
1339 print('Error: {0}'.format(msg)) |
|
1340 exit(1) |
1195 print("Found QScintilla2") |
1341 print("Found QScintilla2") |
1196 |
1342 |
1197 if pyqtVariant == "PyQt4": |
1343 if pyqtVariant == "PyQt4": |
1198 impModulesList = [ |
1344 impModulesList = [ |
1199 "PyQt4.QtGui", "PyQt4.QtNetwork", "PyQt4.QtSql", |
1345 "PyQt4.QtGui", "PyQt4.QtNetwork", "PyQt4.QtSql", |