Write a patch

You want to change a package. This page shows how to make the patch file.

The paths in the patch must be relative to the package folder. For requests, that is the folder with requests/__init__.py in it. So a change to requests/utils.py shows up as utils.py in the patch.

1. Copy the package

Work on a copy, not on the venv:

PKG=$(python -c 'import requests, pathlib; print(pathlib.Path(requests.__file__).parent)')
cp -r "$PKG" /tmp/requests-work
cd /tmp/requests-work
rm -rf __pycache__
git init -q
git add .
git commit -qm base

[!TIP] Copy it from a venv that has no patches yet. Then your patch fits the package as it is installed.

2. Change it

Edit the files. Then commit, with a clear message:

git commit -am "Fix the timeout handling"

Make one commit per patch.

3. Save it

git format-patch -1 -o ~/project/patches/requests

This writes 0001-Fix-the-timeout-handling.patch. For more commits, use -2, -3 and so on. Each commit becomes its own file.

4. Add it to the patches file

version: 1
patches:
  - package: requests
    path: patches/requests/0001-Fix-the-timeout-handling.patch

The default apply-command is git am, which reads exactly this kind of file.

5. Try it

venv-patcher apply -f patches.yml
python -c 'import requests'   # still imports?

To change the patch and try again, see Work on a patch.

In the package folder

You can also work right in the venv. List the package without a patch:

version: 1
patches:
  - package: requests
venv-patcher apply -f patches.yml
initialized git tracking for requests at .../site-packages/requests (22992424)

The package folder is now a git repository. Change it, commit, and save the patch:

cd "$(python -c 'import requests, pathlib; print(pathlib.Path(requests.__file__).parent)')"
# edit files ...
git commit -am "Fix the timeout handling"
git format-patch -1 -o ~/project/patches/requests

Then add path to the entry, and apply it the normal way:

cd ~/project
venv-patcher apply --force -p requests -f patches.yml

--force drops your own commit and applies the saved patch instead. Now the manifest knows about it.

A plain diff

You can also use a plain diff, for example from diff -u or git diff. Then set apply-command:

version: 1
patches:
  - package: requests
    path: patches/requests/fix.diff
    apply-command: git apply
    comments: Fix the timeout handling

A plain diff has no message or author. comments gives the commit message. author, email and date give the rest. See The patches file.

Many patches for one package

List them in order. Each one builds on the one before:

version: 1
patches:
  - package: requests
    path: patches/requests/0001-Fix-the-timeout-handling.patch
  - package: requests
    path: patches/requests/0002-Log-retries.patch

See also