Skip to content

Fix cudf.pandas series accessor failures across numpy/nullable/arrow dtypes - #23056

Merged
rapids-bot[bot] merged 7 commits into
NVIDIA:mainfrom
galipremsagar:accessor_fixes
Jul 14, 2026
Merged

Fix cudf.pandas series accessor failures across numpy/nullable/arrow dtypes#23056
rapids-bot[bot] merged 7 commits into
NVIDIA:mainfrom
galipremsagar:accessor_fixes

Conversation

@galipremsagar

Copy link
Copy Markdown
Contributor

Description

Fixes a batch of cudf.pandas failures in tests/series/accessors (and the corresponding cudf-classic behavior) so the datetime/timedelta/categorical/string/list/struct accessors match pandas. Each fix is validated across the numpy, pandas-nullable, and pyarrow (ArrowDtype) dtype families.

Datetime / timedelta component dtypes

  • Series.dt.dayofweek / day_of_week / weekday now return int32 for numpy-backed datetimes (previously int64) and int64[pyarrow] for ArrowDtype timestamps, matching pandas.
  • Series.dt.seconds / microseconds / nanoseconds now return int32 (previously int64); days stays int64, matching pandas.
  • Series.dt.isocalendar() now returns UInt32 columns for numpy datetimes (previously numpy uint32); the ArrowDtype path stays int64[pyarrow].

DatetimeIndex.microsecond millisecond fold

libcudf's MICROSECOND component excludes the whole-millisecond part, but pandas folds milliseconds into microsecond (e.g. 0.001002s -> 1002, not 2). DatetimeIndex.microsecond now adds millisecond * 1000 to match pandas and Series.dt.microsecond.

Timezone-aware rounding

DatetimeTZColumn rounding (ceil/floor/round) now operates on the local wall-clock time and re-localizes to the original timezone, matching pandas semantics (test_dt_round_tz).

.dt accessor is not writeable

BaseDatelikeProperties now mimics pandas' NoNewAttributesMixin: once constructed, setting a new attribute on the .dt accessor raises AttributeError (test_dt_accessor_no_new_attributes).

cat.codes signed dtype

Series.cat.codes now uses a signed integer dtype (int8/int16/...) matching pandas, rather than an unsigned one.

Accessor error messages

The .str, .list, and .struct accessor error messages now match pandas' wording. .str mirrors pandas' inferred-type naming (integer/floating/boolean/datetime64/timedelta64).

Tests

  • Removed the now-passing entries from the cudf.pandas xfail list (pandas-testing-plugin.py).
  • Added/strengthened cudf-classic tests covering each change, parametrized over the numpy / pandas-nullable / arrow dtype families (test_dt.py, test_cat.py, test_str.py, test_list.py, test_struct.py, datetimeindex/test_attributes.py).

Checklist

  • I am familiar with the Contributing Guidelines.
  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

@galipremsagar
galipremsagar requested a review from a team as a code owner July 1, 2026 00:24
@galipremsagar
galipremsagar requested review from mroeschke and wence- July 1, 2026 00:24
@github-actions github-actions Bot added Python Affects Python cuDF API. cudf.pandas Issues specific to cudf.pandas labels Jul 1, 2026
@galipremsagar galipremsagar added bug Something isn't working non-breaking Non-breaking change labels Jul 1, 2026
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

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

Use the following commands to manage reviews:

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

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR updates cuDF categorical, datetime, timedelta, and accessor validation behavior to better match pandas dtype semantics and error messages. It also updates related tests and pandas-testing-plugin failure mappings.

Changes

Accessor and datetime parity

Layer / File(s) Summary
Accessor invalid-dtype messages
python/cudf/cudf/core/accessors/lists.py, python/cudf/cudf/core/accessors/string.py, python/cudf/cudf/core/accessors/struct.py, python/cudf/cudf/tests/series/accessors/test_list.py, python/cudf/cudf/tests/series/accessors/test_str.py, python/cudf/cudf/tests/series/accessors/test_struct.py
ListMethods, StringMethods, and StructMethods raise more specific AttributeError messages, and tests assert the updated wording.
Categorical signed codes
python/cudf/cudf/core/accessors/categorical.py, python/cudf/cudf/core/column/categorical.py, python/cudf/cudf/core/dtypes.py, python/cudf/cudf/tests/series/accessors/test_cat.py, python/cudf/cudf/tests/series/methods/test_astype.py
CategoricalDtype exposes pandas code dtypes, and categorical codes are cast through that dtype in both accessor and pandas conversion paths; tests update the expected code dtypes.
Datetime component dtype fixes
python/cudf/cudf/core/column/datetime.py, python/cudf/cudf/core/index.py, python/cudf/cudf/tests/indexes/datetimeindex/test_attributes.py
isocalendar, timezone-aware rounding, and DatetimeIndex.microsecond are adjusted for pandas-compatible component behavior, with a new microsecond test.
Series datelike and timedelta casts
python/cudf/cudf/core/mixins/__init__.py, python/cudf/cudf/core/mixins/no_new_attributes.py, python/cudf/cudf/core/series.py, python/cudf/cudf/tests/series/accessors/test_dt.py
BaseDatelikeProperties becomes immutable after initialization, and datetime/timedelta component accessors cast to pandas-matching dtypes; tests cover the updated dtype parity.
pandas-testing-plugin mappings
python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py
Node-id failure mappings are removed and rewritten for categorical and datetime accessor tests.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

  • rapidsai/cudf#22518: Both PRs change the same pandas-parity dtype paths, including DatetimeColumn.isocalendar and datetime component casting.
  • rapidsai/cudf#22904: Both PRs update python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py by adjusting stale datetime and categorical accessor mappings.

Suggested labels: improvement

Suggested reviewers: Matt711, vyasr, mroeschke

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: fixing cudf.pandas series accessor failures across dtype families.
Description check ✅ Passed The description matches the changeset and accurately summarizes the accessor and dtype parity fixes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
python/cudf/cudf/core/series.py (1)

5176-5242: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Stale docstring examples now show the wrong dtype (int64) after the seconds/microseconds/nanoseconds casts to int32.

The class docstring (lines ~5193, 5227, 5234, 5241) and the individual seconds/microseconds/nanoseconds property docstrings (lines ~5311, 5318, 5353, 5388) still show dtype: int64 for these attributes, but the new .astype(get_dtype_of_same_kind(self.series.dtype, np.dtype("int32"))) casts make the actual output int32. If these docstrings are exercised via doctest in CI, they will now fail; at minimum they are misleading documentation.

📝 Proposed fix for stale doctest output
     >>> seconds_series.dt.seconds
     0    1
     1    2
     2    3
-    dtype: int64
+    dtype: int32
     >>> series = cudf.Series([12231312123, 1231231231, 1123236768712, 2135656,
     ...     3244334234], dtype='timedelta64[ms]')
     ...
     >>> series.dt.seconds
     0    48912
     1    21631
     2    36768
     3     2135
     4    47534
-    dtype: int64
+    dtype: int32
     >>> series.dt.microseconds
     0    123000
     1    231000
     2    712000
     3    656000
     4    234000
-    dtype: int64
+    dtype: int32
     >>> s.dt.nanoseconds
     0    0
     1    0
     2    0
     3    0
     4    0
-    dtype: int64
+    dtype: int32

And in the seconds, microseconds, and nanoseconds property docstrings respectively:

     >>> s.dt.seconds
     0    48912
     1    21631
     2    36768
     3     2135
     4    47534
-    dtype: int64
+    dtype: int32
     >>> s.dt.microseconds
     0    123000
     1    231000
     2    712000
     3    656000
     4    234000
-    dtype: int64
+    dtype: int32
     >>> s.dt.microseconds
     0    123000
     1    231000
     2    712000
     3    656000
     4    234000
-    dtype: int64
+    dtype: int32
     >>> s.dt.nanoseconds
     0    123
     1    231
     2    712
     3    656
     4    234
-    dtype: int64
+    dtype: int32

Also applies to: 5283-5323, 5325-5358, 5360-5393

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@python/cudf/cudf/core/series.py` around lines 5176 - 5242, The
TimedeltaProperties docs are stale after the dtype cast change: the class
docstring and the `seconds`, `microseconds`, and `nanoseconds` property
docstrings still show `dtype: int64`, but the actual outputs from these
accessors now use `int32`. Update the doctest examples in `TimedeltaProperties`
and the individual property docstrings to match the new `int32` result so the
documented output stays accurate and doctests continue to pass.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@python/cudf/cudf/core/accessors/categorical.py`:
- Around line 93-101: The categorical codes dtype logic in the accessor should
match pandas at the boundary where the category count reaches 127. Update the
`CategoricalAccessor.codes` path so the cast uses
`min_signed_type(len(self._column.dtype.categories) + 1)` instead of the raw
category count, keeping `Series._from_column` aligned with pandas’ widening
behavior. Add or adjust a regression test around `cat.codes` for a 127-category
`Categorical` to verify the dtype is widened correctly.

---

Outside diff comments:
In `@python/cudf/cudf/core/series.py`:
- Around line 5176-5242: The TimedeltaProperties docs are stale after the dtype
cast change: the class docstring and the `seconds`, `microseconds`, and
`nanoseconds` property docstrings still show `dtype: int64`, but the actual
outputs from these accessors now use `int32`. Update the doctest examples in
`TimedeltaProperties` and the individual property docstrings to match the new
`int32` result so the documented output stays accurate and doctests continue to
pass.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 5589c791-1966-4018-99db-7f58f15136c1

📥 Commits

Reviewing files that changed from the base of the PR and between bd7bb74 and 9a978b4.

📒 Files selected for processing (14)
  • python/cudf/cudf/core/accessors/categorical.py
  • python/cudf/cudf/core/accessors/lists.py
  • python/cudf/cudf/core/accessors/string.py
  • python/cudf/cudf/core/accessors/struct.py
  • python/cudf/cudf/core/column/datetime.py
  • python/cudf/cudf/core/index.py
  • python/cudf/cudf/core/series.py
  • python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py
  • python/cudf/cudf/tests/indexes/datetimeindex/test_attributes.py
  • python/cudf/cudf/tests/series/accessors/test_cat.py
  • python/cudf/cudf/tests/series/accessors/test_dt.py
  • python/cudf/cudf/tests/series/accessors/test_list.py
  • python/cudf/cudf/tests/series/accessors/test_str.py
  • python/cudf/cudf/tests/series/accessors/test_struct.py
💤 Files with no reviewable changes (1)
  • python/cudf/cudf/pandas/scripts/pandas-testing-plugin.py

Comment thread python/cudf/cudf/core/accessors/categorical.py Outdated
@galipremsagar

Copy link
Copy Markdown
Contributor Author

/okay to test 0684181

@GPUtester GPUtester moved this to In Progress in cuDF Python Jul 1, 2026
@galipremsagar

Copy link
Copy Markdown
Contributor Author

/okay to test 136ad66

@galipremsagar

Copy link
Copy Markdown
Contributor Author

/okay to test 5ae8aa1

Comment thread python/cudf/cudf/core/accessors/categorical.py Outdated
Comment thread python/cudf/cudf/tests/series/accessors/test_dt.py Outdated
Comment thread python/cudf/cudf/core/series.py Outdated
@galipremsagar

Copy link
Copy Markdown
Contributor Author

/okay to test d388f10

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
python/cudf/cudf/core/series.py (1)

5271-5379: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Update the timedelta accessor doctests

seconds, microseconds, and nanoseconds still show dtype: int64, but these accessors now return int32 and should match pandas. Please update the doctest outputs in all three examples.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@python/cudf/cudf/core/series.py` around lines 5271 - 5379, The timedelta
accessor doctests in the Series.dt properties `seconds`, `microseconds`, and
`nanoseconds` still expect `int64` output even though these accessors now return
`int32`. Update the example outputs in each of these docstrings in
`cudf/core/series.py` so the doctests match the actual returned dtype and stay
aligned with pandas behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@python/cudf/cudf/core/series.py`:
- Around line 5271-5379: The timedelta accessor doctests in the Series.dt
properties `seconds`, `microseconds`, and `nanoseconds` still expect `int64`
output even though these accessors now return `int32`. Update the example
outputs in each of these docstrings in `cudf/core/series.py` so the doctests
match the actual returned dtype and stay aligned with pandas behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 74037659-cd2a-4e75-9cee-52ebbeafe392

📥 Commits

Reviewing files that changed from the base of the PR and between 5ae8aa1 and 7a07cb2.

📒 Files selected for processing (7)
  • python/cudf/cudf/core/accessors/categorical.py
  • python/cudf/cudf/core/column/categorical.py
  • python/cudf/cudf/core/dtypes.py
  • python/cudf/cudf/core/mixins/__init__.py
  • python/cudf/cudf/core/mixins/no_new_attributes.py
  • python/cudf/cudf/core/series.py
  • python/cudf/cudf/tests/series/accessors/test_dt.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • python/cudf/cudf/tests/series/accessors/test_dt.py

@galipremsagar

Copy link
Copy Markdown
Contributor Author

/merge

@rapids-bot
rapids-bot Bot merged commit e9cb870 into NVIDIA:main Jul 14, 2026
126 checks passed
@github-project-automation github-project-automation Bot moved this from In Progress to Done in cuDF Python Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working cudf.pandas Issues specific to cudf.pandas non-breaking Non-breaking change Python Affects Python cuDF API.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants