Source code for pytc.log
"""Logging utilities for pytc.
This module provides centralized logging functionality including:
- Git commit information for reproducibility
- Dependency version tracking
- Device detection and information
"""
import logging
import subprocess
from importlib.metadata import PackageNotFoundError
from pathlib import Path
from typing import Dict, Optional
logger = logging.getLogger(__name__)
[docs]
def get_git_commit(repo_path: Optional[Path] = None) -> str:
"""Get the current git commit hash.
Args:
repo_path: Path to the git repository. Defaults to the pytc package directory.
Returns:
The git commit hash (short form), or 'unknown' if not available.
"""
if repo_path is None:
repo_path = Path(__file__).parent.parent
try:
result = subprocess.run(
['git', 'rev-parse', 'HEAD'],
cwd=repo_path,
capture_output=True,
text=True,
check=True
)
commit_hash = result.stdout.strip()
# Return short form (first 7 characters)
return commit_hash[:7]
except (subprocess.CalledProcessError, FileNotFoundError):
return 'unknown'
[docs]
def get_pytc_version() -> str:
"""Get the pytc version from pyproject.toml.
Returns:
The pytc version string, or 'unknown' if not available.
"""
try:
from importlib.metadata import version
return version('pytc-qc')
except PackageNotFoundError:
pass
# Fallback: try to read from pyproject.toml
pyproject_path = Path(__file__).parent.parent / 'pyproject.toml'
if pyproject_path.exists():
import tomllib
with open(pyproject_path, 'rb') as f:
data = tomllib.load(f)
return data.get('project', {}).get('version', 'unknown')
return 'unknown'
[docs]
def get_dependency_versions() -> Dict[str, str]:
"""Get versions of key dependencies.
Returns:
Dictionary mapping package names to their versions.
"""
deps = {}
packages = [
'jax',
'numpy',
'optax',
'flax',
'pyscf',
'folx',
]
for pkg in packages:
try:
mod = __import__(pkg)
version = getattr(mod, '__version__', 'unknown')
deps[pkg] = version
except ImportError:
deps[pkg] = 'not installed'
return deps
[docs]
def get_device_info() -> Dict[str, any]:
"""Get information about available compute devices (GPUs/CPUs).
Returns:
Dictionary with device information including type, count, and memory.
"""
info = {
'device_type': 'unknown',
'device_count': 0,
'devices': [],
}
try:
import jax
devices = jax.devices()
info['device_count'] = len(devices)
if devices:
# Get device kind from first device
device_kind = devices[0].device_kind
info['device_type'] = device_kind.lower()
# Get details for each device
for dev in devices:
dev_info = {
'id': dev.id,
'kind': dev.device_kind,
}
# Try to get memory info
try:
stats = dev.memory_stats()
if stats:
total_bytes = stats.get('bytes_in_use', 0) + stats.get('bytes_available', 0)
dev_info['total_memory_gb'] = total_bytes / (1024**3)
except Exception:
pass
info['devices'].append(dev_info)
except ImportError:
info['device_type'] = 'jax not available'
except Exception as e:
info['device_type'] = f'error: {e}'
return info
[docs]
def log_startup_info():
"""Log startup information for reproducibility.
This logs:
- pytc version
- git commit hash
- dependency versions
- device information
"""
# Get info
pytc_version = get_pytc_version()
git_commit = get_git_commit()
deps = get_dependency_versions()
device_info = get_device_info()
# Log pytc info
logger.info("=" * 60)
logger.info("pytc startup information")
logger.info("=" * 60)
logger.info(f"pytc version: {pytc_version}")
logger.info(f"git commit: {git_commit}")
# Log dependency versions
logger.info("Dependency versions:")
for pkg, version in deps.items():
logger.info(f" {pkg}: {version}")
# Log device information
logger.info("Device information:")
logger.info(f" Device type: {device_info['device_type']}")
logger.info(f" Device count: {device_info['device_count']}")
for dev in device_info['devices']:
mem_str = ""
if 'total_memory_gb' in dev:
mem_str = f", {dev['total_memory_gb']:.1f} GB"
logger.info(f" Device {dev['id']}: {dev['kind']}{mem_str}")
logger.info("=" * 60)