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

1# /////////////////////////////////////////////////////////////// 

2# TYPES - Type Aliases Module 

3# Project: ezcompiler 

4# /////////////////////////////////////////////////////////////// 

5 

6""" 

7Type aliases module for ezcompiler. 

8 

9This module centralizes common type aliases used throughout the library 

10to improve code readability, maintainability, and type safety. 

11 

12Example: 

13 >>> from ezcompiler._types import IncludeFiles, CompilerName 

14 >>> 

15 >>> def build(compiler: CompilerName, files: IncludeFiles) -> None: 

16 ... pass 

17""" 

18 

19from __future__ import annotations 

20 

21# /////////////////////////////////////////////////////////////// 

22# IMPORTS 

23# /////////////////////////////////////////////////////////////// 

24# Standard library imports 

25from pathlib import Path 

26from typing import TYPE_CHECKING, Literal, Protocol, runtime_checkable 

27 

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 

30 

31# /////////////////////////////////////////////////////////////// 

32# TYPE ALIASES 

33# /////////////////////////////////////////////////////////////// 

34 

35# ------------------------------------------------ 

36# Path Types 

37# ------------------------------------------------ 

38 

39type FilePath = str | Path 

40"""Type alias for file path inputs. 

41 

42Accepts: 

43 - str: String file path 

44 - Path: pathlib.Path object 

45 

46Used by: CompilerConfig, template loaders, file utilities. 

47""" 

48 

49# ------------------------------------------------ 

50# Compiler Types 

51# ------------------------------------------------ 

52 

53type CompilerName = str 

54"""Type alias for compiler name selection. 

55 

56Valid values: "" (unset -> prompt), "Cx_Freeze", "PyInstaller", "Nuitka" 

57 

58Used by: CompilerConfig.compiler, EzCompiler.compile_project(). 

59""" 

60 

61type RepoDestination = Literal["disk", "server", "r2"] 

62"""Type alias for the TUF repository upload backend. 

63 

64Valid values: "disk", "server", "r2" 

65 

66Used by: CompilerConfig.repo_destination, EzCompiler.upload(). 

67""" 

68 

69type ReleaseDestination = Literal["disk", "server", "r2"] 

70"""Type alias for the release zip upload backend. 

71 

72Valid values: "disk", "server", "r2" 

73 

74Used by: CompilerConfig.release_destination, EzCompiler.upload(). 

75""" 

76 

77type ReleaseTarget = Literal["tufup"] 

78"""Type alias for the secure-release backend selection. 

79 

80Valid values: "tufup" 

81 

82Used by: CompilerConfig.release_type, ReleaserFactory. 

83""" 

84 

85# ------------------------------------------------ 

86# Configuration Types 

87# ------------------------------------------------ 

88 

89type IncludeFiles = dict[str, list[str]] 

90"""Type alias for the include_files configuration structure. 

91 

92Expected shape:: 

93 

94 { 

95 "files": ["path/to/file1.txt", "path/to/file2.dll"], 

96 "folders": ["path/to/assets/", "path/to/data/"], 

97 } 

98 

99Used by: CompilerConfig.include_files. 

100""" 

101 

102type JsonMap = dict[str, object] 

103"""Type alias for a generic JSON-serializable mapping. 

104 

105Used by: configuration parsers, template renderers, YAML/JSON loaders. 

106""" 

107 

108# /////////////////////////////////////////////////////////////// 

109# PORTS (structural contracts — Hexagonal architecture) 

110# /////////////////////////////////////////////////////////////// 

111 

112 

113@runtime_checkable 

114class CompilerPort(Protocol): 

115 """Structural contract for a project compiler (Port). 

116 

117 Any object exposing this surface is a valid compiler — no inheritance 

118 required. ``adapters.BaseCompiler`` and its subclasses conform to it. 

119 

120 Used by: CompilerFactory return type, CompilationResult.compiler_instance. 

121 """ 

122 

123 @property 

124 def config(self) -> CompilerConfig: 

125 """Configuration the compiler was built with.""" 

126 ... 

127 

128 @property 

129 def zip_needed(self) -> bool: 

130 """Whether the compiled output must be zipped.""" 

131 ... 

132 

133 def compile(self, console: bool = True) -> None: 

134 """Compile the project. Raises CompilationError on failure.""" 

135 ... 

136 

137 def get_compiler_name(self) -> str: 

138 """Human-readable compiler name.""" 

139 ... 

140 

141 

142@runtime_checkable 

143class UploaderPort(Protocol): 

144 """Structural contract for an artifact uploader (Port). 

145 

146 Any object exposing this surface is a valid uploader — no inheritance 

147 required. ``adapters.BaseUploader`` and its subclasses conform to it. 

148 

149 Used by: UploaderFactory return type, UploaderService boundaries. 

150 """ 

151 

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

153 """Upload a file or directory. Raises UploadError on failure.""" 

154 ... 

155 

156 def download(self, remote_source: str, local_dir: Path) -> None: 

157 """Download a remote tree into ``local_dir``. Raises UploadError.""" 

158 ... 

159 

160 def get_uploader_name(self) -> str: 

161 """Human-readable uploader name.""" 

162 ... 

163 

164 

165@runtime_checkable 

166class ReleaserPort(Protocol): 

167 """Structural contract for a secure-release packager (Port). 

168 

169 Any object exposing this surface is a valid releaser — no inheritance 

170 required. ``adapters.BaseReleaser`` and its subclasses conform to it. 

171 

172 Used by: ReleaserFactory return type, ReleaseService boundaries. 

173 """ 

174 

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``. 

185 

186 Returns the path to the produced ``repository/`` tree. 

187 Raises ReleaseError on failure. 

188 """ 

189 ... 

190 

191 def init_keys(self, app_name: str, repo_dir: Path, keys_dir: Path) -> bool: 

192 """Initialise clés TUF + squelette repo. Idempotent. 

193 

194 Returns True si init effectuée, False si clés déjà présentes (skip). 

195 Raises ReleaseError / SigningKeyError on failure. 

196 """ 

197 ... 

198 

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. 

209 

210 Returns the local repository directory. 

211 Raises ReleaseError / SigningKeyError on failure. 

212 """ 

213 ... 

214 

215 def get_releaser_name(self) -> str: 

216 """Human-readable releaser name.""" 

217 ... 

218 

219 

220@runtime_checkable 

221class InstallerPort(Protocol): 

222 """Structural contract for a first-deployment installer builder (Port). 

223 

224 Any object exposing this surface is a valid installer builder — no 

225 inheritance required. ``adapters.BaseInstaller`` and its subclasses 

226 conform to it. 

227 

228 Used by: InstallerFactory return type, InstallerService boundaries. 

229 """ 

230 

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 ... 

236 

237 def get_installer_name(self) -> str: 

238 """Human-readable installer backend name.""" 

239 ... 

240 

241 

242# /////////////////////////////////////////////////////////////// 

243# PUBLIC API 

244# /////////////////////////////////////////////////////////////// 

245 

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]