The diversion sum keeps working when pandas removes the copy keyword - #62
Merged
Merged
Conversation
HughRunyan
added a commit
that referenced
this pull request
Sep 8, 2026
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
🟢 Approval recommended
The change is narrowly scoped, well-documented, and backed by targeted regression tests without introducing risky behavioral changes.
Pull request overview
This PR updates DivsDF.sum() to stop passing the deprecated/removed copy= keyword to pandas.DataFrame.infer_objects(), preventing future breakage under pandas 4 and eliminating related pandas deprecation warnings. It also adds regression tests to ensure the dtype behavior remains stable and that a pandas API change won’t get masked into a misleading error by existing callers.
Changes:
- Remove
copy=Falsefrom the fourreindex(...).infer_objects(...).fillna(0)chains inDivsDF.sum()and clarify the rationale for keepinginfer_objects(). - Add a new hermetic test module covering (a) no pandas-change warnings, (b) simulated removal of accepted
infer_objectsarguments, and (c) dtype stability (float/object cases). - Document the change in the September 2026 changelog and the changelog index.
File summaries
| File | Description |
|---|---|
SWEET_python/class_defs.py |
Drops the deprecated copy= argument from infer_objects() in DivsDF.sum() and updates the in-code comment to reflect the real purpose of infer_objects(). |
tests/test_divs_sum_dtypes.py |
Adds regression tests for warning-free behavior, simulated pandas-4-style API strictness, and dtype/value invariants of DivsDF.sum(). |
changelog/README.md |
Updates the “Entries” summary line for 2026-09 to include this change. |
changelog/2026-09.md |
Adds a detailed changelog entry describing the deprecation/removal avoidance and the no-output-change verification. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
10 tasks
The four reindex(...).infer_objects(...).fillna(0) chains in DivsDF.sum
passed copy=False. Since pandas 3.0 made Copy-on-Write unconditional the
keyword is ignored: infer_objects hands it to _check_copy_deprecation,
which warns and returns, and nothing else in the method reads it. So
dropping it is exactly the call that was already running.
Keeping it was not free. It emitted 96 Pandas4Warnings per test run, and
in pandas 4 it raises TypeError. The break is worse than a TypeError,
because every caller of DivsDF.sum wraps it in a bare `except:` whose
fallback -- sum(divs_df.values()) -- does not work on a pydantic model.
The real failure would surface as
AttributeError: 'DivsDF' object has no attribute 'values'
pointing nowhere near the cause. The new test simulates the removal and
pins both the sum and that caller.
infer_objects() itself stays. It does nothing for the reindex -- columns
that reindex adds arrive as float64 NaN whatever the source dtypes, which
is checked against float, int, 0-row and 0-column sources -- but it is
what stops an object-dtype input column from surviving fillna(0) and
dragging the summed frame to object.
No output change. Five city-DST scenarios, including the food-waste
prevention path that drives this code, produce a byte-identical dump of
73,760 numbers across 165 model outputs before and after (at a fixed
PYTHONHASHSEED; column order varies with the hash seed either way, which
is a separate pre-existing quirk and does not touch values).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
HughRunyan
force-pushed
the
divs-sum-without-deprecated-copy-keyword
branch
from
September 8, 2026 23:44
9c01bb6 to
89a5e21
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
DivsDF.sum— the helper that combines the compost / anaerobic / combustion /recycling streams into the diverted-mass frame every DST path subtracts from
generation — passed
copy=Falsetoinfer_objects()in four places. Sincepandas 3.0 made Copy-on-Write unconditional that keyword is ignored, and
pandas 4 removes it.
The keyword is already a no-op
Not assumed — read off
pandas/core/generic.pyat the pinned 3.0.5:_check_copy_deprecationonly emits the warning. The method already returned anew object either way, so
.infer_objects()is exactly the call that wasrunning.
Why it mattered
Passing it produced 96
Pandas4Warnings per test run (24 realsum()calls× 4 streams). More to the point, when pandas 4 removes it the call raises
TypeError— and the break is worse than aTypeError, because all threecallers wrap it in a bare
except:whose fallback does not work:Simulated by making
infer_objectsreject its arguments, the removal surfaces as:— an error pointing nowhere near the cause.
test_removal_of_the_keyword_is_not_maskedpins the sum and that caller against exactly this.
infer_objects()itself is kept — but not for the reason the code impliedThe old comment ("Reindex and fill missing values, then infer object types")
suggested the call was there to clean up after
reindex. It is not:reindexnever produces an object column. Added columns arrive asfloat64NaN regardless of the source dtypes — verified against
float64,int64,0-row and 0-column sources.
What the call actually does is stop an input frame that already carries its
numbers in an object column (a
Seriesbuilt fromNone, a value that arrivedboxed) from surviving
fillna(0)as object and dragging the summed frame withit. Every column in every frame the suite feeds it is
float64(960/960), so itis a no-op here — but it is cheap insurance on frames callers hand in, and this
repo has been bitten by pandas dtype behaviour before (2026-02
pd.NAcrash,2026-04 SDST oxidation hardening). Removing it would turn a provable no-op into
a latent dtype change, so it stays, with a comment that says what it is for.
No output change
Verified twice over, so this is not a
model-output-change:compost+recycling; +25% and +50% food-waste prevention, the path that drives
this code; all four streams) dumped at full float precision: net masses,
waste masses, per-stream
divs_dfframes,DivsDF.sum()output, and everylandfill's
waste_mass/ch4/captured/emissionsseries.73,760 numbers across 165 model outputs, byte-identical —
sha256 83e2019…before and after.Also instrumented all 24 real
sum()calls the suite makes and compared threevariants (
copy=False/ no keyword / noinfer_objectsat all): identicaldtypes and identical values on every one.
Scope check — other deprecated pandas usage
Grepped the package for the same category and tested each pattern under 3.0.5:
infer_objects(copy=False)class_defs.py×4fillna/rename/drop(inplace=True)city_params.py×4pd.to_numeric(errors="coerce")city_params.py×3errors="ignore"was the removed one; unused)downcast=,astype(..., errors=)a[x][y] = …hits are plain nested dictsDataFrame.append,applymap,fillna(method=),iteritems, ….appendhits are all list appends)Suite now runs clean under
-W error::DeprecationWarning -W error::FutureWarning.Acceptance Criteria
copy=keyword passed toinfer_objectsanywhere in the package.whole suite passes with pandas deprecations promoted to errors.
.infer_objects()is retained, and the comment explains what it actuallyguards (object-dtype input, not the reindex).
asserted — hence no
model-output-changelabel.after; the dtype tests pass on both, which is the point.
changelog/2026-09.mdper CLAUDE.md.Definition of Done
Python 3.12 + the pinned
requirements.txt(pandas 3.0.5), matching CIchangelog/README.mdhighlights; in-code comment corrected
Notes for the reviewer
.github/workflows/tests.ymlis not on
mainyet. The results above are from a local run reproducing thatjob exactly: Python 3.12,
pip install -r requirements.txt,pip install -e ..here: model output frames' column order varies with
PYTHONHASHSEED(asetfeeding the waste-type ordering). Values and column sets are identical;only ordering moves. Worth its own change if anything downstream indexes
positionally or diffs serialized output.
🤖 Generated with Claude Code