in a custom target, I have a `StringField`. I know...
# development
f
in a custom target, I have a
StringField
. I know I can use
compute_value
to set a value for some field and it works. Now, if I want to set a field value based on the value that was passed in the BUILD file in a target declaration to another field, is using rules my only option or is there some other clever way to do it?
1
in BUILD file:
Copy code
mytarget(foo=10)
when inspecting the object I want the
mytarget
after creation to have
.bar = foo + 5
h
Yeah, using the rule is the only way to do it. Fields are 100% self-contained It's idiomatic to add a method on the Field though like
compute_based_on_foo(other_field: OtherField)
🙏 1
f
Another pattern you will see in Pants rules is to define a dataclass (or equivalent) to represent the values extracted from the targets separately from the actual targets. Then have most of your rules consume that dataclass. And just map the targets into that dataclass in a single rule once.
1
For example in the Go backend, most compilation is represented by
BuildGoPackageRequest
which has no reference to targets whatsoever.
There is a mapping rule that is able to convert targets into that dataclass.
c
FieldSet’s work like that as well (pretty much)…
f
hm, I am struggling to come up with a minimal example how to make sure a rule is executed. I follow the docs and can run
./pants peek project:
and can see
Copy code
custom_target(source="data.txt")
Copy code
[
  {
    "address": "project:project",
    "target_type": "custom_target",
    "custom_field": null,
    "dependencies": [],
    "dependencies_raw": null,
    "description": null,
    "source_raw": "data.txt",
    "sources": [
      "project/data.txt"
    ],
    "tags": null
  }
]
Now, what's the minimal thing I need to do to set the
custom_field
based on the value provided in
source_raw
? Or let's start with just accessing existing fields.
Copy code
@rule
async def example(custom_target: CustomTarget) -> None:
    <http://logger.info|logger.info>("Logged!")
    <http://logger.info|logger.info>(custom_target.alias)
    return

def rules():
    return (
        *collect_rules(),
    )
doesn't seem to be enough.
the Pants engine determines when rules are used and calls the rules for you.
Says the docs; how can I find out what kind of inputs and outputs do I need to provide to the rule so that Pants enginer would determine that it needs to be run?
h
with example, you will need to return something more interesting like
MyResult
. It's fine if it's an empty class. All the engine cares about is it's a distinct type (class) Then, something needs to request
MyResult
so that it gets executed, typically by using
Get(MyResult, CustomTarget)
inside something like a
@goal_rule
or one of our plugin hooks that get invoked by the builtin goal rules
f
our plugin hooks that get invoked by the builtin goal rules
hm, if I don't have a new goal, just want to populate fields for a target, where I can do
Get(MyResult, CustomTarget)
so that the field is visible, e.g. when doing
./pants peek
?
h
what is your end goal here? for it to render in
./pants peek
?
f
I think for now, yes 🙂
h
I think that would require a new plugin hook inside
./pants peek
for how to evaulate your field Instead, I recommend following the guide on Goal Rules and creating a dummy goal rule
f
oh I see. But with a dummy goal rule, I don't have to call the goal as
./pants my-dummy-goal target:
?
h
you can do
./pants my-dummy-goal
simply, and hardcode what target to run on inside the rule body
1
c
for whack-a-mole coding, there’s all sorts of ways to trigger custom rules from a
peek
invocation.. like registering a custom
ValidateDependenciesRequest
goal rule as one.. 😉
f
thank you all, I am able to progress. Went with a dummy goal to be able to interact with a target. Life is great again! 😄
to trigger custom rules from a
peek
invocation.. like registering a custom
ValidateDependenciesRequest
goal rule as one
@curved-television-6568 If you have an example, please share, if not, not a problem, I'll get to this at some point once I'm past the basic stuff 😄
❤️ 1