repomatic.deps.sources module¶

Swap git-tracked dependencies back to their released versions.

The sync-dep-sources updater manages one precise idiom: a dependency temporarily consumed from a git branch while its next release is awaited. The idiom is machine-recognizable because it pairs two declarations in pyproject.toml:

  • a [tool.uv.sources] entry tracking a branch (not a rev or tag pin), and

  • a dev-version floor on the same package (like mango>=2.1.0.dev0), whose base version names the awaited release.

Once the awaited release ships on the index, the swap rewrites the project back to released artifacts: the source override is dropped, the .dev floor is tightened to its base release, and a cooldown-bypass freeze adopts the release through the exclude-newer window (the same deliberate-bypass mechanism audit --fix uses for security fixes). The freeze then ages out and is pruned by the ordinary sync-uv-lock lifecycle.

Note

The dev floor is authoritative, deliberately: the project declares that anything from the awaited release onward satisfies it. If the project quietly grew a dependency on branch commits newer than the release, the swap PR’s CI run exposes the stale declaration, and the correction (bumping the floor to the next .dev version, which retracts the swap on the next run) is exactly the fix the project needed anyway. Overrides outside the idiom (path or workspace sources, rev/tag pins, floor-less branch tracks) are never touched.

The release gate that refuses to ship while such an override stands lives in repomatic.deps.shippable.

repomatic.deps.sources.DEV_BOUND_PATTERN = re.compile('(?P<op>>=?)\\s*(?P<version>[0-9][A-Za-z0-9.!+]*)')¶

Lower-bound clauses in a PEP 508 requirement string.

Captures the operator and the version literal so strip_dev_bounds() can rewrite >=2.1.0.dev0 into >=2.1.0 in place, leaving extras, markers, and every other clause byte-for-byte untouched.

class repomatic.deps.sources.ReleaseSwap(name, source_key, branch, floor, release, released)[source]¶

Bases: object

A git-tracked dependency whose awaited release has shipped.

Built by find_ready_swaps(); consumed by apply_release_swaps() (the pyproject.toml rewrite) and format_swap_section() (the PR report).

name: str¶

Normalized package name, as it appears on PyPI and in uv.lock.

source_key: str¶

The entry key as written in [tool.uv.sources] (may differ from name in case or separators).

branch: str¶

The git branch the override tracks.

floor: str¶

The .dev version floor that named the awaited release.

release: str¶

The adopted release version, the newest stable satisfying the floor.

released: str¶

Upload date of release (YYYY-MM-DD), from the index.

property freeze_cutoff: str¶

The exclude-newer-package cutoff adopting release.

Delegates the margin policy to repomatic.deps.cooldown.freeze_cutoff_after(): every distribution file of the adopted release sits inside the window even when its uploads straddle midnight, while the global cooldown still shields anything newer.

repomatic.deps.sources.tracked_git_overrides(doc)[source]¶

Read the [tool.uv.sources] entries tracking a git branch.

Only single-source entries carrying both a git URL and a branch are returned: a rev or tag pin is a deliberate point-in-time choice, a path or workspace source is a local development arrangement, and a multi-source list (per-platform markers) is too bespoke to rewrite. None of those encode “waiting for the next release”.

Parameters:

doc (Mapping[str, Any]) – The parsed pyproject.toml.

Return type:

dict[str, str]

Returns:

Source-entry key to tracked branch name; empty when the table is absent.

repomatic.deps.sources.find_ready_swaps(doc)[source]¶

Probe the index for git-tracked packages whose awaited release shipped.

For each branch-tracking override inside the managed idiom, the awaited release is considered shipped once PyPI carries a stable (non-prerelease, non-yanked) version satisfying the dev floor. The newest such release is adopted. Index misses (an unpublished package, a network failure) read as “not ready”: a swap needs positive confirmation, so the failure mode is always a skipped run, never a wrong rewrite.

Parameters:

doc (Mapping[str, Any]) – The parsed pyproject.toml.

Return type:

list[ReleaseSwap]

Returns:

Ready swaps sorted by package name; empty when there is nothing to do.

repomatic.deps.sources.strip_dev_bounds(requirement, release)[source]¶

Tighten a requirement string’s .dev lower bounds to their release.

Rewrites only the version literal of >=/> clauses whose version is a dev release older than or equal to release, replacing it with its base version (>=2.1.0.dev0 becomes >=2.1.0). Everything else in the string (extras, markers, other clauses, spacing) is preserved byte-for-byte.

Parameters:
  • requirement (str) – The PEP 508 requirement string.

  • release (str) – The adopted release; bounds newer than it are left alone (they await a later release).

Return type:

str

Returns:

The rewritten string, or the original when nothing matched.

repomatic.deps.sources.apply_release_swaps(doc, swaps)[source]¶

Rewrite a parsed pyproject.toml for the given swaps, in place.

Two of the three swap edits happen here: the [tool.uv.sources] override is removed (and the emptied table with it), and every .dev floor on the swapped packages is tightened to its base release. The third edit, the cooldown-bypass freeze at ReleaseSwap.freeze_cutoff, goes through repomatic.deps.cooldown.UvSettings.upsert() so the insertion position and inline-table formatting stay canonical.

Parameters:
Return type:

None

repomatic.deps.sources.SWAP_SECTION_NOTE = 'Dependencies tracked from a git branch while awaiting a release, swapped back to the package index: the `[tool.uv.sources]` override is dropped, the `.dev` version floor is tightened to its release form, and a cooldown bypass freezes the adoption until it ages past the [`exclude-newer`](https://docs.astral.sh/uv/reference/settings/#exclude-newer) cutoff.'¶

Intro paragraph for the sync-dep-sources swap section.

repomatic.deps.sources.format_swap_section(swaps, *, name_urls=None, reference_date=None)[source]¶

Format the release swaps as a markdown section.

The sync-dep-sources report section explaining the pyproject.toml hunks: one row per swapped package, with the branch it tracked, the release it adopted, and when that release shipped.

Parameters:
  • swaps (list[ReleaseSwap]) – Ready swaps from find_ready_swaps().

  • name_urls (Mapping[str, str] | None) – Optional mapping of names to a URL the name links to. Names absent from the mapping render plain.

  • reference_date (date | None) – When set, the “Released” date gains a relative hint measured from this date.

Return type:

str

Returns:

A markdown string with a ## 🔀 Source swaps heading and table, or an empty string when swaps is empty.