diff --git a/CHANGELOG.md b/CHANGELOG.md index f646299..8ce458d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,28 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) ## [Unreleased] +## [0.8.0] - 2026-09-24 + +The first release with a Raiser's Edge on-ramp and `as_of` scoring cutoffs on the +gift and encounter roll-ups. Everything under Breaking shipped in 0.7.0 and 0.7.1 +emitting a `DeprecationWarning` naming this version. + +### Breaking +- `FiscalYearGroupedSplitter(drop_repeat_donors=...)` now + defaults to `True`, as the `DeprecationWarning` in 0.7.0 and 0.7.1 said it + would. Each test fold drops donors already seen in its training rows, which + is the safe default for a static per-donor label. It needs `groups` as + `(n_samples, 2)` (fiscal year, donor id); code that passes fiscal years alone + now raises a `ValueError` that names both fixes. Pass + `drop_repeat_donors=False` for a time-varying target to keep the 0.7.x + behaviour. The two leakage experiment scripts now pass it explicitly. +- Removed `philanthropy.utils.make_donor_dataset`, deprecated since + 0.7.0. Import it from `philanthropy.datasets`. +- Removed `WealthScreeningImputerKNN(group_col_idx=...)` and its + `group_imputers_` attribute, deprecated since 0.7.0. Per-group and global KNN + fits were measured bit-identical, so the parameter bought nothing; passing it + is now a `TypeError`. `tests/test_knn_group_stratification.py` goes with it. + ### Added - `examples/notebooks/04_kdd98_end_to_end.ipynb` and the tutorial page "End to End on Real Donor Data": the whole library path on the 95,412 real @@ -72,15 +94,39 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) `Returns`, and `Raises` sections that now properly render in the mkdocstrings-generated API reference. +- Added regression coverage for `PlannedGivingSignalTransformer` when transforming a NumPy array after fitting on a DataFrame. + +- `tests/test_public_api_contract.py` gains two contracts over every public + transformer, covering the two `get_feature_names_out` call shapes the suite + never exercised. It previously only ever called `get_feature_names_out()` with + no argument on a DataFrame-fitted transformer. + `test_feature_names_out_accepts_input_features` passes the real column names + through, which is the call `ColumnTransformer` and `Pipeline.get_feature_names_out` + actually make, and `test_feature_names_out_width_after_array_fit` fits on an + unnamed array. The second one is what caught the `CRMCleaner` defect above. + Transformers that genuinely cannot fit on an unnamed array are listed in a new + `_EXEMPT_ARRAY_FIT` table with a written reason each: `EncounterTransformer` + merges on a named `donor_id`, and `MatchingGiftFeaturizer` rejects a + non-DataFrame outright. That table is kept separate from `_EXEMPT` on purpose, + because folding these two into `_EXEMPT` would also have dropped them from the + width and `input_features` checks they do pass. Three hygiene tests police it: + no stale entry, no name in both tables, and a reason on every entry in both. +- Notebooks 02 and 03 install the published wheel instead of a `git+main` + snapshot. Both imported `datasets.make_donor_panel`, which 0.7.0 did not + ship, and fell back to a `try/except ImportError` that pip-installed from + `git+...@main`. That fallback could not work in-process: the failed + `from philanthropy.datasets import make_donor_panel` leaves the stale module + cached in `sys.modules`, so the re-import after a *successful* install raises + the same `ImportError`. It only worked where philanthropy was absent + entirely, which is fresh Colab, so anyone who followed the README's + `pip install philanthropy` and then opened a notebook locally got a hard + failure, and the "zero install, try it now" Colab badge ran an unreleased + snapshot rather than the archived release `paper.md` points at. Now a plain + `pip install -q "philanthropy[viz]>=0.7.1"`, which 0.7.1 satisfies from PyPI. + Notebook 01 keeps its `try/except` because a bare `import philanthropy` + succeeds against any release, so its guard never misfires. + ### Changed -- **Breaking:** `FiscalYearGroupedSplitter(drop_repeat_donors=...)` now - defaults to `True`, as the `DeprecationWarning` in 0.7.0 and 0.7.1 said it - would. Each test fold drops donors already seen in its training rows, which - is the safe default for a static per-donor label. It needs `groups` as - `(n_samples, 2)` (fiscal year, donor id); code that passes fiscal years alone - now raises a `ValueError` that names both fixes. Pass - `drop_repeat_donors=False` for a time-varying target to keep the 0.7.x - behaviour. The two leakage experiment scripts now pass it explicitly. - The docs homepage hero no longer uses an all-caps eyebrow label or a gradient-clipped headline; it's now a two-column layout with the headline beside a real ranked-donor ledger table showing what @@ -129,12 +175,6 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) Closes #195. ### Removed -- **Breaking:** `philanthropy.utils.make_donor_dataset`, deprecated since - 0.7.0. Import it from `philanthropy.datasets`. -- **Breaking:** `WealthScreeningImputerKNN(group_col_idx=...)` and its - `group_imputers_` attribute, deprecated since 0.7.0. Per-group and global KNN - fits were measured bit-identical, so the parameter bought nothing; passing it - is now a `TypeError`. `tests/test_knn_group_stratification.py` goes with it. - Deleted `philanthropy/preprocessing/_solicitation_window.py`, a dead module nothing imported. The deprecated `SolicitationWindowTransformer` alias it held was already served by the subpackage's PEP 562 module-level `__getattr__`, so @@ -156,38 +196,6 @@ Format: [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) the input carried column names. It now falls back to `x0`, `x1`, ... for an array fit, matching what `WealthScreeningImputer` and `WealthScreeningImputerKNN` already did. Closes #157. -- Added regression coverage for `PlannedGivingSignalTransformer` when transforming a NumPy array after fitting on a DataFrame. - -### Added -- `tests/test_public_api_contract.py` gains two contracts over every public - transformer, covering the two `get_feature_names_out` call shapes the suite - never exercised. It previously only ever called `get_feature_names_out()` with - no argument on a DataFrame-fitted transformer. - `test_feature_names_out_accepts_input_features` passes the real column names - through, which is the call `ColumnTransformer` and `Pipeline.get_feature_names_out` - actually make, and `test_feature_names_out_width_after_array_fit` fits on an - unnamed array. The second one is what caught the `CRMCleaner` defect above. - Transformers that genuinely cannot fit on an unnamed array are listed in a new - `_EXEMPT_ARRAY_FIT` table with a written reason each: `EncounterTransformer` - merges on a named `donor_id`, and `MatchingGiftFeaturizer` rejects a - non-DataFrame outright. That table is kept separate from `_EXEMPT` on purpose, - because folding these two into `_EXEMPT` would also have dropped them from the - width and `input_features` checks they do pass. Three hygiene tests police it: - no stale entry, no name in both tables, and a reason on every entry in both. -- Notebooks 02 and 03 install the published wheel instead of a `git+main` - snapshot. Both imported `datasets.make_donor_panel`, which 0.7.0 did not - ship, and fell back to a `try/except ImportError` that pip-installed from - `git+...@main`. That fallback could not work in-process: the failed - `from philanthropy.datasets import make_donor_panel` leaves the stale module - cached in `sys.modules`, so the re-import after a *successful* install raises - the same `ImportError`. It only worked where philanthropy was absent - entirely, which is fresh Colab, so anyone who followed the README's - `pip install philanthropy` and then opened a notebook locally got a hard - failure, and the "zero install, try it now" Colab badge ran an unreleased - snapshot rather than the archived release `paper.md` points at. Now a plain - `pip install -q "philanthropy[viz]>=0.7.1"`, which 0.7.1 satisfies from PyPI. - Notebook 01 keeps its `try/except` because a bare `import philanthropy` - succeeds against any release, so its guard never misfires. ## [0.7.1] - 2026-09-08 diff --git a/CITATION.cff b/CITATION.cff index 603f9cc..d5cf895 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -12,8 +12,8 @@ authors: given-names: "Shivam Ashokbhai" orcid: "https://orcid.org/0009-0000-5110-6540" email: shivamlalakiya151299@gmail.com -version: 0.7.1 -date-released: "2026-09-08" +version: 0.8.0 +date-released: "2026-09-24" license: MIT repository-code: "https://github.com/PhilanthroPy-Project/PhilanthroPy" url: "https://PhilanthroPy-Project.github.io/PhilanthroPy/" diff --git a/SECURITY.md b/SECURITY.md index 4648c7e..7e650a3 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -8,8 +8,8 @@ cannot `pip install`, that is a bug, please report it. | Version | Supported | | ------- | ------------------ | -| 0.7.x | :white_check_mark: | -| < 0.7 | :x: | +| 0.8.x | :white_check_mark: | +| < 0.8 | :x: | ## Loading models (trust boundary) diff --git a/docs/reference/index.md b/docs/reference/index.md index 8d6b2f6..e31eaf9 100755 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -90,7 +90,7 @@ Every domain method returns a number on its own scale. None of them are calibrat ## Deprecations !!! info "This page is built from `main`, which is ahead of the release" - `pip install philanthropy` currently gives you **0.7.1**. The tier tables + `pip install philanthropy` currently gives you **0.8.0**. The tier tables above describe the API as it stands on `main`; the deprecations below are live in the version you actually have installed. diff --git a/docs/tutorials/end_to_end_on_real_donor_data.md b/docs/tutorials/end_to_end_on_real_donor_data.md index 644f8f5..5d6e397 100644 --- a/docs/tutorials/end_to_end_on_real_donor_data.md +++ b/docs/tutorials/end_to_end_on_real_donor_data.md @@ -47,9 +47,6 @@ From one run (`random_state=0`, 30% of donors held out): - **Disparity:** selection rates of 0.62 (F) and 0.66 (M), a ratio of 0.94, above the usual 0.8 flag. -The Raiser's Edge reader in step 3 is newer than the 0.7.1 release; until the -next release, install from GitHub (the first cell shows how). - !!! note "Dataset terms" Under the KDD Cup 1998 terms, teaching material must not name the organisation that supplied the data. Cite it only as "KDD Cup 1998". diff --git a/examples/notebooks/04_kdd98_end_to_end.ipynb b/examples/notebooks/04_kdd98_end_to_end.ipynb index cece2b0..fc4e565 100644 --- a/examples/notebooks/04_kdd98_end_to_end.ipynb +++ b/examples/notebooks/04_kdd98_end_to_end.ipynb @@ -50,8 +50,10 @@ }, "outputs": [], "source": [ - "# In Colab, install the library first (the Raiser's Edge reader needs 0.8+ or main):\n", - "# !pip install \"git+https://github.com/PhilanthroPy-Project/PhilanthroPy.git\"\n", + "# Colab and other fresh environments only; an existing install satisfies this\n", + "# and pip exits without touching the network.\n", + "!pip install -q \"philanthropy[viz]>=0.8.0\"\n", + "\n", "import tempfile\n", "from pathlib import Path\n", "\n", diff --git a/pyproject.toml b/pyproject.toml index 2c57215..0114a8d 100755 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "philanthropy" -version = "0.7.1" +version = "0.8.0" description = "scikit-learn-native predictive analytics for nonprofit and academic-medical-center fundraising: donor propensity, lapse, planned giving, wealth screening, and revenue forecasting." readme = "README.md" requires-python = ">=3.9"