From 232883c7b9e876ffafe4a9baf0e26d5ed22e1f8a Mon Sep 17 00:00:00 2001 From: OjusWiZard Date: Thu, 19 Sep 2024 01:30:32 +0530 Subject: [PATCH] feat: support custom components in publish and eject commands Signed-off-by: OjusWiZard --- aea/cli/eject.py | 13 ++++++++++++- aea/cli/publish.py | 5 +++-- aea/cli/registry/push.py | 6 ++++-- aea/configurations/constants.py | 1 + tests/test_cli/test_eject.py | 14 +++++++++++++- tests/test_cli/test_publish.py | 10 ++++++++-- 6 files changed, 41 insertions(+), 8 deletions(-) diff --git a/aea/cli/eject.py b/aea/cli/eject.py index c149fac8fe..c38faab89e 100644 --- a/aea/cli/eject.py +++ b/aea/cli/eject.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # -# Copyright 2022 Valory AG +# Copyright 2022-2024 Valory AG # Copyright 2018-2021 Fetch.AI Limited # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -59,6 +59,7 @@ from aea.configurations.constants import ( CONNECTION, CONTRACT, + CUSTOM, DEFAULT_VERSION, PROTOCOL, SKILL, @@ -136,6 +137,16 @@ def skill(ctx: Context, public_id: PublicId) -> None: _eject_item(ctx, SKILL, public_id, quiet=quiet, with_symlinks=with_symlinks) +@eject.command() +@click.argument("public_id", type=PublicIdParameter(), required=True) +@pass_ctx +def custom(ctx: Context, public_id: PublicId) -> None: + """Eject a vendor custom component.""" + quiet = ctx.config.get("quiet") + with_symlinks = ctx.config.get("with_symlinks") + _eject_item(ctx, CUSTOM, public_id, quiet=quiet, with_symlinks=with_symlinks) + + @clean_after def _eject_item( ctx: Context, diff --git a/aea/cli/publish.py b/aea/cli/publish.py index c1e9571e4c..9a0ac4eeba 100644 --- a/aea/cli/publish.py +++ b/aea/cli/publish.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # -# Copyright 2022 Valory AG +# Copyright 2022-2024 Valory AG # Copyright 2018-2021 Fetch.AI Limited # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -54,6 +54,7 @@ AGENTS, CONNECTIONS, CONTRACTS, + CUSTOMS, DEFAULT_AEA_CONFIG_FILE, DEFAULT_README_FILE, ITEM_TYPE_PLURAL_TO_TYPE, @@ -330,7 +331,7 @@ def _check_dependencies_in_registry( registry: BaseRegistry, agent_config: AgentConfig, push_missing: bool ) -> None: """Check all agent dependencies present in registry.""" - for item_type_plural in (PROTOCOLS, CONTRACTS, CONNECTIONS, SKILLS): + for item_type_plural in (PROTOCOLS, CONTRACTS, CONNECTIONS, SKILLS, CUSTOMS): dependencies = getattr(agent_config, item_type_plural) for public_id in dependencies: if push_missing: diff --git a/aea/cli/registry/push.py b/aea/cli/registry/push.py index 7d95a2ad9f..7e7db0f2d0 100644 --- a/aea/cli/registry/push.py +++ b/aea/cli/registry/push.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # -# Copyright 2022 Valory AG +# Copyright 2022-2024 Valory AG # Copyright 2018-2021 Fetch.AI Limited # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -40,6 +40,7 @@ from aea.configurations.constants import ( CONNECTIONS, CONTRACTS, + CUSTOM, DEFAULT_README_FILE, ITEM_TYPE_PLURAL_TO_TYPE, PROTOCOLS, @@ -61,7 +62,8 @@ def _compress_dir(output_filename: str, source_dir: str) -> None: def load_component_public_id(source_path: str, item_type: str) -> PublicId: """Get component version from source path.""" - config = load_yaml(os.path.join(source_path, item_type + ".yaml")) + config_file = "component" if item_type == CUSTOM else item_type + config = load_yaml(os.path.join(source_path, config_file + ".yaml")) item_author = config.get("author", "") item_name = config.get("name", "") item_version = config.get("version", "") diff --git a/aea/configurations/constants.py b/aea/configurations/constants.py index 1d1483930d..4b5df5d540 100644 --- a/aea/configurations/constants.py +++ b/aea/configurations/constants.py @@ -157,6 +157,7 @@ CONTRACT: CONTRACTS, CONNECTION: CONNECTIONS, SKILL: SKILLS, + CUSTOM: CUSTOMS, } ITEM_TYPE_PLURAL_TO_TYPE = {v: k for k, v in ITEM_TYPE_TO_PLURAL.items()} diff --git a/tests/test_cli/test_eject.py b/tests/test_cli/test_eject.py index 2b3e29fcf2..9cffa3eaa8 100644 --- a/tests/test_cli/test_eject.py +++ b/tests/test_cli/test_eject.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # -# Copyright 2022 Valory AG +# Copyright 2022-2024 Valory AG # Copyright 2018-2021 Fetch.AI Limited # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -20,6 +20,7 @@ """This test module contains the tests for commands in aea.cli.eject module.""" import os +import shutil from pathlib import Path from unittest import mock @@ -54,6 +55,11 @@ def test_eject_commands_positive(self): self.add_item("connection", str(GYM_CONNECTION_PUBLIC_ID)) self.add_item("skill", str(GYM_SKILL_PUBLIC_ID)) self.add_item("contract", str(ERC1155_PUBLIC_ID)) + self.scaffold_item("custom", "test") + shutil.move( + os.path.join(cwd, "customs"), + os.path.join(cwd, "vendor", self.author, "customs"), + ) # the order must be kept as is, because of recursive ejects self.eject_item("skill", str(GYM_SKILL_PUBLIC_ID)) @@ -79,6 +85,12 @@ def test_eject_commands_positive(self): ) assert "erc1155" in os.listdir((os.path.join(cwd, "contracts"))) + self.eject_item("custom", f"{self.author}/test:0.1.0") + assert f"{self.author}/test:0.1.0" not in os.listdir( + (os.path.join(cwd, "vendor", self.author, "customs")) + ) + assert "test" in os.listdir((os.path.join(cwd, "customs"))) + class TestRecursiveEject(AEATestCaseEmpty): """Test that eject is recursive.""" diff --git a/tests/test_cli/test_publish.py b/tests/test_cli/test_publish.py index f37b2efe84..f300887908 100644 --- a/tests/test_cli/test_publish.py +++ b/tests/test_cli/test_publish.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- # ------------------------------------------------------------------------------ # -# Copyright 2021-2023 Valory AG +# Copyright 2021-2024 Valory AG # Copyright 2018-2019 Fetch.AI Limited # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -37,6 +37,7 @@ ) from aea.cli.registry.settings import REMOTE_HTTP, REMOTE_IPFS from aea.configurations.base import PublicId +from aea.configurations.constants import CUSTOMS, SKILLS from aea.helpers.base import cd from aea.test_tools.test_cases import AEATestCaseEmpty, BaseAEATestCase @@ -251,6 +252,8 @@ class TestPublishLocallyWithDeps(AEATestCaseEmpty): NEW_ITEM_TYPE = "skill" NEW_ITEM_NAME = "my_test_skill" + CUSTOM_ITEM_TYPE = "custom" + CUSTOM_ITEM_NAME = "test" @classmethod def setup_class(cls): @@ -258,6 +261,7 @@ def setup_class(cls): super(TestPublishLocallyWithDeps, cls).setup_class() cls.add_item(cls.ITEM_TYPE, str(cls.ITEM_PUBLIC_ID), local=True) cls.scaffold_item(cls.NEW_ITEM_TYPE, cls.NEW_ITEM_NAME) + cls.scaffold_item(cls.CUSTOM_ITEM_TYPE, cls.CUSTOM_ITEM_NAME) def test_publish_ok_with_missing_push( self, @@ -268,9 +272,11 @@ def test_publish_ok_with_missing_push( assert "use --push-missing" in str(e) self.invoke("publish", "--local", "--push-missing") + packages_dir = self.t / self.packages_dir_path # type: ignore + assert (packages_dir / self.author / SKILLS / self.NEW_ITEM_NAME).exists() + assert (packages_dir / self.author / CUSTOMS / self.CUSTOM_ITEM_NAME).exists() # remove agents published and publish again - packages_dir = self.t / self.packages_dir_path # type: ignore rmtree(Path(packages_dir) / self.author / "agents") self.invoke("publish", "--local")