Adapters Layer¶
Compiler and uploader adapter implementations for EzCompiler.
The adapters layer defines abstract base classes and concrete implementations for compilation and upload operations.
Compiler Adapters¶
BaseCompiler¶
Abstract base class defining the compiler interface.
BaseCompiler
¶
BaseCompiler(config: CompilerConfig)
Bases: ABC
Abstract base class for project compilers.
Defines the interface that all compiler implementations must follow. Provides common functionality for compilation operations and enforces the contract for concrete compiler classes.
Attributes:
| Name | Type | Description |
|---|---|---|
_config |
CompilerConfig instance with project settings |
|
_zip_needed |
Whether compilation output needs to be zipped |
Example
Cannot instantiate directly, must subclass¶
class MyCompiler(BaseCompiler): ... def compile(self, console=True) -> None: ... pass ... def get_compiler_name(self) -> str: ... return "MyCompiler"
Initialize the compiler with configuration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
CompilerConfig
|
CompilerConfig instance with project settings |
required |
config
property
¶
config: CompilerConfig
Get the compiler configuration.
Returns:
| Name | Type | Description |
|---|---|---|
CompilerConfig |
CompilerConfig
|
Configuration instance with project settings |
zip_needed
property
¶
Whether the compiled project needs to be zipped.
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True if output should be zipped, False otherwise |
Note
Subclasses set this based on their output format. Cx_Freeze sets to True, PyInstaller sets to False.
compile
abstractmethod
¶
Compile the project.
This method must be implemented by all subclasses to handle the actual compilation using their respective compiler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
console
|
bool
|
Whether to show console window (default: True) |
True
|
Raises:
| Type | Description |
|---|---|
CompilationError
|
If compilation fails |
Example
compiler = PyInstallerCompiler(config) compiler.compile(console=False)
get_compiler_name
abstractmethod
¶
Get the name of this compiler.
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
Display name of the compiler |
Example
compiler = PyInstallerCompiler(config) name = compiler.get_compiler_name() print(name) 'PyInstaller (Empaquetée)'
CxFreezeCompiler¶
Cx_Freeze compiler implementation for directory-based builds.
CxFreezeCompiler
¶
CxFreezeCompiler(config: CompilerConfig)
Bases: BaseCompiler
Cx_Freeze compiler implementation.
Handles project compilation using Cx_Freeze, which creates a directory structure containing the executable and all dependencies. The output is typically zipped for distribution.
Compilation runs in a separate subprocess to prevent cx_Freeze output from interfering with the main process display (DLP).
Attributes:
| Name | Type | Description |
|---|---|---|
_config |
CompilerConfig with project settings |
Example
config = CompilerConfig(...) compiler = CxFreezeCompiler(config) compiler.compile(console=True)
Initialize Cx_Freeze compiler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
CompilerConfig
|
CompilerConfig instance with project settings |
required |
Note
Cx_Freeze output requires zipping, so _zip_needed is set to True.
get_compiler_name
¶
Get the name of this compiler.
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
Display name "Cx_Freeze" |
Example
compiler = CxFreezeCompiler(config) print(compiler.get_compiler_name()) 'Cx_Freeze'
compile
¶
Compile the project using Cx_Freeze in a subprocess.
Generates a temporary setup script and executes it in a separate process to isolate cx_Freeze stdout/stderr from the main process.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
console
|
bool
|
Whether to show console window (default: True) |
True
|
Raises:
| Type | Description |
|---|---|
CompilationError
|
If compilation fails |
Note
On Windows with console=False, uses Win32GUI base. Runs in subprocess to preserve DLP rendering in main process.
Example
config = CompilerConfig(...) compiler = CxFreezeCompiler(config) compiler.compile(console=False)
PyInstallerCompiler¶
PyInstaller compiler implementation for single-file executables.
PyInstallerCompiler
¶
PyInstallerCompiler(config: CompilerConfig)
Bases: BaseCompiler
PyInstaller compiler implementation.
Handles project compilation using PyInstaller, which creates a single executable file with all dependencies bundled. Can generate either single-file or directory-based executables.
Compilation runs in a separate subprocess to prevent PyInstaller output from interfering with the main process display (DLP).
Attributes:
| Name | Type | Description |
|---|---|---|
_config |
CompilerConfig with project settings |
Example
config = CompilerConfig(...) compiler = PyInstallerCompiler(config) compiler.compile(console=True)
Initialize PyInstaller compiler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
CompilerConfig
|
CompilerConfig instance with project settings |
required |
Note
PyInstaller creates single files, so _zip_needed is set to False.
get_compiler_name
¶
Get the name of this compiler.
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
Display name "PyInstaller (Empaquetée)" |
Example
compiler = PyInstallerCompiler(config) print(compiler.get_compiler_name()) 'PyInstaller (Empaquetée)'
compile
¶
Compile the project using PyInstaller in a subprocess.
Validates configuration, prepares output directory, builds PyInstaller command-line arguments, and runs compilation in a separate process to isolate stdout/stderr from the DLP.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
console
|
bool
|
Whether to show console window (default: True) |
True
|
Raises:
| Type | Description |
|---|---|
CompilationError
|
If compilation fails |
Note
Adds version file if it exists. Includes all configured packages, includes, and applies excludes. Adds files and folders with appropriate data paths.
Example
config = CompilerConfig(...) compiler = PyInstallerCompiler(config) compiler.compile(console=False)
NuitkaCompiler¶
Nuitka compiler implementation for optimized native compilation.
NuitkaCompiler
¶
NuitkaCompiler(config: CompilerConfig)
Bases: BaseCompiler
Nuitka compiler implementation.
Handles project compilation using Nuitka, which can produce a standalone folder or a single-file executable depending on options.
Attributes:
| Name | Type | Description |
|---|---|---|
_config |
CompilerConfig with project settings |
Initialize Nuitka compiler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
CompilerConfig
|
CompilerConfig instance with project settings |
required |
get_compiler_name
¶
Get the name of this compiler.
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
Display name "Nuitka" |
compile
¶
Compile the project using Nuitka.
Validates configuration, prepares output directory, builds Nuitka options from project settings, and runs compilation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
console
|
bool
|
Whether to show console window (default: True) |
True
|
Raises:
| Type | Description |
|---|---|
CompilationError
|
If compilation fails |
CompilerFactory¶
Factory class for creating compiler instances based on name or configuration.
CompilerFactory
¶
Factory class for creating compiler instances.
create_compiler
staticmethod
¶
create_compiler(config: CompilerConfig, compiler_name: str) -> BaseCompiler
Create a compiler instance from its name.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
CompilerConfig
|
Compiler configuration to inject |
required |
compiler_name
|
str
|
Compiler name (Cx_Freeze, PyInstaller, Nuitka) |
required |
Returns:
| Name | Type | Description |
|---|---|---|
BaseCompiler |
BaseCompiler
|
Concrete compiler instance |
Raises:
| Type | Description |
|---|---|
CompilationError
|
If compiler name is unsupported |
create_from_config
staticmethod
¶
create_from_config(config: CompilerConfig) -> BaseCompiler
Create a compiler instance using the config default compiler.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
CompilerConfig
|
Compiler configuration |
required |
Returns:
| Name | Type | Description |
|---|---|---|
BaseCompiler |
BaseCompiler
|
Concrete compiler instance |
Raises:
| Type | Description |
|---|---|
CompilationError
|
If config compiler is unsupported |
get_supported_compilers
staticmethod
¶
Return the list of supported compiler names.
File Writer Adapters¶
BaseFileWriter¶
Abstract base class defining the file writer interface.
BaseFileWriter
¶
Bases: ABC
Port for writing text content to a target file path.
write_text
abstractmethod
¶
Write text content to output_path.
DiskFileWriter¶
Concrete file writer implementation for local disk operations.
DiskFileWriter
¶
Bases: BaseFileWriter
Write text files to local disk using pathlib.
write_text
¶
Write text content to disk.
Uploader Adapters¶
BaseUploader¶
Abstract base class defining the uploader interface.
BaseUploader
¶
Bases: ABC
Abstract base class for uploaders.
Defines the interface that all uploaders must implement and provides common functionality for upload operations and validation.
Attributes:
| Name | Type | Description |
|---|---|---|
_config |
Configuration dictionary for the uploader |
Example
class MyUploader(BaseUploader): ... def upload(self, source_path: Path, destination: str) -> None: ... # Implementation ... pass ... def get_uploader_name(self) -> str: ... return "My Uploader"
Initialize the uploader with configuration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
dict[str, Any] | None
|
Configuration dictionary (default: None) |
None
|
Note
Subclasses should call super().init(config) to initialize configuration and validation.
upload
abstractmethod
¶
Upload a file or directory to the destination.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source_path
|
Path
|
Path to the source file or directory |
required |
destination
|
str
|
Destination path or URL |
required |
Raises:
| Type | Description |
|---|---|
UploadError
|
If upload fails |
Note
Subclasses must implement this method to define upload behavior.
get_uploader_name
abstractmethod
¶
Get the name of this uploader.
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
Human-readable name of the uploader |
Note
Used for identification purposes.
DiskUploader¶
Local disk uploader for saving compiled projects to the file system.
DiskUploader
¶
Bases: BaseUploader
Uploader for local disk operations.
Handles copying files and directories to local disk locations with configurable behavior for permissions, overwrites, and backups.
Configuration keys
preserve_permissions (bool): Preserve file permissions (default: True) overwrite (bool): Allow overwriting existing files (default: True) create_backup (bool): Create backup before overwrite (default: False)
Example
config = {"preserve_permissions": True, "overwrite": True} uploader = DiskUploader(config) uploader.upload(Path("source.zip"), "/path/to/destination.zip")
Initialize the disk uploader.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
dict[str, Any] | None
|
Optional configuration dictionary with keys: - preserve_permissions (bool): Preserve file permissions - overwrite (bool): Allow overwriting existing files - create_backup (bool): Create backup before overwrite |
None
|
get_uploader_name
¶
Get the name of this uploader.
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
Name of the uploader |
upload
¶
Upload a file or directory to a local disk location.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source_path
|
Path
|
Path to the source file or directory |
required |
destination
|
str
|
Destination path on local disk |
required |
Raises:
| Type | Description |
|---|---|
UploadError
|
If upload fails |
Note
Creates parent directories automatically if they don't exist.
ServerUploader¶
HTTP/HTTPS server uploader for remote distribution.
ServerUploader
¶
Bases: BaseUploader
Uploader for server operations via HTTP/HTTPS.
Handles uploading files to remote servers using HTTP POST requests with support for authentication, SSL verification, and automatic retry logic.
Configuration keys
server_url (str): Base URL of the upload server username (str): Username for basic authentication (default: "") password (str): Password for basic authentication (default: "") api_key (str): API key for bearer token authentication (default: "") timeout (int|float): Request timeout in seconds (default: 30) verify_ssl (bool): Verify SSL certificates (default: True) chunk_size (int): Chunk size for uploads (default: 8192) retry_attempts (int): Number of retry attempts (default: 3)
Example
config = {"server_url": "https://example.com", "api_key": "abc123"} uploader = ServerUploader(config) uploader.upload(Path("file.zip"), "/uploads/file.zip")
Initialize the server uploader.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
dict[str, Any] | None
|
Optional configuration dictionary with server settings |
None
|
get_uploader_name
¶
Get the name of this uploader.
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
Name of the uploader |
upload
¶
Upload a file to a remote server.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source_path
|
Path
|
Path to the source file |
required |
destination
|
str
|
Destination path on the server |
required |
Raises:
| Type | Description |
|---|---|
UploadError
|
If upload fails after all retry attempts |
Note
Only supports single files, not directories. Automatically retries on failure based on retry_attempts config.
Factory¶
UploaderFactory¶
Factory class for creating uploader instances based on configuration.
UploaderFactory
¶
Factory class for creating uploader instances.
Provides a centralized way to create and configure uploader instances based on type specification, with support for validation and type discovery.
Example
uploader = UploaderFactory.create_uploader("disk", {"overwrite": True}) types = UploaderFactory.get_supported_types() print(types) ['disk', 'server']
create_uploader
staticmethod
¶
create_uploader(upload_type: str, config: dict[str, Any] | None = None) -> BaseUploader
Create an uploader instance based on the specified type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
upload_type
|
str
|
Type of uploader ("disk" or "server") |
required |
config
|
dict[str, Any] | None
|
Configuration dictionary for the uploader (default: None) |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
BaseUploader |
BaseUploader
|
Configured uploader instance |
Raises:
| Type | Description |
|---|---|
UploadError
|
If upload type is not supported |
Example
disk_uploader = UploaderFactory.create_uploader("disk") server_uploader = UploaderFactory.create_uploader( ... "server", {"server_url": "https://example.com"} ... )
create_from_config
staticmethod
¶
create_from_config(config: dict[str, Any]) -> BaseUploader
Create an uploader instance from a configuration dictionary.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
dict[str, Any]
|
Configuration dictionary containing: - type: Upload type ("disk" or "server") - config: Uploader-specific configuration (optional) |
required |
Returns:
| Name | Type | Description |
|---|---|---|
BaseUploader |
BaseUploader
|
Configured uploader instance |
Raises:
| Type | Description |
|---|---|
UploadError
|
If configuration is invalid or type is missing |
Example
config = { ... "type": "disk", ... "config": {"overwrite": True} ... } uploader = UploaderFactory.create_from_config(config)
get_supported_types
staticmethod
¶
Get list of supported upload types.
Returns:
| Type | Description |
|---|---|
list[str]
|
list[str]: List of supported upload type names |
Example
types = UploaderFactory.get_supported_types() print(types) ['disk', 'server']
validate_config
staticmethod
¶
Validate configuration for a specific upload type.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
upload_type
|
str
|
Type of uploader to validate |
required |
config
|
dict[str, Any] | None
|
Configuration to validate (default: None) |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
bool |
bool
|
True if configuration is valid, False otherwise |
Note
Creates a temporary uploader instance to test configuration validity.
Example
is_valid = UploaderFactory.validate_config("disk", {"overwrite": True}) print(is_valid) True