|
35 | 35 | PYTHON = ML_VENV_PYTHON |
36 | 36 | elif getattr(sys, "frozen", False): |
37 | 37 | import shutil as _shutil |
38 | | - PYTHON = _shutil.which("python3") or _shutil.which("python") or "python3" |
| 38 | + if sys.platform == "win32": |
| 39 | + PYTHON = _shutil.which("python") or "python" |
| 40 | + else: |
| 41 | + PYTHON = _shutil.which("python3") or _shutil.which("python") or "python3" |
39 | 42 | else: |
40 | 43 | PYTHON = sys.executable |
41 | 44 |
|
@@ -113,6 +116,88 @@ def _script(name: str) -> Path: |
113 | 116 | ] |
114 | 117 |
|
115 | 118 |
|
| 119 | +def _find_base_python(log_fn: callable) -> str: |
| 120 | + """Find a Python 3 with ssl+venv support. |
| 121 | +
|
| 122 | + Tries (in order): |
| 123 | + 1. Login-shell probe via bash/zsh (Unix only) |
| 124 | + 2. Common conda/system install locations (platform-specific) |
| 125 | + Returns the executable path or '' if nothing is found. |
| 126 | + """ |
| 127 | + import shutil as _sh |
| 128 | + home = Path.home() |
| 129 | + |
| 130 | + # 1) Login shell probe — bash/zsh don't exist on Windows |
| 131 | + if sys.platform != "win32": |
| 132 | + log_fn("► Probing login shell for Python …") |
| 133 | + for shell_cmd in [ |
| 134 | + ["bash", "-l", "-c", |
| 135 | + "python3 -c 'import ssl,venv,sys; print(sys.executable)'"], |
| 136 | + ["zsh", "-l", "-c", |
| 137 | + "python3 -c 'import ssl,venv,sys; print(sys.executable)'"], |
| 138 | + ]: |
| 139 | + try: |
| 140 | + r = subprocess.run(shell_cmd, capture_output=True, |
| 141 | + text=True, timeout=15) |
| 142 | + if r.returncode == 0: |
| 143 | + for line in reversed(r.stdout.strip().splitlines()): |
| 144 | + line = line.strip() |
| 145 | + if line and Path(line).exists(): |
| 146 | + return line |
| 147 | + except Exception: |
| 148 | + pass |
| 149 | + |
| 150 | + # 2) Common install locations (platform-specific) |
| 151 | + if sys.platform == "win32": |
| 152 | + _candidates = [ |
| 153 | + str(home / "miniconda3" / "python.exe"), |
| 154 | + str(home / "Miniconda3" / "python.exe"), |
| 155 | + str(home / "anaconda3" / "python.exe"), |
| 156 | + str(home / "Anaconda3" / "python.exe"), |
| 157 | + str(home / "miniforge3" / "python.exe"), |
| 158 | + str(home / "mambaforge" / "python.exe"), |
| 159 | + # Standard Windows Python installer locations |
| 160 | + str(home / "AppData" / "Local" / "Programs" / "Python" / "Python313" / "python.exe"), |
| 161 | + str(home / "AppData" / "Local" / "Programs" / "Python" / "Python312" / "python.exe"), |
| 162 | + str(home / "AppData" / "Local" / "Programs" / "Python" / "Python311" / "python.exe"), |
| 163 | + str(home / "AppData" / "Local" / "Programs" / "Python" / "Python310" / "python.exe"), |
| 164 | + str(Path("C:/miniconda3/python.exe")), |
| 165 | + str(Path("C:/anaconda3/python.exe")), |
| 166 | + str(Path("C:/ProgramData/miniconda3/python.exe")), |
| 167 | + str(Path("C:/ProgramData/anaconda3/python.exe")), |
| 168 | + _sh.which("python") or "", |
| 169 | + ] |
| 170 | + else: |
| 171 | + _candidates = [ |
| 172 | + str(home / "miniconda3/bin/python3"), |
| 173 | + str(home / "miniconda3/bin/python"), |
| 174 | + str(home / "anaconda3/bin/python3"), |
| 175 | + str(home / "anaconda3/bin/python"), |
| 176 | + str(home / "miniforge3/bin/python3"), |
| 177 | + str(home / "miniforge3/bin/python"), |
| 178 | + str(home / "mambaforge/bin/python3"), |
| 179 | + str(home / "mambaforge/bin/python"), |
| 180 | + str(home / ".local/share/mamba/bin/python3"), |
| 181 | + "/opt/conda/bin/python3", |
| 182 | + "/opt/miniconda3/bin/python3", |
| 183 | + "/opt/anaconda3/bin/python3", |
| 184 | + _sh.which("python3") or "", |
| 185 | + _sh.which("python") or "", |
| 186 | + "/usr/bin/python3", |
| 187 | + "/usr/local/bin/python3", |
| 188 | + ] |
| 189 | + |
| 190 | + for cand in _candidates: |
| 191 | + if not cand or not Path(cand).exists(): |
| 192 | + continue |
| 193 | + r = subprocess.run([cand, "-c", "import ssl, venv"], |
| 194 | + capture_output=True, timeout=5) |
| 195 | + if r.returncode == 0: |
| 196 | + return cand |
| 197 | + |
| 198 | + return "" |
| 199 | + |
| 200 | + |
116 | 201 | def _detect_cuda() -> tuple[int, int] | None: |
117 | 202 | """Return (major, minor) CUDA version from nvidia-smi, or None if no GPU.""" |
118 | 203 | try: |
@@ -1485,69 +1570,22 @@ def _worker(): |
1485 | 1570 | global PYTHON |
1486 | 1571 |
|
1487 | 1572 | # ── Find a Python that has SSL (required for pip HTTPS) ────────── |
1488 | | - import shutil as _sh |
1489 | | - home = Path.home() |
1490 | | - |
1491 | 1573 | # 1) Manual override from the text field |
1492 | 1574 | base_py = _base_py_v["v"].strip() |
1493 | 1575 |
|
1494 | | - # 2) Login shell — respects .bashrc/.zshrc and conda init |
1495 | | - if not base_py: |
1496 | | - _append_log("► Probing login shell for Python …") |
1497 | | - for shell_cmd in [ |
1498 | | - ["bash", "-l", "-c", |
1499 | | - "python3 -c 'import ssl,venv,sys; print(sys.executable)'"], |
1500 | | - ["zsh", "-l", "-c", |
1501 | | - "python3 -c 'import ssl,venv,sys; print(sys.executable)'"], |
1502 | | - ]: |
1503 | | - try: |
1504 | | - r = subprocess.run(shell_cmd, capture_output=True, |
1505 | | - text=True, timeout=15) |
1506 | | - if r.returncode == 0: |
1507 | | - for line in reversed(r.stdout.strip().splitlines()): |
1508 | | - line = line.strip() |
1509 | | - if line and Path(line).exists(): |
1510 | | - base_py = line |
1511 | | - break |
1512 | | - if base_py: |
1513 | | - break |
1514 | | - except Exception: |
1515 | | - pass |
1516 | | - |
1517 | | - # 3) Common install locations |
| 1576 | + # 2) Auto-detect via login shell + common install locations |
1518 | 1577 | if not base_py: |
1519 | | - _candidates = [ |
1520 | | - str(home / "miniconda3/bin/python3"), |
1521 | | - str(home / "miniconda3/bin/python"), |
1522 | | - str(home / "anaconda3/bin/python3"), |
1523 | | - str(home / "anaconda3/bin/python"), |
1524 | | - str(home / "miniforge3/bin/python3"), |
1525 | | - str(home / "miniforge3/bin/python"), |
1526 | | - str(home / "mambaforge/bin/python3"), |
1527 | | - str(home / "mambaforge/bin/python"), |
1528 | | - str(home / ".local/share/mamba/bin/python3"), |
1529 | | - "/opt/conda/bin/python3", |
1530 | | - "/opt/miniconda3/bin/python3", |
1531 | | - "/opt/anaconda3/bin/python3", |
1532 | | - _sh.which("python3") or "", |
1533 | | - _sh.which("python") or "", |
1534 | | - "/usr/bin/python3", |
1535 | | - "/usr/local/bin/python3", |
1536 | | - ] |
1537 | | - for cand in _candidates: |
1538 | | - if not cand or not Path(cand).exists(): |
1539 | | - continue |
1540 | | - r = subprocess.run([cand, "-c", "import ssl, venv"], |
1541 | | - capture_output=True, timeout=5) |
1542 | | - if r.returncode == 0: |
1543 | | - base_py = cand |
1544 | | - break |
| 1578 | + base_py = _find_base_python(_append_log) |
1545 | 1579 |
|
1546 | 1580 | if not base_py: |
1547 | 1581 | _append_log("ERROR: Could not find a Python 3 with SSL support.") |
1548 | 1582 | _append_log("") |
1549 | | - _append_log(" Paste the path to your conda/system Python below") |
1550 | | - _append_log(" (e.g. /home/user/miniconda3/bin/python3)") |
| 1583 | + if sys.platform == "win32": |
| 1584 | + _append_log(" Paste the path to your Python below") |
| 1585 | + _append_log(r" (e.g. C:\Users\you\miniconda3\python.exe)") |
| 1586 | + else: |
| 1587 | + _append_log(" Paste the path to your conda/system Python below") |
| 1588 | + _append_log(" (e.g. /home/user/miniconda3/bin/python3)") |
1551 | 1589 | _append_log(" then click Install again.") |
1552 | 1590 | tf_base_py.visible = True |
1553 | 1591 | env_status.value = "✗ Python not found — enter path below" |
@@ -1947,62 +1985,18 @@ def _run_install(_=None) -> None: |
1947 | 1985 | page.update() |
1948 | 1986 |
|
1949 | 1987 | def _worker(): |
1950 | | - import shutil as _sh |
1951 | | - home = Path.home() |
1952 | 1988 | base_py = _base_py_v2["v"].strip() |
1953 | 1989 |
|
1954 | 1990 | if not base_py: |
1955 | | - _append("► Probing login shell for Python …") |
1956 | | - for shell_cmd in [ |
1957 | | - ["bash", "-l", "-c", |
1958 | | - "python3 -c 'import ssl,venv,sys; print(sys.executable)'"], |
1959 | | - ["zsh", "-l", "-c", |
1960 | | - "python3 -c 'import ssl,venv,sys; print(sys.executable)'"], |
1961 | | - ]: |
1962 | | - try: |
1963 | | - r = subprocess.run(shell_cmd, capture_output=True, |
1964 | | - text=True, timeout=15) |
1965 | | - if r.returncode == 0: |
1966 | | - for line in reversed(r.stdout.strip().splitlines()): |
1967 | | - line = line.strip() |
1968 | | - if line and Path(line).exists(): |
1969 | | - base_py = line |
1970 | | - break |
1971 | | - if base_py: |
1972 | | - break |
1973 | | - except Exception: |
1974 | | - pass |
1975 | | - |
1976 | | - if not base_py: |
1977 | | - for cand in [ |
1978 | | - str(home / "miniconda3/bin/python3"), |
1979 | | - str(home / "miniconda3/bin/python"), |
1980 | | - str(home / "anaconda3/bin/python3"), |
1981 | | - str(home / "anaconda3/bin/python"), |
1982 | | - str(home / "miniforge3/bin/python3"), |
1983 | | - str(home / "miniforge3/bin/python"), |
1984 | | - str(home / "mambaforge/bin/python3"), |
1985 | | - str(home / "mambaforge/bin/python"), |
1986 | | - str(home / ".local/share/mamba/bin/python3"), |
1987 | | - "/opt/conda/bin/python3", |
1988 | | - "/opt/miniconda3/bin/python3", |
1989 | | - "/opt/anaconda3/bin/python3", |
1990 | | - _sh.which("python3") or "", |
1991 | | - _sh.which("python") or "", |
1992 | | - "/usr/bin/python3", |
1993 | | - "/usr/local/bin/python3", |
1994 | | - ]: |
1995 | | - if not cand or not Path(cand).exists(): |
1996 | | - continue |
1997 | | - r = subprocess.run([cand, "-c", "import ssl, venv"], |
1998 | | - capture_output=True, timeout=5) |
1999 | | - if r.returncode == 0: |
2000 | | - base_py = cand |
2001 | | - break |
| 1991 | + base_py = _find_base_python(_append) |
2002 | 1992 |
|
2003 | 1993 | if not base_py: |
2004 | 1994 | _append("ERROR: No Python 3 with SSL support found.") |
2005 | | - _append(" Paste your Python path in the field below and click Install again.") |
| 1995 | + if sys.platform == "win32": |
| 1996 | + _append(r" Paste your Python path below (e.g. C:\Users\you\miniconda3\python.exe)") |
| 1997 | + else: |
| 1998 | + _append(" Paste your Python path below (e.g. /home/user/miniconda3/bin/python3)") |
| 1999 | + _append(" then click Install again.") |
2006 | 2000 | tf_base_py2.visible = True |
2007 | 2001 | inst_status.value = "✗ Python not found — enter path below" |
2008 | 2002 | inst_status.color = C_ERROR |
|
0 commit comments