You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This extends then `pants.backend.experimental.nfpm` backend's plugin
API, allowing multiple implementations of this polymorphic-rule plugin
hook (before this change, only one implementation was allowed):
- `inject_nfpm_package_fields(InjectNfpmPackageFieldsRequest) -> InjectedNfpmPackageFields`
Unlike many polymorphic/union rules, each rule runs sequentially instead
of concurrently. This is conceptually similar to middleware, because the
request passed to each rule includes the results of the previous (lower
priority) rule. So, one rule can override or extend fields that were
injected in previous rules, not just the original fields from the
BUILD-file-based `nfpm_*_package` target.
I tried several approaches to sorting the request classes, but most were
error prone or simply didn't work. Heuristic-based sorting proved to be
complex and didn't work in all of my test cases (eg one heuristic was
looking at the class's module to make pants-provided requests lower
priority). A simple `priority` integer is far simpler and more reliable,
so that's what this implements.
Another thing that didn't work was adding `__lt__` as a `@classmethod`
on the abstract `InjectNfpmPackageFieldsRequest`. That fails because
`sorted()` requires an instance method, not a class method. The only way
I found to add an `__lt__` method on a class is via a metaclass. So,
this adds a `_PrioritizedSortableClassMetaclass` to
`InjectNfpmPackageFieldsRequest` allowing for simple `OneRequest <
TwoRequest` sorting of the class type like this:
```diff
inject_nfpm_config_request_types = union_membership.get(InjectNfpmPackageFieldsRequest)
applicable_inject_nfpm_config_request_types = tuple(
- request
- for request in inject_nfpm_config_request_types
- if request.is_applicable(target)
+ sorted(
+ request_type
+ for request_type in inject_nfpm_config_request_types
+ if request_type.is_applicable(target)
+ )
)
```
Then, to make subclasses higher priority than their parent classes, I
added an `__init_subclass__` method that increases `cls.priority`
(unless the subclass already has a different priority than the parent
class). It's a little odd to use both a metaclass and
`__init_subclass__`, but I did not like the idea of re-implementing the
on-subclass-creation logic in our metaclass.
`InjectNfpmPackageFieldsRequest` was initially modeled on the python
backend's `SetupKwargsRequest` [1].
If the rule-chaining proves itself in the experimental `nfpm` backend,
maybe we can move `_PrioritizedSortableClassMetaclass` out of the
backend to somewhere in pants core, updating `SetupKwargsRequest` and
related rules to make use of rule-chaining as well.
[1] https://www.pantsbuild.org/stable/docs/writing-plugins/common-plugin-tasks/custom-python-artifact-kwargs
Copy file name to clipboardExpand all lines: docs/notes/2.31.x.md
+2Lines changed: 2 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -46,6 +46,8 @@ Pants no longer supports loading `pkg_resources`-style namespace packages for pl
46
46
47
47
Added a new rule to help in-repo plugins implement the `inject_nfpm_package_fields(InjectNfpmPackageFieldsRequest) -> InjectedNfpmPackageFields` polymorphic rule. The `get_package_field_sets_for_nfpm_content_file_deps` rule (in the `pants.backend.nfpm.util_rules.contents` module) collects selected `PackageFieldSet`s from the contents of an `nfpm_*_package` so that the packages can be analyzed to inject things like package requirements.
48
48
49
+
Added prioritized rule chaining for `InjectNfpmPackageFieldsRequest` polymorphic rule implementations. Before, only one request type was allowed to inject fields on each `nfpm_*_package` target. Now, the `InjectNfpmPackageFieldsRequest` subclasses can declare a priority (as `ClassVar[int]`) so that the rule runs after lower-priority requests and before higher-priority requests. By default, `InjectNfpmPackageFieldsRequest` implementations are priority 10, and any subclasses have that priority increased by 1 so that the subclass is higher priority than its parent class. Any implementations distributed with pants should have a lower priority (`< 10`) so that in-repo and external plugins can override the pants-provided defaults.
50
+
49
51
## Full Changelog
50
52
51
53
For the full changelog, see the individual GitHub Releases for this series: <https://github.com/pantsbuild/pants/releases>
0 commit comments