def test_generate_subtarget() -> None: class MockTarget(Target): alias = "mock_target" core_fields = (Dependencies, Tags, Sources) # When the target already only has a single source, the result should be the same, except for a # different address. single_source_tgt = MockTarget( {Sources.alias: ["demo.f95"], Tags.alias: ["demo"]}, address=Address("src/fortran", target_name="demo"), ) expected_single_source_address = Address( "src/fortran", relative_file_path="demo.f95", target_name="demo" ) assert generate_subtarget( single_source_tgt, full_file_name="src/fortran/demo.f95" ) == MockTarget( {Sources.alias: ["demo.f95"], Tags.alias: ["demo"]}, address=expected_single_source_address ) assert ( generate_subtarget_address(single_source_tgt.address, full_file_name="src/fortran/demo.f95") == expected_single_source_address ) subdir_tgt = MockTarget( {Sources.alias: ["demo.f95", "subdir/demo.f95"]}, address=Address("src/fortran", target_name="demo"), ) expected_subdir_address = Address( "src/fortran", relative_file_path="subdir/demo.f95", target_name="demo" ) assert generate_subtarget( subdir_tgt, full_file_name="src/fortran/subdir/demo.f95" ) == MockTarget({Sources.alias: ["subdir/demo.f95"]}, address=expected_subdir_address) assert ( generate_subtarget_address(subdir_tgt.address, full_file_name="src/fortran/subdir/demo.f95") == expected_subdir_address ) # The full_file_name must match the filespec of the base target's Sources field. with pytest.raises(ValueError) as exc: generate_subtarget(single_source_tgt, full_file_name="src/fortran/fake_file.f95") assert "does not match a file src/fortran/fake_file.f95" in str(exc.value) class MissingFieldsTarget(Target): alias = "missing_fields_tgt" core_fields = (Tags,) missing_fields_tgt = MissingFieldsTarget( {Tags.alias: ["demo"]}, address=Address("", target_name="missing_fields") ) with pytest.raises(ValueError) as exc: generate_subtarget(missing_fields_tgt, full_file_name="fake.txt") assert "does not have both a `dependencies` and `sources` field" in str(exc.value)
async def generate_subtargets(address: Address, global_options: GlobalOptions) -> Subtargets: if not address.is_base_target: raise ValueError( f"Cannot generate file Targets for a file Address: {address}") wrapped_base_target = await Get(WrappedTarget, Address, address) base_target = wrapped_base_target.target if not base_target.has_field(Dependencies) or not base_target.has_field( Sources): # If a target type does not support dependencies, we do not split it, as that would prevent # the base target from depending on its splits. return Subtargets(base_target, ()) # Create subtargets for matched sources. sources_field = base_target[Sources] sources_field_path_globs = sources_field.path_globs( global_options.options.files_not_found_behavior) # Generate a subtarget per source. paths = await Get(Paths, PathGlobs, sources_field_path_globs) sources_field.validate_resolved_files(paths.files) wrapped_subtargets = await MultiGet( Get( WrappedTarget, Address, generate_subtarget_address(address, full_file_name=subtarget_file), ) for subtarget_file in paths.files) return Subtargets(base_target, tuple(wt.target for wt in wrapped_subtargets))
async def generate_subtargets( address: Address, glob_match_error_behavior: GlobMatchErrorBehavior, ) -> Subtargets: if not address.is_base_target: raise ValueError( f"Cannot generate file Targets for a file Address: {address}") wrapped_base_target = await Get(WrappedTarget, Address, address) base_target = wrapped_base_target.target if not base_target.has_field(Dependencies) or not base_target.has_field( Sources): # If a target type does not support dependencies, we do not split it, as that would prevent # the base target from depending on its splits. return Subtargets(base_target, ()) # Create subtargets for matched sources. sources_field = base_target[Sources] sources_field_path_globs = sources_field.path_globs( glob_match_error_behavior) if sources_field_path_globs is None: return Subtargets(base_target, ()) # Generate a subtarget per source. snapshot = await Get(Snapshot, PathGlobs, sources_field_path_globs) sources_field.validate_snapshot(snapshot) wrapped_subtargets = await MultiGet( Get( WrappedTarget, Address, generate_subtarget_address(address, full_file_name=subtarget_file), ) for subtarget_file in snapshot.files) return Subtargets(base_target, tuple(wt.target for wt in wrapped_subtargets))
async def generate_subtargets(address: Address) -> Subtargets: if address.is_file_target: raise ValueError(f"Cannot generate file Targets for a file Address: {address}") wrapped_build_target = await Get(WrappedTarget, Address, address) build_target = wrapped_build_target.target if not build_target.has_field(Dependencies) or not build_target.has_field(Sources): # If a target type does not support dependencies, we do not split it, as that would prevent # the BUILD target from depending on its splits. return Subtargets(build_target, ()) # Generate a subtarget per source. paths = await Get(SourcesPaths, SourcesPathsRequest(build_target[Sources])) wrapped_subtargets = await MultiGet( Get( WrappedTarget, Address, generate_subtarget_address(address, full_file_name=subtarget_file), ) for subtarget_file in paths.files ) return Subtargets(build_target, tuple(wt.target for wt in wrapped_subtargets))