Coverage for src/ezcompiler/utils/_compiler_utils.py: 100.00%
33 statements
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-03 15:46 +0000
« prev ^ index » next coverage.py v7.14.1, created at 2026-06-03 15:46 +0000
1# ///////////////////////////////////////////////////////////////
2# COMPILER_UTILS - Compiler-specific utility functions
3# Project: ezcompiler
4# ///////////////////////////////////////////////////////////////
6"""
7Compiler utilities - Compiler-specific utility functions for EzCompiler.
9This module provides specialized utility functions for compiler operations,
10including configuration validation, output directory preparation, and include
11files formatting. Uses thematic utils (FileUtils, ValidationUtils) internally.
13Utils layer can only use DEBUG and ERROR log levels.
14"""
16from __future__ import annotations
18# ///////////////////////////////////////////////////////////////
19# IMPORTS
20# ///////////////////////////////////////////////////////////////
21# Standard library imports
22from pathlib import Path
24# Local imports
25from ..shared import CompilerConfig
26from ..shared.exceptions.utils import (
27 CompilerConfigValidationError,
28 MainFileNotFoundError,
29 OutputDirectoryError,
30)
31from ._file_utils import FileUtils
33# ///////////////////////////////////////////////////////////////
34# CLASSES
35# ///////////////////////////////////////////////////////////////
38class CompilerUtils:
39 """
40 Utility class for compiler-specific operations.
42 Provides static methods for compiler-related tasks such as configuration
43 validation, output directory preparation, and include files formatting.
44 Uses thematic utils (FileUtils, ValidationUtils) internally.
46 Example:
47 >>> config = CompilerConfig(...)
48 >>> CompilerUtils.validate_compiler_config(config)
49 >>> CompilerUtils.prepare_compiler_output_directory(config)
50 >>> files = CompilerUtils.format_include_files_data(config)
51 """
53 # ////////////////////////////////////////////////
54 # VALIDATION METHODS
55 # ////////////////////////////////////////////////
57 # TODO [AUDIT P3]: cette méthode duplique la validation de CompilerConfig.__post_init__()
58 # Un seul point de validation devrait exister — idéalement dans le domain object (__post_init__).
59 # Évaluer si cette méthode peut être supprimée ou réduite à un appel vers CompilerConfig.
60 @staticmethod
61 def validate_compiler_config(config: CompilerConfig) -> None:
62 """
63 Validate configuration for compilation.
65 Checks that all required configuration fields are present
66 and valid (main file exists, output folder is set).
68 Args:
69 config: CompilerConfig instance to validate
71 Raises:
72 MainFileNotFoundError: If main file doesn't exist or is required but missing
73 OutputDirectoryError: If output folder is not set
75 Note:
76 Uses FileUtils for file existence checks.
78 Example:
79 >>> config = CompilerConfig(...)
80 >>> CompilerUtils.validate_compiler_config(config)
81 """
82 if not config.main_file:
83 raise CompilerConfigValidationError("Main file is required")
85 main_file_path = Path(config.main_file)
86 if not main_file_path.exists() or not main_file_path.is_file():
87 raise MainFileNotFoundError(f"Main file not found: {config.main_file}")
89 if not config.output_folder:
90 raise OutputDirectoryError("Output folder is required")
92 # ////////////////////////////////////////////////
93 # PREPARATION METHODS
94 # ////////////////////////////////////////////////
96 @staticmethod
97 def prepare_compiler_output_directory(config: CompilerConfig) -> None:
98 """
99 Prepare the output directory for compilation.
101 Creates the output directory if it doesn't exist, including
102 any parent directories as needed.
104 Args:
105 config: CompilerConfig instance with output_folder path
107 Note:
108 Uses FileUtils.create_directory_if_not_exists() internally.
110 Example:
111 >>> config = CompilerConfig(..., output_folder=Path("dist"))
112 >>> CompilerUtils.prepare_compiler_output_directory(config)
113 """
114 FileUtils.create_directory_if_not_exists(config.output_folder)
116 # ////////////////////////////////////////////////
117 # DATA FORMATTING METHODS
118 # ////////////////////////////////////////////////
120 @staticmethod
121 def format_include_files_data(config: CompilerConfig) -> list[str]:
122 """
123 Format include files data for compilation.
125 Combines individual files and folders from configuration,
126 formatting folders with trailing slashes for compatibility
127 with different compilers.
129 Args:
130 config: CompilerConfig instance with include_files
132 Returns:
133 list[str]: List of formatted include paths
135 Note:
136 Files are included as-is, folders are formatted with
137 trailing slashes for Cx_Freeze compatibility.
139 Example:
140 >>> config.include_files = {
141 ... "files": ["config.yaml"],
142 ... "folders": ["lib", "assets"]
143 ... }
144 >>> files = CompilerUtils.format_include_files_data(config)
145 >>> print(files)
146 ['config.yaml', 'lib/', 'assets/']
147 """
148 files = config.include_files.get("files", [])
149 folders = [f"{folder}/" for folder in config.include_files.get("folders", [])]
150 return files + folders
152 # ////////////////////////////////////////////////
153 # COMPILER-SPECIFIC HELPERS
154 # ////////////////////////////////////////////////
156 @staticmethod
157 def get_windows_base_for_console(console: bool) -> str | None:
158 """
159 Get Windows base executable type based on console setting.
161 Args:
162 console: Whether to show console window
164 Returns:
165 str | None: "Win32GUI" if console=False on Windows, None otherwise
167 Note:
168 Used by Cx_Freeze to determine executable base type.
170 Example:
171 >>> base = CompilerUtils.get_windows_base_for_console(False)
172 >>> print(base)
173 'Win32GUI' # On Windows
174 """
175 import sys
177 if sys.platform == "win32" and not console:
178 return "Win32GUI"
179 return None
181 @staticmethod
182 def check_onefile_mode() -> bool:
183 """
184 Check if onefile mode is requested via command-line arguments.
186 Returns:
187 bool: True if --onefile is in sys.argv, False otherwise
189 Note:
190 Used by PyInstaller and Nuitka to determine output format.
192 Example:
193 >>> # When run with: python script.py --onefile
194 >>> is_onefile = CompilerUtils.check_onefile_mode()
195 >>> print(is_onefile)
196 True
197 """
198 import sys
200 return "--onefile" in sys.argv