install.py

branch
maintenance
changeset 6273
0daf79d65080
parent 6216
2a0eeba143e7
child 6275
8ce9f9c467ec
--- a/install.py	Mon Apr 02 12:04:56 2018 +0200
+++ b/install.py	Tue May 01 12:03:52 2018 +0200
@@ -11,13 +11,15 @@
 
 from __future__ import unicode_literals, print_function
 try:
+    # Python2 only
     import cStringIO as io
     import sip
     sip.setapi('QString', 2)
     sip.setapi('QVariant', 2)
     sip.setapi('QTextStream', 2)
+    input = raw_input       # __IGNORE_WARNING__
 except (ImportError):
-    import io    # __IGNORE_WARNING__
+    import io               # __IGNORE_WARNING__
 
 import sys
 import os
@@ -221,7 +223,8 @@
                 pyqtVariant = "PyQt4"
                 del sys.modules["PyQt4"]
             except ImportError:
-                pyqtVariant = ""
+                # default to PyQt5, installation will be asked for
+                pyqtVariant = "PyQt5"
 
 
 def initGlobals():
@@ -240,7 +243,16 @@
         if not os.path.exists(platBinDir):
             platBinDir = platBinDirOld
     else:
-        platBinDir = "/usr/local/bin"
+        pyBinDir = os.path.normpath(os.path.dirname(sys.executable))
+        if os.access(pyBinDir, os.W_OK):
+            # install the eric scripts along the python executable
+            platBinDir = pyBinDir
+        else:
+            # install them in the user's bin directory
+            platBinDir = os.path.expanduser("~/bin")
+        if platBinDir != "/usr/local/bin" and \
+           os.access("/usr/local/bin", os.W_OK):
+            platBinDirOld = "/usr/local/bin"
 
     modDir = distutils.sysconfig.get_python_lib(True)
     pyModDir = modDir
@@ -249,7 +261,11 @@
     if os.path.exists(os.path.join(pyqtDataDir, "qsci")):
         # it's the installer
         qtDataDir = pyqtDataDir
+    elif os.path.exists(os.path.join(pyqtDataDir, "Qt", "qsci")):
+        # it's the wheel
+        qtDataDir = os.path.join(pyqtDataDir, "Qt")
     else:
+        # determine dynamically
         try:
             if pyqtVariant == "PyQt4":
                 from PyQt4.QtCore import QLibraryInfo
@@ -286,6 +302,8 @@
     @param dst destination file name (string)
     @param marker marker to be used (string)
     """
+    global cfg
+    
     if sys.version_info[0] == 2:
         f = codecs.open(src, "r", "utf-8")
     else:
@@ -293,6 +311,7 @@
     text = f.read()
     f.close()
     
+    text = text.replace("@BINDIR@", cfg['bindir'])
     text = text.replace("@MARKER@", marker)
     if marker:
         t_marker = " ({0})".format(PythonTextMarkers[marker])
@@ -544,25 +563,54 @@
     global pyModDir, progLanguages
     
     # Remove the menu entry for Linux systems
-    if sys.platform.startswith("linux") and os.getuid() == 0:
-        for name in ["/usr/share/pixmaps/eric.png",
-                     "/usr/share/pixmaps/ericWeb.png"]:
-            if os.path.exists(name):
-                os.remove(name)
-        if includePythonVariant:
-            marker = PythonMarkers[sys.version_info.major]
-        else:
-            marker = ""
-        for name in ["/usr/share/applications/eric6" + marker + ".desktop",
-                     "/usr/share/appdata/eric6" + marker + ".appdata.xml",
-                     "/usr/share/metainfo/eric6" + marker + ".appdata.xml",
-                     "/usr/share/applications/eric6_webbrowser" + marker +
-                     ".desktop",
-                     "/usr/share/applications/eric6_browser" + marker +
-                     ".desktop",
-                     ]:
-            if os.path.exists(name):
-                os.remove(name)
+    if sys.platform.startswith("linux"):
+        if os.getuid() == 0:
+            for name in ["/usr/share/pixmaps/eric.png",
+                         "/usr/share/pixmaps/ericWeb.png"]:
+                if os.path.exists(name):
+                    os.remove(name)
+            if includePythonVariant:
+                marker = PythonMarkers[sys.version_info.major]
+            else:
+                marker = ""
+            for name in [
+                "/usr/share/applications/eric6" + marker + ".desktop",
+                "/usr/share/appdata/eric6" + marker + ".appdata.xml",
+                "/usr/share/metainfo/eric6" + marker + ".appdata.xml",
+                "/usr/share/applications/eric6_webbrowser" + marker +
+                ".desktop",
+                "/usr/share/applications/eric6_browser" + marker +
+                ".desktop",
+                "/usr/share/pixmaps/eric" + marker + ".png",
+                "/usr/share/pixmaps/ericWeb" + marker + ".png",
+            ]:
+                if os.path.exists(name):
+                    os.remove(name)
+        elif os.getuid() >= 1000:
+            # it is assumed that user ids start at 1000
+            for name in ["~/.local/share/pixmaps/eric.png",
+                         "~/.local/share/pixmaps/ericWeb.png"]:
+                path = os.path.expanduser(name)
+                if os.path.exists(path):
+                    os.remove(path)
+            if includePythonVariant:
+                marker = PythonMarkers[sys.version_info.major]
+            else:
+                marker = ""
+            for name in [
+                "~/.local/share/applications/eric6" + marker + ".desktop",
+                "~/.local/share/appdata/eric6" + marker + ".appdata.xml",
+                "~/.local/share/metainfo/eric6" + marker + ".appdata.xml",
+                "~/.local/share/applications/eric6_webbrowser" + marker +
+                ".desktop",
+                "~/.local/share/applications/eric6_browser" + marker +
+                ".desktop",
+                "~/.local/share/pixmaps/eric" + marker + ".png",
+                "~/.local/share/pixmaps/ericWeb" + marker + ".png",
+            ]:
+                path = os.path.expanduser(name)
+                if os.path.exists(path):
+                    os.remove(path)
     
     # Remove the wrapper scripts
     rem_wnames = [
@@ -595,9 +643,9 @@
         
         # Cleanup our config file(s)
         for name in ['eric6config.py', 'eric6config.pyc', 'eric6.pth']:
-            e5cfile = os.path.join(pyModDir, name)
-            if os.path.exists(e5cfile):
-                os.remove(e5cfile)
+            e6cfile = os.path.join(pyModDir, name)
+            if os.path.exists(e6cfile):
+                os.remove(e6cfile)
             e5cfile = os.path.join(pyModDir, "__pycache__", name)
             path, ext = os.path.splitext(e5cfile)
             for f in glob.glob("{0}.*{1}".format(path, ext)):
@@ -807,6 +855,8 @@
     if installApis:
         for progLanguage in progLanguages:
             apidir = os.path.join(cfg['apidir'], progLanguage.lower())
+            print("Installing {0} API files to '{1}'.".format(
+                progLanguage, apidir))
             if not os.path.exists(apidir):
                 os.makedirs(apidir)
             for apiName in glob.glob(os.path.join(sourceDir, "APIs",
@@ -814,13 +864,15 @@
                 try:
                     shutilCopy(apiName, apidir)
                 except EnvironmentError:
-                    print("Could not install '{0}'.".format(apiName))
+                    print("Could not install '{0}' (no permission)."
+                          .format(apiName))
             for apiName in glob.glob(os.path.join(sourceDir, "APIs",
                                                   progLanguage, "*.bas")):
                 try:
                     shutilCopy(apiName, apidir)
                 except EnvironmentError:
-                    print("Could not install '{0}'.".format(apiName))
+                    print("Could not install '{0}' (no permission)."
+                          .format(apiName))
             if progLanguage == "Python":
                 # copy Python3 API files to the same destination
                 for apiName in glob.glob(os.path.join(sourceDir, "APIs",
@@ -828,7 +880,8 @@
                     try:
                         shutilCopy(apiName, apidir)
                     except EnvironmentError:
-                        print("Could not install '{0}'.".format(apiName))
+                        print("Could not install '{0}' (no permission)."
+                              .format(apiName))
                 for apiName in glob.glob(os.path.join(sourceDir, "APIs",
                                                       "Python3", "*.bas")):
                     if os.path.exists(os.path.join(
@@ -837,7 +890,8 @@
                         try:
                             shutilCopy(apiName, apidir)
                         except EnvironmentError:
-                            print("Could not install '{0}'.".format(apiName))
+                            print("Could not install '{0}' (no permission)."
+                                  .format(apiName))
     
     # create menu entry for Linux systems
     if sys.platform.startswith("linux"):
@@ -910,6 +964,49 @@
                 "/usr/share/applications/eric6_browser" + marker +
                 ".desktop",
                 marker)
+        elif os.getuid() >= 1000:
+            # it is assumed, that user ids start at 1000
+            localPath = os.path.join(os.path.expanduser("~"),
+                                     ".local", "share")
+            # create directories first
+            for directory in [os.path.join(localPath, name)
+                              for name in ("pixmaps", "applications",
+                                           "metainfo", "appdata")]:
+                if not os.path.isdir(directory):
+                    os.makedirs(directory)
+            # now copy the files
+            shutilCopy(
+                os.path.join(sourceDir, "icons", "default", "eric.png"),
+                os.path.join(localPath, "pixmaps", "eric" + marker + ".png"))
+            copyDesktopFile(
+                os.path.join(sourceDir, "eric6.desktop"),
+                os.path.join(localPath, "applications",
+                             "eric6" + marker + ".desktop"),
+                marker)
+            copyAppStreamFile(
+                os.path.join(sourceDir, "eric6.appdata.xml"),
+                os.path.join(localPath, "metainfo",
+                             "eric6" + marker + ".appdata.xml"),
+                marker)
+            copyAppStreamFile(
+                os.path.join(sourceDir, "eric6.appdata.xml"),
+                os.path.join(localPath, "appdata",
+                             "eric6" + marker + ".appdata.xml"),
+                marker)
+            shutilCopy(
+                os.path.join(sourceDir, "icons", "default", "ericWeb48.png"),
+                os.path.join(localPath, "pixmaps",
+                             "ericWeb" + marker + ".png"))
+            copyDesktopFile(
+                os.path.join(sourceDir, "eric6_webbrowser.desktop"),
+                os.path.join(localPath, "applications",
+                             "eric6_webbrowser" + marker + ".desktop"),
+                marker)
+            copyDesktopFile(
+                os.path.join(sourceDir, "eric6_browser.desktop"),
+                os.path.join(localPath, "applications",
+                             "eric6_browser" + marker + ".desktop"),
+                marker)
     
     # Create a Mac application bundle
     if sys.platform == "darwin":
@@ -1126,6 +1223,29 @@
     copyToFile(fn, config)
 
 
+def pipInstall(packageName, message):
+    """
+    Install the given package via pip.
+    
+    @param packageName name of the package to be installed
+    @type str
+    @param message message to be shown to the user
+    @type str
+    @return flag indicating a successful installation
+    @rtype bool
+    """
+    ok = False
+    print(message, "\n")
+    answer = input("Shall '{0}' be installed using pip? (Y/n) "
+                   .format(packageName))
+    if answer in ("", "Y", "y"):
+        exitCode = subprocess.call(
+            [sys.executable, "-m", "pip", "install", packageName])
+        ok = (exitCode == 0)
+    
+    return ok
+
+
 def doDependancyChecks():
     """
     Perform some dependency checks.
@@ -1164,9 +1284,20 @@
         try:
             from PyQt5.QtCore import qVersion
         except ImportError as msg:
-            print('Sorry, please install PyQt5.')
-            print('Error: {0}'.format(msg))
-            exit(1)
+            installed = pipInstall(
+                "PyQt5",
+                "PyQt5 could not be detected.\nError: {0}".format(msg)
+            )
+            if installed:
+                # try to import it again
+                try:
+                    from PyQt5.QtCore import qVersion
+                except ImportError as msg:
+                    print('Sorry, please install PyQt5.')
+                    print('Error: {0}'.format(msg))
+                    exit(1)
+            else:
+                exit(1)
         print("Found PyQt5")
     
     try:
@@ -1188,10 +1319,25 @@
         else:
             from PyQt5 import Qsci      # __IGNORE_WARNING__
     except ImportError as msg:
-        print("Sorry, please install QScintilla2 and")
-        print("its PyQt5/PyQt4 wrapper.")
-        print('Error: {0}'.format(msg))
-        exit(1)
+        if pyqtVariant == "PyQt4":
+            message = str(msg)
+        else:
+            installed = pipInstall(
+                "QScintilla",
+                "QScintilla could not be detected.\nError: {0}".format(msg)
+            )
+            if installed:
+                # try to import it again
+                try:
+                    from PyQt5 import Qsci      # __IGNORE_WARNING__
+                    message = None
+                except ImportError as msg:
+                    message = str(msg)
+        if message:
+            print("Sorry, please install QScintilla2 and")
+            print("its PyQt5/PyQt4 wrapper.")
+            print('Error: {0}'.format(msg))
+            exit(1)
     print("Found QScintilla2")
     
     if pyqtVariant == "PyQt4":

eric ide

mercurial