From 55ff5bf84cde1ddfe7c0b4f4870a2e5e57662cb8 Mon Sep 17 00:00:00 2001 From: tino097 Date: Wed, 28 Oct 2026 18:32:01 +0100 Subject: [PATCH 1/4] build(deps): pin fastapi<0.155 until Prefect drops min_items (#353) Prefect 3.7 only requires fastapi<1.0. FastAPI 0.155.0 (2026-10-20) removed the deprecated min_items argument that prefect/server/api/concurrency_limits_v2.py still passes to Body(), so every fresh install fails on import prefect with "TypeError: Body() got an unexpected keyword argument 'min_items'", taking down the unit suite, prefect server start and the integration CI. A dry-run install of the pinned requirements resolves fastapi 0.154.0 with prefect 3.7.8. Drop the pin once a Prefect release stops passing min_items. Co-Authored-By: Claude Fable 5.1 --- CHANGELOG.md | 3 +++ requirements.txt | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9734e4..1e47908 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * **BREAKING** Bumped `MINIMUM_QSV_VERSION` from `20.0.0` to `20.1.0` (and bumped the qsv version installed by `Dockerfile.worker`, `.github/workflows/ci.yml`, and `.github/workflows/main.yml` to match). Operators must upgrade their `qsv` binary at the path configured by `ckanext.datapusher_plus.qsv_bin` before deploying this version — DP+ will refuse to start otherwise with `JobError: At least qsv version 20.1.0 required. Found 20.0.0.`. qsv 20.1.0 itself introduces no breaking changes against 20.0.0 (per the [20.1.0 release notes](https://github.com/dathere/qsv/releases/tag/20.1.0): "pipelines built on 20.0.0 will upgrade in place"), so the upgrade is binary-swap-only — no data re-ingestion is required. The reason this is still flagged as **BREAKING** is the minimum-version gate, not the qsv behavior. User-visible improvement justifying the floor bump: qsv-dateparser 0.14 → 0.15 in qsv 20.1.0 adds recognition for ISO 8601 `T`-separated datetimes without a timezone suffix (e.g. `2024-10-11T14:30:00`) — qsv 20.0.0 misclassified these as `String` during `qsv stats --infer-dates`, which in DP+ surfaced as a date-typed column being demoted to text on certain CSV shapes (one of the gaps documented in the issue #173 regression test, now closed). The regression-test matrix in `tests/test_issue_173_date_format_inference.py` is updated to the new baseline. * **BREAKING** Bumped `MINIMUM_QSV_VERSION` from `20.1.0` to `25.0.0` (and bumped the qsv version installed by `Dockerfile.worker`, `.github/workflows/ci.yml`, `.github/workflows/main.yml` and `.github/workflows/test.yml` to match). Operators must upgrade their `qsv` binary at the path configured by `ckanext.datapusher_plus.qsv_bin` before deploying this version — DP+ will refuse to start otherwise with `JobError: At least qsv version 25.0.0 required. Found 20.1.0.`. qsv [25.0.0](https://github.com/dathere/qsv/releases/tag/25.0.0) is the first release with what `QSVCommand` reads through `qsv-client`: structured JSON errors (`QSV_ERROR_FORMAT=json`, [qsv#4765](https://github.com/dathere/qsv/pull/4765)), so a failed qsv step reports its error kind and message instead of raw stderr, and `qsv --capabilities` for the version check. On older qsv, both fell back to parsing plain text. It also redacts API keys from `describegpt`'s attribution ([qsv#4766](https://github.com/dathere/qsv/pull/4766)). Date inference is unchanged: the issue #173 matrix in `tests/test_issue_173_date_format_inference.py` gives the same type for every column under qsv 25.0.0 as under 20.1.0, and is now pinned to 25.0.x. +### Fixed +* Pinned `fastapi<0.155`. FastAPI 0.155.0 (2026-10-20) removed the deprecated `min_items` argument that Prefect 3.7 still passes to `Body()`, so a fresh install failed on `import prefect` with `TypeError: Body() got an unexpected keyword argument 'min_items'`, taking down the unit suite, `prefect server start` and the integration CI. Prefect itself only requires `fastapi<1.0`; the pin goes away once a Prefect release stops passing `min_items` (issue #353). + ### qsv 20.0.0 migration notes (operator-facing) The new minimum brings the following user-visible changes from qsv 4.0.0 → 20.0.0 that may affect existing CKAN deployments: diff --git a/requirements.txt b/requirements.txt index 994212c..ec63636 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,6 +6,15 @@ pandas==2.2.3 shapely==2.1.0 pyproj>=3.7.1 prefect>=3.7,<3.8 +# fastapi: prefect 3.7 only requires fastapi<1.0, but FastAPI 0.155.0 +# (2026-10-20) removed the deprecated ``min_items`` argument that +# prefect/server/api/concurrency_limits_v2.py still passes to ``Body()``. +# A fresh install then fails on ``import prefect`` with +# ``TypeError: Body() got an unexpected keyword argument 'min_items'``, +# which takes down the unit suite, ``prefect server start`` and the +# integration CI (issue #353). Drop the pin once a Prefect release stops +# passing ``min_items``. +fastapi<0.155 # importlib_metadata: declared explicitly because prefect 3.7.1's # ``workers/base.py`` imports it unconditionally but doesn't list it # as a direct dep — it was being satisfied transitively by From 03f79192d3b8f0e15bc1d00988e933ad8e04c8c6 Mon Sep 17 00:00:00 2001 From: tino097 Date: Wed, 28 Oct 2026 18:41:54 +0100 Subject: [PATCH 2/4] build(deps): lower the fastapi pin to <0.144 (#353) The first CI run with fastapi<0.155 got past import prefect and prefect server start, then failed in prefect-deploy: FastAPI 0.144 to 0.154 no longer treat a JSON null as "missing" for Body(None) on an int parameter, so the Prefect client's workers/filter request (limit: null, offset: null) is rejected with 422 "Input should be a valid integer". Reproduced against a local Prefect 3.7.8 server: 422 on fastapi 0.154.0, 404 (pool lookup, as expected) on 0.143.5, and read_workers_for_work_pool succeeds on 0.143.5. 0.143.x is what the last green main CI run installed. Unit suite: 342 passed on 0.143.5. Co-Authored-By: Claude Fable 5.1 --- CHANGELOG.md | 2 +- requirements.txt | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e47908..bba075c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * **BREAKING** Bumped `MINIMUM_QSV_VERSION` from `20.1.0` to `25.0.0` (and bumped the qsv version installed by `Dockerfile.worker`, `.github/workflows/ci.yml`, `.github/workflows/main.yml` and `.github/workflows/test.yml` to match). Operators must upgrade their `qsv` binary at the path configured by `ckanext.datapusher_plus.qsv_bin` before deploying this version — DP+ will refuse to start otherwise with `JobError: At least qsv version 25.0.0 required. Found 20.1.0.`. qsv [25.0.0](https://github.com/dathere/qsv/releases/tag/25.0.0) is the first release with what `QSVCommand` reads through `qsv-client`: structured JSON errors (`QSV_ERROR_FORMAT=json`, [qsv#4765](https://github.com/dathere/qsv/pull/4765)), so a failed qsv step reports its error kind and message instead of raw stderr, and `qsv --capabilities` for the version check. On older qsv, both fell back to parsing plain text. It also redacts API keys from `describegpt`'s attribution ([qsv#4766](https://github.com/dathere/qsv/pull/4766)). Date inference is unchanged: the issue #173 matrix in `tests/test_issue_173_date_format_inference.py` gives the same type for every column under qsv 25.0.0 as under 20.1.0, and is now pinned to 25.0.x. ### Fixed -* Pinned `fastapi<0.155`. FastAPI 0.155.0 (2026-10-20) removed the deprecated `min_items` argument that Prefect 3.7 still passes to `Body()`, so a fresh install failed on `import prefect` with `TypeError: Body() got an unexpected keyword argument 'min_items'`, taking down the unit suite, `prefect server start` and the integration CI. Prefect itself only requires `fastapi<1.0`; the pin goes away once a Prefect release stops passing `min_items` (issue #353). +* Pinned `fastapi<0.144`. Prefect 3.7 only requires `fastapi<1.0`, and the FastAPI releases of 2026-10-18 to 23 break it twice: from 0.155 a fresh install fails on `import prefect` with `TypeError: Body() got an unexpected keyword argument 'min_items'` (unit suite, `prefect server start` and the integration CI all die), and from 0.144 the server starts but rejects the Prefect client's `workers/filter` request with `422 Input should be a valid integer` for `limit: null`, so `ckan datapusher_plus prefect-deploy` fails. 0.143.x is what the last green CI run installed. The pin goes away once a Prefect release in range works on current FastAPI (issue #353). ### qsv 20.0.0 migration notes (operator-facing) The new minimum brings the following user-visible changes from qsv 4.0.0 → 20.0.0 that may affect existing CKAN deployments: diff --git a/requirements.txt b/requirements.txt index ec63636..7d52357 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,15 +6,16 @@ pandas==2.2.3 shapely==2.1.0 pyproj>=3.7.1 prefect>=3.7,<3.8 -# fastapi: prefect 3.7 only requires fastapi<1.0, but FastAPI 0.155.0 -# (2026-10-20) removed the deprecated ``min_items`` argument that -# prefect/server/api/concurrency_limits_v2.py still passes to ``Body()``. -# A fresh install then fails on ``import prefect`` with -# ``TypeError: Body() got an unexpected keyword argument 'min_items'``, -# which takes down the unit suite, ``prefect server start`` and the -# integration CI (issue #353). Drop the pin once a Prefect release stops -# passing ``min_items``. -fastapi<0.155 +# fastapi: prefect 3.7 only requires fastapi<1.0, but the FastAPI releases +# of 2026-10-18..23 (0.144 through 0.162) break Prefect 3.7.8 twice. From +# 0.155, ``import prefect`` fails because concurrency_limits_v2.py passes the +# removed ``min_items`` argument to ``Body()``. Between 0.144 and 0.154 the +# server starts, but ``Body(None)`` on an ``int`` parameter no longer treats +# a JSON ``null`` as "missing", so the client's ``workers/filter`` call +# (``limit: null``) is rejected with 422 and ``prefect-deploy`` fails. 0.143.x +# is what main's last green CI run installed (issue #353). Drop the pin once +# a Prefect release in range passes on current FastAPI. +fastapi<0.144 # importlib_metadata: declared explicitly because prefect 3.7.1's # ``workers/base.py`` imports it unconditionally but doesn't list it # as a direct dep — it was being satisfied transitively by From 5c05c3f66a2768f19851c6e8d4dc3eff769b7e53 Mon Sep 17 00:00:00 2001 From: tino097 Date: Wed, 28 Oct 2026 19:12:41 +0100 Subject: [PATCH 3/4] build(deps): shorten the fastapi pin comment Rationale stays in the commit history, PR #358 and issue #353. Co-Authored-By: Claude Fable 5.1 --- requirements.txt | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/requirements.txt b/requirements.txt index 7d52357..6a3319c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,15 +6,9 @@ pandas==2.2.3 shapely==2.1.0 pyproj>=3.7.1 prefect>=3.7,<3.8 -# fastapi: prefect 3.7 only requires fastapi<1.0, but the FastAPI releases -# of 2026-10-18..23 (0.144 through 0.162) break Prefect 3.7.8 twice. From -# 0.155, ``import prefect`` fails because concurrency_limits_v2.py passes the -# removed ``min_items`` argument to ``Body()``. Between 0.144 and 0.154 the -# server starts, but ``Body(None)`` on an ``int`` parameter no longer treats -# a JSON ``null`` as "missing", so the client's ``workers/filter`` call -# (``limit: null``) is rejected with 422 and ``prefect-deploy`` fails. 0.143.x -# is what main's last green CI run installed (issue #353). Drop the pin once -# a Prefect release in range passes on current FastAPI. +# fastapi: 0.155+ breaks `import prefect` (removed min_items); 0.144-0.154 reject +# the Prefect client's `limit: null` with 422 (issue #353). Drop the pin once a +# Prefect release in range works on current FastAPI. fastapi<0.144 # importlib_metadata: declared explicitly because prefect 3.7.1's # ``workers/base.py`` imports it unconditionally but doesn't list it From 2cdd878b8bf81787cc3675998cf98e800b03718b Mon Sep 17 00:00:00 2001 From: tino097 Date: Wed, 28 Oct 2026 19:14:00 +0100 Subject: [PATCH 4/4] build(deps): keep the fastapi pin comment to the reason Co-Authored-By: Claude Fable 5.1 --- requirements.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index 6a3319c..07c1ea2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,9 +6,8 @@ pandas==2.2.3 shapely==2.1.0 pyproj>=3.7.1 prefect>=3.7,<3.8 -# fastapi: 0.155+ breaks `import prefect` (removed min_items); 0.144-0.154 reject -# the Prefect client's `limit: null` with 422 (issue #353). Drop the pin once a -# Prefect release in range works on current FastAPI. +# fastapi 0.155+ breaks `import prefect` (removed min_items); 0.144-0.154 reject +# the Prefect client's `limit: null` with 422. fastapi<0.144 # importlib_metadata: declared explicitly because prefect 3.7.1's # ``workers/base.py`` imports it unconditionally but doesn't list it