fix: synchronize PyPI and pixi dependency version bounds#378
Conversation
Add SemVer-aware upper bounds to [project].dependencies to match the caps already present in [tool.pixi.dependencies], and add the missing psycopg2-binary entry to the pixi block. - cap = major+1 for >=1.0 packages, minor+1 for 0.x packages - cryptography (rolling-major) and packaging (CalVer) left uncapped - httpx kept at <0.29 - x2s3 and py-cluster-api (first-party, PyPI-only) left uncapped for now Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Apply SemVer-aware upper bounds to the first-party PyPI-only deps: x2s3 >=1.2.0,<2 (SemVer 1.x) and py-cluster-api >=0.6.0,<0.7 (0.x). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Regenerated by the pre-push pixi solve after adding psycopg2-binary and the click cap to [tool.pixi.dependencies]. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
I think this makes sense to set the major version caps to be equal across PyPI and pixi requirements rather than removing the upper bound in the PyPI constraints. I didn't check all the packages, but looking at I have a larger question which perhaps comes from me not fully understanding how pixi and PyPI dependencies work in the pyproject.toml. I understand that we want to use conda-forge packages whenever possible to avoid licensing issues, and that this is possible via But are the |
I posted a full analysis of all the packages of this on the comment in #377: |
There are two package repositories that we use, PyPI and conda-forge. There are not particularly differences in licensing issues between them. The main controversy is if we would want to use packages from Anaconda, Inc's default channels, which we do not, although we do now have a subscription that would permit us to do so.
|
@mkitti I did see the full analysis in #377. My point was I checked the ones that Claude decided to leave uncapped, since these would be the exceptions to the general rule of capping at the major version change. I think |
How do you determine which ones you can remove from |
Analysis: Are the
|
| Package | With conda overrides | Without conda overrides |
|---|---|---|
alembic, fastapi, pandas, pydantic, sqlalchemy, uvicorn, etc. |
conda-forge | PyPI |
Version differences (conda-forge lags PyPI):
| Package | conda version | PyPI version |
|---|---|---|
| authlib | 1.6.9 | 1.7.2 |
| cryptography | 46.0.7 | 48.0.0 |
| pydantic | 2.12.5 | 2.13.4 |
| sqlalchemy | 2.0.49 | 2.0.50 |
| numpy | 2.4.3 | 2.4.6 |
Additional transitive conda dependencies pulled in only when using conda overrides: libopenblas, libpq, libgfortran, greenlet, uvloop, watchfiles, websockets, krb5, openldap, lxml, and more — because conda packages declare their own native library dependencies.
Notable example: pandas from conda is only 13.48 MiB vs 37.95 MiB from PyPI, because the conda version links against the shared conda-provided OpenBLAS instead of bundling its own.
Conclusion
The duplication is intentional and meaningful. Removing the conda overrides silently falls back to PyPI wheels, losing:
- conda-vetted binary builds linked against shared native libraries
- Consistent native dependency management (BLAS, libpq, etc.)
The version bounds do need to stay synchronized between the two sections (which is what this PR does) to avoid solver conflicts.
…installed in fileglancer pypi build - the current fileglancer package available on pypi has cryotgraphy 48.0.0. updated both the pypi dependencies and the dev environment dependencies to require >=48, <49. cryptography can have breaking changes across major releases.
|
Okay - after looking into whether there was some option available to have pixi automatically convert the PyPI deps into conda-forge packages in the dev environment, it seems not. prefix-dev/pixi#5981 (comment) It does look like it might newly exist for builds, in a preview |
allison-truhlar
left a comment
There was a problem hiding this comment.
I added an lower and upper bound on crypotraphy, per my earlier comment. If that looks okay to you, @mkitti, then this looks good to me for you to merge.
|
The cryptography upper bound is a conservative choice. While there are backwards incompatible changes frequently, it is not clear that these are backwards incompatible for fileglancer. In fact, this package is never imported directly by fileglancer currently. We're only using the bound since it's an optional transitive dependency of Assessment from Antigravity CLI / Gemini Flash 3.5:1. Cryptography’s Rapid Major Version Cycle Since version 3.0, the PyCA (Python Cryptography Authority) has adopted a rapid release cycle, bumping the major version number frequently (e.g., v41, v42, ... v46) to reflect • The Risk of "Dependency Hell": If you place a strict upper bound (such as <47.0.0 or <48.0.0 ) in pyproject.toml , your package will immediately block downstream 2. Security Criticality (CVE Patches)cryptography is a security-critical package. Vulnerabilities (CVEs) are patched rapidly, and those fixes are typically rolled out in newer major or minor releases. • Blocking Security Updates: Imposing an upper bound can prevent environments from pulling in crucial security patches, leaving them vulnerable. The standard industry guideline is 3. Indirect/Transitive Dependency UsageA search of the fileglancer codebase shows that cryptography is not imported directly in your Python code. • Instead, it is pulled in as a transitive dependency of packages like authlib , python-jose , and atlassian-python-api . 4. Lockfiles vs. Abstract Dependenciesfileglancer uses modern environment and dependency managers (Pixi via pixi.lock and uv via uv.lock ). • The Best of Both Worlds: ────── Recommendation Summary • Do not add an upper bound to cryptography in pyproject.toml . Keep it as cryptography >=41.0.0 (or raise the lower bound if a newer minimum secure version is desired). Assessment by Claude Opus 4.8● Here's how fileglancer uses the cryptography package: It's used transitively, not directly There is no import cryptography anywhere in fileglancer's source. It's declared as a direct runtime dependency (cryptography >=41.0.0) purely to nail down the crypto backend for the
Why it's pinned explicitly The git history tells the story:
Relevance to the dependency-bounds work This is also exactly why #378 leaves cryptography uncapped (>=41.0.0, no ): it uses a rolling-major release scheme (41→48), and since fileglancer never touches its API |
Synchronize PyPI and pixi dependency version bounds
An alternative to #377. Rather than loosening the pixi caps to match the un-capped PyPI list, this PR tightens the PyPI list to match the pixi caps, so both dependency surfaces carry identical, SemVer-aware bounds.
Approach
Bounds follow SemVer principles — cap = major + 1 for
>=1.0packages, cap = minor + 1 for0.xpackages (where0.xtreats the minor as the breaking boundary) — with two documented exceptions that use a non-SemVer scheme and are intentionally left uncapped.Changes
[project.dependencies](PyPI): added upper caps toalembic,atlassian-python-api,authlib,cachetools,click,fastapi,itsdangerous,loguru,pandas,pydantic,pydantic-settings,sqlalchemy,uvicorn, matching the caps already present in the pixi block.[tool.pixi.dependencies](conda): added theclickcap and the missingpsycopg2-binary >=2.9.10,<3entry.x2s3 >=1.2.0,<2andpy-cluster-api >=0.6.0,<0.7(PyPI-only; not on conda-forge, so they appear only in the PyPI block).pixi.lockregenerated for the new pixi bounds.Scheme exceptions (intentionally uncapped)
cryptography— uses a rolling-major scheme (bumps the major on every feature release, 41→48); a<next-major>cap would break on the next normal release. Left at>=41.0.0.packaging— CalVer (24.0, 25.0, 26.x), not SemVer. Left at>=24.0.Scope / what this PR does NOT do
fastapistays at>=0.119.1,<0.120and Starlette stays at the currently-locked0.48.0. Bumping FastAPI (which drops the oldstarlette <0.49cap and unblocks Starlette 1.x) is a behavioral upgrade and is deferred to its own follow-up PR.httpxkept at>=0.28.1,<0.29(unchanged).After this, the two blocks list identical bounds for every shared runtime package; the only divergences are pixi-only build tooling (
python/pip/nodejs) and the PyPI-only first-party packages.🤖 Generated with Claude Code