Coverage for src/devboard/debug.py: 90.12%

61 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-03-19 20:21 +0100

1"""Debugging utilities.""" 

2 

3from __future__ import annotations 

4 

5import os 

6import platform 

7import sys 

8from dataclasses import dataclass 

9from importlib import metadata 

10 

11 

12@dataclass 

13class Variable: 

14 """Dataclass describing an environment variable.""" 

15 

16 name: str 

17 """Variable name.""" 

18 value: str 

19 """Variable value.""" 

20 

21 

22@dataclass 

23class Package: 

24 """Dataclass describing a Python package.""" 

25 

26 name: str 

27 """Package name.""" 

28 version: str 

29 """Package version.""" 

30 

31 

32@dataclass 

33class Environment: 

34 """Dataclass to store environment information.""" 

35 

36 interpreter_name: str 

37 """Python interpreter name.""" 

38 interpreter_version: str 

39 """Python interpreter version.""" 

40 platform: str 

41 """Operating System.""" 

42 packages: list[Package] 

43 """Installed packages.""" 

44 variables: list[Variable] 

45 """Environment variables.""" 

46 

47 

48def _interpreter_name_version() -> tuple[str, str]: 

49 if hasattr(sys, "implementation"): 49 ↛ 56line 49 didn't jump to line 56, because the condition on line 49 was never false

50 impl = sys.implementation.version 

51 version = f"{impl.major}.{impl.minor}.{impl.micro}" 

52 kind = impl.releaselevel 

53 if kind != "final": 53 ↛ 54line 53 didn't jump to line 54, because the condition on line 53 was never true

54 version += kind[0] + str(impl.serial) 

55 return sys.implementation.name, version 

56 return "", "0.0.0" 

57 

58 

59def get_version(dist: str = "devboard") -> str: 

60 """Get version of the given distribution. 

61 

62 Parameters: 

63 dist: A distribution name. 

64 

65 Returns: 

66 A version number. 

67 """ 

68 try: 

69 return metadata.version(dist) 

70 except metadata.PackageNotFoundError: 

71 return "0.0.0" 

72 

73 

74def get_debug_info() -> Environment: 

75 """Get debug/environment information. 

76 

77 Returns: 

78 Environment information. 

79 """ 

80 py_name, py_version = _interpreter_name_version() 

81 packages = ["devboard"] 

82 variables = ["PYTHONPATH", *[var for var in os.environ if var.startswith("DEVBOARD")]] 

83 return Environment( 

84 interpreter_name=py_name, 

85 interpreter_version=py_version, 

86 platform=platform.platform(), 

87 variables=[Variable(var, val) for var in variables if (val := os.getenv(var))], 

88 packages=[Package(pkg, get_version(pkg)) for pkg in packages], 

89 ) 

90 

91 

92def print_debug_info() -> None: 

93 """Print debug/environment information.""" 

94 info = get_debug_info() 

95 print(f"- __System__: {info.platform}") 

96 print(f"- __Python__: {info.interpreter_name} {info.interpreter_version}") 

97 print("- __Environment variables__:") 

98 for var in info.variables: 

99 print(f" - `{var.name}`: `{var.value}`") 

100 print("- __Installed packages__:") 

101 for pkg in info.packages: 

102 print(f" - `{pkg.name}` v{pkg.version}") 

103 

104 

105if __name__ == "__main__": 105 ↛ 106line 105 didn't jump to line 106, because the condition on line 105 was never true

106 print_debug_info()