From 29d7a7cb07d184257d09ae51b2b3dd7af3118e50 Mon Sep 17 00:00:00 2001 From: galipremsagar Date: Thu, 25 Jun 2026 18:03:12 +0000 Subject: [PATCH 01/11] fix --- .github/workflows/pr.yaml | 39 +++++++- .../pandas-tests/merge-results.py | 37 ++++++++ ci/cudf_pandas_scripts/pandas-tests/run.sh | 23 +++++ .../pandas-tests/summary.sh | 92 +++++++++++++++++++ .../pandas/scripts/pandas-testing-plugin.py | 70 ++++++++++++++ 5 files changed, 259 insertions(+), 2 deletions(-) create mode 100644 ci/cudf_pandas_scripts/pandas-tests/merge-results.py create mode 100755 ci/cudf_pandas_scripts/pandas-tests/summary.sh diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 27195b379a61..5a61ed53bd44 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -46,6 +46,7 @@ jobs: - devcontainer - unit-tests-cudf-pandas - pandas-tests + - pandas-tests-summary - narwhals-tests - telemetry-setup - third-party-integration-tests-cudf-pandas @@ -951,8 +952,15 @@ jobs: container_image: "rapidsai/ci-conda:26.10-latest" script: "ci/test_cuml_compat.sh" pandas-tests: - # run the Pandas unit tests using PR branch + # run the Pandas unit tests using PR branch, sharded across runners. + # To change the shard count, update all three places it appears: the matrix + # list below, the num-shards argument to run.sh below, and the argument to + # summary.sh in the pandas-tests-summary job. needs: [wheel-build-cudf, changed-files] + strategy: + fail-fast: false + matrix: + shard_id: [0, 1] permissions: actions: read contents: read @@ -969,7 +977,34 @@ jobs: sha: ${{ inputs.sha }} node_type: "gpu-l4-latest-1" container_image: "rapidsai/citestwheel:26.10-latest" - script: ci/cudf_pandas_scripts/pandas-tests/run.sh pr + script: "ci/cudf_pandas_scripts/pandas-tests/run.sh pr ${{ matrix.shard_id }} 2" + file_to_upload: ./pr-results.json + artifact-name: "pandas-test-pr-results-${{ matrix.shard_id }}" + pandas-tests-summary: + # Merge the sharded Pandas test results and post the diff against nightly. + # Informational only; the pass/fail signal comes from the pandas-tests job. + needs: [pandas-tests, changed-files] + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main + # Run whenever the shards ran (pass or fail) so we always get a diff, but + # not when pandas-tests was skipped. continue-on-error keeps this purely + # informational job from ever blocking the PR. + if: ${{ !cancelled() && needs.pandas-tests.result != 'skipped' }} + with: + build_type: pull-request + branch: ${{ inputs.branch }} + date: ${{ inputs.date }} + sha: ${{ inputs.sha }} + node_type: "cpu8" + continue-on-error: true + container_image: "rapidsai/citestwheel:26.10-latest" + script: "ci/cudf_pandas_scripts/pandas-tests/summary.sh 2" narwhals-tests: needs: [conda-python-build, conda-python-build-noarch, changed-files] permissions: diff --git a/ci/cudf_pandas_scripts/pandas-tests/merge-results.py b/ci/cudf_pandas_scripts/pandas-tests/merge-results.py new file mode 100644 index 000000000000..b87eee65f92d --- /dev/null +++ b/ci/cudf_pandas_scripts/pandas-tests/merge-results.py @@ -0,0 +1,37 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +""" +Merge the per-module summaries produced by ``summarize-test-results.py`` for +several test shards into a single summary. + +Each shard runs a disjoint subset of the suite (see the ``--num-shards`` +sharding in ``pandas-testing-plugin.py``), so the combined result for a module +is obtained by summing every numeric field (test counts and the GPU/CPU +function-call counters) across the shards. The same module may appear in more +than one shard because sharding is per test, not per module. + +Examples +-------- + python merge-results.py shard-0/pr-results.json shard-1/pr-results.json > pr-results.json +""" + +import json +import sys + +merged: dict[str, dict] = {} +for path in sys.argv[1:]: + with open(path) as f: + results = json.load(f) + for module_name, row in results.items(): + combined = merged.setdefault(module_name, {}) + for key, value in row.items(): + if isinstance(value, bool): + # No boolean fields are expected; keep the first seen value. + combined.setdefault(key, value) + elif isinstance(value, (int, float)): + combined[key] = combined.get(key, 0) + value + else: + combined.setdefault(key, value) + +print(json.dumps(merged, indent=4)) diff --git a/ci/cudf_pandas_scripts/pandas-tests/run.sh b/ci/cudf_pandas_scripts/pandas-tests/run.sh index eae1b272d367..7412405e7a49 100755 --- a/ci/cudf_pandas_scripts/pandas-tests/run.sh +++ b/ci/cudf_pandas_scripts/pandas-tests/run.sh @@ -14,9 +14,22 @@ rapids-logger "Check GPU usage" nvidia-smi PANDAS_TESTS_BRANCH=${1} +# Optional sharding args: run.sh [shard_id] [num_shards] +# When num_shards is provided, only this shard's subset of the suite runs and +# the diff against the nightly results is deferred to the separate +# pandas-tests-summary job, which merges every shard's results first. +SHARD_ID=${2:-} +NUM_SHARDS=${3:-} +SHARD_ARGS=() +if [[ -n "${NUM_SHARDS}" ]]; then + SHARD_ARGS=(--shard-id "${SHARD_ID}" --num-shards "${NUM_SHARDS}") +fi RAPIDS_FULL_VERSION=$(<./VERSION) rapids-logger "Running Pandas tests using $PANDAS_TESTS_BRANCH branch and rapids-version $RAPIDS_FULL_VERSION" rapids-logger "PR number: ${RAPIDS_REF_NAME:-"unknown"}" +if [[ -n "${NUM_SHARDS}" ]]; then + rapids-logger "Running shard ${SHARD_ID} of ${NUM_SHARDS}" +fi RAPIDS_PY_CUDA_SUFFIX="$(rapids-wheel-ctk-name-gen "${RAPIDS_CUDA_VERSION}")" @@ -42,6 +55,7 @@ timeout 90m bash python/cudf/cudf/pandas/scripts/run-pandas-tests.sh \ --max-worker-restart=3 \ --junitxml="${RAPIDS_TESTS_DIR}/junit-cudf-pandas.xml" \ --dist worksteal \ + ${SHARD_ARGS[@]+"${SHARD_ARGS[@]}"} \ --report-log="${PANDAS_TESTS_BRANCH}.json" 2>&1 SUMMARY_FILE_NAME=${PANDAS_TESTS_BRANCH}-results.json @@ -54,6 +68,15 @@ if [[ "${PANDAS_TESTS_BRANCH}" == "main" ]]; then exit ${EXITCODE} fi +# When this run is one shard of a sharded PR run, it only holds part of the +# results. The diff against the nightly is computed once, by the +# pandas-tests-summary job, after merging every shard's results. This shard +# just uploads its partial results (pr-results.json) for that job to collect. +if [[ -n "${NUM_SHARDS}" ]]; then + rapids-logger "Shard ${SHARD_ID}/${NUM_SHARDS}: skipping diff (done by pandas-tests-summary). Exit: ${EXITCODE}" + exit ${EXITCODE} +fi + MAIN_RUN_ID=$( gh run list \ diff --git a/ci/cudf_pandas_scripts/pandas-tests/summary.sh b/ci/cudf_pandas_scripts/pandas-tests/summary.sh new file mode 100755 index 000000000000..582a4af49585 --- /dev/null +++ b/ci/cudf_pandas_scripts/pandas-tests/summary.sh @@ -0,0 +1,92 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +# Aggregate the results of the sharded pandas-tests PR jobs. +# +# Each shard uploads its partial per-module summary as the GitHub artifact +# "pandas-test-pr-results-". This job downloads them all, merges them +# into a single pr-results.json, and posts the diff against the latest nightly +# ("main") results to the job summary. +# +# Usage: +# summary.sh +# +# This step is purely informational, so it never fails the workflow; the +# pass/fail signal for the suite comes from the individual shard jobs. + +# No `set -e`: this step is best effort and must never fail the workflow, so +# every fallible command is guarded explicitly and the script always exits 0. +set -uo pipefail + +source rapids-init-pip + +NUM_SHARDS=${1:?usage: summary.sh } +RAPIDS_FULL_VERSION=$(<./VERSION) + +rapids-logger "Aggregating pandas-tests results from ${NUM_SHARDS} shards" + +# job-summary.py renders markdown tables with pandas; tabulate backs to_markdown. +if ! rapids-pip-retry install pandas tabulate; then + rapids-logger "Could not install summary dependencies; skipping summary." + exit 0 +fi + +# Download each shard's partial results from the current run. A shard that +# crashed before uploading is tolerated (its results are simply omitted). +for ((shard = 0; shard < NUM_SHARDS; shard++)); do + if ! gh run download "${GITHUB_RUN_ID}" \ + --repo "${GITHUB_REPOSITORY}" \ + --name "pandas-test-pr-results-${shard}" \ + --dir "shard-${shard}"; then + rapids-logger "Could not download results for shard ${shard}; skipping it." + fi +done + +shopt -s nullglob +SHARD_RESULTS=(shard-*/pr-results.json) +if [[ ${#SHARD_RESULTS[@]} -eq 0 ]]; then + rapids-logger "No shard results were downloaded; nothing to summarize." + exit 0 +fi + +rapids-logger "Merging ${#SHARD_RESULTS[@]} shard result file(s)" +if ! python ci/cudf_pandas_scripts/pandas-tests/merge-results.py \ + "${SHARD_RESULTS[@]}" > pr-results.json; then + rapids-logger "Failed to merge shard results; skipping summary." + exit 0 +fi + +# Fetch the latest successful nightly results to diff against. +MAIN_RUN_ID=$( + gh run list \ + -w "Pandas Test Job" \ + -b "$(<./RAPIDS_BRANCH)" \ + --repo 'rapidsai/cudf' \ + --status success \ + --limit 7 \ + --json 'createdAt,databaseId' \ + --jq 'sort_by(.createdAt) | reverse | .[0] | .databaseId' || true +) + +if [[ -z "${MAIN_RUN_ID}" ]]; then + rapids-logger "No nightly main results found; skipping diff." + exit 0 +fi + +rapids-logger "Fetching latest available results from nightly: ${MAIN_RUN_ID}" +if ! gh run download \ + --repo 'rapidsai/cudf' \ + --name main-results.json \ + "${MAIN_RUN_ID}"; then + rapids-logger "Could not download nightly results; skipping diff." + exit 0 +fi + +# Compute the diff and prepare the job summary (best effort). +if ! python ci/cudf_pandas_scripts/pandas-tests/job-summary.py \ + main-results.json pr-results.json "${RAPIDS_FULL_VERSION}" >> "$GITHUB_STEP_SUMMARY"; then + rapids-logger "Failed to render the job summary." +fi + +exit 0 diff --git a/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py b/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py index 6ef0b3c6c088..f63e06793664 100644 --- a/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py +++ b/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py @@ -1,6 +1,7 @@ # SPDX-FileCopyrightText: Copyright (c) 2023-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 +import hashlib import json import sys import traceback @@ -10,6 +11,64 @@ import pytest +def positive_int(value): + value = int(value) + if value < 0: + raise ValueError(f"Argument {value} must be non-negative") + return value + + +def pytest_addoption(parser): + """Add options to split the test suite into deterministic shards. + + Adapted from https://github.com/AdamGleave/pytest-shard so a single + pandas-tests job can be parallelized across multiple CI runners. With the + defaults (``--num-shards 1``) the full suite runs, so existing + (non-sharded) invocations are unaffected. + """ + group = parser.getgroup("shard") + group.addoption( + "--shard-id", + dest="shard_id", + type=positive_int, + default=0, + help="Zero-based index of this shard.", + ) + group.addoption( + "--num-shards", + dest="num_shards", + type=positive_int, + default=1, + help="Total number of shards.", + ) + + +def _sha256_hash(value: str) -> int: + return int.from_bytes(hashlib.sha256(value.encode()).digest(), "little") + + +def filter_items_by_shard(items, shard_id, num_shards): + """Return the subset of ``items`` assigned to ``shard_id``. + + Assignment is by a stable hash of each item's node id, so every pytest + worker (and every shard) partitions the suite identically and the shards + are disjoint and collectively exhaustive. + """ + return [ + item + for item in items + if _sha256_hash(item.nodeid) % num_shards == shard_id + ] + + +def pytest_report_collectionfinish(config, items): + if config.getoption("num_shards") > 1: + return ( + f"Running {len(items)} items in shard " + f"{config.getoption('shard_id')}/{config.getoption('num_shards')}" + ) + + def replace_kwargs(new_kwargs): def wrapper(func): @wraps(func) @@ -5247,6 +5306,17 @@ def pytest_configure(config): @pytest.hookimpl(trylast=True) def pytest_collection_modifyitems(session, config, items): + num_shards = config.getoption("num_shards") + if num_shards > 1: + shard_id = config.getoption("shard_id") + if shard_id >= num_shards: + raise ValueError( + f"--shard-id ({shard_id}) must be less than " + f"--num-shards ({num_shards})" + ) + # Keep only this shard's items before applying skip/xfail markers so + # the markers are only attached to the tests this shard will run. + items[:] = filter_items_by_shard(items, shard_id, num_shards) for item in items: if any( substr in item.nodeid for substr in NODEIDS_TOLERANT_INDEX_COMPARE From 0e72ffb717e5550fea1ad4750f212a434b5fc731 Mon Sep 17 00:00:00 2001 From: galipremsagar Date: Fri, 26 Jun 2026 22:50:23 +0000 Subject: [PATCH 02/11] update --- .../pandas/scripts/pandas-testing-plugin.py | 241 ++++++++++++++++++ 1 file changed, 241 insertions(+) diff --git a/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py b/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py index f63e06793664..b33157110fb6 100644 --- a/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py +++ b/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py @@ -5286,6 +5286,247 @@ def pytest_unconfigure(config): "tests/window/moments/test_moments_consistency_rolling.py::test_rolling_apply_consistency_sum[all_data6-rolling_consistency_cases0-False-sum]": "pandas xfails, but xpasses with cudf.pandas", "tests/window/moments/test_moments_consistency_rolling.py::test_rolling_apply_consistency_sum[all_data6-rolling_consistency_cases0-True-sum]": "pandas xfails, but xpasses with cudf.pandas", "tests/window/moments/test_moments_consistency_rolling.py::test_rolling_apply_consistency_sum[all_data7-rolling_consistency_cases0-False-sum]": "pandas xfails, but xpasses with cudf.pandas", + "tests/extension/test_arrow.py::TestArrowArray::test_compare_array[timestamp[ns]-eq]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/frame/test_stack_unstack.py::TestStackUnstackMultiLevel::test_stack_names_and_numbers[False]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/frame/test_stack_unstack.py::TestStackUnstackMultiLevel::test_stack_names_and_numbers[True]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/groupby/methods/test_value_counts.py::test_against_frame_and_seriesgroupby[False-False-False-None-True-proportion-function]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/groupby/methods/test_value_counts.py::test_against_frame_and_seriesgroupby[False-False-True-False-False-count-column]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/groupby/methods/test_value_counts.py::test_against_frame_and_seriesgroupby[False-False-True-False-False-count-function]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/groupby/methods/test_value_counts.py::test_against_frame_and_seriesgroupby[False-False-True-True-True-proportion-column]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/groupby/methods/test_value_counts.py::test_against_frame_and_seriesgroupby[True-False-False-None-True-proportion-function]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/groupby/methods/test_value_counts.py::test_against_frame_and_seriesgroupby[True-False-True-False-False-count-column]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/groupby/methods/test_value_counts.py::test_against_frame_and_seriesgroupby[True-False-True-False-True-proportion-function]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/groupby/methods/test_value_counts.py::test_against_frame_and_seriesgroupby[True-False-True-True-False-count-function]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/groupby/methods/test_value_counts.py::test_against_frame_and_seriesgroupby[True-False-True-True-True-proportion-function]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/indexes/interval/test_interval.py::TestIntervalIndex::test_maybe_convert_i8_errors[Index-datetime64[us, US/Eastern]-datetime64[us]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/indexes/interval/test_interval.py::TestIntervalIndex::test_maybe_convert_i8_errors[scalar-datetime64[us, US/Eastern]-datetime64[us]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/indexes/interval/test_interval.py::TestIntervalIndex::test_maybe_convert_i8_errors[scalar-datetime64[us, US/Eastern]-timedelta64[us]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/indexes/multi/test_formats.py::TestRepr::test_tuple_width": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/frame/test_frame.py::TestDataFramePlots::test_memory_leak[area]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/frame/test_frame.py::TestDataFramePlots::test_memory_leak[line]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/frame/test_frame.py::TestDataFramePlots::test_plot_period_index_makes_no_right_shift[120min]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/frame/test_frame.py::TestDataFramePlots::test_plot_period_index_makes_no_right_shift[3M]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/frame/test_frame.py::TestDataFramePlots::test_plot_period_index_makes_no_right_shift[7h]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/frame/test_frame.py::TestDataFramePlots::test_plot_period_index_makes_no_right_shift[h]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/frame/test_frame.py::TestDataFramePlots::test_scatter_line_xticks": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/frame/test_frame.py::TestDataFramePlots::test_xcompat_plot_period": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/frame/test_frame_subplots.py::TestDataFramePlotsSubplots::test_subplots_timeseries[line]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_axis_limits[obj1]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_business_freq": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_check_xticks_rot": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_finder_annual": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_finder_hourly": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_finder_monthly": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_finder_quarterly": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_format_timedelta_ticks_wide[s]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_format_timedelta_ticks_wide[us]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_datetime_frame[1B30Min]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_datetime_frame[QE-DEC]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_datetime_frame[YE]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_datetime_series[h]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_datetime_series[min]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_datetime_series[s]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_datetime_series[YE]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_inferred_freq[h]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_inferred_freq[min]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_period_frame[ME]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_period_frame[W]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_period_mlt_frame[1s]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_period_mlt_frame[3s]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_period_mlt_frame[4D]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_period_mlt_frame[5min]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_period_mlt_frame[7h]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_period_mlt_frame[8W]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_period_mlt_series[11M]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_period_mlt_series[1s]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_period_mlt_series[3Y]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_period_mlt_series[7h]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_period_series[h]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_period_series[M]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_period_series[min]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_period_series[Q]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_mixed_freq_hf_first": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_mixed_freq_lf_first": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_mixed_freq_lf_first_hourly": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_mixed_freq_shared_ax": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_pickle_fig[DataFrame-idx0]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_pickle_fig[DataFrame-idx1]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_pickle_fig[Series-idx0]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_pickle_fig[Series-idx3]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_secondary_upsample": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_secondary_y_ts": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_to_weekly_resampling_disallow_how_kwd": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_ts_plot_format_coord[D-t = 2014-01-01 y = 1.000000]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_ts_plot_format_coord[YE-DEC-t = 2014 y = 1.000000]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/plotting/test_series.py::TestSeriesPlots::test_ts_area_lim": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_api.py::test_api_per_method[index-empty1-rpartition1-category]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_api.py::test_api_per_method[index-empty1-rpartition1-object]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_api.py::test_api_per_method[index-empty1-rpartition2-category]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_api.py::test_api_per_method[index-empty1-rpartition2-object]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[bool-dtype-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[categorical-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[datetime-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[datetime-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[datetime-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[datetime-tz-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[datetime-tz-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[datetime-tz-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[float32-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[float32-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[float32-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[float64-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int16-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int16-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int32-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int32-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int32-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int8-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[interval-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[multi-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[multi-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_bool-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_float-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_float-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_float-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_int-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_uint-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_uint-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[object-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[object-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[object-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[range-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[range-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[range-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[repeats-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[repeats-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[repeats-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[string-pyarrow-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[string-python-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[string-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[string-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[string-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[tuples-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[tuples-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint16-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint16-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint16-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint32-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint32-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint64-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint8-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint8-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_end_of_string[string=object]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[bool-dtype-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[bool-dtype-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[categorical-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[categorical-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[categorical-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[datetime-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[datetime-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[datetime-tz-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[float32-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[float64-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[float64-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[int16-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[int32-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[int32-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[int64-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[int64-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[int8-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[int8-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[interval-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[interval-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[interval-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[multi-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[multi-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[nullable_bool-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[nullable_bool-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[nullable_bool-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[nullable_bool-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[nullable_float-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[nullable_float-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[nullable_int-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[nullable_int-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[nullable_int-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[nullable_uint-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[nullable_uint-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[object-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[range-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[repeats-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[string-pyarrow-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[string-pyarrow-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[string-python-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[string-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[tuples-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[tuples-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[uint16-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[uint16-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[uint32-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[uint32-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[uint64-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[uint64-string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[uint64-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[uint8-string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[uint8-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups_index[uint8-string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups[string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups[string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups[string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_capture_groups[string=str[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_index_raises": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_expand_True_single_capture_group[index-string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_index_one_two_groups": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_optional_groups[string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_optional_groups[string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_optional_groups[string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_series[string=string[pyarrow]-None]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_series[string=string[pyarrow]-series_name]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_series[string=string[python]-None]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_extract.py::test_extract_series[string=str[python]-None]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_contains_compiled_regex_flags[string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_contains_compiled_regex[string=object]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_contains_compiled_regex[string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_contains_end_of_string[string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_contains_lookarounds[string=object-na5-ab-expected_data4]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_contains_lookarounds[string=object-_NoDefault.no_default-ab-expected_data4]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_contains_lookarounds[string=str[pyarrow]-None-ab-expected_data4]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_contains_lookarounds[string=str[python]-na5-ab-expected_data4]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_contains_lookarounds[string=str[python]-None-ab-expected_data4]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_contains_moar[string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_contains_na_kwarg_for_nullable_string_dtype[string[pyarrow]-False-False-False]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_contains_na_kwarg_for_nullable_string_dtype[string[pyarrow]-False-None-expected0]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_contains_na_kwarg_for_nullable_string_dtype[string[pyarrow]-False-True-True]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_contains_na_kwarg_for_nullable_string_dtype[string[pyarrow]-True-False-False]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_contains_na_kwarg_for_nullable_string_dtype[string[pyarrow]-True-None-expected0]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_pyarrow_ambiguous_group_references[pyarrow_string_dtype0-(\\w+) (\\w+) (\\w+)-\\20]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_pyarrow_backend_group_replacement[\\[(\\d+)\\]-(\\1)-expected_list1]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_replace_end_of_string[string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_replace_end_of_string[string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_startswith[False-None-object-pat1]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_find_replace.py::test_startswith[True-None-object-foo]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_string_array.py::test_string_array_boolean_array[string[pyarrow]-isdigit-expected0]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_string_array.py::test_string_array_boolean_array[string[pyarrow]-isnumeric-expected4]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_string_array.py::test_string_array[string[pyarrow]-contains]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_string_array.py::test_string_array[string[pyarrow]-endswith2]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_string_array.py::test_string_array[string[pyarrow]-endswith3]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_string_array.py::test_string_array[string[pyarrow]-endswith4]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_string_array.py::test_string_array[string[pyarrow]-isdecimal]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_string_array.py::test_string_array[string[pyarrow]-isdigit]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_string_array.py::test_string_array[string[pyarrow]-istitle]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_string_array.py::test_string_array[string[pyarrow]-len]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_string_array.py::test_string_array[string[pyarrow]-startswith0]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_string_array.py::test_string_array[string[pyarrow]-startswith1]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_string_array.py::test_string_array[string[pyarrow]-startswith3]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_string_array.py::test_string_array[string[python]-len]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_strings.py::test_empty_str_methods[string=object]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_strings.py::test_empty_str_methods[string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_strings.py::test_ismethods[string=string[pyarrow]-isalnum-expected1]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_strings.py::test_ismethods[string=string[pyarrow]-isnumeric-expected4]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_strings.py::test_len[string=string[python]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_strings.py::test_slice_replace[string=string[pyarrow]-None--2-z-expected5]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_strings.py::test_slice_replace[string=string[python]--1-None-z-expected4]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_strings.py::test_slice_replace[string=str[python]--10-3-z-expected7]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + "tests/strings/test_strings.py::test_slice_replace[string=str[python]-None--2-z-expected5]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", } # Keep keys in alphabetical order From 950e580824c801784e631c44dd9ff2167b53f95a Mon Sep 17 00:00:00 2001 From: galipremsagar Date: Mon, 13 Jul 2026 19:25:22 +0000 Subject: [PATCH 03/11] Skip order-dependent tests failing in sharded pandas-tests CI Adds the 27 failures from CI run 29231155311 to NODEIDS_TO_SKIP: 6 plain failures from shard 0 (strings/test_find_replace pyarrow group replacement, plotting/test_datetimelike Axes.freq) and 21 strict-XPASSes from shard 1 (test_extract_dataframe_capture_groups_index[*-string=object]), which are moved out of NODEIDS_THAT_FAIL since their outcome depends on test order. Also removes two stale skip entries from the previous batch whose keys were written with single backslashes; pytest ids escape regex params with doubled backslashes, so those keys never matched and the tests kept failing in CI. --- .../pandas/scripts/pandas-testing-plugin.py | 50 ++++++++++--------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py b/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py index b33157110fb6..cd6ed0cb3d9a 100644 --- a/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py +++ b/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py @@ -3535,33 +3535,12 @@ def pytest_unconfigure(config): "tests/strings/test_cat.py::test_str_cat_categorical[series-category-category-None-False]": "AssertionError: Attributes of Series are different", "tests/strings/test_cat.py::test_str_cat_categorical[series-category-object--False]": "AssertionError: Attributes of Series are different", "tests/strings/test_cat.py::test_str_cat_categorical[series-category-object-None-False]": "AssertionError: Attributes of Series are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[bool-dtype-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[categorical-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[datetime-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[datetime-tz-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[float32-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[float64-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int16-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int32-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int64-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int8-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[interval-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[multi-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_bool-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_float-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_int-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_uint-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[object-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[range-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[repeats-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[string-pyarrow-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[string-python-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[string-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[tuples-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint16-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint32-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint64-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint8-string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", "tests/strings/test_extract.py::test_extract_expand_False_mixed_object": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", "tests/strings/test_extract.py::test_extract_expand_True[string=object]": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", "tests/strings/test_extract.py::test_extract_expand_True_mixed_object": "AssertionError: DataFrame.iloc[:, 0] (column name='0') are different", @@ -4198,6 +4177,33 @@ def pytest_unconfigure(config): "tests/extension/test_string.py::TestStringArray::test_memory_usage[string=string[pyarrow]-False]": "GPU/CPU memory_usage differs from sys.getsizeof", "tests/extension/test_string.py::TestStringArray::test_memory_usage[string=string[pyarrow]-True]": "GPU/CPU memory_usage differs from sys.getsizeof", "tests/extension/test_string.py::TestStringArray::test_memory_usage[string=string[python]-False]": "GPU/CPU memory_usage differs from sys.getsizeof", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_datetime_frame[D]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_datetime_frame[W]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_datetime_frame[s]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_inferred_freq[ME]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[bool-dtype-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[categorical-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[datetime-tz-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int16-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int32-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int64-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int8-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[interval-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[multi-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_bool-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_float-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_int-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_uint-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[range-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[repeats-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[string-pyarrow-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[string-python-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[string-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint16-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint32-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint8-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_find_replace.py::test_pyarrow_ambiguous_group_references[pyarrow_string_dtype0-(\\\\w+) (\\\\w+) (\\\\w+)-\\\\20]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_find_replace.py::test_pyarrow_backend_group_replacement[\\\\[(\\\\d+)\\\\]-(\\\\1)-expected_list1]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", "tests/test_downstream.py::test_construct_dask_float_array_int_dtype_match_ndarray": "Flaky under xdist due cross-test state interaction with dask", "tests/extension/test_string.py::TestStringArray::test_memory_usage[string=string[python]-True]": "GPU/CPU memory_usage differs from sys.getsizeof", "tests/extension/test_string.py::TestStringArray::test_series_constructor[string=str[pyarrow]-False]": "Asserts private APIs", @@ -5498,8 +5504,6 @@ def pytest_unconfigure(config): "tests/strings/test_find_replace.py::test_contains_na_kwarg_for_nullable_string_dtype[string[pyarrow]-False-True-True]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", "tests/strings/test_find_replace.py::test_contains_na_kwarg_for_nullable_string_dtype[string[pyarrow]-True-False-False]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", "tests/strings/test_find_replace.py::test_contains_na_kwarg_for_nullable_string_dtype[string[pyarrow]-True-None-expected0]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", - "tests/strings/test_find_replace.py::test_pyarrow_ambiguous_group_references[pyarrow_string_dtype0-(\\w+) (\\w+) (\\w+)-\\20]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", - "tests/strings/test_find_replace.py::test_pyarrow_backend_group_replacement[\\[(\\d+)\\]-(\\1)-expected_list1]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", "tests/strings/test_find_replace.py::test_replace_end_of_string[string=string[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", "tests/strings/test_find_replace.py::test_replace_end_of_string[string=str[pyarrow]]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", "tests/strings/test_find_replace.py::test_startswith[False-None-object-pat1]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", From ddfacb448e299043b69ebba09aa4b512cdc6c1b0 Mon Sep 17 00:00:00 2001 From: galipremsagar Date: Wed, 19 Aug 2026 16:46:35 +0000 Subject: [PATCH 04/11] Shard the nightly pandas-tests run too The PR job was sharded but the nightly still ran the suite on one runner, so the baseline every PR diffs against took as long as the whole suite. Shard it the same way and add a merge job that recombines the per-shard summaries. The combined file keeps the main-results.json artifact name, so run.sh and summary.sh find it exactly as before. The merge job runs only when every shard succeeded. A partial baseline would read as new failures in the PRs that diff against it, so no successful nightly at all is the safer outcome. --- .github/workflows/pandas-tests.yaml | 35 ++++++++++++++- .../pandas-tests/merge-nightly.sh | 44 +++++++++++++++++++ 2 files changed, 77 insertions(+), 2 deletions(-) create mode 100755 ci/cudf_pandas_scripts/pandas-tests/merge-nightly.sh diff --git a/.github/workflows/pandas-tests.yaml b/.github/workflows/pandas-tests.yaml index 9251ae9341f9..c3a545d3e3b1 100644 --- a/.github/workflows/pandas-tests.yaml +++ b/.github/workflows/pandas-tests.yaml @@ -22,7 +22,14 @@ permissions: {} jobs: pandas-tests: - # run the Pandas unit tests + # run the Pandas unit tests, sharded across runners. + # To change the shard count, update both places it appears: the matrix list + # below and the num-shards argument to run.sh, plus the argument to + # merge-nightly.sh in the pandas-tests-merge job. + strategy: + fail-fast: false + matrix: + shard_id: [0, 1] permissions: actions: read contents: read @@ -38,6 +45,30 @@ jobs: sha: ${{ inputs.sha }} node_type: "gpu-l4-latest-1" container_image: "rapidsai/citestwheel:26.10-latest" - script: ci/cudf_pandas_scripts/pandas-tests/run.sh main + script: "ci/cudf_pandas_scripts/pandas-tests/run.sh main ${{ matrix.shard_id }} 2" + file_to_upload: ./main-results.json + artifact-name: "pandas-test-main-results-${{ matrix.shard_id }}" + pandas-tests-merge: + # Merge the sharded results back into the single main-results.json artifact + # that PR runs diff against. Deliberately runs only when every shard + # succeeded: a partial baseline would surface as spurious "new failures" in + # PRs, so it is better for the nightly to have no successful run at all. + needs: pandas-tests + permissions: + actions: read + contents: read + id-token: write + packages: read + pull-requests: read + secrets: inherit # zizmor: ignore[secrets-inherit] + uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main + with: + build_type: nightly + branch: ${{ inputs.branch }} + date: ${{ inputs.date }} + sha: ${{ inputs.sha }} + node_type: "cpu8" + container_image: "rapidsai/citestwheel:26.10-latest" + script: "ci/cudf_pandas_scripts/pandas-tests/merge-nightly.sh 2" file_to_upload: ./main-results.json artifact-name: main-results.json diff --git a/ci/cudf_pandas_scripts/pandas-tests/merge-nightly.sh b/ci/cudf_pandas_scripts/pandas-tests/merge-nightly.sh new file mode 100755 index 000000000000..bde5657782f1 --- /dev/null +++ b/ci/cudf_pandas_scripts/pandas-tests/merge-nightly.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +# Combine the results of the sharded nightly ("main") pandas-tests jobs. +# +# Each shard uploads its partial per-module summary as the GitHub artifact +# "pandas-test-main-results-". This job downloads them all and merges +# them into a single main-results.json, which is re-uploaded under that name so +# that PR runs keep finding it with `gh run download --name main-results.json`. +# +# Usage: +# merge-nightly.sh +# +# Unlike the PR-side summary.sh, this script is NOT best effort: main-results.json +# is the baseline every PR diffs against, and a partial or missing file would show +# up as spurious "new failures" in those PRs. Failing loudly instead keeps the run +# from being picked up as the latest successful nightly. + +set -euo pipefail + +source rapids-init-pip + +NUM_SHARDS=${1:?usage: merge-nightly.sh } + +rapids-logger "Merging pandas-tests results from ${NUM_SHARDS} shards" + +for ((shard = 0; shard < NUM_SHARDS; shard++)); do + rapids-logger "Downloading results for shard ${shard}" + gh run download "${GITHUB_RUN_ID}" \ + --repo "${GITHUB_REPOSITORY}" \ + --name "pandas-test-main-results-${shard}" \ + --dir "shard-${shard}" +done + +SHARD_RESULTS=() +for ((shard = 0; shard < NUM_SHARDS; shard++)); do + SHARD_RESULTS+=("shard-${shard}/main-results.json") +done + +python ci/cudf_pandas_scripts/pandas-tests/merge-results.py \ + "${SHARD_RESULTS[@]}" > main-results.json + +rapids-logger "Merged $(wc -l < main-results.json) lines into main-results.json" From 58ae23c089a4bfa0145024074b3866a1f013a9e3 Mon Sep 17 00:00:00 2001 From: galipremsagar Date: Wed, 19 Aug 2026 19:35:34 +0000 Subject: [PATCH 05/11] Harden the sharding configuration and summary Three problems the sharded CI run exposed, none of which were failing loudly. A shard that fails never reaches its upload step, so summary.sh merged whatever had arrived and diffed part of the suite against the whole nightly baseline, reporting the missing shard's tests as removed. It did this while staying green. Require every shard before summarizing. The shard options were only validated during collection, so a bad --shard-id surfaced as an INTERNALERROR after collecting the whole pandas suite, and --num-shards 0 or 1 silently ran everything on every runner -- which the merge step would then have summed into doubled totals. Validate in pytest_configure and reject a num-shards below 1. summary.sh was written from a pre-rename copy and still pointed at rapidsai/cudf, where run.sh already uses NVIDIA/cudf. Since the script is best effort and always exits 0, that would have gone quiet rather than red if the redirect ever stopped resolving. --- .../pandas-tests/summary.sh | 16 ++++++++------ .../pandas/scripts/pandas-testing-plugin.py | 21 ++++++++++++++----- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/ci/cudf_pandas_scripts/pandas-tests/summary.sh b/ci/cudf_pandas_scripts/pandas-tests/summary.sh index 582a4af49585..cf9ad8e12b95 100755 --- a/ci/cudf_pandas_scripts/pandas-tests/summary.sh +++ b/ci/cudf_pandas_scripts/pandas-tests/summary.sh @@ -32,8 +32,8 @@ if ! rapids-pip-retry install pandas tabulate; then exit 0 fi -# Download each shard's partial results from the current run. A shard that -# crashed before uploading is tolerated (its results are simply omitted). +# Download each shard's partial results from the current run. Every shard +# must be present for the merged total to mean anything; see the check below. for ((shard = 0; shard < NUM_SHARDS; shard++)); do if ! gh run download "${GITHUB_RUN_ID}" \ --repo "${GITHUB_REPOSITORY}" \ @@ -45,8 +45,12 @@ done shopt -s nullglob SHARD_RESULTS=(shard-*/pr-results.json) -if [[ ${#SHARD_RESULTS[@]} -eq 0 ]]; then - rapids-logger "No shard results were downloaded; nothing to summarize." +if [[ ${#SHARD_RESULTS[@]} -ne ${NUM_SHARDS} ]]; then + # A shard that fails never reaches its upload step, so its results are + # simply absent. Summarizing anyway would diff part of this PR's suite + # against the whole nightly baseline and report every test in the missing + # shard as removed, which is worse than printing nothing at all. + rapids-logger "Only ${#SHARD_RESULTS[@]} of ${NUM_SHARDS} shard results are available; skipping the summary rather than reporting a partial diff." exit 0 fi @@ -62,7 +66,7 @@ MAIN_RUN_ID=$( gh run list \ -w "Pandas Test Job" \ -b "$(<./RAPIDS_BRANCH)" \ - --repo 'rapidsai/cudf' \ + --repo 'NVIDIA/cudf' \ --status success \ --limit 7 \ --json 'createdAt,databaseId' \ @@ -76,7 +80,7 @@ fi rapids-logger "Fetching latest available results from nightly: ${MAIN_RUN_ID}" if ! gh run download \ - --repo 'rapidsai/cudf' \ + --repo 'NVIDIA/cudf' \ --name main-results.json \ "${MAIN_RUN_ID}"; then rapids-logger "Could not download nightly results; skipping diff." diff --git a/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py b/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py index cd6ed0cb3d9a..2cb49eba2764 100644 --- a/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py +++ b/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py @@ -5548,17 +5548,28 @@ def pytest_configure(config): "comparison for tests with small GPU-vs-CPU floating-point drift.", ) + # Validate the sharding options before collection rather than during it. + # A misconfigured CI matrix should fail in seconds instead of after + # collecting the whole pandas suite, and raising here gives a clean usage + # error rather than a pytest INTERNALERROR. + num_shards = config.getoption("num_shards") + shard_id = config.getoption("shard_id") + if num_shards < 1: + raise pytest.UsageError( + f"--num-shards ({num_shards}) must be at least 1" + ) + if not 0 <= shard_id < num_shards: + raise pytest.UsageError( + f"--shard-id ({shard_id}) must be in " + f"[0, --num-shards ({num_shards}))" + ) + @pytest.hookimpl(trylast=True) def pytest_collection_modifyitems(session, config, items): num_shards = config.getoption("num_shards") if num_shards > 1: shard_id = config.getoption("shard_id") - if shard_id >= num_shards: - raise ValueError( - f"--shard-id ({shard_id}) must be less than " - f"--num-shards ({num_shards})" - ) # Keep only this shard's items before applying skip/xfail markers so # the markers are only attached to the tests this shard will run. items[:] = filter_items_by_shard(items, shard_id, num_shards) From b08237e4820aeccdcb2864af44d8c23efc6636ba Mon Sep 17 00:00:00 2001 From: galipremsagar Date: Thu, 20 Aug 2026 00:49:48 +0000 Subject: [PATCH 06/11] Skip two tests failing in the sharded pandas run Shard 1 of run 32294121723 failed on test_stack_multiple_out_of_bounds[False] and test_to_datetime_iso8601_fails[True-2012-01-01-%Y-%m-%d %H]. Both are nondeterministic rather than deterministic incompatibilities: the [True] parametrization and the sibling unstack tests run in the other shard and pass, and the to_datetime case passed in the previous run of this same shard. Skip them under the existing test-order-dependent reason. --- python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py b/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py index 2cb49eba2764..6479714ba0dc 100644 --- a/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py +++ b/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py @@ -5531,6 +5531,14 @@ def pytest_unconfigure(config): "tests/strings/test_strings.py::test_slice_replace[string=string[python]--1-None-z-expected4]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", "tests/strings/test_strings.py::test_slice_replace[string=str[python]--10-3-z-expected7]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", "tests/strings/test_strings.py::test_slice_replace[string=str[python]-None--2-z-expected5]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", + # Failing in sharded pandas-tests CI run 32294121723 (shard 1, job + # 96216291366). Both are nondeterministic rather than deterministic + # incompatibilities: test_stack_multiple_out_of_bounds[True] and the + # sibling unstack tests pass in the other shard, and + # test_to_datetime_iso8601_fails passed in the previous run of this + # same shard. + "tests/frame/test_stack_unstack.py::TestStackUnstackMultiLevel::test_stack_multiple_out_of_bounds[False]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/tools/test_to_datetime.py::TestToDatetimeMisc::test_to_datetime_iso8601_fails[True-2012-01-01-%Y-%m-%d %H]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", } # Keep keys in alphabetical order From 8fa52ae3048c8839112aa4ea592636704a949e92 Mon Sep 17 00:00:00 2001 From: galipremsagar Date: Tue, 25 Aug 2026 19:51:31 +0000 Subject: [PATCH 07/11] Address review feedback on the sharding change Derive the shard count from one place. A pandas-tests-shards job emits both the matrix and the num-shards argument from a single NUM_SHARDS value, so the matrix and the scripts can no longer disagree. Share the download-and-merge step between summary.sh and merge-nightly.sh. The two only ever differed in how they react to a missing shard, so that stays with the callers and the rest moves to shard-results.sh. Keep the sharding-only skips out of unsharded runs. The 268 entries added for sharded CI were going into NODEIDS_TO_SKIP, which applies everywhere, so the nightly baseline and local runs lost the coverage too. They move to NODEIDS_TO_SKIP_WHEN_SHARDED, applied only when num_shards > 1. Report the other shards' tests as deselected instead of dropping them during collection, so reporting plugins account for them. --- .github/workflows/pandas-tests.yaml | 30 ++++-- .github/workflows/pr.yaml | 31 +++++-- .../pandas-tests/merge-nightly.sh | 23 ++--- .../pandas-tests/shard-results.sh | 31 +++++++ .../pandas-tests/summary.sh | 36 ++----- .../pandas/scripts/pandas-testing-plugin.py | 93 ++++++++++++------- 6 files changed, 151 insertions(+), 93 deletions(-) create mode 100755 ci/cudf_pandas_scripts/pandas-tests/shard-results.sh diff --git a/.github/workflows/pandas-tests.yaml b/.github/workflows/pandas-tests.yaml index c3a545d3e3b1..4be1f97b1df5 100644 --- a/.github/workflows/pandas-tests.yaml +++ b/.github/workflows/pandas-tests.yaml @@ -21,15 +21,31 @@ on: permissions: {} jobs: + pandas-tests-shards: + # Single source of truth for the shard count: both the matrix below and the + # num-shards argument the scripts receive are derived from NUM_SHARDS here, + # so the two can no longer drift apart. + permissions: {} + runs-on: ubuntu-latest + outputs: + num_shards: ${{ steps.shards.outputs.num_shards }} + shard_ids: ${{ steps.shards.outputs.shard_ids }} + steps: + - id: shards + env: + NUM_SHARDS: 2 + run: | + { + echo "num_shards=${NUM_SHARDS}" + echo "shard_ids=$(seq 0 $((NUM_SHARDS - 1)) | jq -sc .)" + } >> "$GITHUB_OUTPUT" pandas-tests: # run the Pandas unit tests, sharded across runners. - # To change the shard count, update both places it appears: the matrix list - # below and the num-shards argument to run.sh, plus the argument to - # merge-nightly.sh in the pandas-tests-merge job. + needs: pandas-tests-shards strategy: fail-fast: false matrix: - shard_id: [0, 1] + shard_id: ${{ fromJSON(needs.pandas-tests-shards.outputs.shard_ids) }} permissions: actions: read contents: read @@ -45,7 +61,7 @@ jobs: sha: ${{ inputs.sha }} node_type: "gpu-l4-latest-1" container_image: "rapidsai/citestwheel:26.10-latest" - script: "ci/cudf_pandas_scripts/pandas-tests/run.sh main ${{ matrix.shard_id }} 2" + script: "ci/cudf_pandas_scripts/pandas-tests/run.sh main ${{ matrix.shard_id }} ${{ needs.pandas-tests-shards.outputs.num_shards }}" file_to_upload: ./main-results.json artifact-name: "pandas-test-main-results-${{ matrix.shard_id }}" pandas-tests-merge: @@ -53,7 +69,7 @@ jobs: # that PR runs diff against. Deliberately runs only when every shard # succeeded: a partial baseline would surface as spurious "new failures" in # PRs, so it is better for the nightly to have no successful run at all. - needs: pandas-tests + needs: [pandas-tests, pandas-tests-shards] permissions: actions: read contents: read @@ -69,6 +85,6 @@ jobs: sha: ${{ inputs.sha }} node_type: "cpu8" container_image: "rapidsai/citestwheel:26.10-latest" - script: "ci/cudf_pandas_scripts/pandas-tests/merge-nightly.sh 2" + script: "ci/cudf_pandas_scripts/pandas-tests/merge-nightly.sh ${{ needs.pandas-tests-shards.outputs.num_shards }}" file_to_upload: ./main-results.json artifact-name: main-results.json diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 5a61ed53bd44..8f858e752dbe 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -951,16 +951,31 @@ jobs: continue-on-error: true container_image: "rapidsai/ci-conda:26.10-latest" script: "ci/test_cuml_compat.sh" + pandas-tests-shards: + # Single source of truth for the shard count: both the matrix below and the + # num-shards argument the scripts receive are derived from NUM_SHARDS here, + # so the two can no longer drift apart. + permissions: {} + runs-on: ubuntu-latest + outputs: + num_shards: ${{ steps.shards.outputs.num_shards }} + shard_ids: ${{ steps.shards.outputs.shard_ids }} + steps: + - id: shards + env: + NUM_SHARDS: 2 + run: | + { + echo "num_shards=${NUM_SHARDS}" + echo "shard_ids=$(seq 0 $((NUM_SHARDS - 1)) | jq -sc .)" + } >> "$GITHUB_OUTPUT" pandas-tests: # run the Pandas unit tests using PR branch, sharded across runners. - # To change the shard count, update all three places it appears: the matrix - # list below, the num-shards argument to run.sh below, and the argument to - # summary.sh in the pandas-tests-summary job. - needs: [wheel-build-cudf, changed-files] + needs: [wheel-build-cudf, changed-files, pandas-tests-shards] strategy: fail-fast: false matrix: - shard_id: [0, 1] + shard_id: ${{ fromJSON(needs.pandas-tests-shards.outputs.shard_ids) }} permissions: actions: read contents: read @@ -977,13 +992,13 @@ jobs: sha: ${{ inputs.sha }} node_type: "gpu-l4-latest-1" container_image: "rapidsai/citestwheel:26.10-latest" - script: "ci/cudf_pandas_scripts/pandas-tests/run.sh pr ${{ matrix.shard_id }} 2" + script: "ci/cudf_pandas_scripts/pandas-tests/run.sh pr ${{ matrix.shard_id }} ${{ needs.pandas-tests-shards.outputs.num_shards }}" file_to_upload: ./pr-results.json artifact-name: "pandas-test-pr-results-${{ matrix.shard_id }}" pandas-tests-summary: # Merge the sharded Pandas test results and post the diff against nightly. # Informational only; the pass/fail signal comes from the pandas-tests job. - needs: [pandas-tests, changed-files] + needs: [pandas-tests, changed-files, pandas-tests-shards] permissions: actions: read contents: read @@ -1004,7 +1019,7 @@ jobs: node_type: "cpu8" continue-on-error: true container_image: "rapidsai/citestwheel:26.10-latest" - script: "ci/cudf_pandas_scripts/pandas-tests/summary.sh 2" + script: "ci/cudf_pandas_scripts/pandas-tests/summary.sh ${{ needs.pandas-tests-shards.outputs.num_shards }}" narwhals-tests: needs: [conda-python-build, conda-python-build-noarch, changed-files] permissions: diff --git a/ci/cudf_pandas_scripts/pandas-tests/merge-nightly.sh b/ci/cudf_pandas_scripts/pandas-tests/merge-nightly.sh index bde5657782f1..a9c8789d8559 100755 --- a/ci/cudf_pandas_scripts/pandas-tests/merge-nightly.sh +++ b/ci/cudf_pandas_scripts/pandas-tests/merge-nightly.sh @@ -20,25 +20,16 @@ set -euo pipefail source rapids-init-pip +# shellcheck source=ci/cudf_pandas_scripts/pandas-tests/shard-results.sh +source ci/cudf_pandas_scripts/pandas-tests/shard-results.sh NUM_SHARDS=${1:?usage: merge-nightly.sh } rapids-logger "Merging pandas-tests results from ${NUM_SHARDS} shards" -for ((shard = 0; shard < NUM_SHARDS; shard++)); do - rapids-logger "Downloading results for shard ${shard}" - gh run download "${GITHUB_RUN_ID}" \ - --repo "${GITHUB_REPOSITORY}" \ - --name "pandas-test-main-results-${shard}" \ - --dir "shard-${shard}" -done +# set -e propagates a missing or unmergeable shard, which is what we want here: +# see the header comment. +merge_shard_results "pandas-test-main-results" "main-results.json" \ + "${NUM_SHARDS}" main-results.json -SHARD_RESULTS=() -for ((shard = 0; shard < NUM_SHARDS; shard++)); do - SHARD_RESULTS+=("shard-${shard}/main-results.json") -done - -python ci/cudf_pandas_scripts/pandas-tests/merge-results.py \ - "${SHARD_RESULTS[@]}" > main-results.json - -rapids-logger "Merged $(wc -l < main-results.json) lines into main-results.json" +rapids-logger "Wrote main-results.json" diff --git a/ci/cudf_pandas_scripts/pandas-tests/shard-results.sh b/ci/cudf_pandas_scripts/pandas-tests/shard-results.sh new file mode 100755 index 000000000000..0abefce5542a --- /dev/null +++ b/ci/cudf_pandas_scripts/pandas-tests/shard-results.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +# Shared helper for the sharded pandas-tests jobs. Sourced by summary.sh (PR +# side) and merge-nightly.sh (nightly side): both download every shard's partial +# per-module summary from the current run and merge them into one file. The two +# callers differ only in how they react to a missing shard, so that decision is +# left to them and this returns non-zero instead of exiting. + +# merge_shard_results +merge_shard_results() { + local prefix=$1 filename=$2 num_shards=$3 output=$4 + local shard + local results=() + + for ((shard = 0; shard < num_shards; shard++)); do + if ! gh run download "${GITHUB_RUN_ID}" \ + --repo "${GITHUB_REPOSITORY}" \ + --name "${prefix}-${shard}" \ + --dir "shard-${shard}"; then + rapids-logger "Could not download results for shard ${shard}." + return 1 + fi + results+=("shard-${shard}/${filename}") + done + + rapids-logger "Merging ${#results[@]} shard result file(s)" + python ci/cudf_pandas_scripts/pandas-tests/merge-results.py \ + "${results[@]}" > "${output}" +} diff --git a/ci/cudf_pandas_scripts/pandas-tests/summary.sh b/ci/cudf_pandas_scripts/pandas-tests/summary.sh index cf9ad8e12b95..241a62461dd1 100755 --- a/ci/cudf_pandas_scripts/pandas-tests/summary.sh +++ b/ci/cudf_pandas_scripts/pandas-tests/summary.sh @@ -20,6 +20,8 @@ set -uo pipefail source rapids-init-pip +# shellcheck source=ci/cudf_pandas_scripts/pandas-tests/shard-results.sh +source ci/cudf_pandas_scripts/pandas-tests/shard-results.sh NUM_SHARDS=${1:?usage: summary.sh } RAPIDS_FULL_VERSION=$(<./VERSION) @@ -32,32 +34,14 @@ if ! rapids-pip-retry install pandas tabulate; then exit 0 fi -# Download each shard's partial results from the current run. Every shard -# must be present for the merged total to mean anything; see the check below. -for ((shard = 0; shard < NUM_SHARDS; shard++)); do - if ! gh run download "${GITHUB_RUN_ID}" \ - --repo "${GITHUB_REPOSITORY}" \ - --name "pandas-test-pr-results-${shard}" \ - --dir "shard-${shard}"; then - rapids-logger "Could not download results for shard ${shard}; skipping it." - fi -done - -shopt -s nullglob -SHARD_RESULTS=(shard-*/pr-results.json) -if [[ ${#SHARD_RESULTS[@]} -ne ${NUM_SHARDS} ]]; then - # A shard that fails never reaches its upload step, so its results are - # simply absent. Summarizing anyway would diff part of this PR's suite - # against the whole nightly baseline and report every test in the missing - # shard as removed, which is worse than printing nothing at all. - rapids-logger "Only ${#SHARD_RESULTS[@]} of ${NUM_SHARDS} shard results are available; skipping the summary rather than reporting a partial diff." - exit 0 -fi - -rapids-logger "Merging ${#SHARD_RESULTS[@]} shard result file(s)" -if ! python ci/cudf_pandas_scripts/pandas-tests/merge-results.py \ - "${SHARD_RESULTS[@]}" > pr-results.json; then - rapids-logger "Failed to merge shard results; skipping summary." +# Download and merge every shard's partial results. A shard that fails never +# reaches its upload step, so its results are simply absent; summarizing anyway +# would diff part of this PR's suite against the whole nightly baseline and +# report every test in the missing shard as removed, which is worse than +# printing nothing at all. +if ! merge_shard_results "pandas-test-pr-results" "pr-results.json" \ + "${NUM_SHARDS}" pr-results.json; then + rapids-logger "Could not assemble all ${NUM_SHARDS} shards; skipping the summary rather than reporting a partial diff." exit 0 fi diff --git a/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py b/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py index 6479714ba0dc..9e6b76fe609b 100644 --- a/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py +++ b/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py @@ -47,18 +47,20 @@ def _sha256_hash(value: str) -> int: return int.from_bytes(hashlib.sha256(value.encode()).digest(), "little") -def filter_items_by_shard(items, shard_id, num_shards): - """Return the subset of ``items`` assigned to ``shard_id``. +def partition_items_by_shard(items, shard_id, num_shards): + """Split ``items`` into those assigned to ``shard_id`` and the rest. Assignment is by a stable hash of each item's node id, so every pytest worker (and every shard) partitions the suite identically and the shards are disjoint and collectively exhaustive. """ - return [ - item - for item in items - if _sha256_hash(item.nodeid) % num_shards == shard_id - ] + selected, deselected = [], [] + for item in items: + target = selected if ( + _sha256_hash(item.nodeid) % num_shards == shard_id + ) else deselected + target.append(item) + return selected, deselected def pytest_report_collectionfinish(config, items): @@ -4177,33 +4179,6 @@ def pytest_unconfigure(config): "tests/extension/test_string.py::TestStringArray::test_memory_usage[string=string[pyarrow]-False]": "GPU/CPU memory_usage differs from sys.getsizeof", "tests/extension/test_string.py::TestStringArray::test_memory_usage[string=string[pyarrow]-True]": "GPU/CPU memory_usage differs from sys.getsizeof", "tests/extension/test_string.py::TestStringArray::test_memory_usage[string=string[python]-False]": "GPU/CPU memory_usage differs from sys.getsizeof", - "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_datetime_frame[D]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_datetime_frame[W]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_datetime_frame[s]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_inferred_freq[ME]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[bool-dtype-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[categorical-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[datetime-tz-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int16-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int32-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int64-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int8-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[interval-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[multi-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_bool-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_float-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_int-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_uint-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[range-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[repeats-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[string-pyarrow-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[string-python-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[string-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint16-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint32-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint8-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_find_replace.py::test_pyarrow_ambiguous_group_references[pyarrow_string_dtype0-(\\\\w+) (\\\\w+) (\\\\w+)-\\\\20]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", - "tests/strings/test_find_replace.py::test_pyarrow_backend_group_replacement[\\\\[(\\\\d+)\\\\]-(\\\\1)-expected_list1]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", "tests/test_downstream.py::test_construct_dask_float_array_int_dtype_match_ndarray": "Flaky under xdist due cross-test state interaction with dask", "tests/extension/test_string.py::TestStringArray::test_memory_usage[string=string[python]-True]": "GPU/CPU memory_usage differs from sys.getsizeof", "tests/extension/test_string.py::TestStringArray::test_series_constructor[string=str[pyarrow]-False]": "Asserts private APIs", @@ -5292,6 +5267,41 @@ def pytest_unconfigure(config): "tests/window/moments/test_moments_consistency_rolling.py::test_rolling_apply_consistency_sum[all_data6-rolling_consistency_cases0-False-sum]": "pandas xfails, but xpasses with cudf.pandas", "tests/window/moments/test_moments_consistency_rolling.py::test_rolling_apply_consistency_sum[all_data6-rolling_consistency_cases0-True-sum]": "pandas xfails, but xpasses with cudf.pandas", "tests/window/moments/test_moments_consistency_rolling.py::test_rolling_apply_consistency_sum[all_data7-rolling_consistency_cases0-False-sum]": "pandas xfails, but xpasses with cudf.pandas", +} + +#: Tests that only fail when the suite is split across shards. Sharding +#: changes the order tests run in, and cudf.pandas has order-dependent +#: behaviour these expose. They are applied ONLY to sharded runs so the +#: unsharded nightly and local runs keep exercising them -- skipping them +#: everywhere would quietly drop the coverage instead of narrowing it. +NODEIDS_TO_SKIP_WHEN_SHARDED: dict[str, str] = { + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_datetime_frame[D]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_datetime_frame[W]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_datetime_frame[s]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/plotting/test_datetimelike.py::TestTSPlot::test_line_plot_inferred_freq[ME]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[bool-dtype-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[categorical-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[datetime-tz-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int16-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int32-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int64-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[int8-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[interval-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[multi-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_bool-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_float-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_int-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[nullable_uint-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[range-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[repeats-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[string-pyarrow-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[string-python-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[string-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint16-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint32-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_extract.py::test_extract_dataframe_capture_groups_index[uint8-string=object]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_find_replace.py::test_pyarrow_ambiguous_group_references[pyarrow_string_dtype0-(\\\\w+) (\\\\w+) (\\\\w+)-\\\\20]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", + "tests/strings/test_find_replace.py::test_pyarrow_backend_group_replacement[\\\\[(\\\\d+)\\\\]-(\\\\1)-expected_list1]": "Flaky under test sharding: cudf.pandas behavior is test-order-dependent (see #22992)", "tests/extension/test_arrow.py::TestArrowArray::test_compare_array[timestamp[ns]-eq]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", "tests/frame/test_stack_unstack.py::TestStackUnstackMultiLevel::test_stack_names_and_numbers[False]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", "tests/frame/test_stack_unstack.py::TestStackUnstackMultiLevel::test_stack_names_and_numbers[True]": "Skipped: failing in pandas-tests sharded CI (PR #22992, run 28204832469)", @@ -5576,11 +5586,18 @@ def pytest_configure(config): @pytest.hookimpl(trylast=True) def pytest_collection_modifyitems(session, config, items): num_shards = config.getoption("num_shards") - if num_shards > 1: + sharded = num_shards > 1 + if sharded: shard_id = config.getoption("shard_id") # Keep only this shard's items before applying skip/xfail markers so # the markers are only attached to the tests this shard will run. - items[:] = filter_items_by_shard(items, shard_id, num_shards) + items[:], deselected = partition_items_by_shard( + items, shard_id, num_shards + ) + if deselected: + # Tell pytest what the other shards took, so reporting plugins + # account for them instead of seeing them vanish at collection. + config.hook.pytest_deselected(items=deselected) for item in items: if any( substr in item.nodeid for substr in NODEIDS_TOLERANT_INDEX_COMPARE @@ -5588,6 +5605,10 @@ def pytest_collection_modifyitems(session, config, items): item.add_marker(pytest.mark.tolerant_index_compare) if (reason := NODEIDS_TO_SKIP.get(item.nodeid, None)) is not None: item.add_marker(pytest.mark.skip(reason=reason)) + elif sharded and ( + reason := NODEIDS_TO_SKIP_WHEN_SHARDED.get(item.nodeid, None) + ) is not None: + item.add_marker(pytest.mark.skip(reason=reason)) elif ( reason := next( ( From b74530204f2ac61635078237ef7f885c6abf1e65 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 25 Aug 2026 19:58:29 +0000 Subject: [PATCH 08/11] [pre-commit.ci] auto code formatting --- .../cudf/pandas/scripts/pandas-testing-plugin.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py b/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py index 9e6b76fe609b..81313047bacd 100644 --- a/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py +++ b/python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py @@ -56,9 +56,11 @@ def partition_items_by_shard(items, shard_id, num_shards): """ selected, deselected = [], [] for item in items: - target = selected if ( - _sha256_hash(item.nodeid) % num_shards == shard_id - ) else deselected + target = ( + selected + if (_sha256_hash(item.nodeid) % num_shards == shard_id) + else deselected + ) target.append(item) return selected, deselected @@ -5605,9 +5607,11 @@ def pytest_collection_modifyitems(session, config, items): item.add_marker(pytest.mark.tolerant_index_compare) if (reason := NODEIDS_TO_SKIP.get(item.nodeid, None)) is not None: item.add_marker(pytest.mark.skip(reason=reason)) - elif sharded and ( - reason := NODEIDS_TO_SKIP_WHEN_SHARDED.get(item.nodeid, None) - ) is not None: + elif ( + sharded + and (reason := NODEIDS_TO_SKIP_WHEN_SHARDED.get(item.nodeid, None)) + is not None + ): item.add_marker(pytest.mark.skip(reason=reason)) elif ( reason := next( From a9e4961084605b244b4b61dd2a6f78848e252e5e Mon Sep 17 00:00:00 2001 From: galipremsagar Date: Tue, 25 Aug 2026 20:01:26 +0000 Subject: [PATCH 09/11] Drop secrets: inherit from the pandas-tests jobs custom-job.yaml declares no secrets in its workflow_call and reads the secrets context in exactly one place, guarded by the optional alternative-gh-token-secret-name input. None of these jobs pass that input, so the Run script step's GH_TOKEN falls back to github.token, which is available either way. AWS auth is OIDC through vars.AWS_ROLE_ARN and id-token: write rather than a secret, and the shared-actions steps are composite actions, which cannot read the secrets context at all. That makes the inheritance unused here, so it and its zizmor suppression go. Limited to the jobs this PR already touches; the other 29 callers in pr.yaml are left alone. --- .github/workflows/pandas-tests.yaml | 2 -- .github/workflows/pr.yaml | 2 -- 2 files changed, 4 deletions(-) diff --git a/.github/workflows/pandas-tests.yaml b/.github/workflows/pandas-tests.yaml index 4be1f97b1df5..b8079d9d1a74 100644 --- a/.github/workflows/pandas-tests.yaml +++ b/.github/workflows/pandas-tests.yaml @@ -52,7 +52,6 @@ jobs: id-token: write packages: read pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main with: build_type: nightly @@ -76,7 +75,6 @@ jobs: id-token: write packages: read pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main with: build_type: nightly diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 951c0c7fbffe..d4dcdad3e4ee 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -966,7 +966,6 @@ jobs: id-token: write packages: read pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main if: fromJSON(needs.changed-files.outputs.changed_file_groups).test_python_wheels && fromJSON(needs.changed-files.outputs.changed_file_groups).neither_cpp_nor_cudf_polars_nor_dask_cudf with: @@ -989,7 +988,6 @@ jobs: id-token: write packages: read pull-requests: read - secrets: inherit # zizmor: ignore[secrets-inherit] uses: rapidsai/shared-workflows/.github/workflows/custom-job.yaml@main # Run whenever the shards ran (pass or fail) so we always get a diff, but # not when pandas-tests was skipped. continue-on-error keeps this purely From 72e088c69ed39b409f2140b7cff9a691a7553812 Mon Sep 17 00:00:00 2001 From: galipremsagar Date: Wed, 26 Aug 2026 14:41:57 +0000 Subject: [PATCH 10/11] Add pandas-tests-shards to the pr-builder dependencies rapids-check-pr-job-dependencies requires every job in pr.yaml to appear in pr-builder's needs, and the new matrix-generating job was not listed, so other-checks failed with "'pr-builder' job is missing the following dependent jobs: pandas-tests-shards". --- .github/workflows/pr.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index d4dcdad3e4ee..7b9524e61ff9 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -45,6 +45,7 @@ jobs: - wheel-tests-dask-cudf - devcontainer - unit-tests-cudf-pandas + - pandas-tests-shards - pandas-tests - pandas-tests-summary - narwhals-tests From 691447c5c1c83aad792ea84558f35e5a7b0d3f6e Mon Sep 17 00:00:00 2001 From: galipremsagar Date: Wed, 26 Aug 2026 14:46:33 +0000 Subject: [PATCH 11/11] Address CodeRabbit review on the shard result handling Treat an empty nightly run list as absent. The jq expression returned the string "null" when no successful run was found, which passed the -z guard and sent the script off to download run "null", reporting a download failure instead of the real "no baseline yet". run.sh had the same expression, so both are fixed. Cover the merge contract with tests. merge-results.py produces the baseline every PR diffs against, so its aggregation is worth pinning down: the summing of counts for a module split across shards, the union of modules seen in only one shard, first-value handling for non-numeric fields, and that booleans are not summed despite bool being a subclass of int. The merge moves into a function behind a __main__ guard to make that testable; the CLI is unchanged. --- .../pandas-tests/merge-results.py | 38 ++++---- ci/cudf_pandas_scripts/pandas-tests/run.sh | 2 +- .../pandas-tests/summary.sh | 2 +- .../test_pandas_tests_merge_results.py | 94 +++++++++++++++++++ 4 files changed, 118 insertions(+), 18 deletions(-) create mode 100644 python/cudf/cudf_pandas_tests/test_pandas_tests_merge_results.py diff --git a/ci/cudf_pandas_scripts/pandas-tests/merge-results.py b/ci/cudf_pandas_scripts/pandas-tests/merge-results.py index b87eee65f92d..67d018bbb05e 100644 --- a/ci/cudf_pandas_scripts/pandas-tests/merge-results.py +++ b/ci/cudf_pandas_scripts/pandas-tests/merge-results.py @@ -19,19 +19,25 @@ import json import sys -merged: dict[str, dict] = {} -for path in sys.argv[1:]: - with open(path) as f: - results = json.load(f) - for module_name, row in results.items(): - combined = merged.setdefault(module_name, {}) - for key, value in row.items(): - if isinstance(value, bool): - # No boolean fields are expected; keep the first seen value. - combined.setdefault(key, value) - elif isinstance(value, (int, float)): - combined[key] = combined.get(key, 0) + value - else: - combined.setdefault(key, value) - -print(json.dumps(merged, indent=4)) + +def merge_results(paths): + """Sum the per-module summaries in ``paths`` into a single summary.""" + merged: dict[str, dict] = {} + for path in paths: + with open(path) as f: + results = json.load(f) + for module_name, row in results.items(): + combined = merged.setdefault(module_name, {}) + for key, value in row.items(): + if isinstance(value, bool): + # No boolean fields are expected; keep the first seen value. + combined.setdefault(key, value) + elif isinstance(value, (int, float)): + combined[key] = combined.get(key, 0) + value + else: + combined.setdefault(key, value) + return merged + + +if __name__ == "__main__": + print(json.dumps(merge_results(sys.argv[1:]), indent=4)) diff --git a/ci/cudf_pandas_scripts/pandas-tests/run.sh b/ci/cudf_pandas_scripts/pandas-tests/run.sh index 7412405e7a49..9e035d5073ad 100755 --- a/ci/cudf_pandas_scripts/pandas-tests/run.sh +++ b/ci/cudf_pandas_scripts/pandas-tests/run.sh @@ -86,7 +86,7 @@ MAIN_RUN_ID=$( --status success \ --limit 7 \ --json 'createdAt,databaseId' \ - --jq 'sort_by(.createdAt) | reverse | .[0] | .databaseId' + --jq 'sort_by(.createdAt) | reverse | .[0].databaseId // empty' ) if [[ -z "${MAIN_RUN_ID}" ]]; then diff --git a/ci/cudf_pandas_scripts/pandas-tests/summary.sh b/ci/cudf_pandas_scripts/pandas-tests/summary.sh index 241a62461dd1..23d7ed6c8ef2 100755 --- a/ci/cudf_pandas_scripts/pandas-tests/summary.sh +++ b/ci/cudf_pandas_scripts/pandas-tests/summary.sh @@ -54,7 +54,7 @@ MAIN_RUN_ID=$( --status success \ --limit 7 \ --json 'createdAt,databaseId' \ - --jq 'sort_by(.createdAt) | reverse | .[0] | .databaseId' || true + --jq 'sort_by(.createdAt) | reverse | .[0].databaseId // empty' || true ) if [[ -z "${MAIN_RUN_ID}" ]]; then diff --git a/python/cudf/cudf_pandas_tests/test_pandas_tests_merge_results.py b/python/cudf/cudf_pandas_tests/test_pandas_tests_merge_results.py new file mode 100644 index 000000000000..529cc2f5547b --- /dev/null +++ b/python/cudf/cudf_pandas_tests/test_pandas_tests_merge_results.py @@ -0,0 +1,94 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +"""Tests for the sharded pandas-tests result merge. + +The merged file is the baseline every PR diffs against, so a silent error here +shows up as phantom failures in unrelated PRs rather than as a broken job. +""" + +from __future__ import annotations + +import importlib.util +import json +import pathlib + +import pytest + +_SCRIPT = ( + pathlib.Path(__file__).parents[3] + / "ci" + / "cudf_pandas_scripts" + / "pandas-tests" + / "merge-results.py" +) + + +def _load(): + spec = importlib.util.spec_from_file_location("merge_results", _SCRIPT) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module.merge_results + + +@pytest.fixture(scope="module") +def merge_results(): + if not _SCRIPT.is_file(): + pytest.skip(f"{_SCRIPT} not found") + return _load() + + +def _write(tmp_path, name, payload): + path = tmp_path / name + path.write_text(json.dumps(payload)) + return str(path) + + +def test_sums_numeric_fields_for_a_shared_module(merge_results, tmp_path): + # Sharding is per test, not per module, so the same module appears in + # several shards and its counts have to add up. + a = _write( + tmp_path, "a.json", {"m.py": {"total": 10, "passed": 8, "failed": 2}} + ) + b = _write( + tmp_path, "b.json", {"m.py": {"total": 5, "passed": 5, "failed": 0}} + ) + assert merge_results([a, b]) == { + "m.py": {"total": 15, "passed": 13, "failed": 2} + } + + +def test_unions_modules_seen_in_only_one_shard(merge_results, tmp_path): + a = _write(tmp_path, "a.json", {"m.py": {"total": 1}}) + b = _write(tmp_path, "b.json", {"n.py": {"total": 2}}) + assert merge_results([a, b]) == { + "m.py": {"total": 1}, + "n.py": {"total": 2}, + } + + +def test_keeps_first_value_for_nonnumeric_fields(merge_results, tmp_path): + a = _write(tmp_path, "a.json", {"m.py": {"note": "first", "total": 1}}) + b = _write(tmp_path, "b.json", {"m.py": {"note": "second", "total": 1}}) + assert merge_results([a, b])["m.py"] == {"note": "first", "total": 2} + + +def test_does_not_sum_booleans(merge_results, tmp_path): + # bool is a subclass of int; summing it would turn two True into 2. + a = _write(tmp_path, "a.json", {"m.py": {"flag": True}}) + b = _write(tmp_path, "b.json", {"m.py": {"flag": True}}) + assert merge_results([a, b])["m.py"]["flag"] is True + + +def test_sums_floats(merge_results, tmp_path): + a = _write(tmp_path, "a.json", {"m.py": {"seconds": 1.5}}) + b = _write(tmp_path, "b.json", {"m.py": {"seconds": 2.25}}) + assert merge_results([a, b])["m.py"]["seconds"] == pytest.approx(3.75) + + +def test_no_inputs_yields_an_empty_summary(merge_results): + assert merge_results([]) == {} + + +def test_single_shard_is_passed_through_unchanged(merge_results, tmp_path): + payload = {"m.py": {"total": 3, "passed": 3, "name": "x"}} + assert merge_results([_write(tmp_path, "a.json", payload)]) == payload