Skip to content

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

Get the compiler configuration.

Returns:

Name Type Description
CompilerConfig CompilerConfig

Configuration instance with project settings

zip_needed property

zip_needed: bool

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(console: bool = True) -> None

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_compiler_name() -> str

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_compiler_name() -> str

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(console: bool = True) -> None

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_compiler_name() -> str

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(console: bool = True) -> None

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_compiler_name() -> str

Get the name of this compiler.

Returns:

Name Type Description
str str

Display name "Nuitka"

compile

compile(console: bool = True) -> None

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

get_supported_compilers() -> list[str]

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(output_path: Path, content: str, encoding: str = 'utf-8') -> None

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(output_path: Path, content: str, encoding: str = 'utf-8') -> None

Write text content to disk.


Uploader Adapters

BaseUploader

Abstract base class defining the uploader interface.

BaseUploader

BaseUploader(config: dict[str, Any] | None = None)

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(source_path: Path, destination: str) -> None

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_uploader_name() -> str

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

DiskUploader(config: dict[str, Any] | None = None)

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_uploader_name() -> str

Get the name of this uploader.

Returns:

Name Type Description
str str

Name of the uploader

upload

upload(source_path: Path, destination: str) -> None

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

ServerUploader(config: dict[str, Any] | None = None)

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_uploader_name() -> str

Get the name of this uploader.

Returns:

Name Type Description
str str

Name of the uploader

upload

upload(source_path: Path, destination: str) -> None

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_supported_types() -> list[str]

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_config(upload_type: str, config: dict[str, Any] | None = None) -> bool

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