chore(deps): align pins with the verified upgraded toolchain (streamlit 1.58 + pandas 3.0) - #111
Merged
Merged
Conversation
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>
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.
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.pystartup crash. The crash itself was an unrelated orphaneduvicorninstall, but chasing it exposed the pin drift underneath.streamlit and pandas had to move together
This is the load-bearing detail:
pandas<3pandas<4pip install -r requirements.txt -c constraints.txtwithpandas==3.0.5andstreamlit==1.55.0fails outright: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.txtcould 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
constraints.txtnow matches the installed environment 28/28 — zero drift.Code changes (2 lines of real substance)
The pandas 3.0 stubs widened
.loc[scalar]toAny | Series[Any], because a duplicated index would make that lookup return a Series rather than a row. That produced 5mypyerrors across 2 files, all of the formfloat(row["col"]).Fixed by narrowing with
castat the point the row is created, not at each column read — so the five call sites stay untouched and the reason is documented once:No
type: ignorewas added.One test-semantics fix
test_constraints_use_security_reviewed_dependency_versionsasserted 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_PINSmap. The version parsing is hand-rolled rather than usingpackaging, because this module is the supply-chain guard and should not itself depend on a distribution that is absent fromconstraints.txt.Compatibility
All new pins require Python >=3.11, so the
["3.11", "3.12"]CI matrix and thepython:3.11-slim-bookwormDocker base are unaffected. No matrix change needed.uvicornandstarletteare left unpinned, consistent with howtornadowas treated before —constraints.txtis 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:
mypyclean across 245 filesruff,bandit,compileall,pre-commit validate-configcleanpip-audit -r constraints.txt→ no known vulnerabilities (and now resolves at all)streamlit run app.pyboots and serves HTTP 200CI is the real test of the 3.11/3.12 matrix, since local verification ran on 3.13.
🤖 Generated with Claude Code