Skip to content

Run all scikit-learn examples under cuml.accel in nightlies - #7960

Merged
rapids-bot[bot] merged 20 commits into
NVIDIA:mainfrom
csadorf:test-sklearn-examples
Apr 14, 2026
Merged

Run all scikit-learn examples under cuml.accel in nightlies#7960
rapids-bot[bot] merged 20 commits into
NVIDIA:mainfrom
csadorf:test-sklearn-examples

Conversation

@csadorf

@csadorf csadorf commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Adds a pytest-based runner that executes all scikit-learn example scripts under cuml.accel as part of the upstream acceleration test suite. The goal is to catch regressions where cuml.accel breaks example scripts that work with plain scikit-learn.

  • Adjust configuration to only run those tests as part of nightly tests

Closes #7961

@csadorf
csadorf requested a review from a team as a code owner April 8, 2026 17:46
@csadorf csadorf added the improvement Improvement / enhancement to an existing function label Apr 8, 2026
@csadorf
csadorf requested a review from a team as a code owner April 8, 2026 17:46
@csadorf csadorf added the non-breaking Non-breaking change label Apr 8, 2026
@csadorf
csadorf requested review from AyodeAwe and betatim April 8, 2026 17:46
@github-actions github-actions Bot added Cython / Python Cython or Python issue ci labels Apr 8, 2026
@coderabbitai

coderabbitai Bot commented Apr 8, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds infrastructure to run scikit-learn upstream examples under cuml.accel: updates .gitignore, adds a pytest example-collector plugin, a runner script to checkout and run upstream examples, an xfail rules YAML, and a CI step invoking the runner.

Changes

Cohort / File(s) Summary
Gitignore
/.gitignore
Added ignore for upstream test artifact: python/cuml/cuml_accel_tests/upstream/scikit-learn/sklearn-upstream.
CI script
ci/test_python_cuml_accel_upstream.sh
Bumped SPDX year range and inserted a CI step that logs and runs scikit-learn examples via ./python/cuml/cuml_accel_tests/upstream/scikit-learn/run-examples.sh wrapped in timeout 90m with -n 4 --dist worksteal, writing JUnit to ${RAPIDS_TESTS_DIR}/junit-sklearn-examples.xml.
Pytest plugin
python/cuml/cuml_accel_tests/upstream/scikit-learn/example_collector.py
New pytest plugin adding --examples-dir and --example-timeout (default 300s). Collects .py example files under the configured dir, creates ExampleItems that run each example in an isolated subprocess via python -m cuml.accel, enforce per-example timeouts (emit ExampleTimedOut and xfail on timeout), capture/truncate stderr on failure (ExampleFailed), set env vars (MPLBACKEND=Agg, PLOTLY_RENDERER=json), and expose a _FakeModule for xfail integration.
Runner script
python/cuml/cuml_accel_tests/upstream/scikit-learn/run-examples.sh
New Bash script that detects local scikit-learn version, clones/updates sklearn-upstream to the matching tag, and invokes pytest -p example_collector -p cuml.accel against the upstream examples dir, forwarding CLI args and pointing to xfail-examples.yaml and ../pytest.ini.
XFail config
python/cuml/cuml_accel_tests/upstream/scikit-learn/xfail-examples.yaml
New YAML listing expected-failure rules for upstream examples: grouped cuml_accel bug xfails, xfails for missing optional deps (plotly, polars, pooch, scikit-image), and a conditional numpy<2.0 xfail for a gaussian_process example.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • jcrist
  • viclafargue
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main objective: running scikit-learn examples under cuml.accel in nightly tests.
Linked Issues check ✅ Passed The PR successfully implements the core objective from #7961: creating infrastructure to execute scikit-learn example scripts under cuml.accel with timeout handling and xfail configuration.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the scikit-learn examples testing infrastructure specified in issue #7961; no unrelated modifications are present.
Description check ✅ Passed The pull request description is directly related to the changeset, clearly describing the addition of a pytest-based runner for scikit-learn examples under cuml.accel.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@python/cuml/cuml_accel_tests/upstream/scikit-learn/example_collector.py`:
- Around line 45-53: Rel.root-level examples produce rel.parent == Path('.')
which yields a module name "."; update the __init__ in example_collector.py to
detect that case before making self.module: after computing rel, compute
parent_str = str(rel.parent).replace(os.sep, ".") and if parent_str in (".", "")
set module_name = "" (or another empty/neutral name expected by the xfail
plugin), otherwise set module_name = parent_str; then set self.module =
_FakeModule(module_name) so root-level examples do not get a "." module name.
- Around line 70-73: The except block currently catches
subprocess.TimeoutExpired and raises ExampleFailed without preserving the
original traceback; modify the handler so you capture the caught exception
(e.g., except subprocess.TimeoutExpired as e:) and re-raise ExampleFailed using
exception chaining (raise ExampleFailed(f"Example timed out after {timeout}s:
{self.path.name}") from e) to retain the original subprocess.TimeoutExpired
context — update the block in the code that raises ExampleFailed from the
TimeoutExpired handler.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 73f88fdf-3309-4667-8c2a-400574662eb6

📥 Commits

Reviewing files that changed from the base of the PR and between 3420d7f and 569046b.

📒 Files selected for processing (5)
  • .gitignore
  • ci/test_python_cuml_accel_upstream.sh
  • python/cuml/cuml_accel_tests/upstream/scikit-learn/example_collector.py
  • python/cuml/cuml_accel_tests/upstream/scikit-learn/run-examples.sh
  • python/cuml/cuml_accel_tests/upstream/scikit-learn/xfail-examples.yaml

Comment thread python/cuml/cuml_accel_tests/upstream/scikit-learn/example_collector.py Outdated

@betatim betatim left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it. There are a few more test failures that need looking at and then adding to the xfail list.

I'm in two minds wrt installing some of the missing dependencies to see if those examples would run or not. You decide if you think it is worth it or not.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
ci/test_python_cuml_accel_upstream.sh (2)

17-20: Add explicit failure/timeout logging for the examples step.

Right now failures rely on the global trap ERR side effect. Adding a step-local error message makes CI triage faster when the 60-minute timeout is hit.

Suggested patch
 rapids-logger "scikit-learn examples"
-timeout 60m ./python/cuml/cuml_accel_tests/upstream/scikit-learn/run-examples.sh \
-  -n 4 --dist worksteal \
-  --junitxml="${RAPIDS_TESTS_DIR}/junit-sklearn-examples.xml"
+if ! timeout 60m ./python/cuml/cuml_accel_tests/upstream/scikit-learn/run-examples.sh \
+  -n 4 --dist worksteal \
+  --junitxml="${RAPIDS_TESTS_DIR}/junit-sklearn-examples.xml"; then
+  rapids-logger "scikit-learn examples failed or timed out (60m)"
+fi

As per coding guidelines, for CI/build scripts: “Check for proper error handling and meaningful error messages.”

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ci/test_python_cuml_accel_upstream.sh` around lines 17 - 20, The examples
step using "timeout 60m
./python/cuml/cuml_accel_tests/upstream/scikit-learn/run-examples.sh -n 4 --dist
worksteal --junitxml=\"${RAPIDS_TESTS_DIR}/junit-sklearn-examples.xml\"" lacks a
step-local failure/timeout message; wrap the command so you capture its exit
status and on non-zero (including timeout) print a clear, timestamped error to
stderr (e.g. "Examples step failed or timed out after 60m") before exiting with
that status; update the invocation around the run-examples.sh call to check $?
and emit the explicit log to aid CI triage.

15-20: Guard the new 60-minute examples stage behind a nightly gate (or confirm this script is nightly-only).

Lines 17-19 run unconditionally whenever this script is invoked. If this script is used outside nightly jobs, this will significantly increase CI time and flake surface.

Suggested patch (use your repo-standard nightly flag)
 # Run scikit-learn examples under cuml.accel
-rapids-logger "scikit-learn examples"
-timeout 60m ./python/cuml/cuml_accel_tests/upstream/scikit-learn/run-examples.sh \
-  -n 4 --dist worksteal \
-  --junitxml="${RAPIDS_TESTS_DIR}/junit-sklearn-examples.xml"
+if [[ "${RAPIDS_CI_NIGHTLY:-0}" == "1" ]]; then
+  rapids-logger "scikit-learn examples"
+  timeout 60m ./python/cuml/cuml_accel_tests/upstream/scikit-learn/run-examples.sh \
+    -n 4 --dist worksteal \
+    --junitxml="${RAPIDS_TESTS_DIR}/junit-sklearn-examples.xml"
+else
+  rapids-logger "Skipping scikit-learn examples (nightly-only)"
+fi
#!/bin/bash
# Verify how ci/test_python_cuml_accel_upstream.sh is invoked and which nightly gate variable is used in this repo.
fd -e yml -e yaml -e sh . | xargs rg -n -C2 \
  'test_python_cuml_accel_upstream\.sh|cuml_accel_upstream|nightly|RAPIDS_.*NIGHTLY|BUILD_TYPE|TEST_MODE'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ci/test_python_cuml_accel_upstream.sh` around lines 15 - 20, The scikit-learn
examples block (the rapids-logger call and the timeout 60m
./python/.../run-examples.sh invocation with -n 4 --dist worksteal
--junitxml=...) must be run only for nightly jobs; wrap this section in a
conditional that checks the repo-standard nightly gate variable (e.g.,
RAPIDS_NIGHTLY true, BUILD_TYPE == "nightly", or whatever test-mode flag your CI
uses) and skip or log a message when not set so normal CI runs are not slowed
down.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@ci/test_python_cuml_accel_upstream.sh`:
- Around line 17-20: The examples step using "timeout 60m
./python/cuml/cuml_accel_tests/upstream/scikit-learn/run-examples.sh -n 4 --dist
worksteal --junitxml=\"${RAPIDS_TESTS_DIR}/junit-sklearn-examples.xml\"" lacks a
step-local failure/timeout message; wrap the command so you capture its exit
status and on non-zero (including timeout) print a clear, timestamped error to
stderr (e.g. "Examples step failed or timed out after 60m") before exiting with
that status; update the invocation around the run-examples.sh call to check $?
and emit the explicit log to aid CI triage.
- Around line 15-20: The scikit-learn examples block (the rapids-logger call and
the timeout 60m ./python/.../run-examples.sh invocation with -n 4 --dist
worksteal --junitxml=...) must be run only for nightly jobs; wrap this section
in a conditional that checks the repo-standard nightly gate variable (e.g.,
RAPIDS_NIGHTLY true, BUILD_TYPE == "nightly", or whatever test-mode flag your CI
uses) and skip or log a message when not set so normal CI runs are not slowed
down.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a3ed1ed8-bbf9-4a9a-81ba-cd20bb3181af

📥 Commits

Reviewing files that changed from the base of the PR and between 569046b and bf88216.

📒 Files selected for processing (1)
  • ci/test_python_cuml_accel_upstream.sh

@csadorf

csadorf commented Apr 9, 2026

Copy link
Copy Markdown
Contributor Author

I like it. There are a few more test failures that need looking at and then adding to the xfail list.

I'm in two minds wrt installing some of the missing dependencies to see if those examples would run or not. You decide if you think it is worth it or not.

I might install them in a follow-up. We can test locally if any of them not pass.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@python/cuml/cuml_accel_tests/upstream/scikit-learn/example_collector.py`:
- Around line 47-48: The code computes rel = self.path.relative_to(examples_dir)
using an unresolved self.path which can raise ValueError for symlinked files;
resolve self.path first before calling relative_to (e.g., use
self.path.resolve() or reassign self.path = self.path.resolve()), so in
ExampleItem (or wherever rel is computed) replace the relative_to call with one
that uses the resolved path to avoid symlink collection crashes during
pytest_collect_file and item construction.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5468e1ff-6b38-4edd-92f9-cd431a26a3b4

📥 Commits

Reviewing files that changed from the base of the PR and between bf88216 and 610c0aa.

📒 Files selected for processing (2)
  • python/cuml/cuml_accel_tests/upstream/scikit-learn/example_collector.py
  • python/cuml/cuml_accel_tests/upstream/scikit-learn/xfail-examples.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
  • python/cuml/cuml_accel_tests/upstream/scikit-learn/xfail-examples.yaml

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
python/cuml/cuml_accel_tests/upstream/scikit-learn/example_collector.py (1)

52-53: ⚠️ Potential issue | 🟡 Minor

Resolve self.path before deriving the relative example ID.

Collection filters on file_path.resolve(), but this recomputes the relative path from the unresolved self.path. Symlinked example paths can therefore be accepted during collection and then blow up here with ValueError.

Suggested fix
-        rel = self.path.relative_to(examples_dir)
+        rel = self.path.resolve().relative_to(examples_dir)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@python/cuml/cuml_accel_tests/upstream/scikit-learn/example_collector.py`
around lines 52 - 53, The relative path computation uses
self.path.relative_to(examples_dir) with examples_dir resolved but self.path
possibly unresolved, causing ValueError for symlinked paths; fix by resolving
self.path first (e.g., compute resolved_path = self.path.resolve() or similar)
and then derive rel = resolved_path.relative_to(examples_dir) so both sides are
comparable; update references in this function to use the resolved path variable
instead of raw self.path.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@python/cuml/cuml_accel_tests/upstream/scikit-learn/example_collector.py`:
- Around line 114-123: The hook currently silently returns None when
--examples-dir is invalid; update pytest_collect_file to fail loudly: after
obtaining examples_dir via parent.config.getoption("examples_dir"), if
examples_dir is provided verify Path(examples_dir).exists() and is_dir(); if the
check fails raise pytest.UsageError with a clear message (include the provided
examples_dir). Then continue to resolve the path and keep the existing logic
that returns ExampleFile.from_parent(parent, path=file_path) when file_path is
under examples_dir; keep the early return None only when the option was not
supplied.

---

Duplicate comments:
In `@python/cuml/cuml_accel_tests/upstream/scikit-learn/example_collector.py`:
- Around line 52-53: The relative path computation uses
self.path.relative_to(examples_dir) with examples_dir resolved but self.path
possibly unresolved, causing ValueError for symlinked paths; fix by resolving
self.path first (e.g., compute resolved_path = self.path.resolve() or similar)
and then derive rel = resolved_path.relative_to(examples_dir) so both sides are
comparable; update references in this function to use the resolved path variable
instead of raw self.path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 159134c5-f915-4577-b315-e73326ce367a

📥 Commits

Reviewing files that changed from the base of the PR and between 0b9425e and 85531fb.

📒 Files selected for processing (2)
  • python/cuml/cuml_accel_tests/upstream/scikit-learn/example_collector.py
  • python/cuml/cuml_accel_tests/upstream/scikit-learn/xfail-examples.yaml
✅ Files skipped from review due to trivial changes (1)
  • python/cuml/cuml_accel_tests/upstream/scikit-learn/xfail-examples.yaml

@csadorf
csadorf force-pushed the test-sklearn-examples branch from a44fbc6 to 9adde64 Compare April 14, 2026 17:48
@csadorf

csadorf commented Apr 14, 2026

Copy link
Copy Markdown
Contributor Author

I verified that the new test runs are passing on the nightlies configuration in a2e9234 .

@csadorf

csadorf commented Apr 14, 2026

Copy link
Copy Markdown
Contributor Author

/merge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci Cython / Python Cython or Python issue improvement Improvement / enhancement to an existing function non-breaking Non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Run scikit-learn examples under cuml.accel in CI

5 participants