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

287 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-08 23:46 +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 

40try: 

41 from pyTooling.Decorators import export, readonly 

42 from pyTooling.Exceptions import ToolingException 

43 from pyTooling.MetaClasses import ExtendedType 

44 from pyTooling.Versioning import PythonVersion 

45except (ImportError, ModuleNotFoundError): # pragma: no cover 

46 print("[pyTooling.Platform] Could not import from 'pyTooling.*'!") 

47 

48 try: 

49 from Decorators import export, readonly 

50 from Exceptions import ToolingException 

51 from MetaClasses import ExtendedType 

52 from Versioning import PythonVersion 

53 except (ImportError, ModuleNotFoundError) as ex: # pragma: no cover 

54 print("[pyTooling.Platform] Could not import directly!") 

55 raise ex 

56 

57 

58__all__ = ["CurrentPlatform"] 

59 

60 

61@export 

62class PlatformException(ToolingException): 

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

64 

65 

66@export 

67class UnknownPlatformException(PlatformException): 

68 """ 

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

70 

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

72 debugging unknown or new platforms. 

73 """ 

74 

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

76 """ 

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

78 

79 :param args: Forward positional parameters. 

80 """ 

81 super().__init__(*args) 

82 

83 import sys 

84 import os 

85 import platform 

86 import sysconfig 

87 

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

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

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

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

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

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

94 

95 

96@export 

97class UnknownOperatingSystemException(PlatformException): 

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

99 

100 

101@export 

102class PythonImplementation(Enum): 

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

104 Unknown = 0 #: Unknown Python implementation 

105 

106 CPython = 1 #: CPython (reference implementation) 

107 PyPy = 2 #: PyPy 

108 

109 

110@export 

111class Platforms(Flag): 

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

113 Unknown = 0 

114 

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

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

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

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

119 

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

121 

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

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

124 

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

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

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

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

129 

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

131 

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

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

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

135 

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

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

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

139 

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

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

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

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

144 

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

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

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

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

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

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

151 

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

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

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

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

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

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

158 

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

160 

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

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

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

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

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

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

167 

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

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

170 

171 

172@export 

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

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

175 

176 .. seealso:: 

177 

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

179 """ 

180 

181 _platform: Platforms 

182 _pythonImplementation: PythonImplementation 

183 _pythonVersion: PythonVersion 

184 

185 def __init__(self) -> None: 

186 """ 

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

188 """ 

189 import sys 

190 import os 

191 import platform 

192 import sysconfig 

193 

194 # Discover the Python implementation 

195 pythonImplementation = platform.python_implementation() 

196 if pythonImplementation == "CPython": 

197 self._pythonImplementation = PythonImplementation.CPython 

198 elif pythonImplementation == "PyPy": 

199 self._pythonImplementation = PythonImplementation.PyPy 

200 else: # pragma: no cover 

201 self._pythonImplementation = PythonImplementation.Unknown 

202 

203 # Discover the Python version 

204 self._pythonVersion = PythonVersion.FromSysVersionInfo() 

205 

206 # Discover the platform 

207 self._platform = Platforms.Unknown 

208 

209 machine = platform.machine() 

210 sys_platform = sys.platform 

211 sysconfig_platform = sysconfig.get_platform() 

212 

213 if os.name == "nt": 

214 self._platform |= Platforms.OS_Windows 

215 

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

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

218 elif sysconfig_platform == "win-amd64": 

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

220 elif sysconfig_platform == "win-arm64": 

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

222 elif sysconfig_platform.startswith("mingw"): 

223 if machine == "AMD64": 

224 self._platform |= Platforms.ARCH_x86_64 

225 else: # pragma: no cover 

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

227 

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

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

230 elif sysconfig_platform == "mingw_x86_64_msvcrt_gnu": 

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

232 elif sysconfig_platform == "mingw_x86_64_ucrt_gnu": 

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

234 elif sysconfig_platform == "mingw_x86_64_ucrt_llvm": 

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

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

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

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

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

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

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

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

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

244 else: # pragma: no cover 

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

246 else: # pragma: no cover 

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

248 

249 elif os.name == "posix": 

250 if sys_platform == "linux": 

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

252 

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

254 self._platform |= Platforms.ARCH_x86_64 

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

256 self._platform |= Platforms.ARCH_AArch64 

257 else: # pragma: no cover 

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

259 

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

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

262 

263 if machine == "x86_64": 

264 self._platform |= Platforms.ARCH_x86_64 

265 elif machine == "arm64": 

266 self._platform |= Platforms.ARCH_AArch64 

267 else: # pragma: no cover 

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

269 

270 elif sys_platform == "msys": 

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

272 

273 if machine == "i686": 

274 self._platform |= Platforms.ARCH_x86_32 

275 elif machine == "x86_64": 

276 self._platform |= Platforms.ARCH_x86_64 

277 else: # pragma: no cover 

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

279 

280 elif sys_platform == "cygwin": 

281 self._platform |= Platforms.OS_Windows 

282 

283 if machine == "i686": 

284 self._platform |= Platforms.ARCH_x86_32 

285 elif machine == "x86_64": 

286 self._platform |= Platforms.ARCH_x86_64 

287 else: # pragma: no cover 

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

289 

290 elif sys_platform.startswith("freebsd"): 

291 if machine == "amd64": 

292 self._platform = Platforms.FreeBSD 

293 else: # pragma: no cover 

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

295 else: # pragma: no cover 

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

297 else: # pragma: no cover 

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

299 

300 @readonly 

301 def PythonImplementation(self) -> PythonImplementation: 

302 """ 

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

304 

305 :returns: Python implementation of the current interpreter. 

306 """ 

307 return self._pythonImplementation 

308 

309 @readonly 

310 def IsCPython(self) -> bool: 

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

312 

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

314 """ 

315 return self._pythonImplementation is PythonImplementation.CPython 

316 

317 @readonly 

318 def IsPyPy(self) -> bool: 

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

320 

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

322 """ 

323 return self._pythonImplementation is PythonImplementation.PyPy 

324 

325 @readonly 

326 def PythonVersion(self) -> PythonVersion: 

327 """ 

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

329 

330 :returns: Python version of the current interpreter. 

331 """ 

332 return self._pythonVersion 

333 

334 @readonly 

335 def HostOperatingSystem(self) -> Platforms: 

336 return self._platform & Platforms.OperatingSystem 

337 

338 @readonly 

339 def IsNativePlatform(self) -> bool: 

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

341 

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

343 """ 

344 return Platforms.ENV_Native in self._platform 

345 

346 @readonly 

347 def IsNativeFreeBSD(self) -> bool: 

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

349 

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

351 """ 

352 return Platforms.FreeBSD in self._platform 

353 

354 @readonly 

355 def IsNativeMacOS(self) -> bool: 

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

357 

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

359 """ 

360 return Platforms.MacOS in self._platform 

361 

362 @readonly 

363 def IsNativeLinux(self) -> bool: 

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

365 

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

367 """ 

368 return Platforms.Linux in self._platform 

369 

370 @readonly 

371 def IsNativeWindows(self) -> bool: 

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

373 

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

375 """ 

376 return Platforms.Windows in self._platform 

377 

378 @readonly 

379 def IsMSYS2Environment(self) -> bool: 

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

381 

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

383 """ 

384 return Platforms.ENV_MSYS2 in self._platform 

385 

386 @readonly 

387 def IsMSYSOnWindows(self) -> bool: 

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

389 

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

391 """ 

392 return Platforms.Windows_MSYS2_MSYS in self._platform 

393 

394 @readonly 

395 def IsMinGW32OnWindows(self) -> bool: 

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

397 

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

399 """ 

400 return Platforms.Windows_MSYS2_MinGW32 in self._platform 

401 

402 @readonly 

403 def IsMinGW64OnWindows(self) -> bool: 

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

405 

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

407 """ 

408 return Platforms.Windows_MSYS2_MinGW64 in self._platform 

409 

410 @readonly 

411 def IsUCRT64OnWindows(self) -> bool: 

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

413 

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

415 """ 

416 return Platforms.Windows_MSYS2_UCRT64 in self._platform 

417 

418 @readonly 

419 def IsClang32OnWindows(self) -> bool: 

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

421 

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

423 """ 

424 return Platforms.Windows_MSYS2_Clang32 in self._platform 

425 

426 @readonly 

427 def IsClang64OnWindows(self) -> bool: 

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

429 

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

431 """ 

432 return Platforms.Windows_MSYS2_Clang64 in self._platform 

433 

434 @readonly 

435 def IsCygwin32OnWindows(self) -> bool: 

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

437 

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

439 """ 

440 return Platforms.Windows_Cygwin32 in self._platform 

441 

442 @readonly 

443 def IsCygwin64OnWindows(self) -> bool: 

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

445 

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

447 """ 

448 return Platforms.Windows_Cygwin64 in self._platform 

449 

450 @readonly 

451 def IsPOSIX(self) -> bool: 

452 """ 

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

454 

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

456 """ 

457 return Platforms.SEP_WindowsPath not in self._platform 

458 

459 @readonly 

460 def PathSeperator(self) -> str: 

461 """ 

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

463 

464 * POSIX-like: ``/`` 

465 * Windows: ``\\`` 

466 

467 :returns: Path separation character. 

468 """ 

469 if Platforms.SEP_WindowsPath in self._platform: 

470 return "\\" 

471 else: 

472 return "/" 

473 

474 @readonly 

475 def ValueSeperator(self) -> str: 

476 """ 

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

478 

479 * POSIX-like: ``:`` 

480 * Windows: ``;`` 

481 

482 :returns: Value separation character. 

483 """ 

484 if Platforms.SEP_WindowsValue in self._platform: 

485 return ";" 

486 else: 

487 return ":" 

488 

489 @readonly 

490 def ExecutableExtension(self) -> str: 

491 """ 

492 Returns the file extension for an executable. 

493 

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

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

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

497 * Windows: ``"exe"`` 

498 

499 :returns: File extension of an executable. 

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

501 """ 

502 

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

504 return "" 

505 elif Platforms.OS_Linux in self._platform: 

506 return "" 

507 elif Platforms.OS_MacOS in self._platform: 

508 return "" 

509 elif Platforms.OS_Windows in self._platform: 

510 return "exe" 

511 else: # pragma: no cover 

512 raise UnknownOperatingSystemException("Unknown operating system.") 

513 

514 @readonly 

515 def StaticLibraryExtension(self) -> str: 

516 """ 

517 Returns the file extension for a static library. 

518 

519 * FreeBSD: ``"a"`` 

520 * Linux: ``"a"`` 

521 * macOS: ``"lib"`` 

522 * Windows: ``"lib"`` 

523 

524 :returns: File extension of a static library. 

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

526 """ 

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

528 return "a" 

529 elif Platforms.OS_Linux in self._platform: 

530 return "a" 

531 elif Platforms.OS_MacOS in self._platform: 

532 return "a" 

533 elif Platforms.OS_Windows in self._platform: 

534 return "lib" 

535 else: # pragma: no cover 

536 raise UnknownOperatingSystemException("Unknown operating system.") 

537 

538 @readonly 

539 def DynamicLibraryExtension(self) -> str: 

540 """ 

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

542 

543 * FreeBSD: ``"so"`` 

544 * Linux: ``"so"`` 

545 * macOS: ``"dylib"`` 

546 * Windows: ``"dll"`` 

547 

548 :returns: File extension of a dynamic library. 

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

550 """ 

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

552 return "so" 

553 elif Platforms.OS_Linux in self._platform: 

554 return "so" 

555 elif Platforms.OS_MacOS in self._platform: 

556 return "dylib" 

557 elif Platforms.OS_Windows in self._platform: 

558 return "dll" 

559 else: # pragma: no cover 

560 raise UnknownOperatingSystemException("Unknown operating system.") 

561 

562 def __repr__(self) -> str: 

563 """ 

564 Returns the platform's string representation. 

565 

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

567 """ 

568 return str(self._platform) 

569 

570 def __str__(self) -> str: 

571 """ 

572 Returns the platform's string equivalent. 

573 

574 :returns: The string equivalent of the platform. 

575 """ 

576 runtime = "" 

577 

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

579 platform = "FreeBSD" 

580 elif Platforms.OS_MacOS in self._platform: 

581 platform = "macOS" 

582 elif Platforms.OS_Linux in self._platform: 

583 platform = "Linux" 

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

585 platform = "Windows" 

586 else: 

587 platform = "plat:dec-err" 

588 

589 if Platforms.ENV_Native in self._platform: 

590 environment = "" 

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

592 environment = "+WSL" 

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

594 environment = "+MSYS2" 

595 

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

597 runtime = " - MSYS" 

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

599 runtime = " - MinGW32" 

600 elif Platforms.MinGW64 in self._platform: 

601 runtime = " - MinGW64" 

602 elif Platforms.UCRT64 in self._platform: 

603 runtime = " - UCRT64" 

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

605 runtime = " - Clang32" 

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

607 runtime = " - Clang64" 

608 else: 

609 runtime = "rt:dec-err" 

610 

611 elif Platforms.ENV_Cygwin in self._platform: 

612 environment = "+Cygwin" 

613 else: 

614 environment = "env:dec-err" 

615 

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

617 architecture = "x86-32" 

618 elif Platforms.ARCH_x86_64 in self._platform: 

619 architecture = "x86-64" 

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

621 architecture = "aarch64" 

622 else: 

623 architecture = "arch:dec-err" 

624 

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

626 

627 

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