SPB Git

spb/wp34_uqo

Public
2.4 KB · 72 lines python
1"""Provenance block attached to every saved experimental result."""2from __future__ import annotations3import datetime as _dt, json, os, platform, subprocess, sys4from pathlib import Path567def _sysctl(key: str) -> str:8    try:9        return subprocess.run(["sysctl", "-n", key], capture_output=True, text=True, timeout=5).stdout.strip()10    except Exception:  # pragma: no cover11        return ""121314def host_info() -> dict:15    info = {16        "hostname": platform.node(),17        "os": f"{platform.system()} {platform.release()} ({platform.mac_ver()[0] or platform.version()})",18        "machine": platform.machine(),19        "python": sys.version.split()[0],20    }21    if platform.system() == "Darwin":22        info["cpu"] = _sysctl("machdep.cpu.brand_string")23        info["cores"] = int(_sysctl("hw.ncpu") or 0)24        mem = _sysctl("hw.memsize")25        info["ram_gb"] = round(int(mem) / 2**30, 1) if mem else None26    else:  # pragma: no cover27        info["cpu"] = platform.processor()28        info["cores"] = os.cpu_count()29    return info303132def software_versions(mods=("numpy", "scipy", "sympy", "gmpy2", "z3", "pysat", "ecdsa", "coincurve")) -> dict:33    out = {}34    for m in mods:35        try:36            mod = __import__(m)37            v = getattr(mod, "__version__", None)38            if m == "z3":39                v = mod.get_version_string()40            if m == "gmpy2":41                v = mod.version()42            out[m] = v43        except Exception:44            out[m] = None45    return out464748def record(experiment: str, params: dict, measurements, *, seed=None, extra: dict | None = None,49           out: str | os.PathLike | None = None, started: float | None = None) -> dict:50    """Build (and optionally write) a result document with full provenance."""51    doc = {52        "experiment": experiment,53        "timestamp_utc": _dt.datetime.now(_dt.timezone.utc).isoformat(timespec="seconds"),54        "command": " ".join(sys.argv),55        "cwd": os.getcwd(),56        "seed": seed,57        "host": host_info(),58        "software": software_versions(),59        "params": params,60        "measurements": measurements,61    }62    if started is not None:63        import time64        doc["elapsed_s"] = round(time.time() - started, 3)65    if extra:66        doc.update(extra)67    if out:68        p = Path(out)69        p.parent.mkdir(parents=True, exist_ok=True)70        p.write_text(json.dumps(doc, indent=1, default=str))71    return doc72
Files · main
Menu

Theme