Skip to content
Merged
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
40 changes: 0 additions & 40 deletions ci/accel/scikit-learn-tests/README.md

This file was deleted.

95 changes: 0 additions & 95 deletions ci/accel/scikit-learn-tests/summarize-results.sh

This file was deleted.

10 changes: 6 additions & 4 deletions ci/test_python_scikit_learn_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Copyright (c) 2025, NVIDIA CORPORATION.

# Support invoking test script outside the script directory
cd "$(dirname "$(realpath "${BASH_SOURCE[0]}")")"/../
cd "$(dirname "$(realpath "${BASH_SOURCE[0]}")")"/../ || exit 1

# Common setup steps shared by Python test jobs
source ./ci/test_python_common.sh
Expand All @@ -15,12 +15,14 @@ set +e
rapids-logger "Running scikit-learn tests with cuML acceleration"

# Run the tests
./ci/accel/scikit-learn-tests/run-tests.sh \
--junitxml="${RAPIDS_TESTS_DIR}/junit-cuml-accel-scikit-learn.xml" || true
./python/cuml/cuml/accel/tests/scikit-learn/run-tests.sh \
--numprocesses=8 \
--dist=worksteal \
--junitxml="${RAPIDS_TESTS_DIR}/junit-cuml-accel-scikit-learn.xml"

# Analyze results and check pass rate threshold
rapids-logger "Analyzing test results"
./ci/accel/scikit-learn-tests/summarize-results.sh \
./python/cuml/cuml/accel/tests/scikit-learn/summarize-results.py \
--fail-below 80 \
"${RAPIDS_TESTS_DIR}/junit-cuml-accel-scikit-learn.xml"

Expand Down
1 change: 1 addition & 0 deletions conda/environments/all_cuda-118_arch-aarch64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ dependencies:
- pytest-xdist
- pytest==7.*
- python>=3.10,<3.13
- pyyaml
- raft-dask==25.6.*,>=0.0.0a0
- rapids-build-backend>=0.3.0,<0.4.0.dev0
- rapids-dask-dependency==25.6.*,>=0.0.0a0
Expand Down
1 change: 1 addition & 0 deletions conda/environments/all_cuda-118_arch-x86_64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ dependencies:
- pytest-xdist
- pytest==7.*
- python>=3.10,<3.13
- pyyaml
- raft-dask==25.6.*,>=0.0.0a0
- rapids-build-backend>=0.3.0,<0.4.0.dev0
- rapids-dask-dependency==25.6.*,>=0.0.0a0
Expand Down
1 change: 1 addition & 0 deletions conda/environments/all_cuda-128_arch-aarch64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ dependencies:
- pytest-xdist
- pytest==7.*
- python>=3.10,<3.13
- pyyaml
- raft-dask==25.6.*,>=0.0.0a0
- rapids-build-backend>=0.3.0,<0.4.0.dev0
- rapids-dask-dependency==25.6.*,>=0.0.0a0
Expand Down
1 change: 1 addition & 0 deletions conda/environments/all_cuda-128_arch-x86_64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ dependencies:
- pytest-xdist
- pytest==7.*
- python>=3.10,<3.13
- pyyaml
- raft-dask==25.6.*,>=0.0.0a0
- rapids-build-backend>=0.3.0,<0.4.0.dev0
- rapids-dask-dependency==25.6.*,>=0.0.0a0
Expand Down
1 change: 1 addition & 0 deletions dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@ dependencies:
- hypothesis>=6.0,<7
- nltk
- numpydoc
- pyyaml
- pytest==7.*
- pytest-benchmark
- pytest-cases
Expand Down
8 changes: 7 additions & 1 deletion python/cuml/cuml/accel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,18 @@
from cuml.accel.core import enabled, install
from cuml.accel.estimator_proxy import is_proxy
from cuml.accel.magics import load_ipython_extension
from cuml.accel.pytest_plugin import pytest_load_initial_conftests
from cuml.accel.pytest_plugin import (
pytest_addoption,
pytest_collection_modifyitems,
pytest_load_initial_conftests,
)

__all__ = (
"enabled",
"install",
"is_proxy",
"load_ipython_extension",
"pytest_load_initial_conftests",
"pytest_collection_modifyitems",
"pytest_addoption",
)
93 changes: 93 additions & 0 deletions python/cuml/cuml/accel/pytest_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@
# limitations under the License.
#

from collections import defaultdict
from importlib.metadata import version
from pathlib import Path

import yaml
Comment thread
csadorf marked this conversation as resolved.
from packaging.requirements import Requirement

from cuml.accel.core import install


Expand All @@ -26,3 +33,89 @@ def pytest_load_initial_conftests(early_config, parser, args):
raise RuntimeError(
"An existing plugin has already loaded sklearn. Interposing failed."
)


def pytest_addoption(parser):
"""Add command line option for xfail list file."""
parser.addoption(
"--xfail-list",
action="store",
help="Path to YAML file containing list of test IDs to mark as xfail",
)


def create_version_condition(condition_str: str) -> bool:
"""Evaluate a version condition immediately.

Args:
condition_str: String in format 'package[comparison]version'
For example:
- 'scikit-learn>=1.5.2'
- 'numpy<2.0.0'
- 'pandas==2.1.0'

Returns:
bool: True if the condition is met, False otherwise
"""
if not condition_str:
return True

try:
req = Requirement(condition_str)
installed_version = version(req.name)
return req.specifier.contains(installed_version)
except Exception:
return False


def pytest_collection_modifyitems(config, items):
"""Apply xfail markers to tests listed in the xfail list file."""
# Import pytest lazily to avoid requiring it for normal cuml usage.
# pytest is only needed when running tests.
import pytest

xfail_list_path = config.getoption("xfail_list")
if not xfail_list_path:
return

xfail_list_path = Path(xfail_list_path)
if not xfail_list_path.exists():
raise ValueError(f"Xfail list file not found: {xfail_list_path}")

xfail_list = yaml.safe_load(xfail_list_path.read_text())

if not isinstance(xfail_list, list):
raise ValueError("Xfail list must be a list of test entries")

# Convert list of dicts into dict mapping test IDs to lists of xfail configs
xfail_configs = defaultdict(list)
for entry in xfail_list:
if not isinstance(entry, dict):
raise ValueError("Xfail list entry must be a dictionary")
if "id" not in entry:
raise ValueError("Xfail list entry must contain an 'id' field")

test_id = entry["id"]
condition = True
if "condition" in entry:
condition = create_version_condition(entry["condition"])

config = {
"reason": entry.get("reason", "Test listed in xfail list"),
Comment thread
csadorf marked this conversation as resolved.
"strict": entry.get("strict", True),
"condition": condition,
}

xfail_configs[test_id].append(config)

for item in items:
test_id = f"{item.module.__name__}::{item.name}"
if test_id in xfail_configs:
for config in xfail_configs[test_id]:
item.add_marker(
pytest.mark.xfail(
reason=config["reason"],
strict=config["strict"],
condition=config["condition"],
)
)
Loading
Loading