|
| 1 | +# SPDX-License-Identifier: Apache-2.0 |
| 2 | +# Copyright 2026 Ague Samuel Amen |
| 3 | +# |
| 4 | +# Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | +# you may not use this file except in compliance with the License. |
| 6 | +# You may obtain a copy of the License at |
| 7 | +# |
| 8 | +# http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | +# |
| 10 | +# Unless required by applicable law or agreed to in writing, software |
| 11 | +# distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | +# See the License for the specific language governing permissions and |
| 14 | +# limitations under the License. |
| 15 | + |
| 16 | +""" |
| 17 | +PyCompiler ARK - Compiler Core Module |
| 18 | +
|
| 19 | +Module principal du compilateur pour PyCompiler ARK. |
| 20 | +Gère l'exécution des processus de compilation avec support threading |
| 21 | +et communication en temps réel avec l'interface utilisateur. |
| 22 | +
|
| 23 | +Classes principales: |
| 24 | +- CompilerCore: Classe principale du compilateur |
| 25 | +- CompilationThread: Thread pour exécution non-bloquante |
| 26 | +- MainProcess: Processus principal de compilation |
| 27 | +- ProcessKiller: Gestion des processus |
| 28 | +
|
| 29 | +Fonctions: |
| 30 | +- compile_all: Compile tous les fichiers sélectionnés |
| 31 | +- cancel_all_compilations: Annule toutes les compilations en cours |
| 32 | +- kill_process: Tue un processus |
| 33 | +- kill_process_tree: Tue un processus et ses enfants |
| 34 | +- build_command: Construit une commande de compilation |
| 35 | +- validate_command: Valide une commande de compilation |
| 36 | +""" |
| 37 | + |
| 38 | +from __future__ import annotations |
| 39 | + |
| 40 | +# Instance globale du MainProcess (pour compatibilité avec l'UI) |
| 41 | +_global_main_process = None |
| 42 | + |
| 43 | + |
| 44 | +def _get_main_process(): |
| 45 | + """Retourne l'instance globale du MainProcess.""" |
| 46 | + global _global_main_process |
| 47 | + if _global_main_process is None: |
| 48 | + _global_main_process = MainProcess() |
| 49 | + return _global_main_process |
| 50 | + |
| 51 | + |
| 52 | +# Importations de compiler.py |
| 53 | +from Core.Compiler.compiler import ( |
| 54 | + CompilationStatus, |
| 55 | + CompilationSignals, |
| 56 | + CompilationThread, |
| 57 | + CompilerCore, |
| 58 | +) |
| 59 | + |
| 60 | +# Importations de mainprocess.py |
| 61 | +from Core.Compiler.mainprocess import ( |
| 62 | + ProcessState, |
| 63 | + MainProcessSignals, |
| 64 | + MainProcess, |
| 65 | +) |
| 66 | + |
| 67 | +# Importations de command_helpers.py |
| 68 | +from Core.Compiler.command_helpers import ( |
| 69 | + build_command, |
| 70 | + validate_command, |
| 71 | + escape_arguments, |
| 72 | + sanitize_path, |
| 73 | + CommandBuilder, |
| 74 | + detect_python_executable, |
| 75 | + get_interpreter_version, |
| 76 | + check_module_available, |
| 77 | +) |
| 78 | + |
| 79 | +# Importations de process_killer.py |
| 80 | +from Core.Compiler.process_killer import ( |
| 81 | + ProcessInfo, |
| 82 | + ProcessKiller, |
| 83 | + kill_process, |
| 84 | + kill_process_tree, |
| 85 | + get_process_info, |
| 86 | +) |
| 87 | + |
| 88 | + |
| 89 | +def compile_all(gui_instance) -> bool: |
| 90 | + """ |
| 91 | + Compile tous les fichiers sélectionnés en utilisant l'instance GUI. |
| 92 | + |
| 93 | + Args: |
| 94 | + gui_instance: Instance de l'interface graphique PyCompilerArkGui |
| 95 | + |
| 96 | + Returns: |
| 97 | + True si la compilation a démarrer, False sinon |
| 98 | + """ |
| 99 | + mp = _get_main_process() |
| 100 | + |
| 101 | + # Synchroniser le workspace |
| 102 | + if hasattr(gui_instance, 'workspace_dir') and gui_instance.workspace_dir: |
| 103 | + mp.set_workspace(gui_instance.workspace_dir) |
| 104 | + |
| 105 | + # Récupérer les fichiers à compiler |
| 106 | + files = [] |
| 107 | + if hasattr(gui_instance, 'python_files'): |
| 108 | + files = gui_instance.python_files |
| 109 | + |
| 110 | + if not files: |
| 111 | + if hasattr(gui_instance, 'log') and gui_instance.log: |
| 112 | + gui_instance.log.append("⚠️ Aucun fichier à compiler") |
| 113 | + return False |
| 114 | + |
| 115 | + # Vérifier qu'un moteur est sélectionné |
| 116 | + if not hasattr(gui_instance, 'compiler_tabs') or not gui_instance.compiler_tabs: |
| 117 | + if hasattr(gui_instance, 'log') and gui_instance.log: |
| 118 | + gui_instance.log.append("⚠️ Aucun moteur de compilation disponible") |
| 119 | + return False |
| 120 | + |
| 121 | + try: |
| 122 | + import EngineLoader as engines_loader |
| 123 | + idx = gui_instance.compiler_tabs.currentIndex() |
| 124 | + engine_id = engines_loader.registry.get_engine_for_tab(idx) |
| 125 | + |
| 126 | + if not engine_id: |
| 127 | + if hasattr(gui_instance, 'log') and gui_instance.log: |
| 128 | + gui_instance.log.append("⚠️ Aucun moteur sélectionné") |
| 129 | + return False |
| 130 | + |
| 131 | + mp.set_engine(engine_id) |
| 132 | + |
| 133 | + except Exception as e: |
| 134 | + if hasattr(gui_instance, 'log') and gui_instance.log: |
| 135 | + gui_instance.log.append(f"⚠️ Erreur lors de la sélection du moteur: {e}") |
| 136 | + return False |
| 137 | + |
| 138 | + # Démarrer la compilation pour chaque fichier |
| 139 | + success_count = 0 |
| 140 | + for file_path in files: |
| 141 | + try: |
| 142 | + mp.set_file(file_path) |
| 143 | + # La commande sera générée par le moteur |
| 144 | + # Pour l'instant, on retourne True si le MainProcess est prêt |
| 145 | + success_count += 1 |
| 146 | + |
| 147 | + except Exception as e: |
| 148 | + if hasattr(gui_instance, 'log') and gui_instance.log: |
| 149 | + gui_instance.log.append(f"❌ Erreur pour {file_path}: {e}") |
| 150 | + |
| 151 | + if hasattr(gui_instance, 'log') and gui_instance.log: |
| 152 | + gui_instance.log.append(f"✅ {success_count} fichier(s) prêt(s) pour compilation") |
| 153 | + |
| 154 | + return success_count > 0 |
| 155 | + |
| 156 | + |
| 157 | +def cancel_all_compilations() -> bool: |
| 158 | + """ |
| 159 | + Annule toutes les compilations en cours. |
| 160 | + |
| 161 | + Returns: |
| 162 | + True si l'annulation a été demandée, False sinon |
| 163 | + """ |
| 164 | + mp = _get_main_process() |
| 165 | + return mp.cancel() |
| 166 | + |
| 167 | + |
| 168 | +def handle_finished(return_code: int) -> None: |
| 169 | + """ |
| 170 | + Gère la fin d'une compilation. |
| 171 | + |
| 172 | + Args: |
| 173 | + return_code: Code de retour du processus |
| 174 | + """ |
| 175 | + # La gestion est faite via les signaux du MainProcess |
| 176 | + |
| 177 | + |
| 178 | +def handle_stderr(error: str) -> None: |
| 179 | + """ |
| 180 | + Gère les erreurs stderr. |
| 181 | + |
| 182 | + Args: |
| 183 | + error: Message d'erreur |
| 184 | + """ |
| 185 | + pass |
| 186 | + |
| 187 | + |
| 188 | +def handle_stdout(output: str) -> None: |
| 189 | + """ |
| 190 | + Gère la sortie stdout. |
| 191 | + |
| 192 | + Args: |
| 193 | + output: Sortie standard |
| 194 | + """ |
| 195 | + pass |
| 196 | + |
| 197 | + |
| 198 | +def show_error_dialog(parent, title: str, message: str) -> None: |
| 199 | + """ |
| 200 | + Affiche une boîte de dialogue d'erreur. |
| 201 | + |
| 202 | + Args: |
| 203 | + parent: Widget parent |
| 204 | + title: Titre de la boîte de dialogue |
| 205 | + message: Message d'erreur |
| 206 | + """ |
| 207 | + from PySide6.QtWidgets import QMessageBox |
| 208 | + QMessageBox.critical(parent, title, message) |
| 209 | + |
| 210 | + |
| 211 | +def try_install_missing_modules(parent, missing: list) -> bool: |
| 212 | + """ |
| 213 | + Tente d'installer les modules manquants. |
| 214 | + |
| 215 | + Args: |
| 216 | + parent: Widget parent |
| 217 | + missing: Liste des modules manquants |
| 218 | + |
| 219 | + Returns: |
| 220 | + True si l'installation a réussi, False sinon |
| 221 | + """ |
| 222 | + # TODO: Implémenter l'installation des modules manquants |
| 223 | + return False |
| 224 | + |
| 225 | + |
| 226 | +def try_start_processes(gui_instance) -> bool: |
| 227 | + """ |
| 228 | + Tente de démarrer les processus de compilation. |
| 229 | + |
| 230 | + Args: |
| 231 | + gui_instance: Instance de l'interface graphique |
| 232 | + |
| 233 | + Returns: |
| 234 | + True si les processus ont démarrer, False sinon |
| 235 | + """ |
| 236 | + return compile_all(gui_instance) |
| 237 | + |
| 238 | + |
| 239 | +def start_compilation_process(gui_instance) -> bool: |
| 240 | + """ |
| 241 | + Démarre un processus de compilation. |
| 242 | + |
| 243 | + Args: |
| 244 | + gui_instance: Instance de l'interface graphique |
| 245 | + |
| 246 | + Returns: |
| 247 | + True si le processus a démarrer, False sinon |
| 248 | + """ |
| 249 | + return compile_all(gui_instance) |
| 250 | + |
| 251 | + |
| 252 | +def _continue_compile_all(gui_instance) -> bool: |
| 253 | + """ |
| 254 | + Continue la compilation de tous les fichiers. |
| 255 | + |
| 256 | + Args: |
| 257 | + gui_instance: Instance de l'interface graphique |
| 258 | + |
| 259 | + Returns: |
| 260 | + True si la compilation continue, False sinon |
| 261 | + """ |
| 262 | + return compile_all(gui_instance) |
| 263 | + |
| 264 | + |
| 265 | +__all__ = [ |
| 266 | + # Classes de compiler.py |
| 267 | + "CompilationStatus", |
| 268 | + "CompilationSignals", |
| 269 | + "CompilationThread", |
| 270 | + "CompilerCore", |
| 271 | + |
| 272 | + # Classes de mainprocess.py |
| 273 | + "ProcessState", |
| 274 | + "MainProcessSignals", |
| 275 | + "MainProcess", |
| 276 | + |
| 277 | + # Fonctions de command_helpers.py |
| 278 | + "build_command", |
| 279 | + "validate_command", |
| 280 | + "escape_arguments", |
| 281 | + "sanitize_path", |
| 282 | + "CommandBuilder", |
| 283 | + "detect_python_executable", |
| 284 | + "get_interpreter_version", |
| 285 | + "check_module_available", |
| 286 | + |
| 287 | + # Classes et fonctions de process_killer.py |
| 288 | + "ProcessInfo", |
| 289 | + "ProcessKiller", |
| 290 | + "kill_process", |
| 291 | + "kill_process_tree", |
| 292 | + "get_process_info", |
| 293 | + |
| 294 | + # Fonctions de compatibilité UI |
| 295 | + "compile_all", |
| 296 | + "cancel_all_compilations", |
| 297 | + "handle_finished", |
| 298 | + "handle_stderr", |
| 299 | + "handle_stdout", |
| 300 | + "show_error_dialog", |
| 301 | + "try_install_missing_modules", |
| 302 | + "try_start_processes", |
| 303 | + "start_compilation_process", |
| 304 | + "_continue_compile_all", |
| 305 | +] |
| 306 | + |
| 307 | +__version__ = "1.0.0" |
| 308 | +__author__ = "Ague Samuel Amen" |
| 309 | + |
0 commit comments