Skip to content

Commit e61cd02

Browse files
Merge pull request #940 from tiran/proposal-new-patcher-config
[proposal] New patcher config
2 parents d86f938 + 4c3c7ca commit e61cd02

3 files changed

Lines changed: 129 additions & 0 deletions

File tree

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ Contributing to fromager.
7676
:maxdepth: 2
7777

7878
develop.md
79+
proposals/index.rst
7980

8081
What's with the name?
8182
---------------------

docs/proposals/index.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Fromager Enhancement Proposals
2+
==============================
3+
4+
.. toctree::
5+
:maxdepth: 1
6+
7+
new-patcher-config
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# New patching configuration
2+
3+
- Author: Christian Heimes
4+
- Created: 2026-02-26
5+
- Status: Open
6+
7+
## What
8+
9+
This enhancement document proposes a new approach to patch sources and wheel
10+
metadata through declarative configuration. The new feature supplements
11+
current features like patch files and plugin hooks.
12+
13+
## Why
14+
15+
Fromager supports patch files and modifications with Python plugins. Patch
16+
files are limited, because they either apply to a single version or to all
17+
versions of a package. Python plugins are harder to write and take more
18+
effort.
19+
20+
Fromager already supports limited patching of `pyproject.toml` with the
21+
package setting option `project_override`.
22+
23+
## Goals
24+
25+
- provide simple, extensible patching facilities with a declarative
26+
configuration approach
27+
- support version-specific patching (e.g. patch build system requirements for
28+
`>=1.0,<1.0`).
29+
- make common tasks like fixing sdist metadata (`PKG-INFO`) easier
30+
- enable patching of wheel and sdist package metadata so users can pin
31+
installation requirements (`requires-dist`) to constraints. The feature is
32+
designed to pin Torch version to ensure `libtorch` ABI compatibility.
33+
34+
## Non-goals
35+
36+
- patch files will not be deprecated and removed. Patches are still useful
37+
and will be supported in the future.
38+
- CPU architecture-specific and variant-specific patches won't be supported,
39+
They are considered a misfeature. Patches should be architecture-
40+
independent, so they can be pushed to upstream eventually.
41+
- patching of installation requirements (`requires-dist`) beyond pinning to
42+
constraints. Dependency issues should be fixed in upstream projects.
43+
44+
## How
45+
46+
The new system will use a new top-level configuration key `patch`, which is
47+
an array of patch operations. Each patch operation has a title, optional
48+
version specifier, and an action like `replace-line`, `fix-pkg-info`, or
49+
`pyproject-build-system`.
50+
51+
- The action name acts as a tag ([discriminated union](https://docs.pydantic.dev/latest/concepts/unions/#discriminated-unions)).
52+
- The `title` is a human-readable description that explains the purpose of
53+
the operation.
54+
- The optional field `when_version` can be used to limit the action,
55+
e.g. `>=1.0,<2.0`.
56+
> **NOTE**: `when_version` is not compatible with nightly builds.
57+
- Some actions have a `ignore_missing` boolean flag. If an action has no
58+
effect, then it fails and stops the build unless `ignore_missing` is set.
59+
- All file names are relative to `sdist_root_dir`.
60+
- Most patch actions are executed in `prepare_source` phase. Actions that
61+
affect `requires-dist` are run in `get_install_dependencies_of_sdist`
62+
and after `build_wheel` hook.
63+
64+
### Example actions
65+
66+
At first, we will implement a few patch actions that will cover the most
67+
common cases. In the future, we may add additional patch actions.
68+
69+
- The `replace-line` action replaces lines in one or more files.
70+
71+
- The `delete-line` action removes a line from one or more files.
72+
73+
- The `pyproject-build-system` action replaces the old `project_override`
74+
settings `update_build_requires` and `remove_build_requires`.
75+
76+
- The `fix-pkg-info` action addresses issues with sdist's `PKG-INFO` files,
77+
e.g. wrong metadata version.
78+
79+
- The `pin-requires-dist-to-constraint` action pins `requires-dist` in sdist
80+
and wheel metadata to the values of global constraints. The primary use
81+
case is Torch. If a package is built with Torch 2.10.0 constraint, then
82+
we want the wheel to depend on exactly `torch==2.10.0`.
83+
84+
```yaml
85+
patch:
86+
- title: Comment out 'foo' requirement for version >= 1.2
87+
action: replace-line
88+
files:
89+
- 'requirements.txt'
90+
search: '^(foo.*)$'
91+
replace: '# \\1'
92+
when_version: '>=1.2'
93+
ignore_missing: true
94+
95+
- title: Remove 'bar' from constraints.txt
96+
action: delete-line
97+
files:
98+
- 'constraints.txt'
99+
search: 'bar.*'
100+
101+
- title: Fix PKG-INFO metadata and update metadata version
102+
action: fix-pkg-info
103+
metadata_version: '2.4'
104+
when_version: '<1.0'
105+
106+
- title: Add missing setuptools to pyproject.toml
107+
action: pyproject-build-system
108+
update_build_requires:
109+
- setuptools
110+
111+
- title: Pin Torch to global constraint
112+
action: pin-requires-dist-to-constraint
113+
requirements:
114+
- torch
115+
```
116+
117+
### Deprecations
118+
119+
The old settings `project_override.update_build_requires` and
120+
`project_override.remove_build_requires` will be deprecated and eventually
121+
removed.

0 commit comments

Comments
 (0)