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

287 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-09-04 21:48 +0000

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

2# _____ _ _ ____ _ _ __ # 

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

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

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

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

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

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

9# Authors: # 

10# Patrick Lehmann # 

11# # 

12# License: # 

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

14# Copyright 2017-2025 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:: See :ref:`high-level help <COMMON/Platform>` for explanations and usage examples. 

35""" 

36from enum import Flag, auto, Enum 

37 

38try: 

39 from pyTooling.Decorators import export, readonly 

40 from pyTooling.Exceptions import ToolingException 

41 from pyTooling.MetaClasses import ExtendedType 

42 from pyTooling.Versioning import PythonVersion 

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

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

45 

46 try: 

47 from Decorators import export, readonly 

48 from Exceptions import ToolingException 

49 from MetaClasses import ExtendedType 

50 from Versioning import PythonVersion 

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

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

53 raise ex 

54 

55 

56__all__ = ["CurrentPlatform"] 

57 

58 

59@export 

60class PlatformException(ToolingException): 

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

62 

63 

64@export 

65class UnknownPlatformException(PlatformException): 

66 """ 

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

68 

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

70 debugging unknown or new platforms. 

71 """ 

72 

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

74 """ 

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

76 

77 :param args: Forward positional parameters. 

78 """ 

79 super().__init__(*args) 

80 

81 import sys 

82 import os 

83 import platform 

84 import sysconfig 

85 

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

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

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

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

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

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

92 

93 

94@export 

95class UnknownOperatingSystemException(PlatformException): 

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

97 

98 

99@export 

100class PythonImplementation(Enum): 

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

102 Unknown = 0 #: Unknown Python implementation 

103 

104 CPython = 1 #: CPython (reference implementation) 

105 PyPy = 2 #: PyPy 

106 

107 

108@export 

109class Platforms(Flag): 

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

111 Unknown = 0 

112 

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

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

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

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

117 

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

119 

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

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

122 

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

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

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

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

127 

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

129 

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

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

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

133 

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

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

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

137 

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

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

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

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

142 

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

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

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

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

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

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

149 

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

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

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

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

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

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

156 

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

158 

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

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

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

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

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

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

165 

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

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

168 

169 

170@export 

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

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

173 

174 .. seealso:: 

175 

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

177 """ 

178 

179 _platform: Platforms 

180 _pythonImplementation: PythonImplementation 

181 _pythonVersion: PythonVersion 

182 

183 def __init__(self) -> None: 

184 """ 

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

186 """ 

187 import sys 

188 import os 

189 import platform 

190 import sysconfig 

191 

192 # Discover the Python implementation 

193 pythonImplementation = platform.python_implementation() 

194 if pythonImplementation == "CPython": 

195 self._pythonImplementation = PythonImplementation.CPython 

196 elif pythonImplementation == "PyPy": 

197 self._pythonImplementation = PythonImplementation.PyPy 

198 else: # pragma: no cover 

199 self._pythonImplementation = PythonImplementation.Unknown 

200 

201 # Discover the Python version 

202 self._pythonVersion = PythonVersion.FromSysVersionInfo() 

203 

204 # Discover the platform 

205 self._platform = Platforms.Unknown 

206 

207 machine = platform.machine() 

208 sys_platform = sys.platform 

209 sysconfig_platform = sysconfig.get_platform() 

210 

211 if os.name == "nt": 

212 self._platform |= Platforms.OS_Windows 

213 

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

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

216 elif sysconfig_platform == "win-amd64": 

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

218 elif sysconfig_platform == "win-arm64": 218 ↛ 219line 218 didn't jump to line 219 because the condition on line 218 was never true

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

220 elif sysconfig_platform.startswith("mingw"): 

221 if machine == "AMD64": 

222 self._platform |= Platforms.ARCH_x86_64 

223 else: # pragma: no cover 

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

225 

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

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

228 elif sysconfig_platform == "mingw_x86_64_msvcrt_gnu": 

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

230 elif sysconfig_platform == "mingw_x86_64_ucrt_gnu": 

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

232 elif sysconfig_platform == "mingw_x86_64_ucrt_llvm": 

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

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

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

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

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

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

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

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

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

242 else: # pragma: no cover 

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

244 else: # pragma: no cover 

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

246 

247 elif os.name == "posix": 

248 if sys_platform == "linux": 

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

250 

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

252 self._platform |= Platforms.ARCH_x86_64 

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

254 self._platform |= Platforms.ARCH_AArch64 

255 else: # pragma: no cover 

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

257 

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

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

260 

261 if machine == "x86_64": 

262 self._platform |= Platforms.ARCH_x86_64 

263 elif machine == "arm64": 

264 self._platform |= Platforms.ARCH_AArch64 

265 else: # pragma: no cover 

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

267 

268 elif sys_platform == "msys": 

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

270 

271 if machine == "i686": 

272 self._platform |= Platforms.ARCH_x86_32 

273 elif machine == "x86_64": 

274 self._platform |= Platforms.ARCH_x86_64 

275 else: # pragma: no cover 

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

277 

278 elif sys_platform == "cygwin": 

279 self._platform |= Platforms.OS_Windows 

280 

281 if machine == "i686": 

282 self._platform |= Platforms.ARCH_x86_32 

283 elif machine == "x86_64": 

284 self._platform |= Platforms.ARCH_x86_64 

285 else: # pragma: no cover 

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

287 

288 elif sys_platform.startswith("freebsd"): 

289 if machine == "amd64": 

290 self._platform = Platforms.FreeBSD 

291 else: # pragma: no cover 

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

293 else: # pragma: no cover 

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

295 else: # pragma: no cover 

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

297 

298 @readonly 

299 def PythonImplementation(self) -> PythonImplementation: 

300 """ 

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

302 

303 :returns: Python implementation of the current interpreter. 

304 """ 

305 return self._pythonImplementation 

306 

307 @readonly 

308 def IsCPython(self) -> bool: 

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

310 

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

312 """ 

313 return self._pythonImplementation is PythonImplementation.CPython 

314 

315 @readonly 

316 def IsPyPy(self) -> bool: 

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

318 

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

320 """ 

321 return self._pythonImplementation is PythonImplementation.PyPy 

322 

323 @readonly 

324 def PythonVersion(self) -> PythonVersion: 

325 """ 

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

327 

328 :returns: Python version of the current interpreter. 

329 """ 

330 return self._pythonVersion 

331 

332 @readonly 

333 def HostOperatingSystem(self) -> Platforms: 

334 return self._platform & Platforms.OperatingSystem 

335 

336 @readonly 

337 def IsNativePlatform(self) -> bool: 

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

339 

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

341 """ 

342 return Platforms.ENV_Native in self._platform 

343 

344 @readonly 

345 def IsNativeFreeBSD(self) -> bool: 

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

347 

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

349 """ 

350 return Platforms.FreeBSD in self._platform 

351 

352 @readonly 

353 def IsNativeMacOS(self) -> bool: 

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

355 

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

357 """ 

358 return Platforms.MacOS in self._platform 

359 

360 @readonly 

361 def IsNativeLinux(self) -> bool: 

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

363 

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

365 """ 

366 return Platforms.Linux in self._platform 

367 

368 @readonly 

369 def IsNativeWindows(self) -> bool: 

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

371 

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

373 """ 

374 return Platforms.Windows in self._platform 

375 

376 @readonly 

377 def IsMSYS2Environment(self) -> bool: 

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

379 

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

381 """ 

382 return Platforms.ENV_MSYS2 in self._platform 

383 

384 @readonly 

385 def IsMSYSOnWindows(self) -> bool: 

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

387 

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

389 """ 

390 return Platforms.Windows_MSYS2_MSYS in self._platform 

391 

392 @readonly 

393 def IsMinGW32OnWindows(self) -> bool: 

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

395 

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

397 """ 

398 return Platforms.Windows_MSYS2_MinGW32 in self._platform 

399 

400 @readonly 

401 def IsMinGW64OnWindows(self) -> bool: 

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

403 

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

405 """ 

406 return Platforms.Windows_MSYS2_MinGW64 in self._platform 

407 

408 @readonly 

409 def IsUCRT64OnWindows(self) -> bool: 

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

411 

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

413 """ 

414 return Platforms.Windows_MSYS2_UCRT64 in self._platform 

415 

416 @readonly 

417 def IsClang32OnWindows(self) -> bool: 

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

419 

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

421 """ 

422 return Platforms.Windows_MSYS2_Clang32 in self._platform 

423 

424 @readonly 

425 def IsClang64OnWindows(self) -> bool: 

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

427 

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

429 """ 

430 return Platforms.Windows_MSYS2_Clang64 in self._platform 

431 

432 @readonly 

433 def IsCygwin32OnWindows(self) -> bool: 

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

435 

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

437 """ 

438 return Platforms.Windows_Cygwin32 in self._platform 

439 

440 @readonly 

441 def IsCygwin64OnWindows(self) -> bool: 

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

443 

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

445 """ 

446 return Platforms.Windows_Cygwin64 in self._platform 

447 

448 @readonly 

449 def IsPOSIX(self) -> bool: 

450 """ 

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

452 

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

454 """ 

455 return Platforms.SEP_WindowsPath not in self._platform 

456 

457 @readonly 

458 def PathSeperator(self) -> str: 

459 """ 

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

461 

462 * POSIX-like: ``/`` 

463 * Windows: ``\\`` 

464 

465 :returns: Path separation character. 

466 """ 

467 if Platforms.SEP_WindowsPath in self._platform: 

468 return "\\" 

469 else: 

470 return "/" 

471 

472 @readonly 

473 def ValueSeperator(self) -> str: 

474 """ 

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

476 

477 * POSIX-like: ``:`` 

478 * Windows: ``;`` 

479 

480 :returns: Value separation character. 

481 """ 

482 if Platforms.SEP_WindowsValue in self._platform: 

483 return ";" 

484 else: 

485 return ":" 

486 

487 @readonly 

488 def ExecutableExtension(self) -> str: 

489 """ 

490 Returns the file extension for an executable. 

491 

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

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

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

495 * Windows: ``"exe"`` 

496 

497 :returns: File extension of an executable. 

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

499 """ 

500 

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

502 return "" 

503 elif Platforms.OS_Linux in self._platform: 

504 return "" 

505 elif Platforms.OS_MacOS in self._platform: 

506 return "" 

507 elif Platforms.OS_Windows in self._platform: 

508 return "exe" 

509 else: # pragma: no cover 

510 raise UnknownOperatingSystemException("Unknown operating system.") 

511 

512 @readonly 

513 def StaticLibraryExtension(self) -> str: 

514 """ 

515 Returns the file extension for a static library. 

516 

517 * FreeBSD: ``"a"`` 

518 * Linux: ``"a"`` 

519 * macOS: ``"lib"`` 

520 * Windows: ``"lib"`` 

521 

522 :returns: File extension of a static library. 

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

524 """ 

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

526 return "a" 

527 elif Platforms.OS_Linux in self._platform: 

528 return "a" 

529 elif Platforms.OS_MacOS in self._platform: 

530 return "a" 

531 elif Platforms.OS_Windows in self._platform: 

532 return "lib" 

533 else: # pragma: no cover 

534 raise UnknownOperatingSystemException("Unknown operating system.") 

535 

536 @readonly 

537 def DynamicLibraryExtension(self) -> str: 

538 """ 

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

540 

541 * FreeBSD: ``"so"`` 

542 * Linux: ``"so"`` 

543 * macOS: ``"dylib"`` 

544 * Windows: ``"dll"`` 

545 

546 :returns: File extension of a dynamic library. 

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

548 """ 

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

550 return "so" 

551 elif Platforms.OS_Linux in self._platform: 

552 return "so" 

553 elif Platforms.OS_MacOS in self._platform: 

554 return "dylib" 

555 elif Platforms.OS_Windows in self._platform: 

556 return "dll" 

557 else: # pragma: no cover 

558 raise UnknownOperatingSystemException("Unknown operating system.") 

559 

560 def __repr__(self) -> str: 

561 """ 

562 Returns the platform's string representation. 

563 

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

565 """ 

566 return str(self._platform) 

567 

568 def __str__(self) -> str: 

569 """ 

570 Returns the platform's string equivalent. 

571 

572 :returns: The string equivalent of the platform. 

573 """ 

574 runtime = "" 

575 

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

577 platform = "FreeBSD" 

578 elif Platforms.OS_MacOS in self._platform: 

579 platform = "macOS" 

580 elif Platforms.OS_Linux in self._platform: 

581 platform = "Linux" 

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

583 platform = "Windows" 

584 else: 

585 platform = "plat:dec-err" 

586 

587 if Platforms.ENV_Native in self._platform: 

588 environment = "" 

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

590 environment = "+WSL" 

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

592 environment = "+MSYS2" 

593 

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

595 runtime = " - MSYS" 

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

597 runtime = " - MinGW32" 

598 elif Platforms.MinGW64 in self._platform: 

599 runtime = " - MinGW64" 

600 elif Platforms.UCRT64 in self._platform: 

601 runtime = " - UCRT64" 

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

603 runtime = " - Clang32" 

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

605 runtime = " - Clang64" 

606 else: 

607 runtime = "rt:dec-err" 

608 

609 elif Platforms.ENV_Cygwin in self._platform: 

610 environment = "+Cygwin" 

611 else: 

612 environment = "env:dec-err" 

613 

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

615 architecture = "x86-32" 

616 elif Platforms.ARCH_x86_64 in self._platform: 

617 architecture = "x86-64" 

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

619 architecture = "aarch64" 

620 else: 

621 architecture = "arch:dec-err" 

622 

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

624 

625 

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