Skip to content

REF: continue moving freq management off DatetimeArray/TimedeltaArray (GH#24566)#65285

Merged
mroeschke merged 5 commits intopandas-dev:mainfrom
jbrockmendel:ref-array-no-freq-12
Apr 20, 2026
Merged

REF: continue moving freq management off DatetimeArray/TimedeltaArray (GH#24566)#65285
mroeschke merged 5 commits intopandas-dev:mainfrom
jbrockmendel:ref-array-no-freq-12

Conversation

@jbrockmendel
Copy link
Copy Markdown
Member

Summary

Four small steps continuing GH#24566 (push freq handling from DTA/TDA to the Index level):

  1. Remove freq param from DTA/TDA._simple_new_simple_new is now a pure values+dtype constructor; the four call sites that need to set freq do so explicitly via result._freq = freq after construction.
  2. DTA/TDA __setitem__ no longer clears freq_maybe_clear_freq and the __setitem__ call site are removed. _freq on the array is dumb storage that the Index manages, and is allowed to go stale after a mutation. DatetimeIndex.snap now clears _freq on its result DTA explicitly.
  3. Remove freq setter from TimelikeOps; move validation to the IndexDatetimeIndexOpsMixin.freq.setter now does the to_offset coercion, _validate_frequency, Tick/Day check, and ndim check before assigning arr._freq. PeriodArray (no _validate_frequency) raises a clear AttributeError when callers try to set freq through the Index.
  4. Drop the array-level freq sync from __iadd__/__isub__ — they're now just self[:] = result[:]. Array's _freq stays as it was; the Index path naturally produces freq-correct results via __add__/__sub__. A few arithmetic tests had to align the expected freq for the pd.array boxed case, since the rebound dta + x returns a freq-stripped array while in-place dta += x preserves the array's pre-iadd freq.

Test plan

  • pandas/tests/arrays/, pandas/tests/indexes/datetimes|timedeltas|period/, pandas/tests/arithmetic/ all green
  • pandas/tests/series/, pandas/tests/frame/, pandas/tests/indexing/, pandas/tests/base/, pandas/tests/resample/, pandas/tests/reshape/, pandas/tests/tslibs/, pandas/tests/tseries/ all green

_simple_new no longer accepts freq; callers that need to set freq
do so explicitly via result._freq = freq. This makes _simple_new
a pure values+dtype constructor.
Remove _maybe_clear_freq and the __setitem__ call site that invoked it.
Freq management is now fully the Index's responsibility; setitem on a
standalone array no longer mutates self._freq.

__iadd__/__isub__ sync _freq from the arithmetic result (which at the
array level is freq-agnostic), and DatetimeIndex.snap clears _freq on
the result DTA to preserve its documented behavior.
The freq.setter on TimelikeOps is removed; freq mutation flows through
DatetimeIndex/TimedeltaIndex.freq, which now performs the to_offset
coercion and _validate_frequency check itself before assigning to
arr._freq. The array's freq property is now read-only.

PeriodArray (no _validate_frequency) raises a clear AttributeError if a
caller tries to set freq through the Index, matching prior behaviour.

__iadd__/__isub__ guard the _freq sync on dtype.kind to avoid touching
PeriodArray, which derives freq from dtype rather than storing it.
…566)

In-place arithmetic on a DTA/TDA used to sync `_freq` from the
arithmetic result. That belonged to the array's freq-management era;
under the current design `_freq` is Index-managed dumb storage on the
array. Mutating values via __iadd__/__isub__ leaves _freq alone (it can
go stale), matching __setitem__'s behaviour after pandas-dev#65276's cleanup.

Tests that compared `dta += x` vs `dta + x` for the pd.array boxed case
now sync the expected freq from the iadd-result before comparison,
since the rebound `dta + x` returns a freq-stripped array while the
in-place version preserves the array's pre-iadd freq.
@jbrockmendel jbrockmendel added the Refactor Internal refactoring of code label Apr 19, 2026
- Replace the writable `freq: BaseOffset | None` class annotation on
  DatetimeLikeArrayMixin with an abstract read-only property so the
  TimelikeOps and PeriodArray overrides (both read-only) type-check.
- Declare `_freq: BaseOffset | None` on TimelikeOps so reads of
  `self._freq` in `freq.getter` and `copy` resolve.
- Use isinstance narrowing in DatetimeIndexOpsMixin.freq.setter so
  `arr._freq = value` type-checks (PeriodArray is excluded by the
  AttributeError branch).
- Drop the now-unused `# type: ignore[override]` on PeriodArray.freq.
@mroeschke mroeschke added this to the 3.1 milestone Apr 20, 2026
@mroeschke mroeschke merged commit c163176 into pandas-dev:main Apr 20, 2026
45 checks passed
@mroeschke
Copy link
Copy Markdown
Member

Thanks @jbrockmendel

@jbrockmendel jbrockmendel deleted the ref-array-no-freq-12 branch April 20, 2026 15:54
Sharl0tteIsTaken added a commit to Sharl0tteIsTaken/pandas that referenced this pull request Apr 22, 2026
…h-origin

* upstream/main: (31 commits)
  DOC:Missing r in your (pandas-dev#65323)
  DOC: fix grammar in the .dt accessor section (pandas-dev#65325)
  REGR: restore rank() for ExtensionArrays with custom values for sorting (pandas-dev#64976)
  BUG: MultiIndex.get_loc returns scalar for unique key in non-unique index (pandas-dev#65234)
  BUG/TST: add test for _cast_pointwise_result robustness + fix some cases (pandas-dev#65318)
  BUG: fix .loc with tuple key on MultiIndex with IntervalIndex level (pandas-dev#65239)
  BUG: permit building from source with mingw (pandas-dev#64849)
  BUG: DataFrame.loc setitem with list-like value on single-column EA DataFrame (pandas-dev#65241)
  PERF: preserve block memory layout in Block.copy (GH#60469) (pandas-dev#65302)
  PERF: short-circuit sort_index(level=...) on monotonic non-MultiIndex (pandas-dev#65279)
  BUG: fix FloatingArray.astype(str) crash with distinguish_nan_and_na=True (pandas-dev#65038)
  BUG: fix to_timedelta ignoring unit for mixed round/non-round floats (pandas-dev#65170)
  BUG: DataFrame.loc preserves original index name when key is an Index (pandas-dev#65229)
  REF: continue moving freq management off DatetimeArray/TimedeltaArray (GH#24566) (pandas-dev#65285)
  REF: remove redundant BaseMaskedArray.map override (pandas-dev#65297)
  Bump github/codeql-action from 4.35.1 to 4.35.2 (pandas-dev#65310)
  Bump actions/setup-node from 6.3.0 to 6.4.0 (pandas-dev#65309)
  BUG: Fix formatters applied to wrong columns in truncated DataFrame.to_string (GH#35410) (pandas-dev#65288)
  PERF: optimize block consolidation (pandas-dev#64574)
  CLN: Replace no_default signature with False for allow_duplicates in insert and reset_index (pandas-dev#65146)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Refactor Internal refactoring of code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants