36 lines
1004 B
Python
36 lines
1004 B
Python
import os
|
|||
|
|
import subprocess
|
||
|
|
import sys
|
||
|
|
from pathlib import Path
|
||
|
|
|
||
|
|
|
||
|
|
class VirtualEnvManager:
|
||
|
|
def __init__(self, venv_dir: Path, entry_script: Path) -> None:
|
||
|
|
self.venv_dir = venv_dir
|
||
|
|
self.entry_script = entry_script
|
||
|
|
|
||
|
|
@staticmethod
|
||
|
|
def in_virtualenv() -> bool:
|
||
|
|
return (
|
||
|
|
hasattr(sys, "real_prefix")
|
||
|
|
or sys.prefix != getattr(sys, "base_prefix", sys.prefix)
|
||
|
|
)
|
||
|
|
|
||
|
|
def _venv_python(self) -> Path:
|
||
|
|
if os.name == "nt":
|
||
|
|
return self.venv_dir / "Scripts" / "python.exe"
|
||
|
|
return self.venv_dir / "bin" / "python"
|
||
|
|
|
||
|
|
def ensure_and_reexec_if_needed(self) -> None:
|
||
|
|
if self.in_virtualenv():
|
||
|
|
return
|
||
|
|
|
||
|
|
venv_python = self._venv_python()
|
||
|
|
if not venv_python.exists():
|
||
|
|
subprocess.check_call([sys.executable, "-m", "venv", str(self.venv_dir)])
|
||
|
|
|
||
|
|
os.execv(
|
||
|
|
str(venv_python),
|
||
|
|
[str(venv_python), str(self.entry_script.resolve()), *sys.argv[1:]],
|
||
|
|
)
|