Skip to content

Services Layer

Business logic services and orchestration for EzCompiler.

The services layer implements the core business logic, handling compilation, configuration, template processing, and upload operations.


CompilerService

Service for managing compiler selection and orchestrating the compilation process.

CompilerService

CompilerService(config: CompilerConfig)

Compilation orchestration service.

Orchestrates project compilation using different compiler backends. Handles compiler selection, validation, and execution.

Attributes:

Name Type Description
_config

CompilerConfig instance with project settings

Example

config = CompilerConfig(...) service = CompilerService(config) result = service.compile(console=True, compiler="PyInstaller") print(result.zip_needed) False

Initialize the compiler service.

Parameters:

Name Type Description Default
config CompilerConfig

CompilerConfig instance with project settings

required

Raises:

Type Description
ConfigurationError

If config is None or invalid

compiler_instance property

compiler_instance: BaseCompiler | None

Get the current compiler instance.

Returns:

Type Description
BaseCompiler | None

BaseCompiler | None: Current compiler instance or None if not compiled yet

compile

compile(console: bool = True, compiler: _CompilerName | None = None) -> CompilationResult

Compile the project using specified or auto-selected compiler.

Validates configuration, selects compiler if not specified, and executes compilation. Returns result with zip_needed flag.

Parameters:

Name Type Description Default
console bool

Whether to show console window (default: True)

True
compiler _CompilerName | None

Compiler to use or None for auto-selection - "Cx_Freeze": Creates directory with dependencies - "PyInstaller": Creates single executable - "Nuitka": Creates standalone folder or single executable - "auto" or None: Prompt user for choice or use config default

None

Returns:

Name Type Description
CompilationResult CompilationResult

Result with zip_needed flag and compiler instance

Raises:

Type Description
ConfigurationError

If project not initialized

CompilationError

If compilation fails

Example

service = CompilerService(config) result = service.compile(console=False, compiler="PyInstaller") if result.zip_needed: ... # Create ZIP archive


ConfigService

Service for loading, validating, and managing configuration.

ConfigService

Configuration orchestration service.

Orchestrates configuration loading from multiple sources with a cascade merge system. Sources are merged in priority order (later wins):

  1. pyproject.toml [project] + [tool.ezcompiler] (base)
  2. ezcompiler.yaml or ezcompiler.json (override)
  3. CLI arguments (final override)
Example

config = ConfigService.build_compiler_config() config = ConfigService.build_compiler_config( ... config_path=Path("ezcompiler.yaml"), ... cli_overrides={"compiler": "PyInstaller"}, ... )

load_config staticmethod

load_config(config_path: Path | None = None, pyproject_path: Path | None = None, cli_overrides: dict[str, Any] | None = None, search_dir: Path | None = None) -> dict[str, Any]

Load configuration with full cascade.

Merges configuration from multiple sources in priority order: 1. pyproject.toml [project] + [tool.ezcompiler] (base layer) 2. ezcompiler.yaml or .json - explicit or auto-discovered (override) 3. CLI overrides (final override)

Parameters:

Name Type Description Default
config_path Path | None

Explicit config file path for YAML/JSON (skips auto-discovery)

None
pyproject_path Path | None

Explicit pyproject.toml path (default: search_dir/pyproject.toml)

None
cli_overrides dict[str, Any] | None

Dict of CLI-provided overrides (only non-default values)

None
search_dir Path | None

Directory to search for config files (default: cwd)

None

Returns:

Type Description
dict[str, Any]

dict[str, Any]: Merged configuration dictionary

Raises:

Type Description
ConfigurationError

If no configuration source found or loading fails

build_compiler_config staticmethod

build_compiler_config(config_path: Path | None = None, pyproject_path: Path | None = None, cli_overrides: dict[str, Any] | None = None, search_dir: Path | None = None) -> CompilerConfig

Load configuration and create a CompilerConfig instance.

Convenience method that combines load_config() with CompilerConfig.from_dict().

Parameters:

Name Type Description Default
config_path Path | None

Explicit config file path for YAML/JSON

None
pyproject_path Path | None

Explicit pyproject.toml path

None
cli_overrides dict[str, Any] | None

Dict of CLI-provided overrides

None
search_dir Path | None

Directory to search for config files (default: cwd)

None

Returns:

Name Type Description
CompilerConfig CompilerConfig

Validated configuration instance

Raises:

Type Description
ConfigurationError

If configuration is invalid or not found

load_pyproject_as_dict staticmethod

load_pyproject_as_dict(pyproject_path: Path) -> dict[str, Any]

Load and extract configuration from a pyproject.toml file.

Parameters:

Name Type Description Default
pyproject_path Path

Path to the pyproject.toml file

required

Returns:

Type Description
dict[str, Any]

dict[str, Any]: Extracted configuration dictionary

Raises:

Type Description
ConfigurationError

If the file cannot be loaded or parsed

merge_configs staticmethod

merge_configs(base: dict[str, Any], override: dict[str, Any]) -> dict[str, Any]

Deep-merge two configuration dictionaries (override wins on conflicts).

Parameters:

Name Type Description Default
base dict[str, Any]

Base configuration dictionary

required
override dict[str, Any]

Override dictionary (values win over base)

required

Returns:

Type Description
dict[str, Any]

dict[str, Any]: Merged configuration dictionary


TemplateService

Service for processing templates and generating dynamic files.

TemplateService

TemplateService(file_writer: BaseFileWriter | None = None)

Template processing and file generation service.

Orchestrates template loading, processing, and file generation for configuration files, setup.py, and version information files.

Attributes:

Name Type Description
_template_loader

TemplateLoader instance for template operations

_processor

TemplateProcessor instance for variable substitution

Example

service = TemplateService() config = {"version": "1.0.0", "project_name": "MyApp"} service.generate_setup_file(config, Path("setup.py")) service.generate_version_file(config, Path("version_info.txt"))

Initialize the template service.

Creates TemplateLoader and TemplateProcessor instances for template operations.

generate_config_file

generate_config_file(config: dict[str, Any], output_path: Path, format_type: str = 'yaml') -> None

Generate a configuration file (YAML or JSON) from template.

Parameters:

Name Type Description Default
config dict[str, Any]

Project configuration dictionary

required
output_path Path

Path where to save the config file

required
format_type str

Format type ("yaml" or "json")

'yaml'

Raises:

Type Description
TemplateError

If generation fails

Example

config = {"version": "1.0.0", "project_name": "MyApp"} service.generate_config_file(config, Path("ezcompiler.yaml"), "yaml")

generate_setup_file

generate_setup_file(config: dict[str, Any], output_path: Path | None = None, output_dir: Path | None = None) -> Path

Generate a setup.py file from template.

Parameters:

Name Type Description Default
config dict[str, Any]

Project configuration dictionary

required
output_path Path | None

Direct path to setup.py file (optional)

None
output_dir Path | None

Directory where to save setup.py (optional, defaults to current dir)

None

Returns:

Name Type Description
Path Path

Path to the generated setup.py file

Raises:

Type Description
TemplateError

If generation fails

Example

config = {"version": "1.0.0", "project_name": "MyApp"} setup_path = service.generate_setup_file(config, output_dir=Path("build"))

generate_version_file

generate_version_file(config: dict[str, Any], output_path: Path | None = None, format_type: str = 'txt') -> Path

Generate a version information file from template.

Parameters:

Name Type Description Default
config dict[str, Any]

Project configuration dictionary

required
output_path Path | None

Path where to save the version file (optional)

None
format_type str

Template format type (default: "txt")

'txt'

Returns:

Name Type Description
Path Path

Path to the generated version file

Raises:

Type Description
VersionError

If generation fails

Note

If output_path is None, uses version_filename and output_folder from config.

Example

config = { ... "version": "1.0.0", ... "project_name": "MyApp", ... "version_filename": "version_info.txt", ... "output_folder": "dist" ... } version_path = service.generate_version_file(config)

process_config_template

process_config_template(format_type: str, config: dict[str, Any]) -> str

Process a configuration template with values.

Parameters:

Name Type Description Default
format_type str

Format type ("yaml" or "json")

required
config dict[str, Any]

Configuration dictionary

required

Returns:

Name Type Description
str str

Processed template content

Example

config = {"version": "1.0.0", "project_name": "MyApp"} content = service.process_config_template("yaml", config)

process_setup_template

process_setup_template(config: dict[str, Any]) -> str

Process a setup template with values.

Parameters:

Name Type Description Default
config dict[str, Any]

Configuration dictionary

required

Returns:

Name Type Description
str str

Processed template content

Example

config = {"version": "1.0.0", "project_name": "MyApp"} content = service.process_setup_template(config)

process_version_template

process_version_template(version: str, company_name: str, project_description: str, project_name: str, format_type: str = 'txt') -> str

Process a version template with values.

Parameters:

Name Type Description Default
version str

Project version

required
company_name str

Company name

required
project_description str

Project description

required
project_name str

Project name

required
format_type str

Format type (default: "txt")

'txt'

Returns:

Name Type Description
str str

Processed template content

Example

content = service.process_version_template( ... "1.0.0", "MyCompany", "Description", "MyApp" ... )

list_available_templates

list_available_templates() -> dict[str, list[str]]

List all available templates.

Returns:

Type Description
dict[str, list[str]]

dict[str, list[str]]: Dictionary mapping template types to available formats

Example

templates = service.list_available_templates() print(templates)

validate_template

validate_template(template_type: str, format_type: str) -> bool

Validate a template file.

Parameters:

Name Type Description Default
template_type str

Type of template (config, version, setup)

required
format_type str

Format of the template

required

Returns:

Name Type Description
bool bool

True if template is valid, False otherwise

Example

is_valid = service.validate_template("config", "yaml")

generate_mockup_template

generate_mockup_template(template_type: str, format_type: str, output_path: Path) -> None

Generate a template file with mockup values instead of placeholders.

Parameters:

Name Type Description Default
template_type str

Type of template (config, version, setup)

required
format_type str

Format of the template (yaml, json, py, txt)

required
output_path Path

Path where to save the generated file

required

Raises:

Type Description
TemplateError

If generation fails

Example

service.generate_mockup_template("config", "yaml", Path("ezcompiler.yaml"))

generate_raw_template

generate_raw_template(template_type: str, format_type: str, output_path: Path) -> None

Generate a raw template file with placeholders.

Parameters:

Name Type Description Default
template_type str

Type of template (config, version, setup)

required
format_type str

Format of the template (yaml, json, py, txt)

required
output_path Path

Path where to save the template file

required

Raises:

Type Description
TemplateError

If generation fails

Example

service.generate_raw_template("config", "yaml", Path("template.yaml"))


PipelineService

Service for orchestrating the full compile → zip → upload pipeline with injectable factory.

PipelineService

PipelineService(compiler_service_factory: Callable[[CompilerConfig], CompilerService] | None = None)

Service that coordinates compile, zip and upload stages.

Initialise the pipeline service.

Parameters:

Name Type Description Default
compiler_service_factory Callable[[CompilerConfig], CompilerService] | None

Optional factory to create a CompilerService from a CompilerConfig. Defaults to CompilerService constructor. Inject a custom factory in tests to avoid triggering real compilation.

None

compile_project

compile_project(config: CompilerConfig, console: bool = True, compiler: str | None = None) -> tuple[CompilerService, CompilationResult]

Compile a project and return service + result.

zip_artifact

zip_artifact(config: CompilerConfig, compiler_service: CompilerService, compilation_result: CompilationResult | None, progress_callback: Callable[[str, int], None] | None = None) -> bool

Create ZIP artifact when required and return True when created.

build_stages staticmethod

build_stages(config: CompilerConfig, should_zip: bool = False, should_upload: bool = False) -> list[dict[str, Any]]

Build the stage list for dynamic_layered_progress.

Parameters:

Name Type Description Default
config CompilerConfig

Compiler configuration (used for display labels)

required
should_zip bool

Whether a ZIP stage should be included

False
should_upload bool

Whether an upload stage should be included

False

Returns:

Type Description
list[dict[str, Any]]

list[dict]: Stage configuration list ready for dynamic_layered_progress

upload_artifact

upload_artifact(config: CompilerConfig, structure: str, destination: str, compilation_result: CompilationResult | None, upload_config: dict[str, Any] | None = None) -> None

Upload project artifact to a destination.


UploaderService

Service for orchestrating upload operations to various backends.

UploaderService

Upload orchestration service.

Orchestrates file and directory uploads using different upload backends. Handles upload type selection, validation, and execution.

Example

service = UploaderService() service.upload( ... source_path=Path("dist.zip"), ... upload_type="disk", ... destination="releases/", ... upload_config={"overwrite": True} ... )

upload staticmethod

upload(source_path: Path, upload_type: UploadType, destination: str, upload_config: dict[str, Any] | None = None) -> None

Upload a file or directory to the specified destination.

Parameters:

Name Type Description Default
source_path Path

Path to the source file or directory

required
upload_type UploadType

Type of upload ("disk" or "server")

required
destination str

Destination path or URL

required
upload_config dict[str, Any] | None

Additional uploader configuration options

None

Raises:

Type Description
UploadError

If upload fails or upload type is invalid

Example

UploaderService.upload( ... Path("dist.zip"), ... "disk", ... "releases/", ... {"overwrite": True} ... )

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 = UploaderService.get_supported_types() print(types) ['disk', 'server']

validate_upload_config staticmethod

validate_upload_config(upload_type: UploadType, config: dict[str, Any] | None = None) -> bool

Validate configuration for a specific upload type.

Parameters:

Name Type Description Default
upload_type UploadType

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

Example

is_valid = UploaderService.validate_upload_config( ... "disk", {"overwrite": True} ... )