Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,5 @@ src/env_doctor/web/*
PR_SUMMARY.md
CHANGES-cuda-install-run.md
*.stackdump
xyz.ipynb

16 changes: 16 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,21 @@ All notable changes to env-doctor will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.3.4] - 2026-06-15

### Added
- **Jupyter / notebook HTML output**: `from env_doctor import check; check()` auto-detects a live Jupyter kernel and renders a rich, self-contained HTML report inline. Falls back to the familiar terminal text report everywhere else.
- **`CheckReport` public API**: `check()` returns a `CheckReport` object with `_repr_html_()` (Jupyter display protocol), `__repr__()`, `.html` (raw HTML string), and `.to_dict()`.
- **`--format {text,html,json}` CLI flag**: `env-doctor check --format html` emits a self-contained HTML fragment for CI reports or `> report.html`. `--json` / `--ci` still work identically.
- **`report` module**: `env_doctor.report.is_notebook()` detects Jupyter/Colab kernels; `env_doctor.report.format_result_html(output)` produces inline-CSS HTML with no external deps.
- **`[notebook]` optional extra**: `pip install env-doctor[notebook]` pulls in IPython. Core deps unchanged — IPython stays optional and lazily imported.

### Changed
- Extracted `collect_check_results()` and `render_check_text()` from `check_command()` so the JSON, HTML, text, and public API renderers share a single detection pass.
- Logo in HTML report now uses the project SVG (`src/env_doctor/report/logo.svg`) instead of an emoji.

---

## [0.3.2] - 2026-05-02

### Fixed
Expand Down Expand Up @@ -301,6 +316,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Basic CUDA toolkit detection
- Library installation commands

[0.3.4]: https://github.com/mitulgarg/env-doctor/compare/v0.3.3...v0.3.4
[0.3.1]: https://github.com/mitulgarg/env-doctor/compare/v0.3.0...v0.3.1
[0.3.0]: https://github.com/mitulgarg/env-doctor/compare/v0.2.9...v0.3.0
[0.2.9]: https://github.com/mitulgarg/env-doctor/compare/v0.2.8...v0.2.9
Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ It takes **5 seconds** to find out if your environment is broken - and exactly h
| **One-Command Diagnosis** | Check compatibility: GPU Driver → CUDA Toolkit → cuDNN → PyTorch/TensorFlow/JAX |
| **Compute Capability Check** | Detect GPU architecture mismatches — catches why `torch.cuda.is_available()` returns `False` on new GPUs (e.g. Blackwell) even when driver and CUDA are healthy |
| **Python Version Compatibility** | Detect Python version conflicts with AI libraries and dependency cascade impacts |
| **Jupyter / Notebook Output** | `from env_doctor import check; check()` renders a rich HTML diagnosis inline in Jupyter, Colab, or VS Code notebooks — falls back to text in the terminal |
| **CUDA Auto-Installer** | Execute CUDA Toolkit installation directly with `--run`; CI-friendly with `--yes`; preview with `--dry-run` |
| **Safe Install Commands** | Get the exact `pip install` command that works with YOUR driver |
| **Extension Library Support** | Install compilation packages (flash-attn, SageAttention, auto-gptq, apex, xformers) with CUDA version matching |
Expand Down Expand Up @@ -211,6 +212,18 @@ env-doctor check
pip install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cu126
```

### Notebook / Jupyter Output

Inside a Jupyter, Colab, or VS Code notebook, the Python API renders a rich, self-contained HTML report inline:

```python
from env_doctor import check
check() # auto-renders HTML in notebooks, prints text in terminals
```

Install the optional extra for notebook support: `pip install "env-doctor[notebook]"`.
You can also force HTML from the CLI with `env-doctor check --format html > report.html`.

### Check Python Version Compatibility

```bash
Expand Down
7 changes: 5 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "env-doctor"
version = "0.3.3"
version = "0.3.4"
description = "A CLI tool to verify and fix AI/ML environment compatibility (Driver <-> CUDA <-> Wheels) with platform-specific installation guides."
readme = "README.md"
license = { file = "LICENSE" }
Expand Down Expand Up @@ -39,6 +39,9 @@ dashboard = [
"sqlalchemy>=2.0.0,<3.0.0",
"aiosqlite>=0.17.0,<1.0.0",
]
notebook = [
"ipython>=7.0",
]

[project.scripts]
env-doctor = "env_doctor.cli:main"
Expand All @@ -57,7 +60,7 @@ package-dir = {"" = "src"}
where = ["src"]

[tool.setuptools.package-data]
"*" = ["data/*.json", "web/**/*"]
"*" = ["data/*.json", "web/**/*", "report/*.svg"]

[dependency-groups]
dev = ["pytest"]
Expand Down
6 changes: 5 additions & 1 deletion src/env_doctor/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
__version__ = "0.3.3"
__version__ = "0.3.4"

from .api import check, CheckReport

__all__ = ["check", "CheckReport", "__version__"]
78 changes: 78 additions & 0 deletions src/env_doctor/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"""Public Python API for env-doctor, designed for notebook use.

Typical usage inside a Jupyter notebook::

from env_doctor import check
check() # last cell expression -> rich HTML report

In a plain terminal / script the same call prints the familiar text report.
"""
from __future__ import annotations

from typing import Any, Dict, Optional

from .report import is_notebook, format_result_html


class CheckReport:
"""Result of :func:`check`, with format-aware display hooks.

- In Jupyter, being the last expression in a cell triggers
``_repr_html_`` and renders the rich HTML report.
- In an interactive terminal, ``__repr__`` shows a one-line summary
(the full text report is printed by :func:`check` itself).
- ``.html`` and ``.to_dict()`` expose the report for programmatic use.
"""

def __init__(self, output: Dict[str, Any]) -> None:
self._output = output

def to_dict(self) -> Dict[str, Any]:
"""Return the underlying structured result dict."""
return self._output

@property
def html(self) -> str:
"""Return the self-contained HTML report as a string."""
return format_result_html(self._output)

def _repr_html_(self) -> str: # noqa: D401 - IPython display protocol
return self.html

def __repr__(self) -> str:
summary = self._output.get("summary", {})
return (
f"<CheckReport status={self._output.get('status', 'unknown')} "
f"issues={summary.get('issues_count', 0)}>"
)


def check(format: Optional[str] = None) -> CheckReport:
"""Run the environment check and render it for the current environment.

In a notebook, return the result as a cell's last expression and Jupyter
renders the rich HTML automatically (via ``_repr_html_``) — no explicit
``display()`` call, so it never double-renders. In a terminal/script the
familiar text report is printed.

Args:
format: Force a renderer regardless of environment: ``"text"`` always
prints the terminal report; ``"html"`` skips the text print and
leaves rendering to the returned object's ``_repr_html_`` (use
``check(format="html").html`` for the raw string). ``None``
(default) auto-detects: HTML in a notebook, text in a terminal.

Returns:
A :class:`CheckReport`.
"""
# Imported here to avoid a circular import (cli imports report, api).
from .cli import collect_check_results, render_check_text

bundle = collect_check_results()
report = CheckReport(bundle["output"])

render_html = format == "html" or (format is None and is_notebook())
if not render_html:
render_check_text(bundle)

return report
Loading
Loading