Exemple #1
0
def _eject_item(ctx: Context, item_type: str, public_id: PublicId):
    """
    Eject item from installed (vendor) to custom folder.

    :param ctx: context object.
    :param item_type: item type.
    :param public_id: item public ID.

    :return: None
    :raises: ClickException if item is absent at source path or present at destenation path.
    """
    item_type_plural = item_type + "s"
    if not is_item_present(ctx, item_type, public_id):  # pragma: no cover
        raise click.ClickException(
            "{} {} not found in agent's vendor items.".format(
                item_type.title(), public_id))
    src = get_package_path(ctx, item_type, public_id)
    dst = get_package_path(ctx, item_type, public_id, is_vendor=False)
    if is_item_present(ctx, item_type, public_id,
                       is_vendor=False):  # pragma: no cover
        raise click.ClickException(
            "{} {} is already in a non-vendor item.".format(
                item_type.title(), public_id))

    ctx.clean_paths.append(dst)
    copy_package_directory(Path(src), dst)

    try_to_load_agent_config(ctx)
    new_public_id = PublicId(author=ctx.agent_config.author,
                             name=public_id.name,
                             version=DEFAULT_VERSION)
    update_item_config(item_type,
                       Path(dst),
                       author=new_public_id.author,
                       version=new_public_id.version)
    update_item_public_id_in_init(item_type, Path(dst), new_public_id)
    supported_items = getattr(ctx.agent_config, item_type_plural)
    for p_id in supported_items:
        if p_id.author == public_id.author and p_id.name == public_id.name:
            present_public_id = p_id
            break
    supported_items.add(new_public_id)
    supported_items.remove(present_public_id)
    update_item_config("agent", Path(ctx.cwd),
                       **{item_type_plural: supported_items})

    shutil.rmtree(src)
    fingerprint_item(ctx, item_type, new_public_id)
    click.echo("Successfully ejected {} {} to {} as {}.".format(
        item_type, public_id, dst, new_public_id))
Exemple #2
0
def add_item(ctx: Context, item_type: str, item_public_id: PublicId) -> None:
    """
    Add an item.

    :param ctx: Context object.
    :param item_type: the item type.
    :param item_public_id: the item public id.
    :return: None
    """
    agent_name = cast(str, ctx.agent_config.agent_name)

    click.echo("Adding {} '{}' to the agent '{}'...".format(
        item_type, item_public_id, agent_name))
    if is_item_present(ctx, item_type, item_public_id):
        raise click.ClickException(
            "A {} with id '{}/{}' already exists. Aborting...".format(
                item_type, item_public_id.author, item_public_id.name))

    dest_path = get_package_path(ctx, item_type, item_public_id)
    is_local = ctx.config.get("is_local")

    ctx.clean_paths.append(dest_path)
    if item_public_id in [DEFAULT_CONNECTION, *LOCAL_PROTOCOLS, DEFAULT_SKILL]:
        source_path = find_item_in_distribution(ctx, item_type, item_public_id)
        package_path = copy_package_directory(source_path, dest_path)
    elif is_local:
        source_path = find_item_locally(ctx, item_type, item_public_id)
        package_path = copy_package_directory(source_path, dest_path)
    else:
        package_path = fetch_package(item_type,
                                     public_id=item_public_id,
                                     cwd=ctx.cwd,
                                     dest=dest_path)
    item_config = load_item_config(item_type, package_path)

    if not is_fingerprint_correct(package_path,
                                  item_config):  # pragma: no cover
        raise click.ClickException(
            "Failed to add an item with incorrect fingerprint.")

    _add_item_deps(ctx, item_type, item_config)
    register_item(ctx, item_type, item_public_id)
Exemple #3
0
def find_item_locally_or_distributed(ctx: Context, item_type: str,
                                     item_public_id: PublicId,
                                     dest_path: str) -> Path:
    """
    Unify find item locally both in case it is distributed or not.

    :param ctx: the CLI context.
    :param item_type: the item type.
    :param item_public_id: the item public id.
    :param dest_path: the path to the destination.
    :return: the path to the found package.
    """
    is_distributed = is_distributed_item(item_public_id)
    if is_distributed:  # pragma: nocover
        source_path = find_item_in_distribution(ctx, item_type, item_public_id)
        package_path = copy_package_directory(source_path, dest_path)
    else:
        source_path, _ = find_item_locally(ctx, item_type, item_public_id)
        package_path = copy_package_directory(source_path, dest_path)

    return package_path
Exemple #4
0
def _eject_item(
    ctx: Context,
    item_type: str,
    public_id: PublicId,
    quiet: bool = True,
    with_symlinks: bool = False,
) -> None:
    """
    Eject item from installed (vendor) to custom folder.

    :param ctx: context object.
    :param item_type: item type.
    :param public_id: item public ID.
    :param quiet: if false, the function will ask the user in case of recursive eject.

    :return: None
    :raises: ClickException if item is absent at source path or present at destenation path.
    """
    # we know cli_author is set because of the above checks.
    cli_author: str = cast(str, ctx.config.get("cli_author"))
    item_type_plural = item_type + "s"
    if not is_item_present(
            ctx.cwd,
            ctx.agent_config,
            item_type,
            public_id,
            is_vendor=True,
            with_version=True,
    ):  # pragma: no cover
        raise click.ClickException(
            f"{item_type.title()} {public_id} not found in agent's vendor items."
        )
    src = get_package_path(ctx.cwd, item_type, public_id)
    dst = get_package_path(ctx.cwd, item_type, public_id, is_vendor=False)
    if is_item_present(ctx.cwd,
                       ctx.agent_config,
                       item_type,
                       public_id,
                       is_vendor=False):  # pragma: no cover
        raise click.ClickException(
            f"{item_type.title()} {public_id} is already a non-vendor package."
        )
    configuration = load_item_config(item_type, Path(src))

    if public_id.package_version.is_latest:
        # get 'concrete' public id, in case it is 'latest'
        component_prefix = ComponentType(
            item_type), public_id.author, public_id.name
        component_id = get_latest_component_id_from_prefix(
            ctx.agent_config, component_prefix)
        # component id is necessarily found, due to the checks above.
        public_id = cast(ComponentId, component_id).public_id

    package_id = PackageId(PackageType(item_type), public_id)

    click.echo(
        f"Ejecting item {package_id.package_type.value} {str(package_id.public_id)}"
    )

    # first, eject all the vendor packages that depend on this
    item_remover = ItemRemoveHelper(ctx, ignore_non_vendor=True)
    reverse_dependencies = (
        item_remover.get_agent_dependencies_with_reverse_dependencies())
    reverse_reachable_dependencies = reachable_nodes(reverse_dependencies,
                                                     {package_id})
    # the reversed topological order of a graph
    # is the topological order of the reverse graph.
    eject_order = list(
        reversed(find_topological_order(reverse_reachable_dependencies)))
    eject_order.remove(package_id)
    if len(eject_order) > 0 and not quiet:
        click.echo(
            f"The following vendor packages will be ejected: {eject_order}")
        answer = click.confirm("Do you want to proceed?")
        if not answer:
            click.echo("Aborted.")
            return

    for dependency_package_id in eject_order:
        # 'dependency_package_id' depends on 'package_id',
        # so we need to eject it first
        _eject_item(
            ctx,
            dependency_package_id.package_type.value,
            dependency_package_id.public_id,
            quiet=True,
        )

    # copy the vendor package into the non-vendor packages
    ctx.clean_paths.append(dst)
    copy_package_directory(Path(src), dst)

    new_public_id = PublicId(cli_author, public_id.name, DEFAULT_VERSION)
    current_version = Version(aea.__version__)
    new_aea_range = (
        configuration.aea_version
        if configuration.aea_version_specifiers.contains(current_version) else
        compute_specifier_from_version(current_version))
    update_item_config(
        item_type,
        Path(dst),
        author=new_public_id.author,
        version=new_public_id.version,
        aea_version=new_aea_range,
    )
    update_item_public_id_in_init(item_type, Path(dst), new_public_id)
    shutil.rmtree(src)

    # update references in all the other packages
    component_type = ComponentType(item_type_plural[:-1])
    old_component_id = ComponentId(component_type, public_id)
    new_component_id = ComponentId(component_type, new_public_id)
    update_references(ctx, {old_component_id: new_component_id})

    # need to reload agent configuration with the updated references
    try_to_load_agent_config(ctx)

    # replace import statements in all the non-vendor packages
    replace_all_import_statements(Path(ctx.cwd), ComponentType(item_type),
                                  public_id, new_public_id)

    # fingerprint all (non-vendor) packages
    fingerprint_all(ctx)

    if with_symlinks:
        click.echo(
            "Adding symlinks from vendor to non-vendor and packages to vendor folders."
        )
        create_symlink_vendor_to_local(ctx, item_type, new_public_id)
        create_symlink_packages_to_vendor(ctx)

    click.echo(
        f"Successfully ejected {item_type} {public_id} to {dst} as {new_public_id}."
    )
Exemple #5
0
def _add_item(click_context, item_type, item_public_id) -> None:
    """
    Add an item.

    :param click_context: the click context.
    :param item_type: the item type.
    :param item_public_id: the item public id.
    :return: None
    """
    ctx = cast(Context, click_context.obj)
    agent_name = cast(str, ctx.agent_config.agent_name)
    item_type_plural = item_type + "s"
    supported_items = getattr(ctx.agent_config, item_type_plural)

    is_local = ctx.config.get("is_local")

    click.echo(
        "Adding {} '{}' to the agent '{}'...".format(
            item_type, item_public_id, agent_name
        )
    )

    # check if we already have an item with the same name
    logger.debug(
        "{} already supported by the agent: {}".format(
            item_type_plural.capitalize(), supported_items
        )
    )
    if _is_item_present(item_type, item_public_id, ctx):
        raise click.ClickException(
            "A {} with id '{}/{}' already exists. Aborting...".format(
                item_type, item_public_id.author, item_public_id.name
            )
        )

    # find and add protocol
    dest_path = get_package_dest_path(
        ctx, item_public_id.author, item_type_plural, item_public_id.name
    )
    ctx.clean_paths.append(dest_path)

    if item_public_id in [DEFAULT_CONNECTION, DEFAULT_PROTOCOL, DEFAULT_SKILL]:
        source_path = find_item_in_distribution(ctx, item_type, item_public_id)
        package_path = copy_package_directory(
            ctx,
            source_path,
            item_type,
            item_public_id.name,
            item_public_id.author,
            dest_path,
        )
    elif is_local:
        source_path = find_item_locally(ctx, item_type, item_public_id)
        package_path = copy_package_directory(
            ctx,
            source_path,
            item_type,
            item_public_id.name,
            item_public_id.author,
            dest_path,
        )
    else:
        package_path = fetch_package(
            item_type, public_id=item_public_id, cwd=ctx.cwd, dest=dest_path
        )

    configuration_file_name = _get_default_configuration_file_name_from_type(item_type)
    configuration_path = package_path / configuration_file_name
    configuration_loader = ConfigLoader.from_configuration_type(PackageType(item_type))
    item_configuration = configuration_loader.load(configuration_path.open())

    _validate_fingerprint(package_path, item_configuration)

    if item_type in {"connection", "skill"}:
        _add_protocols(click_context, item_configuration.protocols)

    if item_type == "skill":
        for contract_public_id in item_configuration.contracts:
            if contract_public_id not in ctx.agent_config.contracts:
                _add_item(click_context, "contract", contract_public_id)

    # add the item to the configurations.
    logger.debug(
        "Registering the {} into {}".format(item_type, DEFAULT_AEA_CONFIG_FILE)
    )
    supported_items.add(item_public_id)
    ctx.agent_loader.dump(
        ctx.agent_config, open(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w")
    )