/ src / docstrings2pep727 / debug.py
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()