cool-easter-32542
05/14/2024, 11:46 PMall functionality for __default__ is somewhat of a future-compatibility hazard:
1. In a code base using Pants 2.34, there's a target t1 with a field called f (this could be in any backend, even a private in-repo one), and a second built-in target called t2 without that field.
2. Someone has an existing BUILD file like:
__defaults__(all=dict(f="abc"))
t1(name="one") # after applying __defaults__: t1(name="one", f="abc")
t2(name="two") # after applying __defaults__: t2(name="two")
3. In Pants 2.35, we now add a new field to t2 also called f.
4. When the code above upgrades to Pants 2.35, the t2 target will now become t2(name="two", f="abc") after applying __defaults__, and this could either:
1. silently change behaviour
2. fail with confusing error messages (if abc doesn't make sense for `t2`'s f field)
With Pants' current behaviour, if we wanted to be strict about not breaking existing code, this means we could never add new fields, because someone could have an existing field of the same name, and use it in __defaults__(all=...). Not ever adding new fields is clearly untenable, so either we have to:
1. allow breaking existing user code (but we could do things like improve diagnostics, or have a convention of calling it out in release notes or something)
2. change how all works (e.g. deprecate and remove it(!), have some notion of "all fields as of a particular release", so people need to bump that )
I think we should make an explicit policy decision (even if it's just "users just have to tolerate any breakage due to `all`").
* * *
For instance, in #20894 (comment), a user had:
__defaults__(
extend=True,
all=dict(
# This will set PYTHON_IMAGE build arg in all docker images by default.
extra_build_args=["PYTHON_IMAGE=python:3.11"],
# This will tell pants that all python sources need to use python 3.11 by default.
interpreter_constraints=["==3.11.*"],
),
)
In 2.20 and earlier (before #20737), the only built-in target with the extra_build_args field was docker_image, and so this all was applying that docker-formatted build arg to all.
In 2.21 (which includes #20737), pex_binary also has this field. It has completely different meaning (a list of CLI args to pass to a pex invocation). Thus, that __default__ configuration starts setting pex_binary(..., extra_build_args=["PYTHON_IMAGE=python:3.11"]) and understandably an invocation like pex ... PYTHON_IMAGE=python:3.11 doesn't work.
The fix the user identified is to move the field from all to `docker_image`:
__defaults__(
{
(docker_image,): dict(
# This will set PYTHON_IMAGE build arg in all docker images by default.
extra_build_args=["PYTHON_IMAGE=python:3.11"],
)
},
all=dict(
# This will tell pants that all python sources need to use python 3.11 by default.
interpreter_constraints=["==3.11.*"],
),
extend=True,
)
Pants version
All, although specific example is in 2.21
OS
All
Additional info
N/A
pantsbuild/pants