scripts/install.py

branch
maintenance
changeset 8273
698ae46f40a4
parent 8142
43248bafe9b2
parent 8261
0c2aa0ad149f
child 8400
b3eefd7e58d1
diff -r fb0ef164f536 -r 698ae46f40a4 scripts/install.py
--- a/scripts/install.py	Fri Apr 02 11:59:41 2021 +0200
+++ b/scripts/install.py	Sat May 01 14:27:20 2021 +0200
@@ -24,6 +24,7 @@
 import shlex
 import datetime
 import getpass
+import contextlib
 
 # Define the globals.
 progName = None
@@ -99,10 +100,8 @@
     print()
     
     if sys.platform.startswith(("win", "cygwin")):
-        try:
+        with contextlib.suppress():
             input("Press enter to continue...")             # secok
-        except (EOFError, SyntaxError):
-            pass
     
     os.chdir(currDir)
     
@@ -236,10 +235,7 @@
             qtDataDir = QLibraryInfo.location(QLibraryInfo.DataPath)
         except ImportError:
             qtDataDir = None
-    if qtDataDir:
-        apisDir = os.path.join(qtDataDir, "qsci", "api")
-    else:
-        apisDir = None
+    apisDir = os.path.join(qtDataDir, "qsci", "api") if qtDataDir else None
 
 
 def copyToFile(name, text):
@@ -312,11 +308,11 @@
     @param wfile basename (without extension) of the wrapper script
     @return the names of the wrapper scripts
     """
-    if sys.platform.startswith(("win", "cygwin")):
-        wnames = (dname + "\\" + wfile + ".cmd",
-                  dname + "\\" + wfile + ".bat")
-    else:
-        wnames = (dname + "/" + wfile, )
+    wnames = (
+        (dname + "\\" + wfile + ".cmd", dname + "\\" + wfile + ".bat")
+        if sys.platform.startswith(("win", "cygwin")) else
+        (dname + "/" + wfile, )
+    )
 
     return wnames
 
@@ -560,7 +556,7 @@
                 os.remove(name)
         
         # Cleanup API files
-        try:
+        with contextlib.suppress(AttributeError):
             apidir = getConfig('apidir')
             for progLanguage in progLanguages:
                 for name in getConfig('apis'):
@@ -571,8 +567,6 @@
                         os.path.join(apidir, progLanguage.lower(), "*.bas")):
                     if os.path.basename(apiname) != "eric6.bas":
                         os.remove(apiname)
-        except AttributeError:
-            pass
         
         if sys.platform == "darwin":
             # delete the Mac app bundle
@@ -588,10 +582,6 @@
     Clean up Linux specific files.
     """
     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)
         for name in [
             "/usr/share/applications/eric6.desktop",
             "/usr/share/appdata/eric6.appdata.xml",
@@ -599,6 +589,8 @@
             "/usr/share/applications/eric6_browser.desktop",
             "/usr/share/pixmaps/eric.png",
             "/usr/share/pixmaps/ericWeb.png",
+            "/usr/share/icons/eric.png",
+            "/usr/share/icons/ericWeb.png",
             # from Python2 era
             "/usr/share/applications/eric6_webbrowser.desktop",
         ]:
@@ -606,11 +598,6 @@
                 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)
         for name in [
             "~/.local/share/applications/eric6.desktop",
             "~/.local/share/appdata/eric6.appdata.xml",
@@ -618,6 +605,8 @@
             "~/.local/share/applications/eric6_browser.desktop",
             "~/.local/share/pixmaps/eric.png",
             "~/.local/share/pixmaps/ericWeb.png",
+            "~/.local/share/icons/eric.png",
+            "~/.local/share/icons/ericWeb.png",
             # from Python2 era
             "/usr/share/applications/eric6_webbrowser.desktop",
         ]:
@@ -740,7 +729,7 @@
     try:
         # Install the files
         # make the install directories
-        for key in cfg.keys():
+        for key in cfg:
             if cfg[key] and not os.path.isdir(cfg[key]):
                 os.makedirs(cfg[key])
         
@@ -941,7 +930,7 @@
     global distDir, sourceDir
     
     if distDir:
-        dst = os.path.normpath(os.path.join(distDir, "usr/share/pixmaps"))
+        dst = os.path.normpath(os.path.join(distDir, "usr/share/icons"))
         if not os.path.exists(dst):
             os.makedirs(dst)
         shutilCopy(
@@ -969,7 +958,7 @@
     elif os.getuid() == 0:
         shutilCopy(
             os.path.join(eric6SourceDir, "pixmaps", "eric_icon.png"),
-            "/usr/share/pixmaps/eric.png")
+            "/usr/share/icons/eric.png")
         copyDesktopFile(
             os.path.join(sourceDir, "linux", "eric6.desktop.in"),
             "/usr/share/applications/eric6.desktop")
@@ -983,7 +972,7 @@
                 "/usr/share/appdata/eric6.appdata.xml")
         shutilCopy(
             os.path.join(eric6SourceDir, "pixmaps", "ericWeb48_icon.png"),
-            "/usr/share/pixmaps/ericWeb.png")
+            "/usr/share/icons/ericWeb.png")
         copyDesktopFile(
             os.path.join(sourceDir, "linux", "eric6_browser.desktop.in"),
             "/usr/share/applications/eric6_browser.desktop")
@@ -993,14 +982,14 @@
                                  ".local", "share")
         # create directories first
         for directory in [os.path.join(localPath, name)
-                          for name in ("pixmaps", "applications",
+                          for name in ("icons", "applications",
                                        "metainfo", "appdata")]:
             if not os.path.isdir(directory):
                 os.makedirs(directory)
         # now copy the files
         shutilCopy(
             os.path.join(eric6SourceDir, "pixmaps", "eric_icon.png"),
-            os.path.join(localPath, "pixmaps", "eric.png"))
+            os.path.join(localPath, "icons", "eric.png"))
         copyDesktopFile(
             os.path.join(sourceDir, "linux", "eric6.desktop.in"),
             os.path.join(localPath, "applications", "eric6.desktop"))
@@ -1012,7 +1001,7 @@
             os.path.join(localPath, "appdata", "eric6.appdata.xml"))
         shutilCopy(
             os.path.join(eric6SourceDir, "pixmaps", "ericWeb48_icon.png"),
-            os.path.join(localPath, "pixmaps", "ericWeb.png"))
+            os.path.join(localPath, "icons", "ericWeb.png"))
         copyDesktopFile(
             os.path.join(sourceDir, "linux", "eric6_browser.desktop.in"),
             os.path.join(localPath, "applications", "eric6_browser.desktop"))
@@ -1028,7 +1017,8 @@
     except ImportError:
         installed = pipInstall(
             "pywin32",
-            "\nThe Python package 'pywin32' could not be imported."
+            "\nThe Python package 'pywin32' could not be imported.",
+            force=False
         )
         if installed:
             # create the links via an external script to get around some
@@ -1248,13 +1238,13 @@
                                            "MicroPython", "*.api"))):
                     apis.append(os.path.basename(apiName))
     
-    if sys.platform == "darwin":
-        macConfig = (
-            """    'macAppBundlePath': r'{0}',\n"""
-            """    'macAppBundleName': r'{1}',\n"""
-        ).format(macAppBundlePath, macAppBundleName)
-    else:
-        macConfig = ""
+    macConfig = (
+        ("""    'macAppBundlePath': r'{0}',\n"""
+         """    'macAppBundleName': r'{1}',\n""").format(macAppBundlePath,
+                                                         macAppBundleName)
+        if sys.platform == "darwin" else
+        ""
+    )
     config = (
         """# -*- coding: utf-8 -*-\n"""
         """#\n"""
@@ -1345,7 +1335,7 @@
         installInfo["eric_edited"] = False
 
 
-def pipInstall(packageName, message):
+def pipInstall(packageName, message, force=True):
     """
     Install the given package via pip.
     
@@ -1353,13 +1343,16 @@
     @type str
     @param message message to be shown to the user
     @type str
+    @param force flag indicating to perform the installation
+        without asking the user
+    @type bool
     @return flag indicating a successful installation
     @rtype bool
     """
     global yes2All
     
     ok = False
-    if yes2All:
+    if yes2All or force:
         answer = "y"
     else:
         print("{0}\n\nShall '{1}' be installed using pip? (Y/n)"
@@ -1423,7 +1416,8 @@
     Perform some dependency checks.
     """
     try:
-        isSudo = os.getuid() == 0
+        isSudo = os.getuid() == 0 and sys.platform != "darwin"
+        # disregard sudo installs on macOS
     except AttributeError:
         isSudo = False
     
@@ -1451,7 +1445,7 @@
         from PyQt5.QtCore import qVersion
     except ImportError as msg:
         installed = not isSudo and pipInstall(
-            "PyQt5>=5.12.1,<5.15.2",
+            "PyQt5>=5.12.1",
             "'PyQt5' could not be detected.\nError: {0}".format(msg)
         )
         if installed:
@@ -1487,7 +1481,7 @@
                 print("Optional 'PyQtWebEngine' could not be detected.")
             else:
                 pipInstall(
-                    "PyQtWebEngine>=5.12.1,<5.15.2",
+                    "PyQtWebEngine>=5.12.1",
                     "Optional 'PyQtWebEngine' could not be detected.\n"
                     "Error: {0}".format(msg)
                 )
@@ -1499,7 +1493,7 @@
             print("Optional 'PyQtChart' could not be detected.")
         else:
             pipInstall(
-                "PyQtChart>=5.12.1,<5.15.2",
+                "PyQtChart>=5.12.1",
                 "Optional 'PyQtChart' could not be detected.\n"
                 "Error: {0}".format(msg)
             )
@@ -1539,8 +1533,15 @@
     optionalModulesList = {
         # key is pip project name
         # value is tuple of package name, pip install constraint
-        "PyYAML": ("yaml", ""),
+        "docutils": ("docutils", ""),
+        "Markdown": ("markdown", ""),
+        "pyyaml": ("yaml", ""),
         "toml": ("toml", ""),
+        "chardet": ("chardet", ""),
+        "asttokens": ("asttokens", ""),
+        "EditorConfig": ("editorconfig", ""),
+        "Send2Trash": ("send2trash", ""),
+        "Pygments": ("pygments", ""),
     }
     # dict with tuples of package name and install constraint
     if sys.platform != "darwin" and not ignorePyqt5Tools:
@@ -1567,13 +1568,11 @@
             modulesOK = False
             for altModule in altModules:
                 name = altModule.split(".")[1]
-                try:
+                with contextlib.suppress(ImportError):
                     __import__(altModule)
                     print("Found", name)
                     modulesOK = True
                     break
-                except ImportError:
-                    pass
             if not modulesOK and not forcedOk:
                 altModulesOK = False
                 print('Sorry, please install {0}.'
@@ -1613,7 +1612,7 @@
         exit(2)
     
     # check version of sip
-    try:
+    with contextlib.suppress(ImportError, AttributeError):
         try:
             from PyQt5 import sip
         except ImportError:
@@ -1629,11 +1628,11 @@
             minor = int(minor)
             pat = int(pat)
             if (
-                major < 4 or
-                (major == 4 and minor < 14) or
-                (major == 4 and minor == 14 and pat < 2)
+                major < 5 or
+                (major == 5 and minor < 0) or
+                (major == 5 and minor == 0 and pat < 0)
             ):
-                print('Sorry, you must have sip 4.14.2 or higher or'
+                print('Sorry, you must have sip 5.0.0 or higher or'
                       ' a recent snapshot release.')
                 exit(3)
             # check for blacklisted versions
@@ -1644,8 +1643,6 @@
                         .format(vers))
                     print('Please install another version.')
                     exit(3)
-    except (ImportError, AttributeError):
-        pass
     
     # check version of PyQt
     from PyQt5.QtCore import PYQT_VERSION_STR
@@ -1704,15 +1701,12 @@
                 exit(5)
     
     # print version info for additional modules
-    try:
+    with contextlib.suppress(NameError, AttributeError):
         print("PyQtChart:", QtChart.PYQT_CHART_VERSION_STR)
-    except (NameError, AttributeError):
-        pass
-    try:
+    
+    with contextlib.suppress(ImportError, AttributeError):
         from PyQt5 import QtWebEngine
         print("PyQtWebEngine.", QtWebEngine.PYQT_WEBENGINE_VERSION_STR)
-    except (ImportError, AttributeError):
-        pass
     
     print("All dependencies ok.")
     print()
@@ -1747,10 +1741,8 @@
     if not fileName:
         return
     
-    try:
+    with contextlib.suppress(OSError):
         os.rename(fileName, fileName + ".orig")
-    except OSError:
-        pass
     try:
         hgOut = subprocess.check_output(["hg", "identify", "-i"])   # secok
         hgOut = hgOut.decode()
@@ -1811,16 +1803,13 @@
     from win32com.client import Dispatch
     from pywintypes import com_error
     
-    try:
+    with contextlib.suppress(com_error):
         shell = Dispatch('WScript.Shell')
         shortcut = shell.CreateShortCut(linkPath)
         shortcut.Targetpath = targetPath
         shortcut.WorkingDirectory = os.path.dirname(targetPath)
         shortcut.IconLocation = iconPath
         shortcut.save()
-    except com_error:
-        # maybe restrictions prohibited link creation
-        pass
 
 
 def windowsDesktopNames():
@@ -1939,15 +1928,16 @@
         elif opt == "-z":
             doCompile = False
         elif opt == "-f":
-            try:
-                exec(compile(open(arg).read(), arg, 'exec'), globals())
-                # secok
-                if len(cfg) != configLength:
-                    print("The configuration dictionary in '{0}' is incorrect."
-                          " Aborting".format(arg))
-                    exit(6)
-            except Exception:
-                cfg = {}
+            with open(arg) as f:
+                try:
+                    exec(compile(f.read(), arg, 'exec'), globals())
+                    # secok
+                    if len(cfg) != configLength:
+                        print("The configuration dictionary in '{0}' is"
+                              " incorrect. Aborting".format(arg))
+                        exit(6)
+                except Exception:
+                    cfg = {}
         elif opt == "-m":
             macAppBundleName = arg
         elif opt == "-n":
@@ -1993,15 +1983,13 @@
         createInstallConfig()
     
     # get rid of development config file, if it exists
-    try:
+    with contextlib.suppress(OSError):
         if installFromSource:
             os.rename(configName, configName + ".orig")
             configNameC = configName + 'c'
             if os.path.exists(configNameC):
                 os.remove(configNameC)
         os.remove(configName)
-    except OSError:
-        pass
     
     # cleanup old installation
     print("Cleaning up old installation ...")
@@ -2061,24 +2049,20 @@
             json.dump(installInfo, installInfoFile, indent=2)
     
     # do some cleanup
-    try:
+    with contextlib.suppress(OSError):
         if installFromSource:
             os.remove(configName)
             configNameC = configName + 'c'
             if os.path.exists(configNameC):
                 os.remove(configNameC)
             os.rename(configName + ".orig", configName)
-    except OSError:
-        pass
-    try:
+    with contextlib.suppress(OSError):
         if installFromSource and infoName:
             os.remove(infoName)
             infoNameC = infoName + 'c'
             if os.path.exists(infoNameC):
                 os.remove(infoNameC)
             os.rename(infoName + ".orig", infoName)
-    except OSError:
-        pass
     
     print("\nInstallation complete.")
     print()

eric ide

mercurial