Coverage for src/ezcompiler/adapters/compiler_factory.py: 87.18%
31 statements
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-04 11:22 +0000
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-04 11:22 +0000
1# ///////////////////////////////////////////////////////////////
2# COMPILER_FACTORY - Compiler factory for creating compiler instances
3# Project: ezcompiler
4# ///////////////////////////////////////////////////////////////
6"""
7Compiler factory - Factory for creating compiler instances.
9This module provides a centralized factory for creating compiler
10instances based on type and configuration.
11"""
13from __future__ import annotations
15# ///////////////////////////////////////////////////////////////
16# IMPORTS
17# ///////////////////////////////////////////////////////////////
18# Standard library imports
19import importlib.util
21from .._types import CompilerPort
23# Local imports
24from ..shared import CompilerConfig
25from ..shared.exceptions import CompilationError
27# ///////////////////////////////////////////////////////////////
28# CONSTANTS
29# ///////////////////////////////////////////////////////////////
31_COMPILER_PACKAGES: dict[str, tuple[str, str]] = {
32 "Cx_Freeze": ("cx_Freeze", "ezcompiler[cx-freeze]"),
33 "PyInstaller": ("PyInstaller", "ezcompiler[pyinstaller]"),
34 "Nuitka": ("nuitka", "ezcompiler[nuitka]"),
35}
37# ///////////////////////////////////////////////////////////////
38# CLASSES
39# ///////////////////////////////////////////////////////////////
42class CompilerFactory:
43 """Factory class for creating compiler instances."""
45 @staticmethod
46 def _check_compiler_available(compiler_name: str) -> None:
47 """
48 Verify the compiler package is installed, raise a clear error if not.
50 Args:
51 compiler_name: Canonical compiler name (Cx_Freeze, PyInstaller, Nuitka)
53 Raises:
54 CompilationError: If the package is not installed, with install hint
55 """
56 package, extra = _COMPILER_PACKAGES[compiler_name]
57 if importlib.util.find_spec(package) is None:
58 raise CompilationError(
59 f"{compiler_name} is not installed. "
60 f"Install it with: pip install {extra}"
61 )
63 @staticmethod
64 def create_compiler(config: CompilerConfig, compiler_name: str) -> CompilerPort:
65 """
66 Create a compiler instance from its name.
68 Args:
69 config: Compiler configuration to inject
70 compiler_name: Compiler name (Cx_Freeze, PyInstaller, Nuitka)
72 Returns:
73 CompilerPort: Concrete compiler instance (satisfies the Port)
75 Raises:
76 CompilationError: If compiler name is unsupported or package not installed
77 """
78 normalized_name = compiler_name.strip()
80 if normalized_name == "Cx_Freeze":
81 CompilerFactory._check_compiler_available("Cx_Freeze")
82 from ._cx_freeze_compiler import CxFreezeCompiler
84 return CxFreezeCompiler(config=config)
86 if normalized_name == "PyInstaller":
87 CompilerFactory._check_compiler_available("PyInstaller")
88 from ._pyinstaller_compiler import PyInstallerCompiler
90 return PyInstallerCompiler(config=config)
92 if normalized_name == "Nuitka":
93 CompilerFactory._check_compiler_available("Nuitka")
94 from ._nuitka_compiler import NuitkaCompiler
96 return NuitkaCompiler(config=config)
98 raise CompilationError(f"Unsupported compiler: {normalized_name}")
100 @staticmethod
101 def get_supported_compilers() -> list[str]:
102 """Return the list of supported compiler names."""
103 return ["Cx_Freeze", "PyInstaller", "Nuitka"]