Hey! These docs are for version 2.14, which is no longer officially supported. Click here for the latest version, 2.17!

Pants can build [Python distributions](🔗), such as wheels and sdists, from information you provide in a [`python_distribution`](🔗) target.

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 `version`.

  • Run processes like `git` to dynamically determine kwargs like `version`.

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 `setup()` function.


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.

  1. Set up a subclass of `SetupKwargsRequest`

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 `src/python/project1`.

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:

  1. 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 `setup.py` for.

Your rule should return `SetupKwargs`, which takes two arguments: `kwargs: dict[str, Any]` and `address: Address`.

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 `long_description` kwarg:

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](🔗).