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

## 2.8

See https://github.com/pantsbuild/pants/blob/main/src/python/pants/notes/2.8.x.md for the changelog.

### Target modeling changes

Pants 2.8 cleaned up the modeling of targets. Now, there are targets that describe the atom of each language, like `python_test` and `python_source` which correspond to a single file. There are also target generators which exist solely for less boilerplate, like `python_tests` and `python_sources`.

We recommend re-reading [Targets and BUILD files](🔗).

#### `SourcesField`

The `Sources` class was replaced with `SourcesField`, `SingleSourceField`, and `MultipleSourcesField`.

When defining new target types with the Target API, you should choose between subclassing `SingleSourceField` and `MultipleSourcesField`, depending on if you want the field to be `source: str` or `sources: list[str]`.

Wherever you were using `Sources` in your `@rule`s, simply replace with `SourcesField`.

#### Renames of some `Sources` subclasses

You should update all references to these classes in your `@rule`s.

  • `FilesSources` -> `FileSourceField`

  • `ResourcesSources` -> `ResourceSourceField`

  • `PythonSources` -> `PythonSourceField`

### `OutputPathField.value_or_default()`

The method `OutputPathField.value_or_default()` no longer takes `Address` as an argument.

## 2.7

See https://github.com/pantsbuild/pants/blob/main/src/python/pants/notes/2.7.x.md for the changelog.

### Type hints work properly

Pants was not using PEP 561 properly, which means that MyPy would not enforce type hints when using Pants APIs. Oops! This is now fixed.

### Options scopes should not have `_`

For example, use `my-subsystem` instead of `my_subsystem`. This is to avoid ambiguity with target types.

## 2.6

See https://github.com/pantsbuild/pants/blob/main/src/python/pants/notes/2.6.x.md for the changelog.

### `ProcessCacheScope`

`ProcessCacheScope.NEVER` was renamed to `ProcessCacheScope.PER_SESSION` to better reflect that a rule never runs more than once in a session (i.e. a single Pants run) given the same inputs.

`ProcessCacheScope.PER_RESTART` was replaced with `ProcessCacheScope.PER_RESTART_ALWAYS` and `ProcessCacheScope.PER_RESTART_SUCCESSFUL`.

### `PexInterpreterConstraints`

Now called `InterpreterConstraints` and defined in `pants.backend.python.util_rules.interpreter_constraints`.

## 2.5

See https://github.com/pantsbuild/pants/blob/main/src/python/pants/notes/2.5.x.md for the changelog.

### `TriBoolField`

`BoolField.value` is no longer `bool | None`, but simply `bool`. This means that you must either set `required = True` or set the `default`.

Use `TriBoolField` if you still want to be able to represent a trinary state: `False`, `True`, and `None`.

### Added `RuleRunner.write_files()`

This is a more declarative way to set up files than the older API of `RuleRunner.create_file()`, `.create_files()`, and `.add_to_build_files()`. See [Testing plugins](🔗).

## 2.4

See https://github.com/pantsbuild/pants/blob/main/src/python/pants/notes/2.4.x.md for the changelog.

### `PexRequest` changes how entry point is set

See https://github.com/pantsbuild/pants/pull/11620. Instead of setting `entry_point="pytest"` in the `PexRequest` constructor, now you set `main=ConsoleScript("black")` or `main=EntryPoint("pytest")`.

### Must use `EnvironmentRequest` for accessing environment variables

See https://github.com/pantsbuild/pants/pull/11641. Pants now eagerly purges environment variables from the run, so using `os.environ` in plugins won't work anymore.

Instead, use `await Get(Environment, EnvironmentRequest(["MY_ENV_VAR"])`.

For `RuleRunner` tests, you must now either set `env` or the new `env_inherit` arguments for environment variables to be set. Tests are now hermetic.

## 2.3

There were no substantial changes to the Plugin API in 2.3. See https://github.com/pantsbuild/pants/blob/main/src/python/pants/notes/2.3.x.md for the changelog.

## 2.2

See https://github.com/pantsbuild/pants/blob/main/src/python/pants/notes/2.2.x.md for the changelog.

### `PrimitiveField` and `AsyncField` are removed (2.2.0.dev0)

Rather than subclassing `PrimitiveField`, subclass `Field` directly. `Field` now behaves like `PrimitiveField` used to, and `PrimitiveField` was removed for simplicity.

Rather than subclassing `AsyncField` or `AsyncStringSequenceField`, subclass `Field` or a template like `StringField` and also subclass `AsyncFieldMixin`:

Async fields now access the raw value with the property `.value`, rather than `.sanitized_raw_value`. To override the eager validation, override `compute_value()`, rather than `sanitize_raw_value()`. Both these changes bring async fields into alignment with non-async fields.

### Set the property `help` with Subsystems, Targets, and Fields (2.2.0.dev3)

Previously, you were supposed to set the class's docstring for the `./pants help` message. Instead, now set a class property `help`, like this:

Pants will now properly wrap strings and preserve newlines. You may want to run `./pants help ${target/subsystem}` to verify things render properly.

## 2.1

See https://github.com/pantsbuild/pants/blob/master/src/python/pants/notes/2.1.x.rst for the changelog.

### `SourcesSnapshot` is now `SpecsSnapshot` (2.1.0rc0)

The type was renamed for clarity. Still import it from `pants.engine.fs`.

## 2.0

See https://github.com/pantsbuild/pants/blob/master/src/python/pants/notes/2.0.x.rst for the changelog.

### Use `TransitiveTargetsRequest` as input for resolving `TransitiveTargets` (2.0.0rc0)

Rather than `await Get(TransitiveTargets, Addresses([addr1]))`, use `await Get(TransitiveTargets, TransitiveTargetsRequest([addr1]))`, from `pants.engine.target`.

It's no longer possible to include `TransitiveTargets` in your `@rule` signature in order to get the transitive closure of what the user specified on the command. Instead, put `Addresses` in your rule's signature, and use `await Get(TransitiveTargets, TransitiveTargetsRequest(addresses))`.

### Codegen implementations: use `DependenciesRequestLite` and `TransitiveTargetsLite` (2.0.0rc0)

Due to a new cycle in the rule graph, for any codegen implementations, you must use `DependenciesRequestLite` instead of `DependenciesRequest`, and `TransitiveTargetsLite` instead of `TransitiveTargetsRequest`. Both imports are still from `pants.engine.target`.

These behave identically, except that they do not include dependency inference in the results. Unless you are generating for `input = PythonSources`, this should be fine, as dependency inference is currently only used with Python.

This is tracked by https://github.com/pantsbuild/pants/issues/10917.

### Dependencies-like fields have more robust support (2.0.0rc0)

If you have any custom fields that act like the dependencies field, but do not subclass `Dependencies`, there are two new mechanisms for better support.

  1. Instead of subclassing `StringSequenceField`, subclass `SpecialCasedDependencies` from `pants.engine.target`. This will ensure that the dependencies show up with `./pants dependencies` and `./pants dependees`.

  2. You can use `UnparsedAddressInputs` from `pants.engine.addresses` to resolve the addresses:

If you defined a subclass of `SpecialCasedDependencies`, you can use `await Get(Addresses | Targets, UnparsedAddressInputs, my_tgt[MyField].to_unparsed_address_inputs())`.

(Why would you ever do this? If you have dependencies that you don't treat like normal—e.g. that you will call the equivalent of `./pants package` on those deps—it's often helpful to call out this magic through a dedicated field. For example, Pants's [archive](🔗) target type has the fields `files` and `packages`, rather than `dependencies`.)

### `package` implementations may want to add the field `output_path` (2.0.0rc0)

All of Pants's target types that can be built via `./pants package` now have an `output_path` field, which allows the user to override the path used for the created asset.

You optionally may want to add this `output_path` field to your custom target type for consistency:

  1. Include `OutputPathField` from `pants.core.goals.package` in your target's `core_fields` class property.

  2. In your `PackageFieldSet` subclass, include `output_path: OutputPathField`.

  3. When computing the filename in your rule, use `my_package_field_set.output_path.value_or_default(field_set.address, file_ending="my_ext")`.