perf(deps): drop pandas from the default install - #1391
davidberenstein1957 wants to merge 1 commit into
Conversation
103ea17 to
74b9bff
Compare
0cc3959 to
e5ede33
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## scaling/03-dependency-extras #1391 +/- ##
=============================================================
Coverage 91.43% 91.44%
=============================================================
Files 49 49
Lines 5057 5097 +40
=============================================================
+ Hits 4624 4661 +37
- Misses 433 436 +3 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
74b9bff to
ae1d50d
Compare
pandas was used shallowly — reading three bundled reference CSVs, a handful of row filters, and the emissions.csv writer — and pulled numpy in behind it. It is now an extra: `csv` covers the reads and writes, `codecarbon[carbonboard]` / `[viz-legacy]` still get pandas + numpy, a new `all` extra pulls everything, and pandas moves to the dev group because ten test modules read output CSVs with it. Split out of #1343 (scaling/03-dependency-extras), which keeps only the numpy removal, because reimplementing read_csv/dropna semantics by hand across these files is the higher-risk half and deserves its own review. DataSource.get_cloud_emissions_data() and get_cpu_power_data() now always return list[dict] and warn DeprecationWarning; the supported names are get_cloud_emissions_rows() and get_cpu_power_rows(). An earlier revision returned a DataFrame when pandas happened to be importable and rows otherwise, which made the return type of a public method depend on the environment. Behaviour fixes carried along: Emissions.get_cloud_geo_region returned pandas' NaN for the 30 of 40 cloud regions with a city but no state (`if state is not None` is true for NaN) and now returns the city; the CSV writer renders non-finite floats as empty cells instead of the literal "nan"/"inf" that to_csv wrote. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
e5ede33 to
47abab9
Compare
Verdict: 🔧 Request changes (blocker + public API)Replacing pandas with the stdlib
Blocker:
Public API, per maintainer direction (@benoit-cty): breaking the public API is not acceptable. It needs a new name (or a new version of the endpoint).
Housekeeping: Nit:
|
Part of #1338. Split out of #1343.
pandas was used shallowly — reading three bundled reference CSVs, a handful of row filters, and the
emissions.csvwriter — and pulled numpy in behind it. It is now an extra, replaced by the stdlibcsvmodule. Nothing a user writes changes.This was split off #1343 deliberately: it reimplements
read_csv/dropnasemantics by hand across 14 files, which is the entire regression risk of the dependency work, and it should be reviewed on its own rather than bundled with a three-line numpy swap.Measured on a clean 3.12 venv (
uv venv && uv pip install .), whole stackimport codecarbonImport time is the median of 7
python -X importtimeruns.A default CSV tracker on
masterpulled pandas, numpy, prometheus_client and pycountry.prometheus_clientwas imported before theif OutputMethod.PROMETHEUScheck; that import is now inside the branch.The real risk surface
The original proposal's inventory listed six shallow call sites and "no vectorised arithmetic", and missed
output_methods/file.pyentirely — the writer for the user'semissions.csv, which did dtype-preserving in-place row updates byrun_idand all-NA column dropping. That, not the reference-data parsing, is what to review. It is now oncsv.DictWriter.DataSource.get_cloud_emissions_data()andDataSource.get_cpu_power_data()now always returnlist[dict]and emit aDeprecationWarning. The supported names areget_cloud_emissions_rows()andget_cpu_power_rows().An earlier revision returned a
DataFramewhen pandas happened to be importable and rows otherwise. That makes the return type of a public method depend on the environment, which is worse than a clean break: downstream code would work on the author's machine and fail on a bare install, at the.iloc/.query()call rather than at the import. It is a straight break now, warned and named.Nothing in-tree breaks (three test modules and
codecarbon/viz/updated —vizbuilds its own frame), but these are importable, undecorated, documented-by-name methods. This repo has noCHANGELOG— release notes come from.github/release-drafter.yml— so please label this PRbreaking.Behaviour changes, both fixes
Emissions.get_cloud_geo_regionreturned pandas'NaNfor 30 of 40 cloud regions that have acitybut nostate, becauseif state is not Noneis true forNaN. It now returns the city, as the code plainly intended.fmean/fsum) instead of matching numpy's pairwise order — differences at 1e-16. Two tests were hardcoding pandas'/numpy's summation order in the last ulp and are now tolerance-based. A side-by-side run of the old and new paths overmock_intel_power_gadget_data.csvagrees on all 22 columns to within 4.4e-16.Risks
CSV float formatting now comes from
str(float)rather than pandas'to_csv. These agree on repr-shortest for normal values but not on NaN:str(float("nan"))is the literal"nan"whereto_csvwrote an empty cell._as_csv_rowrenders any non-finite float as"", covered bytests/output_methods/test_file.py::test_non_finite_values_are_written_as_empty_cells(verified to fail when the guard is removed).Blanking infinities is a deliberate divergence from pandas:
to_csvwrote the literalinf, this writes an empty cell. An infinite energy figure is not a measurement, and writinginfpropagates a garbage number into everything that reads the file, where an empty cell reads back as missing.appendmode previously calleddropna(axis=1, how="all")on the single new row, writing a short, column-misaligned row whenever a field wasNone; this writes an empty cell instead — correct, but not byte-identical to that old broken output. Three malformedTDPvalues incpu_power.csv(27.29.5,33.34.8,29.32.9) still raise onfloat()exactly as before; left alone, with a comment on why the column stays text.extrasaction="ignore"on theDictWriteris defensive only and carries a comment saying so.Compatibility
pip install codecarboninstalls less and behaves the same;codecarbon[carbonboard]and[viz-legacy]still get pandas and numpy; a newallextra pulls everything;pandasmoved to thedevgroup, since ten test modules read output CSVs with it.The CLI/auth extras split from the original proposal is not here. It is worth 23 MB and 8 packages with zero runtime benefit — those imports are already off the hot path — and it breaks
pip install codecarbon && codecarbon monitor, a documented headline feature.pycountry(21 MB) also stays: it sits on the live geolocation path, and a lazy import with an empty fallback would be a silentcountry_iso_code/country_nameregression.Tests
uv run pytest tests/ -q --ignore=tests/test_viz_data.py→ 633 passed, 21 skipped.test_viz_data.pyfails to collect onmasteridentically —dashnot installed.New guard in
tests/test_package_integrity.py: runs a full offline tracker in a subprocess and assertspandas,numpyandprometheus_clientare absent fromsys.modules. End-to-end in a bare venv, twoupdate-mode runs produce the same 38-column, 2-rowemissions.csvasmaster.Not included: the CI bare-install job (that is #1342) and the docs/README install-instruction sweep.
🤖 Generated with Claude Code