<#20925 `__defaults__(all=...)` is a future-compat...
# github-notifications
c
#20925 `__defaults__(all=...)` is a future-compatibility hazard for adding new field Issue created by huonw Describe the bug The
all
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:
Copy code
__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:
Copy code
__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`:
Copy code
__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