Exemplo n.º 1
0
def test_explicitly_provided_dependencies_disambiguated() -> None:
    def get_disambiguated(
        ambiguous: List[Address],
        *,
        ignores: Optional[List[Address]] = None,
        includes: Optional[List[Address]] = None,
        owners_must_be_ancestors: bool = False,
    ) -> Optional[Address]:
        epd = ExplicitlyProvidedDependencies(
            address=Address("dir", target_name="input_tgt"),
            includes=FrozenOrderedSet(includes or []),
            ignores=FrozenOrderedSet(ignores or []),
        )
        return epd.disambiguated(
            tuple(ambiguous),
            owners_must_be_ancestors=owners_must_be_ancestors)

    # A mix of normal and generated addresses.
    addr_a = Address("dir", target_name="a", generated_name="gen")
    addr_b = Address("dir", target_name="b", generated_name="gen")
    addr_c = Address("dir", target_name="c")
    all_addr = [addr_a, addr_b, addr_c]

    # If 1 target remains, it's disambiguated. Note that ignores can be normal or generated targets.
    assert get_disambiguated(all_addr, ignores=[addr_b, addr_c]) == addr_a
    assert (get_disambiguated(
        all_addr, ignores=[addr_b.maybe_convert_to_target_generator(),
                           addr_c]) == addr_a)

    assert get_disambiguated(all_addr, ignores=[addr_a]) is None
    assert get_disambiguated(
        all_addr, ignores=[addr_a.maybe_convert_to_target_generator()]) is None
    assert get_disambiguated(all_addr, ignores=all_addr) is None
    assert get_disambiguated([]) is None
    # If any includes would disambiguate the ambiguous target, we don't consider disambiguating
    # via excludes as the user has already explicitly disambiguated the module.
    assert get_disambiguated(
        all_addr, ignores=[addr_a, addr_b], includes=[addr_a]) is None
    assert (get_disambiguated(
        ambiguous=all_addr,
        ignores=[addr_a, addr_b],
        includes=[addr_a.maybe_convert_to_target_generator()],
    ) is None)

    # You can also disambiguate via `owners_must_be_ancestors`.
    another_dir = Address("another_dir")
    assert get_disambiguated([addr_a, another_dir],
                             owners_must_be_ancestors=True) == addr_a
    assert get_disambiguated([addr_a, another_dir],
                             owners_must_be_ancestors=False) is None
    assert (get_disambiguated([addr_a, addr_b, another_dir],
                              ignores=[addr_b],
                              owners_must_be_ancestors=True) == addr_a)
Exemplo n.º 2
0
async def find_build_file(address: Address) -> BuildFileAddress:
    address_family = await Get(AddressFamily,
                               AddressFamilyDir(address.spec_path))
    owning_address = address.maybe_convert_to_target_generator()
    if address_family.get_target_adaptor(owning_address) is None:
        raise ResolveError.did_you_mean(
            bad_name=owning_address.target_name,
            known_names=address_family.target_names,
            namespace=address_family.namespace,
        )
    bfa = next(build_file_address
               for build_file_address in address_family.build_file_addresses
               if build_file_address.address == owning_address)
    return BuildFileAddress(
        address, bfa.rel_path) if address.is_generated_target else bfa
Exemplo n.º 3
0
async def resolve_target(
    address: Address,
    registered_target_types: RegisteredTargetTypes,
    union_membership: UnionMembership,
    target_types_to_generate_requests: TargetTypesToGenerateTargetsRequests,
) -> WrappedTarget:
    if not address.is_generated_target:
        target_adaptor = await Get(TargetAdaptor, Address, address)
        target_type = registered_target_types.aliases_to_types.get(
            target_adaptor.type_alias, None)
        if target_type is None:
            raise UnrecognizedTargetTypeException(target_adaptor.type_alias,
                                                  registered_target_types,
                                                  address)
        if (target_type.deprecated_alias is not None
                and target_type.deprecated_alias == target_adaptor.type_alias
                and not address.is_generated_target):
            await Get(_WarnDeprecatedTarget,
                      _WarnDeprecatedTargetRequest(target_type))
        target = target_type(target_adaptor.kwargs, address, union_membership)
        return WrappedTarget(target)

    wrapped_generator_tgt = await Get(
        WrappedTarget, Address, address.maybe_convert_to_target_generator())
    generator_tgt = wrapped_generator_tgt.target
    if not target_types_to_generate_requests.is_generator(generator_tgt):
        # TODO: Error in this case. You should not use a generator address (or file address) if
        #  the generator does not actually generate.
        return wrapped_generator_tgt

    generate_request = target_types_to_generate_requests[type(generator_tgt)]
    generated = await Get(GeneratedTargets, GenerateTargetsRequest,
                          generate_request(generator_tgt))
    if address not in generated:
        raise ValueError(
            f"The address `{address}` is not generated by the `{generator_tgt.alias}` target "
            f"`{generator_tgt.address}`, which only generates these addresses:\n\n"
            f"{bullet_list(addr.spec for addr in generated)}\n\n"
            "Did you mean to use one of those addresses?")
    return WrappedTarget(generated[address])
Exemplo n.º 4
0
def test_explicitly_provided_dependencies_maybe_warn_of_ambiguous_dependency_inference(
    caplog, ) -> None:
    def maybe_warn(
        ambiguous: List[Address],
        *,
        ignores: Optional[List[Address]] = None,
        includes: Optional[List[Address]] = None,
        owners_must_be_ancestors: bool = False,
    ) -> None:
        caplog.clear()
        epd = ExplicitlyProvidedDependencies(
            Address("dir", target_name="input_tgt"),
            includes=FrozenOrderedSet(includes or []),
            ignores=FrozenOrderedSet(ignores or []),
        )
        epd.maybe_warn_of_ambiguous_dependency_inference(
            tuple(ambiguous),
            Address("some_dir"),
            import_reference="file",
            context="foo",
            owners_must_be_ancestors=owners_must_be_ancestors,
        )

    maybe_warn([])
    assert not caplog.records

    # A mix of normal and generated addresses.
    addr_a = Address("dir", target_name="a", generated_name="gen")
    addr_b = Address("dir", target_name="b", generated_name="gen")
    addr_c = Address("dir", target_name="c")
    all_addr = [addr_a, addr_b, addr_c]

    maybe_warn(all_addr)
    assert len(caplog.records) == 1
    assert f"['{addr_a}', '{addr_b}', '{addr_c}']" in caplog.text

    # Ignored addresses do not show up in the list of ambiguous owners, including for ignores of
    # both file and BUILD targets.
    maybe_warn(all_addr, ignores=[addr_b])
    assert len(caplog.records) == 1
    assert f"['{addr_a}', '{addr_c}']" in caplog.text
    maybe_warn(all_addr, ignores=[addr_b.maybe_convert_to_target_generator()])
    assert len(caplog.records) == 1
    assert f"['{addr_a}', '{addr_c}']" in caplog.text

    # Disambiguating via ignores turns off the warning, including for ignores of both normal and
    # generated targets.
    maybe_warn(all_addr, ignores=[addr_a, addr_b])
    assert not caplog.records
    maybe_warn(
        all_addr,
        ignores=[
            addr_a.maybe_convert_to_target_generator(),
            addr_b.maybe_convert_to_target_generator(),
        ],
    )
    assert not caplog.records

    # Including a target turns off the warning, including for includes of both normal and generated
    # targets.
    maybe_warn(all_addr, includes=[addr_a])
    assert not caplog.records
    maybe_warn(all_addr, includes=[addr_a.maybe_convert_to_target_generator()])
    assert not caplog.records

    # You can also disambiguate via `owners_must_be_ancestors`.
    another_dir = Address("another_dir")
    maybe_warn([addr_a, another_dir], owners_must_be_ancestors=True)
    assert not caplog.records
    maybe_warn([addr_a, another_dir], owners_must_be_ancestors=False)
    assert len(caplog.records) == 1
    assert f"['{another_dir}', '{addr_a}']" in caplog.text
    maybe_warn([addr_a, addr_b, another_dir],
               ignores=[addr_b],
               owners_must_be_ancestors=True)
    assert not caplog.records