Skip to content

chore(deps): align pins with the verified upgraded toolchain (streamlit 1.58 + pandas 3.0) - #111

Merged
DoRmAmMu1997 merged 1 commit into
mainfrom
chore/deps-align-pins-to-verified
Aug 19, 2026
Merged

chore(deps): align pins with the verified upgraded toolchain (streamlit 1.58 + pandas 3.0)#111
DoRmAmMu1997 merged 1 commit into
mainfrom
chore/deps-align-pins-to-verified

Conversation

@DoRmAmMu1997

Copy link
Copy Markdown
Owner

Why

CI installed pandas 2.3.3 while local development had already moved to pandas 3.0.5. The suite was being verified against a version nobody actually runs. This moves the pins forward to the set that has been exercised locally, rather than downgrading the working environment back to the pins.

This surfaced while debugging a streamlit run app.py startup crash. The crash itself was an unrelated orphaned uvicorn install, but chasing it exposed the pin drift underneath.

streamlit and pandas had to move together

This is the load-bearing detail:

pandas bound starlette / uvicorn
streamlit 1.55.0 (old pin) pandas<3 optional extras
streamlit 1.58.0 (new pin) pandas<4 required (tornado dropped)

pip install -r requirements.txt -c constraints.txt with pandas==3.0.5 and streamlit==1.55.0 fails outright:

ERROR: Cannot install -r constraints.txt (line 10) and pandas==3.0.5
because these package versions have conflicting dependencies.
ERROR: ResolutionImpossible

So the locally "working" combination was one pip would refuse to construct — it only ran because the packages were already on disk. pip-audit -r constraints.txt could not resolve either; it does now.

That table also explains the startup crash that started this: 1.58 promotes uvicorn from an optional extra to a hard requirement, so an unmanaged uvicorn becomes fatal rather than irrelevant.

Bumps

Package From To
streamlit 1.55.0 1.58.0
pandas 2.3.3 3.0.5
numpy 2.2.6 2.4.6
requests 2.33.1 2.34.2
claude-agent-sdk 0.2.87 0.2.137
pandas-stubs 2.3.3.260113 3.0.5.260730
pytest / ruff / mypy / pip-audit / pre-commit / types-requests all to installed

constraints.txt now matches the installed environment 28/28 — zero drift.

Code changes (2 lines of real substance)

The pandas 3.0 stubs widened .loc[scalar] to Any | Series[Any], because a duplicated index would make that lookup return a Series rather than a row. That produced 5 mypy errors across 2 files, all of the form float(row["col"]).

Fixed by narrowing with cast at the point the row is created, not at each column read — so the five call sites stay untouched and the reason is documented once:

prior = cast("pd.Series[Any]", enriched.loc[int(prior_index)])

No type: ignore was added.

One test-semantics fix

test_constraints_use_security_reviewed_dependency_versions asserted exact equality on the pins that were bumped to clear advisories (python-dotenv, lxml, pytest). Its own docstring calls those "known-vulnerable pins must not re-enter" — which is a floor, not an exact match. As written it tripped on any forward bump, including a bump to a newer, safer version.

Converted to a real floor comparison with a SECURITY_FLOOR_PINS map. The version parsing is hand-rolled rather than using packaging, because this module is the supply-chain guard and should not itself depend on a distribution that is absent from constraints.txt.

Compatibility

All new pins require Python >=3.11, so the ["3.11", "3.12"] CI matrix and the python:3.11-slim-bookworm Docker base are unaffected. No matrix change needed.

uvicorn and starlette are left unpinned, consistent with how tornado was treated before — constraints.txt is documented as direct dependency pins, and these are transitive to streamlit.

Verification

Run on the upgraded stack (streamlit 1.58.0 + pandas 3.0.5), with the previously shadowing streamlit 1.55 removed from the path so 1.58 genuinely loads:

  • 1,780 tests pass, coverage 89.55% (floor 87%)
  • mypy clean across 245 files
  • ruff, bandit, compileall, pre-commit validate-config clean
  • pip-audit -r constraints.txt → no known vulnerabilities (and now resolves at all)
  • streamlit run app.py boots and serves HTTP 200

CI is the real test of the 3.11/3.12 matrix, since local verification ran on 3.13.

🤖 Generated with Claude Code

CI installed pandas 2.3.3 while local development had moved to pandas 3.0.5,
so the suite was being verified against a version nobody actually runs. This
closes that gap by moving the pins forward to the set that has been exercised
locally, rather than downgrading the working environment back to the pins.

streamlit and pandas had to move together. streamlit 1.55 caps pandas<3, so
`pip install -r requirements.txt -c constraints.txt` with pandas 3.0.5 fails
outright with ResolutionImpossible - the locally working combination was one
pip would refuse to construct. streamlit 1.58 raises the cap to pandas<4, and
also promotes starlette/uvicorn from optional extras to required dependencies
(dropping tornado), which is why an unmanaged uvicorn could break startup.

Bumps: streamlit 1.55.0 -> 1.58.0, pandas 2.3.3 -> 3.0.5, numpy 2.2.6 -> 2.4.6,
requests 2.33.1 -> 2.34.2, claude-agent-sdk 0.2.87 -> 0.2.137, pytest 9.0.3 ->
9.1.1, ruff 0.15.1 -> 0.16.3, pip-audit 2.10.0 -> 2.10.1, mypy 1.19.1 ->
1.20.2, types-requests and pre-commit, plus pandas-stubs 2.3.3.260113 ->
3.0.5.260730 so the stubs keep tracking the pinned pandas series.

The pandas 3.0 stubs widened `.loc[scalar]` to `Any | Series[Any]`, since a
duplicated index would make that lookup return a Series. Two row lookups are
narrowed with `cast` at the point the row is created rather than at each column
read, which keeps the five call sites unchanged and documents why once.

test_supply_chain_policy previously asserted exact equality on the pins that
were bumped to clear advisories (python-dotenv, lxml, pytest). Its own docstring
describes those as "known-vulnerable pins must not re-enter", which is a floor,
not an exact match - so it tripped on any forward bump. Converted to a real
floor comparison, hand-rolled rather than using `packaging` because the
supply-chain guard should not depend on a distribution absent from
constraints.txt.

All new pins require Python >=3.11, so the 3.11/3.12 CI matrix and the 3.11
Docker base are unaffected. Verified on the upgraded stack: 1780 tests pass at
89.55% coverage, mypy/ruff/bandit/compileall clean, pip-audit resolves (it could
not before, due to the streamlit/pandas conflict), and `streamlit run app.py`
boots and serves HTTP 200.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@DoRmAmMu1997
DoRmAmMu1997 merged commit b946ad1 into main Aug 19, 2026
3 checks passed
@DoRmAmMu1997
DoRmAmMu1997 deleted the chore/deps-align-pins-to-verified branch August 19, 2026 17:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant