Skip to content

Commit d211819

Browse files
committed
Allow BXLs to make atarget_set. For symmetry with the other target set types.
facebook#1251
1 parent eaaa1a9 commit d211819

4 files changed

Lines changed: 108 additions & 0 deletions

File tree

app/buck2_bxl/src/bxl/starlark_defs/analysis_result.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use buck2_build_api::analysis::AnalysisResult;
1515
use buck2_build_api::interpreter::rule_defs::provider::collection::FrozenProviderCollection;
1616
use buck2_build_api::interpreter::rule_defs::provider::dependency::Dependency;
1717
use buck2_core::provider::label::ConfiguredProvidersLabel;
18+
use buck2_interpreter::types::configured_providers_label::StarlarkConfiguredProvidersLabel;
1819
use dupe::Dupe;
1920
use starlark::any::ProvidesStaticType;
2021
use starlark::environment::Methods;
@@ -100,6 +101,22 @@ fn starlark_analysis_result_methods(builder: &mut MethodsBuilder) {
100101
}
101102
}
102103

104+
/// Gets the configured providers label for this analysis result.
105+
///
106+
/// Sample usage:
107+
/// ```python
108+
/// def _impl_label(ctx):
109+
/// actions = ctx.aquery().all_actions("//target")
110+
/// for node in actions:
111+
/// if analysis := node.analysis():
112+
/// ctx.output.print(analysis.label())
113+
/// ```
114+
fn label<'v>(
115+
this: &StarlarkAnalysisResult,
116+
) -> starlark::Result<StarlarkConfiguredProvidersLabel> {
117+
Ok(StarlarkConfiguredProvidersLabel::new(this.label.dupe()))
118+
}
119+
103120
/// Converts the analysis result into a `Dependency`. Currently, you can only get a `Dependency` without any
104121
/// transitions. This means that you cannot create an exec dep or toolchain from an analysis result.
105122
///

app/buck2_bxl/src/bxl/starlark_defs/functions.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
use std::time::Instant;
1212

13+
use buck2_build_api::actions::query::ActionQueryNode;
1314
use buck2_build_api::interpreter::rule_defs::artifact::starlark_artifact_like::ValueAsInputArtifactLikeUnpack;
1415
use buck2_build_api::interpreter::rule_defs::cmd_args::value_as::ValueAsCommandLineLike;
1516
use buck2_core::cells::CellAliasResolver;
@@ -42,6 +43,7 @@ use super::context::output::get_cmd_line_inputs;
4243
use super::nodes::unconfigured::StarlarkTargetNode;
4344
use crate::bxl::starlark_defs::context::BxlContext;
4445
use crate::bxl::starlark_defs::eval_extra::BxlEvalExtra;
46+
use crate::bxl::starlark_defs::nodes::action::StarlarkActionQueryNode;
4547
use crate::bxl::starlark_defs::nodes::configured::StarlarkConfiguredTargetNode;
4648
use crate::bxl::starlark_defs::targetset::StarlarkTargetSet;
4749
use crate::bxl::starlark_defs::time::StarlarkInstant;
@@ -92,6 +94,30 @@ pub(crate) fn register_target_function(builder: &mut GlobalsBuilder) {
9294
.map(|node| node.0),
9395
))
9496
}
97+
98+
/// Creates a target set from a list of action query nodes.
99+
///
100+
/// Sample usage:
101+
/// ```python
102+
/// def _impl_atarget_set(ctx):
103+
/// actions = ctx.aquery().all_actions("//target")
104+
/// action_a = actions[0]
105+
/// action_b = actions[1]
106+
/// action_set = bxl.atarget_set([action_a, action_b])
107+
/// # Now can use in further queries
108+
/// deps = ctx.aquery().deps(action_set)
109+
/// ```
110+
fn atarget_set(
111+
nodes: Option<UnpackList<StarlarkActionQueryNode>>,
112+
) -> starlark::Result<StarlarkTargetSet<ActionQueryNode>> {
113+
Ok(StarlarkTargetSet::from_iter(
114+
nodes
115+
.unwrap_or(UnpackList::default())
116+
.items
117+
.into_iter()
118+
.map(|node| node.0),
119+
))
120+
}
95121
}
96122

97123
#[derive(Debug, buck2_error::Error, Clone)]

tests/core/query/aquery/test_aquery.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,15 @@ async def test_bxl_action_deps_0(buck: Buck) -> None:
167167
async def test_bxl_action_deps(buck: Buck) -> None:
168168
"""Test that you can isolate the deps of one action by itself"""
169169
await buck.bxl("//:aquery.bxl:action_deps")
170+
171+
172+
@buck_test()
173+
async def test_bxl_atarget_set(buck: Buck) -> None:
174+
"""Test bxl.atarget_set() creates a target set from ActionQueryNodes"""
175+
await buck.bxl("//:aquery.bxl:atarget_set_test")
176+
177+
178+
@buck_test()
179+
async def test_bxl_analysis_label(buck: Buck) -> None:
180+
"""Test analysis.label() returns the configured providers label"""
181+
await buck.bxl("//:aquery.bxl:analysis_label_test")

tests/core/query/aquery/test_aquery_data/aquery.bxl

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,3 +176,56 @@ action_deps = bxl_main(
176176
impl = _impl_action_deps,
177177
cli_args = {},
178178
)
179+
180+
def _impl_atarget_set_test(ctx):
181+
"""Test bxl.atarget_set() creates a target set from ActionQueryNodes"""
182+
nodes = ctx.aquery().eval("//:test")
183+
184+
# Get two action query nodes
185+
node_a = nodes[0]
186+
node_b = nodes[1]
187+
188+
# Create a target set from action query nodes
189+
action_set = bxl.atarget_set([node_a, node_b])
190+
191+
# Verify it's a target_set type
192+
_assert_eq(type(action_set), "target_set")
193+
194+
# Verify we can use it in further aquery operations
195+
deps = ctx.aquery().deps(action_set, depth = 0)
196+
_assert_eq(len(deps), 2)
197+
198+
atarget_set_test = bxl_main(
199+
impl = _impl_atarget_set_test,
200+
cli_args = {},
201+
)
202+
203+
def _impl_analysis_label_test(ctx):
204+
"""Test analysis.label() returns the configured providers label"""
205+
nodes = ctx.aquery().eval("//:test")
206+
207+
# Find an analysis node by iterating through results
208+
analysis = None
209+
for node in nodes:
210+
if node.rule_type == "analysis":
211+
analysis = node.analysis()
212+
break
213+
214+
if not analysis:
215+
fail("No analysis node found in results")
216+
217+
_assert_eq(type(analysis), "bxl.AnalysisResult")
218+
219+
# Test the label() method
220+
label = analysis.label()
221+
_assert_eq(type(label), "Label")
222+
223+
# Verify it's a valid label (should contain the target)
224+
label_str = str(label)
225+
if "root//:test" not in label_str:
226+
fail("Expected label to contain 'root//:test', got: {}".format(label_str))
227+
228+
analysis_label_test = bxl_main(
229+
impl = _impl_analysis_label_test,
230+
cli_args = {},
231+
)

0 commit comments

Comments
 (0)