Coverage for src/ezcompiler/_types.py: 90.91%
20 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# TYPES - Type Aliases Module
3# Project: ezcompiler
4# ///////////////////////////////////////////////////////////////
6"""
7Type aliases module for ezcompiler.
9This module centralizes common type aliases used throughout the library
10to improve code readability, maintainability, and type safety.
12Example:
13 >>> from ezcompiler._types import IncludeFiles, CompilerName
14 >>>
15 >>> def build(compiler: CompilerName, files: IncludeFiles) -> None:
16 ... pass
17"""
19from __future__ import annotations
21# ///////////////////////////////////////////////////////////////
22# IMPORTS
23# ///////////////////////////////////////////////////////////////
24# Standard library imports
25from pathlib import Path
26from typing import TYPE_CHECKING, Literal, Protocol, runtime_checkable
28if TYPE_CHECKING: 28 ↛ 29line 28 didn't jump to line 29 because the condition on line 28 was never true
29 from .shared import CompilerConfig
31# ///////////////////////////////////////////////////////////////
32# TYPE ALIASES
33# ///////////////////////////////////////////////////////////////
35# ------------------------------------------------
36# Path Types
37# ------------------------------------------------
39type FilePath = str | Path
40"""Type alias for file path inputs.
42Accepts:
43 - str: String file path
44 - Path: pathlib.Path object
46Used by: CompilerConfig, template loaders, file utilities.
47"""
49# ------------------------------------------------
50# Compiler Types
51# ------------------------------------------------
53type CompilerName = str
54"""Type alias for compiler name selection.
56Valid values: "" (unset -> prompt), "Cx_Freeze", "PyInstaller", "Nuitka"
58Used by: CompilerConfig.compiler, EzCompiler.compile_project().
59"""
61type RepoDestination = Literal["disk", "server", "r2"]
62"""Type alias for the TUF repository upload backend.
64Valid values: "disk", "server", "r2"
66Used by: CompilerConfig.repo_destination, EzCompiler.upload().
67"""
69type ReleaseDestination = Literal["disk", "server", "r2"]
70"""Type alias for the release zip upload backend.
72Valid values: "disk", "server", "r2"
74Used by: CompilerConfig.release_destination, EzCompiler.upload().
75"""
77type ReleaseTarget = Literal["tufup"]
78"""Type alias for the secure-release backend selection.
80Valid values: "tufup"
82Used by: CompilerConfig.release_type, ReleaserFactory.
83"""
85# ------------------------------------------------
86# Configuration Types
87# ------------------------------------------------
89type IncludeFiles = dict[str, list[str]]
90"""Type alias for the include_files configuration structure.
92Expected shape::
94 {
95 "files": ["path/to/file1.txt", "path/to/file2.dll"],
96 "folders": ["path/to/assets/", "path/to/data/"],
97 }
99Used by: CompilerConfig.include_files.
100"""
102type JsonMap = dict[str, object]
103"""Type alias for a generic JSON-serializable mapping.
105Used by: configuration parsers, template renderers, YAML/JSON loaders.
106"""
108# ///////////////////////////////////////////////////////////////
109# PORTS (structural contracts — Hexagonal architecture)
110# ///////////////////////////////////////////////////////////////
113@runtime_checkable
114class CompilerPort(Protocol):
115 """Structural contract for a project compiler (Port).
117 Any object exposing this surface is a valid compiler — no inheritance
118 required. ``adapters.BaseCompiler`` and its subclasses conform to it.
120 Used by: CompilerFactory return type, CompilationResult.compiler_instance.
121 """
123 @property
124 def config(self) -> CompilerConfig:
125 """Configuration the compiler was built with."""
126 ...
128 @property
129 def zip_needed(self) -> bool:
130 """Whether the compiled output must be zipped."""
131 ...
133 def compile(self, console: bool = True) -> None:
134 """Compile the project. Raises CompilationError on failure."""
135 ...
137 def get_compiler_name(self) -> str:
138 """Human-readable compiler name."""
139 ...
142@runtime_checkable
143class UploaderPort(Protocol):
144 """Structural contract for an artifact uploader (Port).
146 Any object exposing this surface is a valid uploader — no inheritance
147 required. ``adapters.BaseUploader`` and its subclasses conform to it.
149 Used by: UploaderFactory return type, UploaderService boundaries.
150 """
152 def upload(self, source_path: Path, destination: str) -> None:
153 """Upload a file or directory. Raises UploadError on failure."""
154 ...
156 def download(self, remote_source: str, local_dir: Path) -> None:
157 """Download a remote tree into ``local_dir``. Raises UploadError."""
158 ...
160 def get_uploader_name(self) -> str:
161 """Human-readable uploader name."""
162 ...
165@runtime_checkable
166class ReleaserPort(Protocol):
167 """Structural contract for a secure-release packager (Port).
169 Any object exposing this surface is a valid releaser — no inheritance
170 required. ``adapters.BaseReleaser`` and its subclasses conform to it.
172 Used by: ReleaserFactory return type, ReleaseService boundaries.
173 """
175 def release(
176 self,
177 bundle_dir: Path,
178 app_name: str,
179 version: str,
180 repo_dir: Path,
181 *,
182 patch: bool = True,
183 ) -> Path:
184 """Build and sign the local TUF repository for ``bundle_dir``.
186 Returns the path to the produced ``repository/`` tree.
187 Raises ReleaseError on failure.
188 """
189 ...
191 def init_keys(self, app_name: str, repo_dir: Path, keys_dir: Path) -> bool:
192 """Initialise clés TUF + squelette repo. Idempotent.
194 Returns True si init effectuée, False si clés déjà présentes (skip).
195 Raises ReleaseError / SigningKeyError on failure.
196 """
197 ...
199 def refresh_expiration(
200 self,
201 app_name: str,
202 repo_dir: Path,
203 keys_dir: Path,
204 *,
205 roles: tuple[str, ...] = ...,
206 days: int | None = None,
207 ) -> Path:
208 """Re-sign metadata to push out expiration without a new release.
210 Returns the local repository directory.
211 Raises ReleaseError / SigningKeyError on failure.
212 """
213 ...
215 def get_releaser_name(self) -> str:
216 """Human-readable releaser name."""
217 ...
220@runtime_checkable
221class InstallerPort(Protocol):
222 """Structural contract for a first-deployment installer builder (Port).
224 Any object exposing this surface is a valid installer builder — no
225 inheritance required. ``adapters.BaseInstaller`` and its subclasses
226 conform to it.
228 Used by: InstallerFactory return type, InstallerService boundaries.
229 """
231 def build(
232 self, bundle_dir: Path, app_name: str, version: str, output_dir: Path
233 ) -> Path:
234 """Build the installer executable. Raises InstallerError on failure."""
235 ...
237 def get_installer_name(self) -> str:
238 """Human-readable installer backend name."""
239 ...
242# ///////////////////////////////////////////////////////////////
243# PUBLIC API
244# ///////////////////////////////////////////////////////////////
246__all__ = [
247 "FilePath",
248 "CompilerName",
249 "RepoDestination",
250 "ReleaseDestination",
251 "ReleaseTarget",
252 "IncludeFiles",
253 "JsonMap",
254 "CompilerPort",
255 "UploaderPort",
256 "ReleaserPort",
257 "InstallerPort",
258]