Coverage for pyTooling / Platform / __init__.py: 79%

316 statements  

« prev     ^ index     » next       coverage.py v7.13.3, created at 2026-02-07 17:18 +0000

1# ==================================================================================================================== # 

2# _____ _ _ ____ _ _ __ # 

3# _ __ _ |_ _|__ ___ | (_)_ __ __ _ | _ \| | __ _| |_ / _| ___ _ __ _ __ ___ # 

4# | '_ \| | | || |/ _ \ / _ \| | | '_ \ / _` | | |_) | |/ _` | __| |_ / _ \| '__| '_ ` _ \ # 

5# | |_) | |_| || | (_) | (_) | | | | | | (_| |_| __/| | (_| | |_| _| (_) | | | | | | | | # 

6# | .__/ \__, ||_|\___/ \___/|_|_|_| |_|\__, (_)_| |_|\__,_|\__|_| \___/|_| |_| |_| |_| # 

7# |_| |___/ |___/ # 

8# ==================================================================================================================== # 

9# Authors: # 

10# Patrick Lehmann # 

11# # 

12# License: # 

13# ==================================================================================================================== # 

14# Copyright 2017-2026 Patrick Lehmann - Bötzingen, Germany # 

15# # 

16# Licensed under the Apache License, Version 2.0 (the "License"); # 

17# you may not use this file except in compliance with the License. # 

18# You may obtain a copy of the License at # 

19# # 

20# http://www.apache.org/licenses/LICENSE-2.0 # 

21# # 

22# Unless required by applicable law or agreed to in writing, software # 

23# distributed under the License is distributed on an "AS IS" BASIS, # 

24# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # 

25# See the License for the specific language governing permissions and # 

26# limitations under the License. # 

27# # 

28# SPDX-License-Identifier: Apache-2.0 # 

29# ==================================================================================================================== # 

30# 

31""" 

32Common platform information gathered from various sources. 

33 

34.. hint:: 

35 

36 See :ref:`high-level help <COMMON/Platform>` for explanations and usage examples. 

37""" 

38from enum import Flag, auto, Enum 

39 

40from pyTooling.Decorators import export, readonly 

41from pyTooling.Exceptions import ToolingException 

42from pyTooling.MetaClasses import ExtendedType 

43from pyTooling.Versioning import PythonVersion 

44 

45 

46__all__ = ["CurrentPlatform"] 

47 

48 

49@export 

50class PlatformException(ToolingException): 

51 """Base-exception of all exceptions raised by :mod:`pyTooling.Platform`.""" 

52 

53 

54@export 

55class UnknownPlatformException(PlatformException): 

56 """ 

57 The exception is raised by pyTooling.Platform when the platform can't be determined. 

58 

59 For debugging purposes, a list of system properties from various APIs is added as notes to this exception to ease 

60 debugging unknown or new platforms. 

61 """ 

62 

63 def __init__(self, *args) -> None: 

64 """ 

65 Initialize a new :class:`UnknownPlatformException` instance and add notes with further debugging information. 

66 

67 :param args: Forward positional parameters. 

68 """ 

69 super().__init__(*args) 

70 

71 import sys 

72 import os 

73 import platform 

74 import sysconfig 

75 

76 self.add_note(f"os.name: {os.name}") 

77 self.add_note(f"platform.system: {platform.system()}") 

78 self.add_note(f"platform.machine: {platform.machine()}") 

79 self.add_note(f"platform.architecture: {platform.architecture()}") 

80 self.add_note(f"sys.platform: {sys.platform}") 

81 self.add_note(f"sysconfig.get_platform: {sysconfig.get_platform()}") 

82 

83 

84@export 

85class UnknownOperatingSystemException(PlatformException): 

86 """The exception is raised by pyTooling.Platform when the operating system is unknown.""" 

87 

88 

89@export 

90class PythonImplementation(Enum): 

91 """An enumeration describing the Python implementation (CPython, PyPy, ...).""" 

92 Unknown = 0 #: Unknown Python implementation 

93 

94 CPython = 1 #: CPython (reference implementation) 

95 PyPy = 2 #: PyPy 

96 

97 

98@export 

99class Platforms(Flag): 

100 """A flag describing on which platform Python is running on and/or in which environment it's running in.""" 

101 Unknown = 0 

102 

103 OS_FreeBSD = auto() #: Operating System: BSD (Unix). 

104 OS_Linux = auto() #: Operating System: Linux. 

105 OS_MacOS = auto() #: Operating System: macOS. 

106 OS_Windows = auto() #: Operating System: Windows. 

107 

108 OperatingSystem = OS_FreeBSD | OS_Linux | OS_MacOS | OS_Windows #: Mask: Any operating system. 

109 

110 SEP_WindowsPath = auto() #: Seperator: Path element seperator (e.g. for directories). 

111 SEP_WindowsValue = auto() #: Seperator: Value seperator in variables (e.g. for paths in PATH). 

112 

113 ENV_Native = auto() #: Environment: :term:`native`. 

114 ENV_WSL = auto() #: Environment: :term:`Windows System for Linux <WSL>`. 

115 ENV_MSYS2 = auto() #: Environment: :term:`MSYS2`. 

116 ENV_Cygwin = auto() #: Environment: :term:`Cygwin`. 

117 

118 Environment = ENV_Native | ENV_WSL | ENV_MSYS2 | ENV_Cygwin #: Mask: Any environment. 

119 

120 CI_None = auto() #: CI: No CI environment detected. Running on host. 

121 CI_AppVeyor = auto() #: CI: AppVayor 

122 CI_GitHubActions = auto() #: CI: GitHub Actions 

123 CI_GitLabCI = auto() #: CI: GitLab CI 

124 CI_TravisCI = auto() #: CI: Travis CI 

125 

126 ContinuousIntegration = CI_None | CI_AppVeyor | CI_GitHubActions | CI_GitLabCI | CI_TravisCI #: Mask: Any CI environment. 

127 

128 ARCH_x86_32 = auto() #: Architecture: x86-32 (IA32). 

129 ARCH_x86_64 = auto() #: Architecture: x86-64 (AMD64). 

130 ARCH_AArch64 = auto() #: Architecture: AArch64 (arm64). 

131 

132 Arch_x86 = ARCH_x86_32 | ARCH_x86_64 #: Mask: Any x86 architecture. 

133 Arch_Arm = ARCH_AArch64 #: Mask: Any Arm architecture. 

134 Architecture = Arch_x86 | Arch_Arm #: Mask: Any architecture. 

135 

136 FreeBSD = OS_FreeBSD | ENV_Native #: Group: native FreeBSD on x86-64. 

137 Linux = OS_Linux | ENV_Native #: Group: native Linux on x86-64. 

138 MacOS = OS_MacOS | ENV_Native #: Group: native macOS. 

139 Windows = OS_Windows | ENV_Native | SEP_WindowsPath | SEP_WindowsValue #: Group: native Windows on x86-64. 

140 

141 Linux_x86_64 = Linux | ARCH_x86_64 #: Group: native Linux on x86-64. 

142 Linux_AArch64 = Linux | ARCH_AArch64 #: Group: native Linux on aarch64. 

143 MacOS_Intel = MacOS | ARCH_x86_64 #: Group: native macOS on x86-64. 

144 MacOS_ARM = MacOS | ARCH_AArch64 #: Group: native macOS on aarch64. 

145 Windows_x86_64 = Windows | ARCH_x86_64 #: Group: native Windows on x86-64. 

146 Windows_AArch64 = Windows | ARCH_AArch64 #: Group: native Windows on aarch64. 

147 

148 MSYS = auto() #: MSYS2 Runtime: MSYS. 

149 MinGW32 = auto() #: MSYS2 Runtime: :term:`MinGW32 <MinGW>`. 

150 MinGW64 = auto() #: MSYS2 Runtime: :term:`MinGW64 <MinGW>`. 

151 UCRT64 = auto() #: MSYS2 Runtime: :term:`UCRT64 <UCRT>`. 

152 Clang32 = auto() #: MSYS2 Runtime: Clang32. 

153 Clang64 = auto() #: MSYS2 Runtime: Clang64. 

154 

155 MSYS2_Runtime = MSYS | MinGW32 | MinGW64 | UCRT64 | Clang32 | Clang64 #: Mask: Any MSYS2 runtime environment. 

156 

157 Windows_MSYS2_MSYS = OS_Windows | ENV_MSYS2 | ARCH_x86_64 | MSYS #: Group: MSYS runtime running on Windows x86-64 

158 Windows_MSYS2_MinGW32 = OS_Windows | ENV_MSYS2 | ARCH_x86_32 | MinGW32 #: Group: MinGW32 runtime running on Windows x86-64 

159 Windows_MSYS2_MinGW64 = OS_Windows | ENV_MSYS2 | ARCH_x86_64 | MinGW64 #: Group: MinGW64 runtime running on Windows x86-64 

160 Windows_MSYS2_UCRT64 = OS_Windows | ENV_MSYS2 | ARCH_x86_64 | UCRT64 #: Group: UCRT64 runtime running on Windows x86-64 

161 Windows_MSYS2_Clang32 = OS_Windows | ENV_MSYS2 | ARCH_x86_32 | Clang32 #: Group: Clang32 runtime running on Windows x86-64 

162 Windows_MSYS2_Clang64 = OS_Windows | ENV_MSYS2 | ARCH_x86_64 | Clang64 #: Group: Clang64 runtime running on Windows x86-64 

163 

164 Windows_Cygwin32 = OS_Windows | ENV_Cygwin | ARCH_x86_32 #: Group: 32-bit Cygwin runtime on Windows x86-64 

165 Windows_Cygwin64 = OS_Windows | ENV_Cygwin | ARCH_x86_64 #: Group: 64-bit Cygwin runtime on Windows x86-64 

166 

167 

168@export 

169class Platform(metaclass=ExtendedType, singleton=True, slots=True): 

170 """An instance of this class contains all gathered information available from various sources. 

171 

172 .. seealso:: 

173 

174 StackOverflow question: `Python: What OS am I running on? <https://stackoverflow.com/a/54837707/3719459>`__ 

175 """ 

176 

177 _platform: Platforms 

178 _pythonImplementation: PythonImplementation 

179 _pythonVersion: PythonVersion 

180 

181 def __init__(self) -> None: 

182 """ 

183 Initializes a platform by accessing multiple APIs of Python to gather all necessary information. 

184 """ 

185 import sys 

186 import os 

187 import platform 

188 import sysconfig 

189 

190 # Discover the Python implementation 

191 pythonImplementation = platform.python_implementation() 

192 if pythonImplementation == "CPython": 

193 self._pythonImplementation = PythonImplementation.CPython 

194 elif pythonImplementation == "PyPy": 

195 self._pythonImplementation = PythonImplementation.PyPy 

196 else: # pragma: no cover 

197 self._pythonImplementation = PythonImplementation.Unknown 

198 

199 # Discover the Python version 

200 self._pythonVersion = PythonVersion.FromSysVersionInfo() 

201 

202 # Discover the platform 

203 self._platform = Platforms.Unknown 

204 

205 machine = platform.machine() 

206 sys_platform = sys.platform 

207 sysconfig_platform = sysconfig.get_platform() 

208 

209 if "APPVEYOR" in os.environ: 209 ↛ 210line 209 didn't jump to line 210 because the condition on line 209 was never true

210 self._platform |= Platforms.CI_AppVeyor 

211 elif "GITHUB_ACTIONS" in os.environ: 211 ↛ 213line 211 didn't jump to line 213 because the condition on line 211 was always true

212 self._platform |= Platforms.CI_GitHubActions 

213 elif "GITLAB_CI" in os.environ: 

214 self._platform |= Platforms.CI_GitLabCI 

215 elif "TRAVIS" in os.environ: 

216 self._platform |= Platforms.CI_TravisCI 

217 else: 

218 self._platform |= Platforms.CI_None 

219 

220 if os.name == "nt": 

221 self._platform |= Platforms.OS_Windows 

222 

223 if sysconfig_platform == "win32": 223 ↛ 224line 223 didn't jump to line 224 because the condition on line 223 was never true

224 self._platform |= Platforms.ENV_Native | Platforms.ARCH_x86_32 | Platforms.SEP_WindowsPath | Platforms.SEP_WindowsValue 

225 elif sysconfig_platform == "win-amd64": 

226 self._platform |= Platforms.ENV_Native | Platforms.ARCH_x86_64 | Platforms.SEP_WindowsPath | Platforms.SEP_WindowsValue 

227 elif sysconfig_platform == "win-arm64": 

228 self._platform |= Platforms.ENV_Native | Platforms.ARCH_AArch64 | Platforms.SEP_WindowsPath | Platforms.SEP_WindowsValue 

229 elif sysconfig_platform.startswith("mingw"): 

230 if machine == "AMD64": 

231 self._platform |= Platforms.ARCH_x86_64 

232 else: # pragma: no cover 

233 raise UnknownPlatformException(f"Unknown architecture '{machine}' for Windows.") 

234 

235 if sysconfig_platform == "mingw_i686_msvcrt_gnu": 235 ↛ 236line 235 didn't jump to line 236 because the condition on line 235 was never true

236 self._platform |= Platforms.ENV_MSYS2 | Platforms.MinGW32 

237 elif sysconfig_platform == "mingw_x86_64_msvcrt_gnu": 

238 self._platform |= Platforms.ENV_MSYS2 | Platforms.MinGW64 

239 elif sysconfig_platform == "mingw_x86_64_ucrt_gnu": 

240 self._platform |= Platforms.ENV_MSYS2 | Platforms.UCRT64 

241 elif sysconfig_platform == "mingw_x86_64_ucrt_llvm": 

242 self._platform |= Platforms.ENV_MSYS2 | Platforms.Clang64 

243 elif sysconfig_platform == "mingw_i686": # pragma: no cover 

244 self._platform |= Platforms.ENV_MSYS2 | Platforms.MinGW32 

245 elif sysconfig_platform == "mingw_x86_64": # pragma: no cover 

246 self._platform |= Platforms.ENV_MSYS2 | Platforms.MinGW64 

247 elif sysconfig_platform == "mingw_x86_64_ucrt": # pragma: no cover 

248 self._platform |= Platforms.ENV_MSYS2 | Platforms.UCRT64 

249 elif sysconfig_platform == "mingw_x86_64_clang": # pragma: no cover 

250 self._platform |= Platforms.ENV_MSYS2 | Platforms.Clang64 

251 else: # pragma: no cover 

252 raise UnknownPlatformException(f"Unknown MSYS2 architecture '{sysconfig_platform}'.") 

253 else: # pragma: no cover 

254 raise UnknownPlatformException(f"Unknown platform '{sysconfig_platform}' running on Windows.") 

255 

256 elif os.name == "posix": 

257 if sys_platform == "linux": 

258 self._platform |= Platforms.OS_Linux | Platforms.ENV_Native 

259 

260 if sysconfig_platform == "linux-x86_64": # native Linux x86_64; Windows 64 + WSL 260 ↛ 262line 260 didn't jump to line 262 because the condition on line 260 was always true

261 self._platform |= Platforms.ARCH_x86_64 

262 elif sysconfig_platform == "linux-aarch64": # native Linux Aarch64 

263 self._platform |= Platforms.ARCH_AArch64 

264 else: # pragma: no cover 

265 raise UnknownPlatformException(f"Unknown architecture '{sysconfig_platform}' for a native Linux.") 

266 

267 elif sys_platform == "darwin": 267 ↛ 277line 267 didn't jump to line 277 because the condition on line 267 was always true

268 self._platform |= Platforms.OS_MacOS | Platforms.ENV_Native 

269 

270 if machine == "x86_64": 

271 self._platform |= Platforms.ARCH_x86_64 

272 elif machine == "arm64": 

273 self._platform |= Platforms.ARCH_AArch64 

274 else: # pragma: no cover 

275 raise UnknownPlatformException(f"Unknown architecture '{machine}' for a native macOS.") 

276 

277 elif sys_platform == "msys": 

278 self._platform |= Platforms.OS_Windows | Platforms.ENV_MSYS2 | Platforms.MSYS 

279 

280 if machine == "i686": 

281 self._platform |= Platforms.ARCH_x86_32 

282 elif machine == "x86_64": 

283 self._platform |= Platforms.ARCH_x86_64 

284 else: # pragma: no cover 

285 raise UnknownPlatformException(f"Unknown architecture '{machine}' for MSYS2-MSYS on Windows.") 

286 

287 elif sys_platform == "cygwin": 

288 self._platform |= Platforms.OS_Windows 

289 

290 if machine == "i686": 

291 self._platform |= Platforms.ARCH_x86_32 

292 elif machine == "x86_64": 

293 self._platform |= Platforms.ARCH_x86_64 

294 else: # pragma: no cover 

295 raise UnknownPlatformException(f"Unknown architecture '{machine}' for Cygwin on Windows.") 

296 

297 elif sys_platform.startswith("freebsd"): 

298 if machine == "amd64": 

299 self._platform = Platforms.FreeBSD 

300 else: # pragma: no cover 

301 raise UnknownPlatformException(f"Unknown architecture '{machine}' for FreeBSD.") 

302 else: # pragma: no cover 

303 raise UnknownPlatformException(f"Unknown POSIX platform '{sys_platform}'.") 

304 else: # pragma: no cover 

305 raise UnknownPlatformException(f"Unknown operating system '{os.name}'.") 

306 

307 @readonly 

308 def PythonImplementation(self) -> PythonImplementation: 

309 """ 

310 Read-only property to return the :class:`PythonImplementation` of the current interpreter. 

311 

312 :returns: Python implementation of the current interpreter. 

313 """ 

314 return self._pythonImplementation 

315 

316 @readonly 

317 def IsCPython(self) -> bool: 

318 """Returns true, if the Python implementation is a :term:`CPython`. 

319 

320 :returns: ``True``, if the Python implementation is CPython. 

321 """ 

322 return self._pythonImplementation is PythonImplementation.CPython 

323 

324 @readonly 

325 def IsPyPy(self) -> bool: 

326 """Returns true, if the Python implementation is a :term:`PyPy`. 

327 

328 :returns: ``True``, if the Python implementation is PyPY. 

329 """ 

330 return self._pythonImplementation is PythonImplementation.PyPy 

331 

332 @readonly 

333 def PythonVersion(self) -> PythonVersion: 

334 """ 

335 Read-only property to return the :class:`pyTooling.Versioning.PythonVersion` of the current interpreter. 

336 

337 :returns: Python version of the current interpreter. 

338 """ 

339 return self._pythonVersion 

340 

341 @readonly 

342 def HostOperatingSystem(self) -> Platforms: 

343 return self._platform & Platforms.OperatingSystem 

344 

345 @readonly 

346 def IsNativePlatform(self) -> bool: 

347 """Returns true, if the platform is a :term:`native` platform. 

348 

349 :returns: ``True``, if the platform is a native platform. 

350 """ 

351 return Platforms.ENV_Native in self._platform 

352 

353 @readonly 

354 def IsNativeFreeBSD(self) -> bool: 

355 """Returns true, if the platform is a :term:`native` FreeBSD x86-64 platform. 

356 

357 :returns: ``True``, if the platform is a native FreeBSD x86-64 platform. 

358 """ 

359 return Platforms.FreeBSD in self._platform 

360 

361 @readonly 

362 def IsNativeMacOS(self) -> bool: 

363 """Returns true, if the platform is a :term:`native` macOS x86-64 platform. 

364 

365 :returns: ``True``, if the platform is a native macOS x86-64 platform. 

366 """ 

367 return Platforms.MacOS in self._platform 

368 

369 @readonly 

370 def IsNativeLinux(self) -> bool: 

371 """Returns true, if the platform is a :term:`native` Linux x86-64 platform. 

372 

373 :returns: ``True``, if the platform is a native Linux x86-64 platform. 

374 """ 

375 return Platforms.Linux in self._platform 

376 

377 @readonly 

378 def IsNativeWindows(self) -> bool: 

379 """Returns true, if the platform is a :term:`native` Windows x86-64 platform. 

380 

381 :returns: ``True``, if the platform is a native Windows x86-64 platform. 

382 """ 

383 return Platforms.Windows in self._platform 

384 

385 @readonly 

386 def IsMSYS2Environment(self) -> bool: 

387 """Returns true, if the platform is a :term:`MSYS2` environment on Windows. 

388 

389 :returns: ``True``, if the platform is a MSYS2 environment on Windows. 

390 """ 

391 return Platforms.ENV_MSYS2 in self._platform 

392 

393 @readonly 

394 def IsMSYSOnWindows(self) -> bool: 

395 """Returns true, if the platform is a MSYS runtime on Windows. 

396 

397 :returns: ``True``, if the platform is a MSYS runtime on Windows. 

398 """ 

399 return Platforms.Windows_MSYS2_MSYS in self._platform 

400 

401 @readonly 

402 def IsMinGW32OnWindows(self) -> bool: 

403 """Returns true, if the platform is a :term:`MinGW32 <MinGW>` runtime on Windows. 

404 

405 :returns: ``True``, if the platform is a MINGW32 runtime on Windows. 

406 """ 

407 return Platforms.Windows_MSYS2_MinGW32 in self._platform 

408 

409 @readonly 

410 def IsMinGW64OnWindows(self) -> bool: 

411 """Returns true, if the platform is a :term:`MinGW64 <MinGW>` runtime on Windows. 

412 

413 :returns: ``True``, if the platform is a MINGW64 runtime on Windows. 

414 """ 

415 return Platforms.Windows_MSYS2_MinGW64 in self._platform 

416 

417 @readonly 

418 def IsUCRT64OnWindows(self) -> bool: 

419 """Returns true, if the platform is a :term:`UCRT64 <UCRT>` runtime on Windows. 

420 

421 :returns: ``True``, if the platform is a UCRT64 runtime on Windows. 

422 """ 

423 return Platforms.Windows_MSYS2_UCRT64 in self._platform 

424 

425 @readonly 

426 def IsClang32OnWindows(self) -> bool: 

427 """Returns true, if the platform is a Clang32 runtime on Windows. 

428 

429 :returns: ``True``, if the platform is a Clang32 runtime on Windows. 

430 """ 

431 return Platforms.Windows_MSYS2_Clang32 in self._platform 

432 

433 @readonly 

434 def IsClang64OnWindows(self) -> bool: 

435 """Returns true, if the platform is a Clang64 runtime on Windows. 

436 

437 :returns: ``True``, if the platform is a Clang64 runtime on Windows. 

438 """ 

439 return Platforms.Windows_MSYS2_Clang64 in self._platform 

440 

441 @readonly 

442 def IsCygwin32OnWindows(self) -> bool: 

443 """Returns true, if the platform is a 32-bit Cygwin runtime on Windows. 

444 

445 :returns: ``True``, if the platform is a 32-bit Cygwin runtime on Windows. 

446 """ 

447 return Platforms.Windows_Cygwin32 in self._platform 

448 

449 @readonly 

450 def IsCygwin64OnWindows(self) -> bool: 

451 """Returns true, if the platform is a 64-bit Cygwin runtime on Windows. 

452 

453 :returns: ``True``, if the platform is a 64-bit Cygwin runtime on Windows. 

454 """ 

455 return Platforms.Windows_Cygwin64 in self._platform 

456 

457 @readonly 

458 def IsPOSIX(self) -> bool: 

459 """ 

460 Returns true, if the platform is POSIX or POSIX-like. 

461 

462 :returns: ``True``, if POSIX or POSIX-like. 

463 """ 

464 return Platforms.SEP_WindowsPath not in self._platform 

465 

466 @readonly 

467 def IsCI(self) -> bool: 

468 """ 

469 Returns true, if the platform is a CI environment. 

470 

471 :returns: ``True``, if on CI runner. 

472 """ 

473 return Platforms.CI_None not in self._platform 

474 

475 @readonly 

476 def IsAppVeyor(self) -> bool: 

477 """ 

478 Returns true, if the platform is on AppVeyor. 

479 

480 :returns: ``True``, if on AppVeyor. 

481 """ 

482 return Platforms.CI_AppVeyor in self._platform 

483 

484 @readonly 

485 def IsGitHub(self) -> bool: 

486 """ 

487 Returns true, if the platform is on GitHub. 

488 

489 :returns: ``True``, if on GitHub. 

490 """ 

491 return Platforms.CI_GitHubActions in self._platform 

492 

493 @readonly 

494 def IsGitLab(self) -> bool: 

495 """ 

496 Returns true, if the platform is on GitLab CI. 

497 

498 :returns: ``True``, if on GitLab CI. 

499 """ 

500 return Platforms.CI_GitLabCI in self._platform 

501 

502 @readonly 

503 def IsTravisCI(self) -> bool: 

504 """ 

505 Returns true, if the platform is on Travis CI. 

506 

507 :returns: ``True``, if on Travis CI. 

508 """ 

509 return Platforms.CI_TravisCI in self._platform 

510 

511 @readonly 

512 def PathSeperator(self) -> str: 

513 """ 

514 Returns the path element separation character (e.g. for directories). 

515 

516 * POSIX-like: ``/`` 

517 * Windows: ``\\`` 

518 

519 :returns: Path separation character. 

520 """ 

521 if Platforms.SEP_WindowsPath in self._platform: 

522 return "\\" 

523 else: 

524 return "/" 

525 

526 @readonly 

527 def ValueSeperator(self) -> str: 

528 """ 

529 Returns the value separation character (e.g. for paths in PATH). 

530 

531 * POSIX-like: ``:`` 

532 * Windows: ``;`` 

533 

534 :returns: Value separation character. 

535 """ 

536 if Platforms.SEP_WindowsValue in self._platform: 

537 return ";" 

538 else: 

539 return ":" 

540 

541 @readonly 

542 def ExecutableExtension(self) -> str: 

543 """ 

544 Returns the file extension for an executable. 

545 

546 * FreeBSD: ``""`` (empty string) 

547 * Linux: ``""`` (empty string) 

548 * macOS: ``""`` (empty string) 

549 * Windows: ``"exe"`` 

550 

551 :returns: File extension of an executable. 

552 :raises UnknownOperatingSystemException: If the operating system is unknown. 

553 """ 

554 

555 if Platforms.OS_FreeBSD in self._platform: 555 ↛ 556line 555 didn't jump to line 556 because the condition on line 555 was never true

556 return "" 

557 elif Platforms.OS_Linux in self._platform: 

558 return "" 

559 elif Platforms.OS_MacOS in self._platform: 

560 return "" 

561 elif Platforms.OS_Windows in self._platform: 

562 return "exe" 

563 else: # pragma: no cover 

564 raise UnknownOperatingSystemException("Unknown operating system.") 

565 

566 @readonly 

567 def StaticLibraryExtension(self) -> str: 

568 """ 

569 Returns the file extension for a static library. 

570 

571 * FreeBSD: ``"a"`` 

572 * Linux: ``"a"`` 

573 * macOS: ``"lib"`` 

574 * Windows: ``"lib"`` 

575 

576 :returns: File extension of a static library. 

577 :raises UnknownOperatingSystemException: If the operating system is unknown. 

578 """ 

579 if Platforms.OS_FreeBSD in self._platform: 579 ↛ 580line 579 didn't jump to line 580 because the condition on line 579 was never true

580 return "a" 

581 elif Platforms.OS_Linux in self._platform: 

582 return "a" 

583 elif Platforms.OS_MacOS in self._platform: 

584 return "a" 

585 elif Platforms.OS_Windows in self._platform: 

586 return "lib" 

587 else: # pragma: no cover 

588 raise UnknownOperatingSystemException("Unknown operating system.") 

589 

590 @readonly 

591 def DynamicLibraryExtension(self) -> str: 

592 """ 

593 Returns the file extension for a dynamic/shared library. 

594 

595 * FreeBSD: ``"so"`` 

596 * Linux: ``"so"`` 

597 * macOS: ``"dylib"`` 

598 * Windows: ``"dll"`` 

599 

600 :returns: File extension of a dynamic library. 

601 :raises UnknownOperatingSystemException: If the operating system is unknown. 

602 """ 

603 if Platforms.OS_FreeBSD in self._platform: 603 ↛ 604line 603 didn't jump to line 604 because the condition on line 603 was never true

604 return "so" 

605 elif Platforms.OS_Linux in self._platform: 

606 return "so" 

607 elif Platforms.OS_MacOS in self._platform: 

608 return "dylib" 

609 elif Platforms.OS_Windows in self._platform: 

610 return "dll" 

611 else: # pragma: no cover 

612 raise UnknownOperatingSystemException("Unknown operating system.") 

613 

614 def __repr__(self) -> str: 

615 """ 

616 Returns the platform's string representation. 

617 

618 :returns: The string representation of the current platform. 

619 """ 

620 return str(self._platform) 

621 

622 def __str__(self) -> str: 

623 """ 

624 Returns the platform's string equivalent. 

625 

626 :returns: The string equivalent of the platform. 

627 """ 

628 runtime = "" 

629 

630 if Platforms.OS_FreeBSD in self._platform: 630 ↛ 631line 630 didn't jump to line 631 because the condition on line 630 was never true

631 platform = "FreeBSD" 

632 elif Platforms.OS_MacOS in self._platform: 

633 platform = "macOS" 

634 elif Platforms.OS_Linux in self._platform: 

635 platform = "Linux" 

636 elif Platforms.OS_Windows in self._platform: 636 ↛ 639line 636 didn't jump to line 639 because the condition on line 636 was always true

637 platform = "Windows" 

638 else: 

639 platform = "plat:dec-err" 

640 

641 if Platforms.ENV_Native in self._platform: 

642 environment = "" 

643 elif Platforms.ENV_WSL in self._platform: 643 ↛ 644line 643 didn't jump to line 644 because the condition on line 643 was never true

644 environment = "+WSL" 

645 elif Platforms.ENV_MSYS2 in self._platform: 645 ↛ 663line 645 didn't jump to line 663 because the condition on line 645 was always true

646 environment = "+MSYS2" 

647 

648 if Platforms.MSYS in self._platform: 648 ↛ 649line 648 didn't jump to line 649 because the condition on line 648 was never true

649 runtime = " - MSYS" 

650 elif Platforms.MinGW32 in self._platform: 650 ↛ 651line 650 didn't jump to line 651 because the condition on line 650 was never true

651 runtime = " - MinGW32" 

652 elif Platforms.MinGW64 in self._platform: 

653 runtime = " - MinGW64" 

654 elif Platforms.UCRT64 in self._platform: 

655 runtime = " - UCRT64" 

656 elif Platforms.Clang32 in self._platform: 656 ↛ 657line 656 didn't jump to line 657 because the condition on line 656 was never true

657 runtime = " - Clang32" 

658 elif Platforms.Clang64 in self._platform: 658 ↛ 661line 658 didn't jump to line 661 because the condition on line 658 was always true

659 runtime = " - Clang64" 

660 else: 

661 runtime = "rt:dec-err" 

662 

663 elif Platforms.ENV_Cygwin in self._platform: 

664 environment = "+Cygwin" 

665 else: 

666 environment = "env:dec-err" 

667 

668 if Platforms.ARCH_x86_32 in self._platform: 668 ↛ 669line 668 didn't jump to line 669 because the condition on line 668 was never true

669 architecture = "x86-32" 

670 elif Platforms.ARCH_x86_64 in self._platform: 

671 architecture = "x86-64" 

672 elif Platforms.ARCH_AArch64 in self._platform: 672 ↛ 675line 672 didn't jump to line 675 because the condition on line 672 was always true

673 architecture = "aarch64" 

674 else: 

675 architecture = "arch:dec-err" 

676 

677 return f"{platform}{environment} ({architecture}){runtime}" 

678 

679 

680CurrentPlatform = Platform() #: Gathered information for the current platform.