Pants can build [Python distributions](🔗), such as wheels and sdists, from information you provide in a [`
When doing so, and if you don't provide your own `
setup.py` file, Pants generates one and passes it the kwargs provided in the `
provides=python_artifact(...)` field to the `
setup(...)` call (Pants also generates some of the kwargs, such as `
install_requires` and `
namespace_packages` by analyzing your code).
It's fairly common to want to generate more of the kwargs dynamically. For example, you may want to:
Reduce boilerplate by not repeating common kwargs across BUILD files.
Read from the file system to dynamically determine kwargs, such as the `
long_description` or `
Run processes like `
git` to dynamically determine kwargs like `
You can write a plugin to add custom kwarg generation logic.
Note: there may only be at most one applicable plugin per target customizing the kwargs for the `
See [here](🔗) for an example that Pants uses internally for its `
python_distribution` targets. This plugin demonstrates reading from the file system to set the `
version` and `
long_description` kwargs, along with adding hardcoded kwargs.
Set up a subclass of `
Set the class method `
is_applicable()` to determine whether your implementation should be used for the particular `
python_distribution` target. If `
False`, Pants will use the default implementation which simply uses the explicitly provided `
python_artifact` from the BUILD file.
In this example, we will always use our custom implementation:
This example will only use our plugin implementation for `
python_distribution` targets defined in the folder `
Then, register your new `
SetupKwargsRequest ` with a [`
UnionRule`](🔗) so that Pants knows your implementation exists:
Consider defining custom `
python_distribution` target types
If you don't want to always use a single custom implementation, an effective approach could be to create custom `
python_distribution` target types so that your users decide which implementation they want to use in their BUILD files.
For example, a user could do this:
To support this workflow, [create new target types](🔗).
Then, for each `
SetupKwargsRequest` subclass, check which target type was used:
Create a rule with your logic
Your rule should take as a parameter the `
SetupKwargsRequest ` from step 1. This type has two fields: `
target: Target` and `
explicit_kwargs: dict[str, Any]`. You can use these fields to get more information on the target you are generating a `
Your rule should return `
SetupKwargs`, which takes two arguments: `
kwargs: dict[str, Any]` and `
For example, this will simply hardcode a kwarg:
Update your plugin's `
register.py` to activate this file's rules.
Then, run `
./pants package path/to:python_distribution` and inspect the generated `
setup.py`to confirm that your plugin worked correctly.
Often, you will want to read from a file in your project to set kwargs like `
version` or `
long_description`. Use `
await Get(DigestContents, PathGlobs)` to do this (see [File system](🔗)):
It can be helpful to allow users to add additional kwargs to their BUILD files for you to consume in your plugin. For example, this plugin adds a custom `
long_description_path` field, which gets popped and replaced by the plugin with a normalized `
Refer to these guides for additional things you may want to do in your plugin:
[Read from options](🔗). Also see [here](🔗) for an example.
[Read values from the target](🔗) using the Target API.
[Run a `
Process`](🔗), such as `
git`. Also see [Installing tools](🔗).