From de5505c7d880f4ec4d7781285352a782ae359460 Mon Sep 17 00:00:00 2001 From: Salil Mhatre <32305505+Deadpool2000@users.noreply.github.com> Date: Sun, 5 Apr 2026 17:58:05 +0530 Subject: [PATCH] =?UTF-8?q?feat(doctor):=20add=20RAM=20and=20disk=20space?= =?UTF-8?q?=20checks=20to=20soup=20doctor=20command=20wi=E2=80=A6=20(#7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(doctor): add RAM and disk space checks to soup doctor command with tests and updated docs * fix(doctor): resolve subprocess type checker error by manually validating macOS RAM query return code --- .claude/CLAUDE.md | 6 +-- CONTRIBUTING.md | 2 +- README.md | 4 +- soup_cli/commands/doctor.py | 75 +++++++++++++++++++++++++++++++++++++ tests/test_doctor.py | 9 +++++ 5 files changed, 90 insertions(+), 6 deletions(-) diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 4fb8b60..900e783 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -87,7 +87,7 @@ soup_cli/ runs.py # soup runs (list/show/compare/delete experiments) sweep.py # soup sweep (grid/random hyperparameter search) diff.py # soup diff (compare two models side-by-side) - doctor.py # soup doctor (dependency + GPU checker) + doctor.py # soup doctor (resources, dependency + GPU checker) quickstart.py # soup quickstart (20-example TinyLlama demo) ui.py # soup ui (launches FastAPI web UI) ui/ @@ -174,7 +174,7 @@ soup runs compare # Side-by-side loss curves soup runs delete # Remove from DB soup sweep # Hyperparameter search (grid/random) soup diff # Compare two models' outputs -soup doctor # Check system + dependencies +soup doctor # Check system resources, GPU, + dependencies soup quickstart # One-command demo soup ui # Web UI (Dashboard, Training, Data Explorer, Chat) soup version # Show version (--full for details) @@ -399,7 +399,7 @@ soup version # Show version (--full for details) | test_diff.py | Diff prompts collection, metrics, CLI | | test_deepspeed.py | DeepSpeed configs, multi-GPU detection, trainer integration | | test_errors.py | Friendly error messages, --verbose flag, error mapping | -| test_doctor.py | `soup doctor` command, version checking, dependency table | +| test_doctor.py | `soup doctor` command, version checking, system resources, dependency table | | test_quickstart.py | `soup quickstart` demo, data/config creation, --dry-run | | test_grpo.py | GRPO config, rewards, data prep, template, sweep shortcuts | | test_progress.py | Rich download progress bar, `_enable_hf_transfer_progress` | diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9a3bd2c..95f4291 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -165,7 +165,7 @@ pytest tests/ --cov=soup_cli --cov-report=html | test_diff.py | Diff prompts collection, metrics, CLI | | test_deepspeed.py | DeepSpeed configs, multi-GPU detection, trainer integration | | test_errors.py | Friendly error messages, --verbose flag, error mapping | -| test_doctor.py | `soup doctor` command, version checking, dependency table | +| test_doctor.py | `soup doctor` command, version checking, system resources, dependency table | | test_quickstart.py | `soup quickstart` demo, data/config creation, --dry-run | | test_grpo.py | GRPO config, rewards, data prep, template, sweep shortcuts | | test_progress.py | Rich download progress bar, `_enable_hf_transfer_progress` | diff --git a/README.md b/README.md index b4c3bd8..e73a970 100644 --- a/README.md +++ b/README.md @@ -1151,7 +1151,7 @@ Check your environment for compatibility issues: soup doctor ``` -Shows: Python version, GPU availability, all dependency versions, and fix suggestions. +Shows: Python version, GPU availability, system resources (RAM/Disk), all dependency versions, and fix suggestions. ## Version Info @@ -1556,7 +1556,7 @@ pip install soup-cli ### Quick environment check ```bash -soup doctor # Shows GPU, dependencies, and version info +soup doctor # Shows GPU, system resources, dependencies, and version info ``` ## Development diff --git a/soup_cli/commands/doctor.py b/soup_cli/commands/doctor.py index bc4f4a6..f9fe778 100644 --- a/soup_cli/commands/doctor.py +++ b/soup_cli/commands/doctor.py @@ -58,6 +58,9 @@ def doctor(): # GPU check _check_gpu() + # Resources check + _check_resources() + # Dependencies table table = Table(title="Dependencies") table.add_column("Package", style="bold") @@ -171,6 +174,78 @@ def _check_gpu(): ) +def _check_resources(): + """Check RAM and Disk space and display info.""" + import shutil + + table = Table(title="System Resources") + table.add_column("Resource", style="bold") + table.add_column("Value") + + # RAM + ram_str = "Unknown" + try: + import psutil + mem = psutil.virtual_memory() + ram_str = f"{mem.total / (1024 ** 3):.0f} GB" + except ImportError: + pass + + if ram_str == "Unknown": + if platform.system() == "Linux": + try: + with open("/proc/meminfo", "r") as f: + for line in f: + if line.startswith("MemTotal:"): + kb = int(line.split()[1]) + ram_str = f"{kb / (1024 ** 2):.0f} GB" + break + except Exception: + pass + elif platform.system() == "Darwin": + try: + import subprocess + res = subprocess.run(["sysctl", "-n", "hw.memsize"], capture_output=True, text=True) + if res.returncode == 0: + ram_str = f"{int(res.stdout.strip()) / (1024 ** 3):.0f} GB" + except Exception: + pass + elif platform.system() == "Windows": + try: + import ctypes + class MEMORYSTATUSEX(ctypes.Structure): + _fields_ = [ + ("dwLength", ctypes.c_ulong), + ("dwMemoryLoad", ctypes.c_ulong), + ("ullTotalPhys", ctypes.c_ulonglong), + ("ullAvailPhys", ctypes.c_ulonglong), + ("ullTotalPageFile", ctypes.c_ulonglong), + ("ullAvailPageFile", ctypes.c_ulonglong), + ("ullTotalVirtual", ctypes.c_ulonglong), + ("ullAvailVirtual", ctypes.c_ulonglong), + ("sullAvailExtendedVirtual", ctypes.c_ulonglong), + ] + stat = MEMORYSTATUSEX() + stat.dwLength = ctypes.sizeof(MEMORYSTATUSEX) + ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(stat)) + ram_str = f"{stat.ullTotalPhys / (1024 ** 3):.0f} GB" + except Exception: + pass + + table.add_row("RAM", ram_str) + + # Disk + try: + usage = shutil.disk_usage(".") + disk_str = f"{usage.free / (1024 ** 3):.0f} GB" + except Exception: + disk_str = "Unknown" + + table.add_row("Disk", disk_str) + console.print(table) + console.print() + + def _check_torchvision_compat(issues: list): """Check that torchvision version is compatible with torch.""" try: diff --git a/tests/test_doctor.py b/tests/test_doctor.py index cd53def..6aa3f0a 100644 --- a/tests/test_doctor.py +++ b/tests/test_doctor.py @@ -80,6 +80,15 @@ def test_doctor_shows_gpu_section(): assert "GPU" in result.output +def test_doctor_shows_system_resources(): + """soup doctor shows System Resources section.""" + result = runner.invoke(app, ["doctor"]) + assert result.exit_code == 0 + assert "System Resources" in result.output + assert "RAM" in result.output + assert "Disk" in result.output + + def test_doctor_checks_torch(): """soup doctor checks for torch.""" result = runner.invoke(app, ["doctor"])