src/eric7/SystemUtilities/PythonUtilities.py

branch
eric7
changeset 10351
1f9bafeff96c
parent 10334
24300d16a154
child 10359
de0420dac60e
diff -r b2297669c065 -r 1f9bafeff96c src/eric7/SystemUtilities/PythonUtilities.py
--- a/src/eric7/SystemUtilities/PythonUtilities.py	Wed Nov 29 11:33:32 2023 +0100
+++ b/src/eric7/SystemUtilities/PythonUtilities.py	Wed Nov 29 14:27:25 2023 +0100
@@ -7,10 +7,14 @@
 Module implementing Python related utility functions.
 """
 
+import contextlib
 import os
+import platform
 import sys
 import sysconfig
 
+from .OSUtilities import isWindowsPlatform
+
 
 def getPythonExecutable():
     """
@@ -135,3 +139,135 @@
             pyVer = 3
 
     return pyVer
+
+
+def searchInterpreters(environments=None):
+    """
+    Function to determine a list of all Python interpreters available via the
+    executable search path (i.e. PATH) (Windows variant).
+
+    @param environments list of environment directories to scan for Python interpreters
+        (defaults to None)
+    @type list of str (optional)
+    @return list of found interpreter executables
+    @rtype list of str
+    """
+    if isWindowsPlatform():
+        return __searchInterpreters_Windows(environments=environments)
+    else:
+        return __searchInterpreters_Linux(environments=environments)
+
+
+def __searchInterpreters_Windows(environments=None):
+    """
+    Function to determine a list of all Python interpreters available via the
+    executable search path (i.e. PATH) (Windows variant).
+
+    @param environments list of environment directories to scan for Python interpreters
+        (defaults to None)
+    @type list of str (optional)
+    @return list of found interpreter executables
+    @rtype list of str
+    """
+    try:
+        import winreg
+    except ImportError:
+        import _winreg as winreg  # __IGNORE_WARNING__
+
+    def getExePath(branch, access, versionStr):
+        with contextlib.suppress(WindowsError, OSError):
+            software = winreg.OpenKey(branch, "Software", 0, access)
+            python = winreg.OpenKey(software, "Python", 0, access)
+            pcore = winreg.OpenKey(python, "PythonCore", 0, access)
+            version = winreg.OpenKey(pcore, versionStr, 0, access)
+            installpath = winreg.QueryValue(version, "InstallPath")
+            exe = os.path.join(installpath,  "python.exe")
+            if os.access(exe, os.X_OK):
+                return exe
+
+        return None
+
+    minorVersions = range(8, 16)  # Py 3.8 until Py 3.15
+    interpreters = set()
+
+    if environments:
+        for directory in [os.path.join(d, "Scripts") for d in environments]:
+            exe = os.path.join(directory, "python.exe")
+            if os.access(exe, os.X_OK):
+                interpreters.add(exe)
+
+    else:
+        versionSuffixes = ["", "-32", "-64"]
+        for minorVersion in minorVersions:
+            for versionSuffix in versionSuffixes:
+                versionStr = "{0}.{1}{2}".format(
+                    "3", minorVersion, versionSuffix
+                )
+                exePath = getExePath(
+                    winreg.HKEY_CURRENT_USER,
+                    winreg.KEY_WOW64_32KEY | winreg.KEY_READ,
+                    versionStr,
+                )
+                if exePath:
+                    interpreters.add(exePath)
+
+                exePath = getExePath(
+                    winreg.HKEY_LOCAL_MACHINE,
+                    winreg.KEY_WOW64_32KEY | winreg.KEY_READ,
+                    versionStr,
+                )
+                if exePath:
+                    interpreters.add(exePath)
+
+                # Even on Intel 64-bit machines it's 'AMD64'
+                if platform.machine() == "AMD64":
+                    exePath = getExePath(
+                        winreg.HKEY_CURRENT_USER,
+                        winreg.KEY_WOW64_64KEY | winreg.KEY_READ,
+                        versionStr,
+                    )
+                    if exePath:
+                        interpreters.add(exePath)
+
+                    exePath = getExePath(
+                        winreg.HKEY_LOCAL_MACHINE,
+                        winreg.KEY_WOW64_64KEY | winreg.KEY_READ,
+                        versionStr,
+                    )
+                    if exePath:
+                        interpreters.add(exePath)
+
+    return list(interpreters)
+
+
+def __searchInterpreters_Linux(environments=None):
+    """
+    Function to determine a list of all Python interpreters available via the
+    executable search path (i.e. PATH) (non Windows variant).
+
+    @param environments list of environment directories to scan for Python interpreters
+        (defaults to None)
+    @type list of str (optional)
+    @return list of found interpreter executables
+    @rtype list of str
+    """
+    from eric7.SystemUtilities import OSUtilities
+
+    minorVersions = range(8, 16)  # Py 3.8 until Py 3.15
+    interpreters = []
+
+    if environments:
+        directories = [os.path.join(d, "bin") for d in environments]
+    else:
+        searchpath = OSUtilities.getEnvironmentEntry("PATH")
+        directories = searchpath.split(os.pathsep) if searchpath else []
+
+    if directories:
+        pythonNames = ["python3.{0}".format(v) for v in minorVersions]
+        for directory in directories:
+            for interpreter in pythonNames:
+                exe = os.path.join(directory, interpreter)
+                if os.access(exe, os.X_OK):
+                    interpreters.append(exe)
+
+    return interpreters

eric ide

mercurial