Skip to main content

pl_vendor

pl_vendor copies Git repositories or selected upstream directories into another repository as ordinary files and records their exact commits in a deterministic YAML lockfile. It supports optional downstream patches and can verify that checked-in vendor trees still match their locked upstream commits.

Requirements

  • Python 3.13 or newer
  • Git 2.30 or newer

The package has no Python runtime dependencies.

Every command checks the installed Git version before reading or changing vendored trees.

Configuration

Add a dependency interactively:

pl-vendor add

Or provide its settings as arguments (the path defaults to vendor/NAME and the branch defaults to main):

pl-vendor add example https://github.com/example/example.git vendor/example release

Dependencies can instead be pinned to an exact commit. Use --subdirectory to export only one directory from an upstream repository:

pl-vendor add prairielearn-schemas \
  https://github.com/PrairieLearn/PrairieLearn.git \
  .prairielearn/schemas \
  --commit 2c60f70a0ef817a2dc33fe15cb8e56de5035d6ed \
  --subdirectory apps/prairielearn/src/schemas/schemas

This creates or updates plvendor.toml at the root of the consuming Git repository, fetches the dependency, and records its revision. The resulting manifest looks like:

schema_version = 1

[dependencies.example]
path = "vendor/example"
url = "https://github.com/example/example.git"
branch = "release"

A commit-pinned subdirectory dependency looks like this:

[dependencies.prairielearn-schemas]
path = ".prairielearn/schemas"
url = "https://github.com/PrairieLearn/PrairieLearn.git"
commit = "2c60f70a0ef817a2dc33fe15cb8e56de5035d6ed"
subdirectory = "apps/prairielearn/src/schemas/schemas"

Every dependency must set exactly one of branch or commit. Commit values are complete lowercase 40-character Git SHAs. subdirectory is relative to the upstream repository and defaults to its root.

The generated plvendor-lock.yaml records the resolved commit:

lockfileVersion: 1

dependencies:
  example: '0123456789abcdef0123456789abcdef01234567'

Optional patches live at .vendor-patches/<dependency-name>.patch and are applied after selecting the upstream subdirectory, so patch paths are relative to the installed vendored tree.

Commands

pl-vendor update
pl-vendor update example
pl-vendor add example https://github.com/example/example.git --branch release
pl-vendor remove example
pl-vendor remove first second
pl-vendor lock
pl-vendor lock --check
pl-vendor lock --upgrade
pl-vendor lock --upgrade-package example
pl-vendor sync
pl-vendor sync example
pl-vendor check
pl-vendor require-latest
pl-vendor require-latest example second
pl-vendor verify

Like uv add and uv remove, pl-vendor add and pl-vendor remove update the manifest, lockfile, and installed files together. Remove accepts one or more dependency names and deletes their complete managed trees, including local or generated content. Removing the final dependency also removes the now-unused manifest and lockfile; downstream patches are retained.

pl-vendor lock fills missing lock entries while preferring existing revisions. Pass --upgrade or --upgrade-package NAME to explicitly advance branch dependencies; commit-pinned dependencies never advance. A commit pin is authoritative, so lock reconciles a stale lock entry to the manifest without contacting the remote. This does not modify vendored files.

pl-vendor update remains a convenience command that advances branch dependencies and syncs one or all dependencies in one step. For a pinned dependency, it installs the manifest commit and updates the lockfile to that exact value without rewriting the manifest. If the manifest exists but the lockfile does not, update bootstraps a complete lockfile from the manifest instead of requiring a separate lock step. Because the lockfile is generated state, update also replaces it when it has uncommitted changes; uncommitted manifest and vendored-tree changes remain protected.

pl-vendor sync does not update the lockfile: it replaces the selected vendored trees with their exact locked revisions and reapplies downstream patches. As with uv's default exact sync, local or generated files inside those managed trees are removed.

pl-vendor check reports commit-pinned dependencies as pinned and checks branch dependencies for newer revisions. Use pl-vendor require-latest [PACKAGE ...] in CI when pins should be forbidden: it fails for every selected commit-pinned dependency and for every selected branch dependency whose locked revision is not the branch head. With no package names, it checks all dependencies.

Each command discovers the consuming repository from the current directory. Pass --root PATH after the command to operate on a different repository.

Development

This repository uses uv 0.9 or newer to manage its development environment:

uv sync --dev
make test
make format
make build

The test suite is kept in the top-level tests directory so it is separate from the installable pl_vendor package.

To publish a release, start from a clean working tree and run:

make publish-version VERSION=0.2.0

This runs the test suite and static checks, updates pyproject.toml and uv.lock, builds the distributions, creates a release commit and annotated v0.2.0 tag, and atomically pushes both to origin. The tag starts the PyPI publishing workflow. Use REMOTE=name to publish through a different Git remote. The requested version must be semantically newer than the current package version and all local or remote release tags.

Release files for pl_vendor 0.3.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pl_vendor 0.3.2
File Size Uploaded
pl_vendor-0.3.2.tar.gz 26.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pl_vendor 0.3.2
File Interpreter ABI Platform
pl_vendor-0.3.2-py3-none-any.whl Python 3 none any Details

Total release size: 45.2 kB

Release files / pl_vendor-0.3.2.tar.gz

Download URL pl_vendor-0.3.2.tar.gz
Size 26.7 kB
Tags Source
SHA-256 checksum
How to use checksums
8ae52c1781376848dd202d36707e7d4108ca9e585707cb5923875068dc06e9a4
BLAKE2b-256 checksum
How to use checksums
5a5dbff9de97f4539f7b913c48af0908c8016f8109fa569945110075153aa5ea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release files / pl_vendor-0.3.2-py3-none-any.whl

Download URL pl_vendor-0.3.2-py3-none-any.whl
Size 18.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cc86fd75a2862f204b46e9a2f8ff3f1b63bf3e3ae8985e7473f590200c93ec0a
BLAKE2b-256 checksum
How to use checksums
59612a120aae12f9dd5f2475a9c92178fc4d9ebd68311319f3f51001f9b19237
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 19, 2026.

Transparency log

Release history Release notifications | RSS feed

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.4

2 release files

0.3.3

2 release files

This release

0.3.2 This release

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page