Skip to content

chore(deps): bump packaging from 23.2 to 26.2 - #4067

Merged
snopoke merged 1 commit into
mainfrom
dependabot/uv/packaging-26.2
Aug 4, 2026
Merged

snopoke merged 1 commit into
mainfrom
dependabot/uv/packaging-26.2

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Aug 3, 2026 •

Copy link
Copy Markdown
Contributor

Bumps packaging from 23.2 to 26.2.

Release notes

Sourced from packaging's releases.

26.2

What's Changed

Fixes:

Documentation:

Internal:

New Contributors

Full Changelog: pypa/packaging@26.1...26.2

26.1

Features:

Behavior adaptations:

... (truncated)

Changelog

Sourced from packaging's changelog.

26.2 - 2026-04-24


Fixes:
  • Fix incorrect sysconfig var name for pyemscripten in (:pull:1160)
  • Make Version, Specifier, SpecifierSet, Tag, Marker, and Requirement pickle-safe
    and backward-compatible with pickles created in 25.0-26.1 (including references to the removed
    packaging._structures module) (:pull:1163, :pull:1168, :pull:1170, :pull:1171)
  • Re-export ExceptionGroup in metadata for now in (:pull:1164)

Documentation:

  • Add errors section and fix missing details in (:pull:1159)
  • Document our property-based test suite in (:pull:1167)
  • Fix a DirectUrl typo in (:pull:1169)
  • Add example of is_unsatisfiable in (:pull:1166)

Internal:

  • Enable the auditor persona on zizmor in (:pull:1158)
  • Test new pickle guarantees in (:pull:1174)
  • Use new native ReadTheDocs uv integration in (:pull:1175)

26.1 - 2026-04-14

Features:

  • PEP 783: add handling for Emscripten wheel tags in (:pull:804) (old name used in implementation, fixed in next release)
  • PEP 803: add handling for the abi3.abi3t free-threading tag in (:pull:1099)
  • PEP 735: add packaging.dependency_groups module, based on the dependency-groups package in (:pull:1065)
  • Add the packaging.direct_url module in (:pull:944)
  • Add the packaging.errors module in (:pull:1071)
  • Add SpecifierSet.is_unsatisfiable using ranges (new internals that will be expanded in future versions) in (:pull:1119)
  • Add create_compatible_tags_selector to select compatible tags in (:pull:1110)
  • Add a key argument to SpecifierSet.filter() in (:pull:1068)
  • Support & and | for Marker's in (:pull:1146)
  • Normalize Version.__replace__ and add Version.from_parts in (:pull:1078)
  • Add an option to validate compressed tag set sort order in parse_wheel_filename in (:pull:1150)

Behavior adaptations:

  • Narrow exclusion of pre-releases for <V.postN to match spec in (:pull:1140)
  • Narrow exclusion of post-releases for >V to match spec in (:pull:1141)
  • Rename format_full_version to _format_full_version to make it visibly private in (:pull:1125)
  • Restrict local version to ASCII in (:pull:1102)

Pylock (PEP 751) updates:

... (truncated)

Commits

@dependabot dependabot Bot added dependencies Pull requests that update a dependency file python:uv Pull requests that update python:uv code labels Aug 3, 2026
codescene-delta-analysis[bot]

This comment was marked as outdated.

@claude

claude Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

🔍 Dependency Analysis Summary

Package Change Type Ecosystem
packaging 23.2 → 26.2 Floor bump + lock uv (Python)

Single dependency, spanning 7 releases (24.0, 24.1, 24.2, 25.0, 26.0, 26.1, 26.2). uv.lock shows no transitive churn — only the packaging entry itself changed (4 lines).

Overall risk: 🟢 LOW — OCS touches only Version and InvalidVersion, and I verified empirically that this surface is behaviourally identical between 23.2 and 26.2.


📋 Detailed Changelog Review

Package: packaging (23.2 → 26.2)

Breaking changes in the release history

Version Change Affects OCS?
24.0 BREAKING: optional metadata.Metadata attributes now default to None ❌ packaging.metadata unused
26.0 Removed LegacyVersion / LegacySpecifier ❌ (already gone since 22.0)
26.0 Removed the pyparsing dependency ❌ dependency-count reduction only
26.0 format_full_version → _format_full_version (made private) ❌ only used internally by packaging.markers
26.0 PEP 440 pre-release handling changed for Specifier.contains, SpecifierSet.contains, filter ❌ specifiers unused
26.0 Marker evaluation now assumes an empty extra when not provided ❌ markers unused
26.0 Pre-release/post-release prefix matching now forbidden; specifier version normalised for prefix matching ❌ specifiers unused
26.1 Narrowed pre-release exclusion for <V.postN, post-release exclusion for >V ❌ specifiers unused
26.1 Local version restricted to ASCII ❌ verified no delta (23.2 already rejected non-ASCII locals)
24.2 Pre-release detection fixed for > / < operators ❌ specifiers unused
24.0 Specifier matching fixed when epoch has more components than version ❌ specifiers unused

Every behaviour change in this span lands in specifiers, markers, requirements, tags, or metadata — none in version.Version parsing or comparison, which is the only thing OCS uses.

Security fixes

None disclosed in this span — no CVEs, no GHSA advisories. This is a maintenance/feature upgrade, not a security bump.

🎯 Notable: 26.2 is specifically the right target in the 26.x series

25.0 removed the packaging._structures module, which broke unpickling of Version, Specifier, SpecifierSet, Tag, Marker, and Requirement objects. 26.2 (pypa/packaging#1163, #1168, #1170, #1171) restores pickle-safety and makes it backward-compatible with pickles created under 25.0–26.1. It also re-exports ExceptionGroup in metadata (#1164).

Landing on 26.0 or 26.1 would have carried that pickle regression; 26.2 does not. Worth noting since OCS runs Celery — though the default serializer is JSON, so no Version objects cross a pickle boundary here regardless.

New features (informational)

packaging.dependency_groups (PEP 735), packaging.direct_url, packaging.errors, packaging.pylock (PEP 751), SpecifierSet.is_unsatisfiable(), create_compatible_tags_selector, Marker &/| operators, Version.from_parts, Android (PEP 738) and Emscripten (PEP 783) tags, abi3t free-threading tag (PEP 803).


⚠️ Impact Assessment

Breaking changes affecting OCS: No.

Affected files (all usage sites)

File Usage
apps/channels/widget_versions.py:15 Version, InvalidVersion — widget version policy, deprecation/sunset, auth-level gating
apps/channels/migrations/0029_experimentchannel_required_auth_level.py:4 Version, InvalidVersion — data migration grandfathering widget auth levels
tasks.py:11 Version — inv Node.js minimum-version check

All three do the same three things: construct Version, compare with </>=, catch InvalidVersion. No SpecifierSet, no Requirement, no Marker, no packaging.metadata, no private APIs anywhere in apps/, config/, scripts/, libs/, or tasks.py.

Verification performed

1. Differential behaviour fingerprint. Ran 39 version strings (real widget versions 0.4.2–0.11.0, pre-releases, epochs, local versions, post/dev releases, plus the malformed inputs OCS deliberately feeds in: "unknown", "", "latest", "not-a-version", whitespace-padded) through both 23.2 and 26.2, capturing parse result, normalised str(), and all 528 pairwise </==/> comparisons:

23.2 → 5e408a72caaa0800e02a8da23f1217c887182fdb1feb0af60b5101c90966c971
26.2 → 5e408a72caaa0800e02a8da23f1217c887182fdb1feb0af60b5101c90966c971

Byte-identical. Notably "unknown" still raises InvalidVersion — the sentinel that _parse() and migration 0029 rely on to grade a widget as AUTH_LEVEL_NONE.

2. Removed-API sweep across the installed tree. No third-party package imports packaging._structures, LegacyVersion, LegacySpecifier, or format_full_version from the real packaging. The apparent hits are vendored private copies (pandas/util/version, numpy/_utils/_pep440, pyarrow/vendored/version), comments (google/cloud/bigquery/_versions_helpers.py), or unrelated words (prompt_toolkit → data_structures). packaging._structures is in fact still shipped in 26.2 as the pickle-compat shim.

3. Import smoke test under 26.2. transformers, huggingface_hub, langchain_core, langchain_classic, celery, pandas, sentry_sdk, openai, anthropic, pydantic, django, rest_framework, markitdown, numpy, pyarrow, djlint, google.cloud.bigquery — all import cleanly.

4. Lockfile consistency. uv lock --check passes (296 packages resolved, no drift). No package in the tree caps packaging, so the >=26.2 floor resolves without conflict.

5. Python compatibility. packaging 26.2 declares Requires-Python: >=3.8; OCS requires 3.13+. No conflict.

Test impact: none expected. apps/channels/tests/test_widget_versions.py and test_widget_auth_level_ratchet.py are the tests that exercise this surface; given the identical fingerprint they should pass unchanged. ⚠️ I could not execute pytest in this environment (no SECRET_KEY/Postgres available to the review sandbox) — please confirm via the CI run rather than treating point 1 as a substitute for green tests.

Configuration changes: none.


🛠️ Recommendations

Action required: none. Merge once CI is green.

Testing focus (all low-probability, listed for completeness):

  • Widget version policy: deprecation badges, Deprecation/Sunset/Link headers on x-ocs-widget-version traffic, and the AUTH_LEVEL_* gating in level_for_version().
  • uv run inv runserver — exercises the _check_node_version path in tasks.py.
  • Migration 0029 needs no attention: it is already applied, and this upgrade does not change how it would grade any version string.

Follow-up (optional nit, non-blocking): packaging>=26.2 in pyproject.toml is a much stricter floor than OCS needs. The only APIs used — Version and InvalidVersion — have been stable since well before 20.0. Dependabot raises the floor to the new version mechanically; a looser floor (>=23.2, i.e. a lock-only bump) would keep resolver headroom for any future co-installed package that caps packaging. Nothing in the tree caps it today, so this costs nothing right now — worth considering as a Dependabot config preference (versioning-strategy: lockfile-only / increase-if-necessary) rather than a change to this PR.

Merge recommendation: ✅ APPROVE

Rationale: three usage sites, all on the single most stable API in the library; every breaking change in the 23.2→26.2 span lands in modules OCS does not import; behaviour verified byte-identical on the exact inputs OCS feeds in; and 26.2 is the release that resolves the 25.0-era pickle regression rather than carrying it.


📚 Useful Links

🤖 Automated Dependabot review by Claude Code

@dependabot
dependabot Bot force-pushed the dependabot/uv/packaging-26.2 branch from 4603716 to 2bc57a7 Compare August 4, 2026 08:55
codescene-delta-analysis[bot]

This comment was marked as outdated.

@claude

claude Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

🔍 Dependency Analysis Summary

Package Old New Kind
packaging 23.2 26.2 direct, runtime — spans 3 major versions

Overall risk: LOW

Two things that keep this small despite the version jump:

  • The only name/version delta in the entire 64-line lockfile diff is packaging itself — verified with gh pr diff 4067 --patch | grep -E '^[-+](name|version) = ', which returns exactly -23.2 / +26.2. No package added, removed, or re-resolved.
  • packaging 26.2 is pure Python with zero runtime dependencies (Requires-Dist: None).

📋 Detailed Changelog Review

Package: packaging (23.2 → 26.2) — covers releases 24.0, 24.1, 24.2, 25.0, 26.0, 26.1, 26.2.

Key changes — the bulk of this range is new surface area OCS does not touch: PEP 751 pylock support, packaging.dependency_groups (PEP 735), packaging.direct_url, packaging.errors, packaging.licenses (PEP 639), Android/Emscripten/free-threading wheel tags (PEP 738/783/803), SpecifierSet.is_unsatisfiable.

Breaking changes in the range (all confined to modules OCS never imports):

Version Breaking change Reaches OCS?
26.0 Removed packaging._structures (Infinity / NegativeInfinity) No — and 26.2 re-added it as a compat shim
26.0 Renamed format_full_version → _format_full_version (markers) No
26.0 Restrict local version to ASCII Yes — see below
26.0/26.1 Narrowed pre-release exclusion for <V.postN, post-release exclusion for >V, SpecifierSet.filter PEP 440 edge cases, arbitrary equality on arbitrary strings No — Specifier/SpecifierSet only
26.0 Dropped Python 3.8 No — OCS requires 3.13+
24.0 metadata.Metadata optional attributes default to None No
23.2 Requirement parsing no longer auto-validates URLs No

Security fixes: none announced in this range.

Migration notes: none applicable to how OCS uses the library.

Worth noting that 26.2 specifically is the right landing spot: 26.0/26.1 broke pickling of Version/Specifier/Marker/Requirement/Tag (the removed _structures module was referenced by old pickles), and 26.2 is the fix. Not a live concern here — Celery has no task_serializer override in config/settings.py, so it uses the JSON default — but it means skipping 26.0/26.1 is a good thing.


⚠️ Impact Assessment

Breaking changes found: No (none that reach OCS code).

OCS imports exactly two names from packaging, in three places:

  • apps/channels/widget_versions.py:15 — Version, InvalidVersion
  • apps/channels/migrations/0029_experimentchannel_required_auth_level.py:4 — Version, InvalidVersion
  • tasks.py:11 — Version (the MIN_NODE_VERSION gate in _check_node_version)

Confirmed by grep that there is no usage anywhere of Specifier, SpecifierSet, Requirement, Marker, Tag, canonicalize_name, parse_wheel_filename, packaging.metadata, packaging._structures, or format_full_version.

I exercised the exact comparison semantics widget_versions.py relies on against 26.2 in the branch venv (EMBED_KEY_INTRODUCED=0.5.1, SESSION_TOKEN_INTRODUCED=0.9.0, LATEST_VERSION=0.11.0):

'0.4.0'            parsed=0.4.0           <0.5.1 True   <0.9.0 True   <latest True
'0.5.1'            parsed=0.5.1           <0.5.1 False  <0.9.0 True   <latest True
'0.8.9'            parsed=0.8.9           <0.5.1 False  <0.9.0 True   <latest True
'0.9.0'            parsed=0.9.0           <0.5.1 False  <0.9.0 False  <latest True
'0.10.0'           parsed=0.10.0          <0.5.1 False  <0.9.0 False  <latest True   <- ordering, not string compare
'0.11.0'           parsed=0.11.0          <0.5.1 False  <0.9.0 False  <latest False
'0.11.0rc1'        parsed=0.11.0rc1       <0.5.1 False  <0.9.0 False  <latest True
'1.0.0-beta.1'     parsed=1.0.0b1         <0.5.1 False  <0.9.0 False  <latest False
'v0.11.0'          parsed=0.11.0          (v-prefix still normalised)
'0.11.0+deadbeef'  parsed=0.11.0+deadbeef
'unknown'          INVALID: Invalid version: 'unknown'
''                 INVALID: Invalid version: ''
max(['0.6.0','0.5.1','0.11.0'], key=Version) -> 0.11.0     (latest_deprecation)
Version('24.18.0') >= Version('20.0.0') -> True            (tasks.py node gate)

All identical to 23.2 behaviour. The UNKNOWN_WIDGET_VERSION = "unknown" sentinel still raises InvalidVersion as the code assumes.

The one observable change, 26.0's ASCII restriction on local versions:

'0.11.0+café'   -> INVALID: Invalid version: '0.11.0+café'    (parsed fine on 23.2)

This degrades gracefully at both runtime call sites, which already catch InvalidVersion:

  • widget_versions._parse() (widget_versions.py:236-237) returns None, which the module documents as "older than everything" → the widget is reported as deprecated / needs-update.
  • The migration's _level_for_version() (0029_...py:31-32) returns LEVEL_NONE, the conservative auth level.

Since the only source of these strings is the attacker-controllable x-ocs-widget-version header (already length-capped at MAX_VERSION_LENGTH = 32), the change is a very slight tightening — no real widget emits a non-ASCII local segment.

Affected files: none require changes.

Test impact: none expected.

Configuration changes: none.

Incidental lockfile churn — flagging, not blocking

About 14 of the diff hunks have nothing to do with packaging. They strip markers from dependency edges:

-    { name = "google-auth", marker = "python_full_version >= '3.14'" },
+    { name = "google-auth" },
-    { name = "click", marker = "sys_platform != 'emscripten'" },
+    { name = "click" },

This is almost certainly an artefact of Dependabot resolving with a different uv version than the one that generated main's lock — uv is Rust and does not consume the Python packaging library, so the bump cannot be the cause. It is harmless: the edges only widen, the affected [[package]] entries keep their resolution-markers unchanged, and the two google-api-core / google-cloud-storage entries are still selected by Python version as before. On any real target (linux/macOS, py3.13) the installed set is byte-identical, which the name/version grep above confirms. uv lock --check passes with uv 0.12.1.

Expect it to flip back the next time someone runs uv lock locally. Worth a glance only if the team wants lock diffs to stay minimal.


🛠️ Recommendations

Action required: None. Merge once CI is green.

Testing focus — the widget version-policy paths, since they are the only runtime consumers:

  • apps/channels/tests/test_widget_versions.py
  • apps/channels/tests/test_widget_auth_level_ratchet.py
  • apps/api/tests/test_widget_version_tracking.py
  • apps/data_migrations/tests/test_notify_widget_version_release.py, test_notify_deprecated_widget_versions.py
  • Migration bot_channels.0029 forward-run on a copy of real data (it calls Version() on every stored widget_version)

Follow-up (optional, stylistic): the pyproject.toml floor moved >=23.2 → >=26.2. OCS only needs Version / InvalidVersion, stable since 20.x, so a >=26.2 floor is stricter than the code requires and is the one thing here that could bite later — it would conflict with any future dependency that caps packaging<27. Leaving the floor at >=23.2 and letting uv.lock carry 26.2 would be lower friction. Ignore if the convention is to track floors to the lock.

Merge recommendation: APPROVE


Verification notes (what I did and did not run)

Ran and confirmed green:

  • uv lock --check — lock consistent with pyproject.toml
  • Import smoke test of every packaging consumer in the tree: transformers, huggingface_hub, langchain_core, langsmith, celery, kombu, pytest, opentelemetry.sdk, google.cloud.storage, onnxruntime — all import cleanly against 26.2 (relevant because these call packaging.version.parse internally, the classic major-bump breakage vector). gunicorn is not in the dev sync, so it was not exercised.
  • The Version semantics table above, in the branch venv (packaging.__version__ == '26.2').

Not run here: the Django test suite. This sandbox has no .env or Postgres and I could not create them, so pytest fails at SECRET_KEY. The behavioural claims above rest on direct API-level verification plus grep coverage of every call site — please treat CI as the authority on the suite.

Pre-existing and unrelated: uv pip check reports langchain-voyageai requires Python >=3.10,<=3.13, but 3.13.14 is installed. That is a bad upper cap in that package, present on main too, and not introduced by this PR.


📚 Useful Links

Bumps [packaging](https://github.com/pypa/packaging) from 23.2 to 26.2.
- [Release notes](https://github.com/pypa/packaging/releases)
- [Changelog](https://github.com/pypa/packaging/blob/main/CHANGELOG.rst)
- [Commits](pypa/packaging@23.2...26.2)

---
updated-dependencies:
- dependency-name: packaging
  dependency-version: '26.2'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot
dependabot Bot force-pushed the dependabot/uv/packaging-26.2 branch from 2bc57a7 to 761455b Compare August 4, 2026 09:13
@claude

claude Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

🔍 Dependency Analysis Summary

One Python dependency changed; no JS/TS changes.

Package Old → New Jump Scope
packaging 23.2 → 26.2 +3 major versions Direct dep (pyproject.toml floor + uv.lock pin)

Overall risk: LOW. The version jump looks alarming, but OCS touches only two symbols from this library, and I verified their behaviour is byte-identical across the two versions rather than inferring it from the changelog.


📋 Detailed Changelog Review

Package: packaging (23.2 → 26.2), spanning 24.0, 24.1, 24.2, 25.0, 26.0, 26.1, 26.2.

Breaking changes / behaviour adaptations across the range (none of which OCS is exposed to — see Impact):

  • 24.0 — BREAKING: optional metadata.Metadata attributes now default to None. Epoch handling fixed in specifier matching.
  • 24.2 — PEP 639 License-Expression/License-File; PEP 730 iOS tags; prerelease detection fixed for > / <.
  • 25.0 — extras / dependency_groups markers; PEP 738 Android tags.
  • 26.0 — PEP 751 pylock support; PEP 440 prerelease handling changed for Specifier.contains; .contains now returns False instead of raising on an invalid version; extras normalisation fixed.
  • 26.1 — format_full_version renamed to _format_full_version (now private); local versions restricted to ASCII; pre-release exclusion narrowed for <V.postN, post-release exclusion narrowed for >V; Version.__replace__ normalised, Version.from_parts added; SpecifierSet.is_unsatisfiable added; & / | supported on Marker.
  • 26.2 — Fixes a real regression introduced in 25.0–26.1: Version, Specifier, SpecifierSet, Tag, Marker, and Requirement were not pickle-safe (including dangling references to the removed packaging._structures module). Also re-exports ExceptionGroup from packaging.metadata.

Security fixes: none in this range — no CVEs, no advisories. This is a maintenance/feature bump.

Migration notes: none required for OCS. packaging 26.2 declares Requires-Python >=3.8 and has zero runtime dependencies of its own, so it is compatible with this project's 3.13+ floor.

Worth noting the 26.2 pickle fix cuts the other way: do not downgrade this PR to 26.0 or 26.1, which carry the pickle regression. 26.2 is the correct landing point.


⚠️ Impact Assessment

Breaking changes affecting OCS: No.

OCS's entire usage of this library is Version and InvalidVersion:

  • apps/channels/widget_versions.py:15 — widget version policy (parse, compare, max(key=Version), str() round-trip)
  • apps/channels/migrations/0029_experimentchannel_required_auth_level.py:4 — auth-level grandfathering by stored widget_version
  • tasks.py:11 — dev-only Node version check against MIN_NODE_VERSION

None of the changed APIs (metadata.Metadata, Specifier.contains, format_full_version, tags, pylock, markers) are used anywhere in apps/, config/, or scripts/.

Differential verification. I ran every version string these three call sites can realistically receive through both 23.2 and 26.2 — real widget releases (0.4.2, 0.5.1, 0.6.0, 0.9.0, 0.11.0), the unknown sentinel, empty and unparseable input, semver prereleases (1.0.0-beta.1, 0.10.0-rc.1), a local segment (0.9.0+build.5), a non-ASCII local segment (0.9.0+bü, the input most likely to trip the 26.1 ASCII restriction), Node's 18 / 24.18.0, and normalisation edge cases (v0.9.0, " 0.9.0 ", 0.9, 0.09.0) — checking the parsed value, InvalidVersion behaviour, and < against each EMBED_KEY_INTRODUCED / SESSION_TOKEN_INTRODUCED / LATEST_VERSION / MIN_NODE_VERSION boundary.

The output was byte-identical between 23.2 and 26.2 for all 18 inputs. Notably 0.9.0+bü already raised InvalidVersion under 23.2, so the ASCII restriction changes nothing here, and it would be swallowed by the existing _parse() guard regardless.

Transitive dependents. 16 installed packages depend on packaging. No upper bound is violated — the only cap in the tree is langfuse: packaging>=23.2,<27.0, which 26.2 satisfies. I also grepped the whole venv for imports of internals removed in this range (packaging._structures, packaging.version._*, LegacyVersion, format_full_version, packaging._manylinux): the only hits are vendored copies inside numpy and pyarrow plus comments in google-cloud-bigquery, none of which import from the real packaging. An import smoke test of 17 consumers (langchain_core, langfuse, langsmith, transformers, huggingface_hub, kombu, celery, google.cloud.bigquery, google.cloud.aiplatform, onnxruntime, rest_framework_api_key, pytest, openai, anthropic, pandas, numpy) passed under 26.2.

Pickle regression exposure: none. Version objects never cross a Celery boundary in this codebase — ratchet_widget_auth_levels passes version strings and ints, and min_version_for_level() returns str. Immaterial anyway, since 26.2 fixes it.

Affected files: none need changes.

Test impact: none expected. python-tests passed on this SHA in CI. Locally I ran apps/channels/tests/test_widget_versions.py — all 32 non-DB tests pass; the 13 DB-backed tests could not run in my sandbox because Postgres wasn't reachable and I lacked permission to start it or write a .env. CI's green python-tests job covers those.

Configuration changes: none.


🛠️ Recommendations

Action required: none. Merge as-is.

Testing focus: nothing beyond CI. If you want a single manual sanity check, hit an API endpoint with an x-ocs-widget-version header of 0.4.2 and confirm the Deprecation / Sunset / Link headers still come back — that exercises the parse-compare path end to end.

Minor, optional (non-blocking): Dependabot raised the pyproject.toml floor to packaging>=26.2, but nothing in OCS needs anything newer than 23.2 — Version and InvalidVersion have been stable for years. Combined with langfuse's <27.0 cap, the resolvable window is now just [26.2, 27.0). That is fine today and consistent with how the other floors in this file are maintained, so no change is needed; flagging only in case the team prefers keeping loose floors and letting uv.lock do the pinning.

Follow-up tasks: none.

Merge recommendation: ✅ APPROVE

CI is green across python-tests, type-check, code-style, inline-imports, check-uv-lock, build-frontend, and CodeScene.


📚 Useful Links

@snopoke
snopoke merged commit a51b177 into main Aug 4, 2026
16 checks passed
@snopoke
snopoke deleted the dependabot/uv/packaging-26.2 branch August 4, 2026 09:40
@snopoke

snopoke commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

@claude please create a new PR to address this followup item:

Follow-up (optional nit, non-blocking): packaging>=26.2 in pyproject.toml is a much stricter floor than OCS needs. The only APIs used — Version and InvalidVersion — have been stable since well before 20.0. Dependabot raises the floor to the new version mechanically; a looser floor (>=23.2, i.e. a lock-only bump) would keep resolver headroom for any future co-installed package that caps packaging. Nothing in the tree caps it today, so this costs nothing right now — worth considering as a Dependabot config preference (versioning-strategy: lockfile-only / increase-if-necessary) rather than a change to this PR.

@claude

claude Bot commented Aug 4, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @snopoke's task in 3m 44s —— View job • claude/pr-4067-20260804-0943 • [Create PR ➔](https://github.com/dimagi/open-chat-studio/compare/main...claude/pr-4067-20260804-0943?quick_pull=1&title=PR%20%234067%3A%20Changes%20from%20Claude&body=This%20PR%20addresses%20pr%20%234067%0A%0AGenerated%20with%20%5BClaude%20Code%5D(https%3A%2F%2Fclaude.ai%2Fcode)


Follow-up PR created: #4087

  • Gather context (pyproject.toml floor conventions, .github/dependabot.yml)
  • Verify Dependabot versioning-strategy support for the uv ecosystem — ⚠️ couldn't confirm, see caveat below
  • Decide scope: config change and reverting the packaging floor
  • Implement
  • Verify what was verifiable
  • Push branch + open PR

→ #4087 chore(deps): stop Dependabot ratcheting uv dependency floors

What it does

Three lines of substance across three files:

# .github/dependabot.yml  (uv ecosystem)
+    versioning-strategy: "increase-if-necessary"
# pyproject.toml
-    "packaging>=26.2",
+    "packaging>=23.2",
# uv.lock  (root requires-dist only — resolved version stays 26.2)
-    { name = "packaging", specifier = ">=26.2" },
+    { name = "packaging", specifier = ">=23.2" },

Why increase-if-necessary and not lockfile-only

Your follow-up offered both. lockfile-only never touches the manifest at all, which would freeze the deps that are intentionally pinned or capped — pyTelegramBotAPI==4.12.0, Django<6, django-oauth-toolkit>=3.2.0,<4.0.0 — out of updates entirely, since a new release falls outside their declared range by construction. increase-if-necessary edits pyproject.toml only in that case, and updates uv.lock alone otherwise. That's exactly the "lock-only bump for floors, manifest bump when genuinely required" behaviour you described.

Scoped to the uv ecosystem only; npm / github-actions / pre-commit left alone.

I also confirmed >=23.2 was the literal pre-#4067 value (gh api .../pulls/4067/files), so the revert restores the previous state rather than inventing a floor.

Two caveats worth your eyes

  1. uv.lock was hand-edited. uv commands weren't permitted in this sandbox, so I edited the requires-dist specifier directly instead of running uv lock. It's what a re-lock produces for a floor loosening that doesn't change resolution — 26.2 satisfies >=23.2, and nothing in the tree constrains packaging — but treat CI's check-uv-lock as the authority. If it's red, a local uv lock fixes it.
  2. I could not verify that versioning-strategy is honoured for the uv ecosystem specifically. No web access this run, so I couldn't re-read the Dependabot options reference. It's supported for the Python ecosystems and uv support was built on that code path, but I'd rather flag it than assert it. After merge, an unsupported key shows up as a config error under Insights → Dependency graph → Dependabot; the next monthly uv PR is the real proof. The pyproject.toml revert stands on its own either way.

Not run: pytest, uv lock --check, pre-commit — no uv/python execution available here. Nothing changed is importable code, so CI's check-yaml / check-toml / check-uv-lock cover the surface.
· claude/pr-4067-20260804-0943

lisa-tarbo pushed a commit to lisa-tarbo/open-chat-studio that referenced this pull request Aug 4, 2026
Dependabot's default versioning strategy raises the pyproject.toml floor to
whatever version it just resolved, even when the code works fine on much older
releases. dimagi#4067 is the example: it moved the floor to `packaging>=26.2` although
OCS only uses `Version` and `InvalidVersion`, stable since well before 20.0.

Mechanically-raised floors cost resolver headroom — they make the project
unresolvable alongside any future co-installed package that caps the dependency,
for no benefit.

Set `versioning-strategy: increase-if-necessary` on the uv ecosystem so
Dependabot updates uv.lock alone and only edits pyproject.toml when the new
version genuinely falls outside the declared constraint. `increase-if-necessary`
rather than `lockfile-only` so intentionally pinned or capped deps
(`pyTelegramBotAPI==4.12.0`, `Django<6`, `django-oauth-toolkit<4.0.0`) can still
be updated — `lockfile-only` would freeze them out of updates entirely.

Also restore the `packaging` floor to `>=23.2` (its value before dimagi#4067). The
resolved version in uv.lock stays 26.2.

Co-authored-by: Simon Kelly <249606+snopoke@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file python:uv Pull requests that update python:uv code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant