debug.py
1 """Debugging utilities.""" 2 3 from __future__ import annotations 4 5 import os 6 import platform 7 import sys 8 from dataclasses import dataclass 9 from importlib import metadata 10 11 12 @dataclass 13 class Variable: 14 """Dataclass describing an environment variable.""" 15 16 name: str 17 """Variable name.""" 18 value: str 19 """Variable value.""" 20 21 22 @dataclass 23 class Package: 24 """Dataclass describing a Python package.""" 25 26 name: str 27 """Package name.""" 28 version: str 29 """Package version.""" 30 31 32 @dataclass 33 class 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 48 def _interpreter_name_version() -> tuple[str, str]: 49 if hasattr(sys, "implementation"): 50 impl = sys.implementation.version 51 version = f"{impl.major}.{impl.minor}.{impl.micro}" 52 kind = impl.releaselevel 53 if kind != "final": 54 version += kind[0] + str(impl.serial) 55 return sys.implementation.name, version 56 return "", "0.0.0" 57 58 59 def get_version(dist: str = "docstrings2pep727") -> 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 74 def 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 = ["docstrings2pep727"] 82 variables = ["PYTHONPATH", *[var for var in os.environ if var.startswith("DOCSTRINGS2PEP727")]] 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 92 def 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 105 if __name__ == "__main__": 106 print_debug_info()