Skip to content

Commit de6c3a1

Browse files
committed
Refactor VenvManager and related code to delegate to venv_manager object
1 parent 933187f commit de6c3a1

4 files changed

Lines changed: 59 additions & 291 deletions

File tree

Core/Compiler/mainprocess.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -725,12 +725,28 @@ def try_install_missing_modules(self, process):
725725
if not hasattr(self, "_install_report"):
726726
self._install_report = []
727727
if missing_modules:
728-
pip_exe = os.path.join(
729-
self.workspace_dir,
730-
"venv",
731-
"Scripts" if platform.system() == "Windows" else "bin",
732-
"pip",
733-
)
728+
# Use venv_manager to get the correct pip path
729+
venv_manager = getattr(self, "venv_manager", None)
730+
if venv_manager:
731+
venv_path = venv_manager.resolve_project_venv()
732+
if venv_path:
733+
pip_exe = venv_manager.pip_path(venv_path)
734+
else:
735+
# Fallback to hardcoded path
736+
pip_exe = os.path.join(
737+
self.workspace_dir,
738+
"venv",
739+
"Scripts" if platform.system() == "Windows" else "bin",
740+
"pip",
741+
)
742+
else:
743+
# Fallback to hardcoded path
744+
pip_exe = os.path.join(
745+
self.workspace_dir,
746+
"venv",
747+
"Scripts" if platform.system() == "Windows" else "bin",
748+
"pip",
749+
)
734750
all_installed = True
735751
new_modules = [
736752
m for m in missing_modules if m not in self._already_tried_modules

Core/MainWindow.py

Lines changed: 18 additions & 278 deletions
Original file line numberDiff line numberDiff line change
@@ -591,305 +591,45 @@ def apply_workspace_selection(self, folder: str, source: str = "ui") -> bool:
591591
return False
592592

593593
def _check_next_venv_pkg(self):
594-
if self._venv_check_index >= len(self._venv_check_pkgs):
595-
self.venv_check_progress.set_message("Vérification terminée.")
596-
self.venv_check_progress.set_progress(2, 2)
597-
self.venv_check_progress.close()
598-
# Installer les dépendances du projet si un requirements.txt est présent
599-
if self.workspace_dir:
600-
self.install_requirements_if_needed(self.workspace_dir)
601-
return
602-
pkg = self._venv_check_pkgs[self._venv_check_index]
603-
process = QProcess(self)
604-
self._venv_check_process = process
605-
process.setProgram(self._venv_check_pip_exe)
606-
process.setArguments(["show", pkg])
607-
process.setWorkingDirectory(self._venv_check_path)
608-
process.finished.connect(
609-
lambda code, status: self._on_venv_pkg_checked(process, code, status, pkg)
610-
)
611-
process.start()
594+
# Delegated to venv_manager - these methods are now handled by VenvManager
595+
pass
612596

613597
def _on_venv_pkg_checked(self, process, code, status, pkg):
614-
if code == 0:
615-
self.log_i18n(
616-
f"✅ {pkg} déjà installé dans le venv.",
617-
f"✅ {pkg} already installed in venv.",
618-
)
619-
self._venv_check_index += 1
620-
self.venv_check_progress.set_message(
621-
f"Vérification de {self._venv_check_pkgs[self._venv_check_index] if self._venv_check_index < len(self._venv_check_pkgs) else ''}..."
622-
)
623-
self.venv_check_progress.set_progress(self._venv_check_index, 2)
624-
self._check_next_venv_pkg()
625-
else:
626-
self.log_i18n(
627-
f"📦 Installation automatique de {pkg} dans le venv...",
628-
f"📦 Automatic installation of {pkg} in venv...",
629-
)
630-
self.venv_check_progress.set_message(f"Installation de {pkg}...")
631-
self.venv_check_progress.progress.setRange(0, 0)
632-
process2 = QProcess(self)
633-
self._venv_check_install_process = process2
634-
process2.setProgram(self._venv_check_pip_exe)
635-
process2.setArguments(["install", pkg])
636-
process2.setWorkingDirectory(self._venv_check_path)
637-
process2.readyReadStandardOutput.connect(
638-
lambda: self._on_venv_check_output(process2)
639-
)
640-
process2.readyReadStandardError.connect(
641-
lambda: self._on_venv_check_output(process2, error=True)
642-
)
643-
process2.finished.connect(
644-
lambda code2, status2: self._on_venv_pkg_installed(
645-
process2, code2, status2, pkg
646-
)
647-
)
648-
process2.start()
598+
# Delegated to venv_manager
599+
pass
649600

650601
def _on_venv_check_output(self, process, error=False):
651-
if getattr(self, "_closing", False):
652-
return
653-
data = (
654-
process.readAllStandardError().data().decode()
655-
if error
656-
else process.readAllStandardOutput().data().decode()
657-
)
658-
if hasattr(self, "venv_check_progress") and self.venv_check_progress:
659-
lines = data.strip().splitlines()
660-
if lines:
661-
self.venv_check_progress.set_message(lines[-1])
662-
self._safe_log(data)
602+
# Delegated to venv_manager
603+
pass
663604

664605
def _on_venv_pkg_installed(self, process, code, status, pkg):
665-
if getattr(self, "_closing", False):
666-
return
667-
if code == 0:
668-
self._safe_log(f"✅ {pkg} installé dans le venv.")
669-
else:
670-
self._safe_log(f"❌ Erreur installation {pkg} (code {code})")
671-
self._venv_check_index += 1
672-
self.venv_check_progress.progress.setRange(0, 2)
673-
self.venv_check_progress.set_progress(self._venv_check_index, 2)
674-
self._check_next_venv_pkg()
606+
# Delegated to venv_manager
607+
pass
675608

676609
def select_venv_manually(self):
677610
self.venv_manager.select_venv_manually()
678611

679612
def create_venv_if_needed(self, path):
680-
# Support both '.venv' and 'venv'
681-
existing = None
682-
for name in (".venv", "venv"):
683-
cand = os.path.join(path, name)
684-
if os.path.exists(cand):
685-
existing = cand
686-
break
687-
venv_path = existing or os.path.join(path, "venv")
688-
if not existing:
689-
self._safe_log("🔧 Aucun venv trouvé, création automatique...")
690-
try:
691-
# Recherche d'un python embarqué à côté de l'exécutable
692-
python_candidate = None
693-
exe_dir = os.path.dirname(sys.executable)
694-
# Windows: python.exe, Linux/Mac: python3 ou python
695-
candidates = [
696-
os.path.join(exe_dir, "python.exe"),
697-
os.path.join(exe_dir, "python3"),
698-
os.path.join(exe_dir, "python"),
699-
os.path.join(exe_dir, "python_embedded", "python.exe"),
700-
os.path.join(exe_dir, "python_embedded", "python3"),
701-
os.path.join(exe_dir, "python_embedded", "python"),
702-
]
703-
# Recherche également les interpréteurs système disponibles dans le PATH
704-
path_candidates = []
705-
try:
706-
if platform.system() == "Windows":
707-
w = shutil.which("py")
708-
if w:
709-
path_candidates.append(w)
710-
for name in ("python3", "python"):
711-
w = shutil.which(name)
712-
if w:
713-
path_candidates.append(w)
714-
except Exception:
715-
pass
716-
for c in path_candidates:
717-
if c not in candidates:
718-
candidates.append(c)
719-
for c in candidates:
720-
if os.path.isfile(c):
721-
python_candidate = c
722-
break
723-
if not python_candidate:
724-
python_candidate = sys.executable
725-
# Journalisation du type d'interpréteur détecté
726-
base = os.path.basename(python_candidate).lower()
727-
if (
728-
python_candidate.startswith(exe_dir)
729-
or "python_embedded" in python_candidate
730-
):
731-
self.log_i18n(
732-
f"➡️ Utilisation de l'interpréteur Python embarqué : {python_candidate}",
733-
f"➡️ Using embedded Python interpreter: {python_candidate}",
734-
)
735-
elif base in ("py", "py.exe") or shutil.which(base):
736-
self.log_i18n(
737-
f"➡️ Utilisation de l'interpréteur système : {python_candidate}",
738-
f"➡️ Using system interpreter: {python_candidate}",
739-
)
740-
else:
741-
self.log_i18n(
742-
f"➡️ Utilisation de sys.executable : {python_candidate}",
743-
f"➡️ Using sys.executable: {python_candidate}",
744-
)
745-
self.venv_progress_dialog = ProgressDialog(
746-
"Création de l'environnement virtuel", self
747-
)
748-
self.venv_progress_dialog.set_message("Création du venv...")
749-
process = QProcess(self)
750-
self._venv_create_process = process
751-
process.setProgram(python_candidate)
752-
args = ["-m", "venv", venv_path]
753-
# Si l'on utilise le launcher Windows 'py', forcer Python 3 avec -3
754-
if base in ("py", "py.exe"):
755-
args = ["-3"] + args
756-
process.setArguments(args)
757-
process.setWorkingDirectory(path)
758-
process.readyReadStandardOutput.connect(
759-
lambda: self._on_venv_output(process)
760-
)
761-
process.readyReadStandardError.connect(
762-
lambda: self._on_venv_output(process, error=True)
763-
)
764-
process.finished.connect(
765-
lambda code, status: self._on_venv_created(
766-
process, code, status, venv_path
767-
)
768-
)
769-
self._venv_progress_lines = 0
770-
self.venv_progress_dialog.show()
771-
process.start()
772-
except Exception as e:
773-
self._safe_log(f"❌ Échec de création du venv : {e}")
613+
self.venv_manager.create_venv_if_needed(path)
774614

775615
def _on_venv_output(self, process, error=False):
776-
if getattr(self, "_closing", False):
777-
return
778-
data = (
779-
process.readAllStandardError().data().decode()
780-
if error
781-
else process.readAllStandardOutput().data().decode()
782-
)
783-
if hasattr(self, "venv_progress_dialog") and self.venv_progress_dialog:
784-
lines = data.strip().splitlines()
785-
if lines:
786-
self.venv_progress_dialog.set_message(lines[-1])
787-
self._venv_progress_lines += len(lines)
788-
self.venv_progress_dialog.set_progress(self._venv_progress_lines, 0)
789-
self._safe_log(data)
616+
# Delegated to venv_manager
617+
pass
790618

791619
def _on_venv_created(self, process, code, status, venv_path):
792-
if getattr(self, "_closing", False):
793-
return
794-
if code == 0:
795-
self._safe_log("✅ Environnement virtuel créé avec succès.")
796-
if hasattr(self, "venv_progress_dialog") and self.venv_progress_dialog:
797-
self.venv_progress_dialog.set_message("Environnement prêt.")
798-
self.venv_progress_dialog.set_progress(1, 1)
799-
self.venv_progress_dialog.close()
800-
# Installer les dépendances du projet à partir de requirements.txt si présent
801-
self.install_requirements_if_needed(os.path.dirname(venv_path))
802-
else:
803-
self._safe_log(f"❌ Échec de création du venv (code {code})")
804-
if hasattr(self, "venv_progress_dialog") and self.venv_progress_dialog:
805-
self.venv_progress_dialog.set_message(
806-
"Erreur lors de la création du venv."
807-
)
808-
self.venv_progress_dialog.close()
809-
QApplication.processEvents()
620+
# Delegated to venv_manager
621+
pass
810622

811623
def install_requirements_if_needed(self, path):
812-
req_path = os.path.join(path, "requirements.txt")
813-
if os.path.exists(req_path):
814-
self._safe_log(
815-
"📦 Installation des dépendances à partir de requirements.txt..."
816-
)
817-
# Resolve pip inside '.venv' or 'venv'
818-
venv_root = None
819-
for name in (".venv", "venv"):
820-
cand = os.path.join(path, name)
821-
if os.path.isdir(cand):
822-
venv_root = cand
823-
break
824-
if not venv_root:
825-
self._safe_log("⚠️ Aucun venv détecté pour installer requirements.txt.")
826-
return
827-
pip_exe = os.path.join(
828-
venv_root, "Scripts" if platform.system() == "Windows" else "bin", "pip"
829-
)
830-
try:
831-
self.progress_dialog = ProgressDialog(
832-
"Installation des dépendances", self
833-
)
834-
self.progress_dialog.set_message(
835-
"Démarrage de l'installation des dépendances..."
836-
)
837-
process = QProcess(self)
838-
self._req_install_process = process
839-
process.setProgram(pip_exe)
840-
process.setArguments(["install", "-r", req_path])
841-
process.setWorkingDirectory(path)
842-
process.readyReadStandardOutput.connect(
843-
lambda: self._on_pip_output(process)
844-
)
845-
process.readyReadStandardError.connect(
846-
lambda: self._on_pip_output(process, error=True)
847-
)
848-
process.finished.connect(
849-
lambda code, status: self._on_pip_finished(process, code, status)
850-
)
851-
self._pip_progress_lines = 0
852-
self.progress_dialog.show()
853-
process.start()
854-
# NE PAS bloquer ici, la fermeture se fait dans _on_pip_finished
855-
except Exception as e:
856-
self.log_i18n(
857-
f"❌ Échec installation requirements.txt : {e}",
858-
f"❌ Failed to install requirements.txt: {e}",
859-
)
624+
self.venv_manager.install_requirements_if_needed(path)
860625

861626
def _on_pip_output(self, process, error=False):
862-
if getattr(self, "_closing", False):
863-
return
864-
data = (
865-
process.readAllStandardError().data().decode()
866-
if error
867-
else process.readAllStandardOutput().data().decode()
868-
)
869-
if hasattr(self, "progress_dialog") and self.progress_dialog:
870-
# Affiche la dernière ligne reçue
871-
lines = data.strip().splitlines()
872-
if lines:
873-
self.progress_dialog.set_message(lines[-1])
874-
self._pip_progress_lines += len(lines)
875-
# Simule une progression (pip ne donne pas de %)
876-
self.progress_dialog.set_progress(self._pip_progress_lines, 0)
877-
self._safe_log(data)
627+
# Delegated to venv_manager
628+
pass
878629

879630
def _on_pip_finished(self, process, code, status):
880-
if getattr(self, "_closing", False):
881-
return
882-
if code == 0:
883-
self._safe_log("✅ requirements.txt installé.")
884-
if hasattr(self, "progress_dialog") and self.progress_dialog:
885-
self.progress_dialog.set_message("Installation terminée.")
886-
else:
887-
self._safe_log(f"❌ Échec installation requirements.txt (code {code})")
888-
if hasattr(self, "progress_dialog") and self.progress_dialog:
889-
self.progress_dialog.set_message("Erreur lors de l'installation.")
890-
if hasattr(self, "progress_dialog") and self.progress_dialog:
891-
self.progress_dialog.close()
892-
QApplication.processEvents()
631+
# Delegated to venv_manager
632+
pass
893633

894634
def select_files_manually(self):
895635
if not self.workspace_dir:

0 commit comments

Comments
 (0)