Skip to content

fix: make _data code and unit tests pandas-3 compatible#711

Merged
mplatzer merged 3 commits into
chore/update-engine-2.5.0-qa-1.10.4-githubfrom
cursor/fix-data-unit-pandas3-dfc3
Apr 24, 2026
Merged

fix: make _data code and unit tests pandas-3 compatible#711
mplatzer merged 3 commits into
chore/update-engine-2.5.0-qa-1.10.4-githubfrom
cursor/fix-data-unit-pandas3-dfc3

Conversation

@mplatzer

Copy link
Copy Markdown
Contributor

Pull Request

Changes

Fixes the remaining 10 failed / 2 errored unit tests in tests/_data/unit on chore/update-engine-2.5.0-qa-1.10.4-github, all caused by pandas 3.0 / numpy 2 / pyarrow 24 behavior changes that CI now picks up on this branch. Three small commits:

  1. mostlyai/sdk/_data/dtype.py — restore errors="ignore" semantics for VirtualInteger.cast / VirtualFloat.cast (pandas 3 removed that value from pd.to_numeric); normalize time_coerce's null output from pd.NaT to pd.NA for consistent equality.
  2. mostlyai/sdk/_data/file/table/json.pySeries.str[:-7]Series.str.slice(stop=-7) (pandas 3 removed __getitem__ on the string accessor for pyarrow extension arrays).
  3. tests/_data/unit/test_finalize_generation.py, tests/_data/unit/test_push.pynp.array_split(df, n) now returns ndarrays under numpy 2 / pandas 3; split via positional indices so each part stays a DataFrame. And compare the all-null column via .isna() instead of equality against [None] * 9.

Why this change?

On PR #708 (engine 2.5.0 / qa 1.10.4 from GitHub) the CPU CI job was red. The E2E hang was already fixed in #709; the remaining failures are all unit tests in tests/_data/unit that regressed because pandas 3.0 / numpy 2.4 / pyarrow 24 changed behavior:

  • pd.to_numeric(..., errors="ignore") now raises ValueError: invalid error value specified. Our .cast() methods used that to return input unchanged on non-numeric data; after the bump every .cast() raised, the outer try/except in encompasses() swallowed it, and VirtualInteger/Float.encompasses() silently returned False for valid int/float series (cascading into VirtualInteger().encompass(int) == VirtualVarchar() in test_encompass_integer).
  • Under object dtype, pandas 3's assert_series_equal now distinguishes pd.NaT and pd.NA; time_coerce was returning NaT while tests asserted <NA>.
  • np.array_split(df, n) now returns a list of ndarrays instead of DataFrames for a DataFrame input, breaking df_part.to_parquet(...) in two fixtures.
  • Series.str[key] (StringMethods.__getitem__) no longer works on pyarrow-backed extension arrays; Series.str.slice(...) still does.
  • assert_frame_equal with check_dtype=False still rejects NaN vs None for all-null columns.

The first two are real runtime bugs in mostlyai/sdk/_data/ (they would hit users writing JSON or using auto-typing on pandas 3), not just test fragility.

Testing

With the CI-matched env (pandas==3.0.2, numpy==2.4.3, pyarrow==24.0.0, engine 2.5.0 + qa 1.10.4 from git):

Each commit is scoped to one logical change so they can be cherry-picked or reverted independently.

Additional Notes

Targets the PR #708 branch, not main. After #708 merges this can be folded in on top.

Open in Web Open in Cursor 

cursoragent and others added 3 commits April 24, 2026 07:09
…t.cast under pandas 3

pandas 3.0 removed the 'ignore' value from pd.to_numeric's errors kwarg,
so any call with errors='ignore' now raises ValueError. Our
VirtualInteger.cast / VirtualFloat.cast passed errors='ignore' (so that
non-numeric input could be returned unchanged and encompasses() could
fall back). After the bump, every cast() raised, the outer try/except
in encompasses() swallowed it, and encompasses() silently returned
False for valid integer/float series — turning VirtualInteger/Float
encompassment into VirtualVarchar.

Replace with pd.to_numeric(errors='raise') wrapped in a try/except that
falls back to the original series on ValueError/TypeError, matching the
previous contract on both pandas 2.2 and 3.0.

Also normalize time_coerce's null output to pd.NA (instead of pd.NaT)
so pd.testing.assert_series_equal on object-dtype series behaves
consistently across pandas versions.

Co-authored-by: Michi Platzer <michael.platzer@gmail.com>
…backed strings

pandas 3.0 removed StringMethods.__getitem__ for pyarrow-backed
extension arrays, so the old df[c].str[:-7] trim (used to strip the
trailing '.XXXXXX' microseconds that pyarrow-backed timestamp strftime
still emits regardless of format string) raises AttributeError.

Replace with .str.slice(stop=-7), which is supported on both numpy- and
pyarrow-backed string arrays on pandas 2.x and 3.0.

Co-authored-by: Michi Platzer <michael.platzer@gmail.com>
… compatible

- np.array_split(df, n) returns ndarrays on numpy 2 / pandas 3 instead
  of DataFrames, which breaks df_part.to_parquet(...). Split via
  positional indices so each part stays a DataFrame.
- test_export_data_to_excel compared a read_excel output (float NaN)
  against an expected column of [None]*9 (object dtype). Pandas 3's
  assert_frame_equal is strict about the NaN vs None distinction; assert
  the column is fully NA via .isna() instead.

Co-authored-by: Michi Platzer <michael.platzer@gmail.com>
@mplatzer mplatzer marked this pull request as ready for review April 24, 2026 07:14
@mplatzer mplatzer merged commit 5b7d18f into chore/update-engine-2.5.0-qa-1.10.4-github Apr 24, 2026
9 checks passed
@mplatzer mplatzer deleted the cursor/fix-data-unit-pandas3-dfc3 branch April 24, 2026 07:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants