From d902e616a4f4f6092f9a1d843d75da0f156673eb Mon Sep 17 00:00:00 2001 From: panasevychol Date: Wed, 8 Jan 2020 17:56:18 +0200 Subject: [PATCH 1/7] Local push and publish commands re-implemented to use context generated value of packages path. Tests fixed. --- aea/cli/publish.py | 8 ++++-- aea/cli/push.py | 16 +++++++++-- aea/cli/registry/publish.py | 6 ++-- aea/cli/registry/push.py | 9 ++++-- aea/cli/registry/utils.py | 30 ++++++++++++++++++-- tests/test_cli/test_registry/test_publish.py | 2 +- tests/test_cli/test_registry/test_push.py | 8 ++++-- tests/test_cli/test_registry/test_utils.py | 5 ++-- 8 files changed, 65 insertions(+), 19 deletions(-) diff --git a/aea/cli/publish.py b/aea/cli/publish.py index a0bc72c2ed..7c2949d36a 100644 --- a/aea/cli/publish.py +++ b/aea/cli/publish.py @@ -20,16 +20,20 @@ """Implementation of the 'aea publish' subcommand.""" import click +from aea.cli.common import pass_ctx, Context, DEFAULT_AEA_CONFIG_FILE, Path from aea.cli.registry.publish import publish_agent, save_agent_locally +from aea.cli.registry.utils import get_default_registry_path @click.command(name='publish') @click.option( '--registry', is_flag=True, help="For publishing agent to Registry." ) -def publish(registry): +@pass_ctx +def publish(ctx: Context, registry): """Publish Agent to Registry.""" if not registry: - save_agent_locally() + packages_path = get_default_registry_path(ctx) + save_agent_locally(packages_path) else: publish_agent() diff --git a/aea/cli/push.py b/aea/cli/push.py index dc87a3ef66..c03275d7b3 100644 --- a/aea/cli/push.py +++ b/aea/cli/push.py @@ -22,6 +22,7 @@ from aea.cli.common import pass_ctx, Context, PublicIdParameter from aea.cli.registry.push import push_item, save_item_locally +from aea.cli.registry.utils import get_default_registry_path @click.group() @@ -33,6 +34,9 @@ def push(ctx: Context, registry): """Push item to Registry or save it in local packages.""" ctx.set_config("registry", registry) + packages_path = get_default_registry_path(ctx) + ctx.set_config("packages_path", packages_path) + @push.command(name='connection') @click.argument('connection-id', type=PublicIdParameter(), required=True) @@ -40,7 +44,9 @@ def push(ctx: Context, registry): def connection(ctx: Context, connection_id): """Push connection to Registry or save it in local packages.""" if not ctx.config.get("registry"): - save_item_locally('connection', connection_id) + save_item_locally( + 'connection', connection_id, ctx.config.get("packages_path") + ) else: push_item('connection', connection_id.name) @@ -51,7 +57,9 @@ def connection(ctx: Context, connection_id): def protocol(ctx: Context, protocol_id): """Push protocol to Registry or save it in local packages.""" if not ctx.config.get("registry"): - save_item_locally('protocol', protocol_id) + save_item_locally( + 'protocol', protocol_id, ctx.config.get("packages_path") + ) else: push_item('protocol', protocol_id.name) @@ -62,6 +70,8 @@ def protocol(ctx: Context, protocol_id): def skill(ctx: Context, skill_id): """Push skill to Registry or save it in local packages.""" if not ctx.config.get("registry"): - save_item_locally('skill', skill_id) + save_item_locally( + 'skill', skill_id, ctx.config.get("packages_path") + ) else: push_item('skill', skill_id.name) diff --git a/aea/cli/registry/publish.py b/aea/cli/registry/publish.py index 78fb3fffb5..0a7f1b9358 100644 --- a/aea/cli/registry/publish.py +++ b/aea/cli/registry/publish.py @@ -78,10 +78,12 @@ def publish_agent(): ) -def save_agent_locally() -> None: +def save_agent_locally(packages_path: str) -> None: """ Save agent to local packages. + :param packages_path: str path to packages dir + :return: None """ item_type_plural = 'agents' @@ -91,7 +93,7 @@ def save_agent_locally() -> None: agent_config = _load_agent_config(agent_config_path) name = agent_config['agent_name'] - target_dir = get_item_target_path(item_type_plural, name) + target_dir = get_item_target_path(item_type_plural, name, packages_path) # TODO: now - copy only config file. Change to copy whole agent. source_path = os.path.join(cwd, DEFAULT_AEA_CONFIG_FILE) if not os.path.exists(target_dir): diff --git a/aea/cli/registry/push.py b/aea/cli/registry/push.py index 78f983b412..bd5cd73280 100644 --- a/aea/cli/registry/push.py +++ b/aea/cli/registry/push.py @@ -116,12 +116,15 @@ def _check_package_public_id(source_path, item_type, item_id): ) -def save_item_locally(item_type: str, item_id: PublicId) -> None: +def save_item_locally( + item_type: str, item_id: PublicId, packages_path +) -> None: """ Save item to local packages. :param item_type: str type of item (connection/protocol/skill). :param item_id: the public id of the item. + :param packages_path: path to packages dir :return: None """ @@ -129,7 +132,9 @@ def save_item_locally(item_type: str, item_id: PublicId) -> None: cwd = os.getcwd() source_path = get_item_source_path(cwd, item_type_plural, item_id.name) - target_path = get_item_target_path(item_type_plural, item_id.name) + target_path = get_item_target_path( + item_type_plural, item_id.name, packages_path + ) _check_package_public_id(source_path, item_type, item_id) copytree(source_path, target_path) click.echo( diff --git a/aea/cli/registry/utils.py b/aea/cli/registry/utils.py index 7ca0a07d97..b80b49404b 100644 --- a/aea/cli/registry/utils.py +++ b/aea/cli/registry/utils.py @@ -27,7 +27,10 @@ import requests import yaml -from aea.cli.common import logger, DEFAULT_REGISTRY_PATH, AEAConfigException +from aea.cli.common import ( + logger, AEAConfigException, Context, DEFAULT_REGISTRY_PATH, + DEFAULT_AEA_CONFIG_FILE +) from aea.cli.registry.settings import ( REGISTRY_API_URL, CLI_CONFIG_PATH, @@ -306,18 +309,39 @@ def get_item_source_path( return source_path -def get_item_target_path(item_type_plural: str, item_name: str) -> str: +def get_item_target_path( + item_type_plural: str, item_name: str, packages_path: str +) -> str: """ Get the item target path. :param item_type_plural: the item type (plural) :param item_name: the item name + :param packages_path: str path to packages dir + :return: the item target path """ - packages_path = DEFAULT_REGISTRY_PATH target_path = os.path.join(packages_path, item_type_plural, item_name) if os.path.exists(target_path): raise click.ClickException( 'Item "{}" already exists in packages folder.'.format(item_name) ) return target_path + + +def get_default_registry_path(click_ctx: Context) -> str: + """ + Get agent's default registry path (packages path). + + :param click_ctx context object of click command. + + :return: str agent's default registry path. + """ + try: + with open(DEFAULT_AEA_CONFIG_FILE, mode="r", encoding="utf-8") as f: + agent_config = click_ctx.agent_loader.load(f) + registry_path = agent_config.registry_path + except FileNotFoundError: + registry_path = os.path.join(click_ctx.cwd, DEFAULT_REGISTRY_PATH) + + return registry_path diff --git a/tests/test_cli/test_registry/test_publish.py b/tests/test_cli/test_registry/test_publish.py index 0b7fddc396..0b9991a663 100644 --- a/tests/test_cli/test_registry/test_publish.py +++ b/tests/test_cli/test_registry/test_publish.py @@ -125,6 +125,6 @@ def test_save_agent_locally_positive( copyfile_mock ): """Test for save_agent_locally positive result.""" - save_agent_locally() + save_agent_locally('packages_path') makedirs_mock.assert_called_once_with('target-dir', exist_ok=True) copyfile_mock.assert_called_once_with('joined-path', 'joined-path') diff --git a/tests/test_cli/test_registry/test_push.py b/tests/test_cli/test_registry/test_push.py index a4a884eaaf..0a2d42a69d 100644 --- a/tests/test_cli/test_registry/test_push.py +++ b/tests/test_cli/test_registry/test_push.py @@ -134,11 +134,13 @@ def test_save_item_locally_positive( """Test for save_item_locally positive result.""" item_type = 'skill' item_id = PublicId.from_string('fetchai/skill_name:0.1.0') - save_item_locally(item_type, item_id) + save_item_locally(item_type, item_id, 'packages_path') get_item_source_path_mock.assert_called_once_with( 'cwd', 'skills', item_id.name ) - get_item_target_path_mock.assert_called_once_with('skills', item_id.name) + get_item_target_path_mock.assert_called_once_with( + 'skills', item_id.name, 'packages_path' + ) getcwd_mock.assert_called_once() copy_tree_mock.assert_called_once_with('source', 'target') @@ -169,7 +171,7 @@ def test_save_item_locally_positive( with self.assertRaises(ClickException): item_type = 'skill' item_id = PublicId.from_string('non_existing_author/skill_name:0.1.0') - save_item_locally(item_type, item_id) + save_item_locally(item_type, item_id, 'packages_path') class TestPushLocalFailsArgumentNotPublicId: diff --git a/tests/test_cli/test_registry/test_utils.py b/tests/test_cli/test_registry/test_utils.py index 8f003c2c27..0a000df30e 100644 --- a/tests/test_cli/test_registry/test_utils.py +++ b/tests/test_cli/test_registry/test_utils.py @@ -301,7 +301,6 @@ def test_get_item_source_path_not_exists(self, exists_mock, join_mock): get_item_source_path('cwd', 'skills', 'skill-name') -@mock.patch('aea.cli.registry.utils.DEFAULT_REGISTRY_PATH', 'packages') @mock.patch('aea.cli.registry.utils.os.path.join', return_value='some-path') class GetItemTargetPathTestCase(TestCase): """Test case for get_item_target_path method.""" @@ -309,7 +308,7 @@ class GetItemTargetPathTestCase(TestCase): @mock.patch('aea.cli.registry.utils.os.path.exists', return_value=False) def test_get_item_target_path_positive(self, exists_mock, join_mock): """Test for get_item_source_path positive result.""" - result = get_item_target_path('skills', 'skill-name') + result = get_item_target_path('skills', 'skill-name', 'packages') expected_result = 'some-path' self.assertEqual(result, expected_result) join_mock.assert_called_once_with('packages', 'skills', 'skill-name') @@ -319,4 +318,4 @@ def test_get_item_target_path_positive(self, exists_mock, join_mock): def test_get_item_target_path_already_exists(self, exists_mock, join_mock): """Test for get_item_target_path item already exists.""" with self.assertRaises(ClickException): - get_item_target_path('skills', 'skill-name') + get_item_target_path('skills', 'skill-name', 'packages_path') From 010ccd0bcb2c23f4c838454a9de716dc84d68eb8 Mon Sep 17 00:00:00 2001 From: Oleg Panasevych Date: Thu, 9 Jan 2020 12:48:24 +0200 Subject: [PATCH 2/7] Unnecessary imports removed. --- aea/cli/publish.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aea/cli/publish.py b/aea/cli/publish.py index 7c2949d36a..4683288921 100644 --- a/aea/cli/publish.py +++ b/aea/cli/publish.py @@ -20,7 +20,7 @@ """Implementation of the 'aea publish' subcommand.""" import click -from aea.cli.common import pass_ctx, Context, DEFAULT_AEA_CONFIG_FILE, Path +from aea.cli.common import pass_ctx, Context from aea.cli.registry.publish import publish_agent, save_agent_locally from aea.cli.registry.utils import get_default_registry_path From bd21984ac006ae318a507c8e5b042ce9cbeb5d09 Mon Sep 17 00:00:00 2001 From: David Minarsch Date: Thu, 9 Jan 2020 18:39:30 +0000 Subject: [PATCH 3/7] attempts to unify some of the code in cli section --- aea/cli/common.py | 49 +++++++- aea/cli/core.py | 2 +- aea/cli/create.py | 4 +- aea/cli/fetch.py | 35 +++++- aea/cli/publish.py | 32 ++++- aea/cli/push.py | 61 +++++++--- aea/cli/registry/fetch.py | 46 +------ aea/cli/registry/publish.py | 41 +------ aea/cli/registry/push.py | 73 +++-------- aea/cli/registry/utils.py | 60 +-------- aea/cli/remove.py | 1 + aea/cli/scaffold.py | 64 +++++----- aea/cli/search.py | 22 ++-- tests/test_cli/test_common.py | 45 ++++++- tests/test_cli/test_fetch.py | 44 +++++++ tests/test_cli/test_publish.py | 55 +++++++++ tests/test_cli/test_push.py | 114 ++++++++++++++++++ tests/test_cli/test_registry/test_fetch.py | 43 +------ tests/test_cli/test_registry/test_publish.py | 34 +----- tests/test_cli/test_registry/test_push.py | 90 -------------- tests/test_cli/test_registry/test_utils.py | 43 +------ .../test_cli/test_scaffold/test_connection.py | 2 +- .../test_cli/test_scaffold/test_protocols.py | 2 +- 23 files changed, 477 insertions(+), 485 deletions(-) create mode 100644 tests/test_cli/test_fetch.py create mode 100644 tests/test_cli/test_publish.py create mode 100644 tests/test_cli/test_push.py diff --git a/aea/cli/common.py b/aea/cli/common.py index 994ad37653..ad1feed915 100644 --- a/aea/cli/common.py +++ b/aea/cli/common.py @@ -40,6 +40,7 @@ logger = logging.getLogger("aea") logger = default_logging_config(logger) +DEFAULT_VERSION = "0.1.0" DEFAULT_REGISTRY_PATH = str(Path("./", "packages")) DEFAULT_CONNECTION = PublicId.from_string("fetchai/stub:0.1.0") # type: PublicId DEFAULT_SKILL = PublicId.from_string("fetchai/error:0.1.0") # type: PublicId @@ -101,18 +102,20 @@ def get_dependencies(self) -> Dependencies: pass_ctx = click.make_pass_decorator(Context) -def _try_to_load_agent_config(ctx: Context): +def _try_to_load_agent_config(ctx: Context, exit_on_except: bool = True): try: path = Path(DEFAULT_AEA_CONFIG_FILE) fp = open(str(path), mode="r", encoding="utf-8") ctx.agent_config = ctx.agent_loader.load(fp) logging.config.dictConfig(ctx.agent_config.logging_config) except FileNotFoundError: - logger.error("Agent configuration file '{}' not found in the current directory.".format(DEFAULT_AEA_CONFIG_FILE)) - sys.exit(1) + if exit_on_except: + logger.error("Agent configuration file '{}' not found in the current directory.".format(DEFAULT_AEA_CONFIG_FILE)) + sys.exit(1) except jsonschema.exceptions.ValidationError: - logger.error("Agent configuration file '{}' is invalid. Please check the documentation.".format(DEFAULT_AEA_CONFIG_FILE)) - sys.exit(1) + if exit_on_except: + logger.error("Agent configuration file '{}' is invalid. Please check the documentation.".format(DEFAULT_AEA_CONFIG_FILE)) + sys.exit(1) def _try_to_load_protocols(ctx: Context): @@ -248,3 +251,39 @@ def convert(self, value, param, ctx): return PublicId.from_string(value) except ValueError: raise click.BadParameter(value) + + +def try_get_item_source_path(path: str, item_type_plural: str, item_name: str) -> str: + """ + Get the item source path. + + :param path: the source path root + :param item_type_plural: the item type (plural) + :param item_name: the item name + + :return: the item source path + """ + source_path = os.path.join(path, item_type_plural, item_name) + if not os.path.exists(source_path): + raise click.ClickException( + 'Item "{}" not found in source folder.'.format(item_name) + ) + return source_path + + +def try_get_item_target_path(path: str, item_type_plural: str, item_name: str) -> str: + """ + Get the item target path. + + :param path: the target path root + :param item_type_plural: the item type (plural) + :param item_name: the item name + + :return: the item target path + """ + target_path = os.path.join(path, item_type_plural, item_name) + if os.path.exists(target_path): + raise click.ClickException( + 'Item "{}" already exists in target folder.'.format(item_name) + ) + return target_path diff --git a/aea/cli/core.py b/aea/cli/core.py index 80dcc76fde..540dfdd856 100644 --- a/aea/cli/core.py +++ b/aea/cli/core.py @@ -67,9 +67,9 @@ def delete(ctx: Context, agent_name): """Delete an agent.""" path = Path(agent_name) - # check that the target folder is an AEA project. cwd = os.getcwd() try: + # check that the target folder is an AEA project. os.chdir(agent_name) fp = open(DEFAULT_AEA_CONFIG_FILE, mode="r", encoding="utf-8") ctx.agent_config = ctx.agent_loader.load(fp) diff --git a/aea/cli/create.py b/aea/cli/create.py index 1664c60f64..cc6ea79afc 100644 --- a/aea/cli/create.py +++ b/aea/cli/create.py @@ -30,7 +30,7 @@ import aea from aea.cli.add import connection, skill -from aea.cli.common import Context, logger, DEFAULT_REGISTRY_PATH, DEFAULT_CONNECTION, DEFAULT_SKILL, DEFAULT_LEDGER +from aea.cli.common import Context, logger, DEFAULT_REGISTRY_PATH, DEFAULT_CONNECTION, DEFAULT_SKILL, DEFAULT_LEDGER, DEFAULT_VERSION from aea.configurations.base import DEFAULT_AEA_CONFIG_FILE, AgentConfig @@ -76,7 +76,7 @@ def create(click_context, agent_name): logger.info("Creating config file {}".format(DEFAULT_AEA_CONFIG_FILE)) config_file = open(os.path.join(agent_name, DEFAULT_AEA_CONFIG_FILE), "w") agent_config = AgentConfig(agent_name=agent_name, aea_version=aea.__version__, - author="", version="0.1.0", license="", fingerprint="", + author="", version=DEFAULT_VERSION, license="", fingerprint="", registry_path=os.path.join("..", DEFAULT_REGISTRY_PATH), description="") agent_config.default_connection = DEFAULT_CONNECTION agent_config.default_ledger = DEFAULT_LEDGER diff --git a/aea/cli/fetch.py b/aea/cli/fetch.py index 07a0939017..7cd0e654fd 100644 --- a/aea/cli/fetch.py +++ b/aea/cli/fetch.py @@ -19,9 +19,12 @@ """Implementation of the 'aea fetch' subcommand.""" import click +from distutils.dir_util import copy_tree +import os -from aea.cli.common import PublicIdParameter -from aea.cli.registry.fetch import fetch_agent, fetch_agent_locally +from aea.cli.common import Context, pass_ctx, PublicIdParameter, DEFAULT_REGISTRY_PATH, try_get_item_source_path +from aea.cli.registry.fetch import fetch_agent +from aea.configurations.base import PublicId @click.command(name='fetch') @@ -29,9 +32,31 @@ '--registry', is_flag=True, help="For fetching agent from Registry." ) @click.argument('public-id', type=PublicIdParameter(), required=True) -def fetch(public_id, registry): +@pass_ctx +def fetch(ctx: Context, public_id, registry): """Fetch Agent from Registry.""" if not registry: - fetch_agent_locally(public_id) + _fetch_agent_locally(ctx, public_id) else: - fetch_agent(public_id) + fetch_agent(ctx, public_id) + + +def _fetch_agent_locally(ctx: Context, public_id: PublicId) -> None: + """ + Fetch Agent from local packages. + + :param ctx: Context + :param public_id: public ID of agent to be fetched. + + :return: None + """ + packages_path = os.path.basename(DEFAULT_REGISTRY_PATH) + source_path = try_get_item_source_path(packages_path, 'agents', public_id.name) + target_path = os.path.join(ctx.cwd, public_id.name) + if os.path.exists(target_path): + raise click.ClickException( + 'Item "{}" already exists in target folder.'.format(public_id.name) + ) + copy_tree(source_path, target_path) + click.echo('Agent {} successfully fetched.'.format(public_id.name)) + # TODO: install all dependencies recursively diff --git a/aea/cli/publish.py b/aea/cli/publish.py index 4683288921..5a27213eb8 100644 --- a/aea/cli/publish.py +++ b/aea/cli/publish.py @@ -19,10 +19,11 @@ """Implementation of the 'aea publish' subcommand.""" import click +import os +from shutil import copyfile -from aea.cli.common import pass_ctx, Context -from aea.cli.registry.publish import publish_agent, save_agent_locally -from aea.cli.registry.utils import get_default_registry_path +from aea.cli.common import pass_ctx, Context, _try_to_load_agent_config, try_get_item_target_path, DEFAULT_AEA_CONFIG_FILE +from aea.cli.registry.publish import publish_agent @click.command(name='publish') @@ -32,8 +33,29 @@ @pass_ctx def publish(ctx: Context, registry): """Publish Agent to Registry.""" + _try_to_load_agent_config(ctx) if not registry: - packages_path = get_default_registry_path(ctx) - save_agent_locally(packages_path) + # TODO: check agent dependencies are available in local packages dir. + _save_agent_locally(ctx) else: publish_agent() + + +def _save_agent_locally(ctx: Context) -> None: + """ + Save agent to local packages. + + :param ctx: the context + + :return: None + """ + item_type_plural = 'agents' + + target_dir = try_get_item_target_path(ctx.agent_config.registry_path, item_type_plural, ctx.agent_config.name) + if not os.path.exists(target_dir): + os.makedirs(target_dir, exist_ok=True) + + source_path = os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE) + target_path = os.path.join(target_dir, DEFAULT_AEA_CONFIG_FILE) + copyfile(source_path, target_path) + click.echo('Agent "{}" successfully saved in packages folder.'.format(ctx.agent_config.name)) diff --git a/aea/cli/push.py b/aea/cli/push.py index c03275d7b3..ca7422144d 100644 --- a/aea/cli/push.py +++ b/aea/cli/push.py @@ -19,10 +19,11 @@ """Implementation of the 'aea push' subcommand.""" import click +from shutil import copytree -from aea.cli.common import pass_ctx, Context, PublicIdParameter -from aea.cli.registry.push import push_item, save_item_locally -from aea.cli.registry.utils import get_default_registry_path +from aea.cli.common import pass_ctx, Context, PublicIdParameter, try_get_item_target_path, try_get_item_source_path, _try_to_load_agent_config +from aea.cli.registry.push import push_item +from aea.configurations.base import PublicId @click.group() @@ -32,11 +33,9 @@ @pass_ctx def push(ctx: Context, registry): """Push item to Registry or save it in local packages.""" + _try_to_load_agent_config(ctx) ctx.set_config("registry", registry) - packages_path = get_default_registry_path(ctx) - ctx.set_config("packages_path", packages_path) - @push.command(name='connection') @click.argument('connection-id', type=PublicIdParameter(), required=True) @@ -44,11 +43,9 @@ def push(ctx: Context, registry): def connection(ctx: Context, connection_id): """Push connection to Registry or save it in local packages.""" if not ctx.config.get("registry"): - save_item_locally( - 'connection', connection_id, ctx.config.get("packages_path") - ) + _save_item_locally(ctx, 'connection', connection_id) else: - push_item('connection', connection_id.name) + push_item(ctx, 'connection', connection_id) @push.command(name='protocol') @@ -57,11 +54,9 @@ def connection(ctx: Context, connection_id): def protocol(ctx: Context, protocol_id): """Push protocol to Registry or save it in local packages.""" if not ctx.config.get("registry"): - save_item_locally( - 'protocol', protocol_id, ctx.config.get("packages_path") - ) + _save_item_locally(ctx, 'protocol', protocol_id) else: - push_item('protocol', protocol_id.name) + push_item(ctx, 'protocol', protocol_id) @push.command(name='skill') @@ -70,8 +65,38 @@ def protocol(ctx: Context, protocol_id): def skill(ctx: Context, skill_id): """Push skill to Registry or save it in local packages.""" if not ctx.config.get("registry"): - save_item_locally( - 'skill', skill_id, ctx.config.get("packages_path") - ) + _save_item_locally(ctx, 'skill', skill_id) else: - push_item('skill', skill_id.name) + push_item(ctx, 'skill', skill_id) + + +def _save_item_locally(ctx: Context, item_type: str, item_id: PublicId) -> None: + """ + Save item to local packages. + + :param item_type: str type of item (connection/protocol/skill). + :param item_id: the public id of the item. + :param packages_path: path to packages dir + + :return: None + """ + item_type_plural = item_type + 's' + + source_path = try_get_item_source_path(ctx.cwd, item_type_plural, item_id.name) + target_path = try_get_item_target_path(ctx.agent_config.registry_path, item_type_plural, item_id.name) + # _check_package_public_id(source_path, item_type, item_id) + copytree(source_path, target_path) + click.echo('{} "{}" successfully saved in packages folder.'.format(item_type.title(), item_id)) + + +# TODO: clarify whether this is indeed needed +# def _check_package_public_id(source_path, item_type, item_id): +# config = load_yaml(os.path.join(source_path, item_type + ".yaml")) +# item_author = config.get("author", "") +# item_name = config.get("name", "") +# item_version = config.get("version", "") +# if item_id.name != item_name or item_id.author != item_author or item_id.version != item_version: +# raise click.ClickException( +# "Version or author do not match. Expected '{}', found '{}'" +# .format(item_id, item_author + "/" + item_name + ":" + item_version) +# ) diff --git a/aea/cli/registry/fetch.py b/aea/cli/registry/fetch.py index 08af9d0d95..d4e07ef077 100644 --- a/aea/cli/registry/fetch.py +++ b/aea/cli/registry/fetch.py @@ -17,22 +17,19 @@ # # ------------------------------------------------------------------------------ """Methods for CLI fetch functionality.""" -from typing import Union import click import os - -from distutils.dir_util import copy_tree from shutil import rmtree -from aea.cli.common import DEFAULT_REGISTRY_PATH +from aea.cli.common import Context from aea.cli.registry.utils import ( request_api, download_file, extract, fetch_package ) from aea.configurations.base import PublicId -def fetch_agent(public_id: Union[PublicId, str]) -> None: +def fetch_agent(ctx: Context, public_id: PublicId) -> None: """ Fetch Agent from Registry. @@ -40,15 +37,12 @@ def fetch_agent(public_id: Union[PublicId, str]) -> None: :return: None """ - if isinstance(public_id, str): - public_id = PublicId.from_string(public_id) author, name, version = public_id.author, public_id.name, public_id.version api_path = '/agents/{}/{}/{}'.format(author, name, version) resp = request_api('GET', api_path) file_url = resp['file'] - cwd = os.getcwd() - target_folder = os.path.join(cwd, name) + target_folder = os.path.join(ctx.cwd, name) for item_type in ('connection', 'skill', 'protocol'): item_type_plural = item_type + 's' @@ -62,41 +56,9 @@ def fetch_agent(public_id: Union[PublicId, str]) -> None: .format(name, e) ) - filepath = download_file(file_url, cwd) + filepath = download_file(file_url, ctx.cwd) extract(filepath, target_folder) click.echo( 'Agent {} successfully fetched to {}.' .format(name, target_folder) ) - - -def _get_agent_source_path(item_name: str) -> str: - packages_path = os.path.basename(DEFAULT_REGISTRY_PATH) - target_path = os.path.join(packages_path, 'agents', item_name) - if not os.path.exists(target_path): - raise click.ClickException( - 'Agent "{}" not found in packages folder.'.format(item_name) - ) - return target_path - - -def fetch_agent_locally(public_id: Union[PublicId, str]) -> None: - """ - Fetch Agent from local packages. - - :param public_id: str public ID of desirable Agent. - - :return: None - """ - if isinstance(public_id, str): - public_id = PublicId.from_string(public_id) - - name = public_id.name - source_dir = _get_agent_source_path(name) - cwd = os.getcwd() - target_dir = os.path.join(cwd, name) - copy_tree(source_dir, target_dir) - click.echo( - 'Agent {} successfully saved in {}.' - .format(name, cwd) - ) diff --git a/aea/cli/registry/publish.py b/aea/cli/registry/publish.py index 0a7f1b9358..be26f7478c 100644 --- a/aea/cli/registry/publish.py +++ b/aea/cli/registry/publish.py @@ -21,13 +21,11 @@ import os import click import tarfile - -from shutil import copyfile from typing import Dict -from aea.cli.common import logger +from aea.cli.common import Context, logger from aea.cli.registry.utils import ( - clean_tarfiles, load_yaml, request_api, get_item_target_path + clean_tarfiles, load_yaml, request_api ) from aea.configurations.base import DEFAULT_AEA_CONFIG_FILE @@ -49,13 +47,12 @@ def _load_agent_config(agent_config_path: str) -> Dict: @clean_tarfiles -def publish_agent(): +def publish_agent(ctx: Context): """Publish an agent.""" - cwd = os.getcwd() - agent_config_path = os.path.join(cwd, DEFAULT_AEA_CONFIG_FILE) + agent_config_path = os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE) agent_config = _load_agent_config(agent_config_path) name = agent_config['agent_name'] - output_tar = os.path.join(cwd, '{}.tar.gz'.format(name)) + output_tar = os.path.join(ctx.cwd, '{}.tar.gz'.format(name)) _compress(output_tar, agent_config_path) data = { @@ -76,31 +73,3 @@ def publish_agent(): name, resp['public_id'] ) ) - - -def save_agent_locally(packages_path: str) -> None: - """ - Save agent to local packages. - - :param packages_path: str path to packages dir - - :return: None - """ - item_type_plural = 'agents' - cwd = os.getcwd() - - agent_config_path = os.path.join(cwd, DEFAULT_AEA_CONFIG_FILE) - agent_config = _load_agent_config(agent_config_path) - name = agent_config['agent_name'] - - target_dir = get_item_target_path(item_type_plural, name, packages_path) - # TODO: now - copy only config file. Change to copy whole agent. - source_path = os.path.join(cwd, DEFAULT_AEA_CONFIG_FILE) - if not os.path.exists(target_dir): - os.makedirs(target_dir, exist_ok=True) - - target_file = os.path.join(target_dir, DEFAULT_AEA_CONFIG_FILE) - copyfile(source_path, target_file) - click.echo( - 'Agent "{}" successfully saved in packages folder.'.format(name) - ) diff --git a/aea/cli/registry/push.py b/aea/cli/registry/push.py index bd5cd73280..6fe18cb420 100644 --- a/aea/cli/registry/push.py +++ b/aea/cli/registry/push.py @@ -21,19 +21,14 @@ import os import shutil import tarfile -from shutil import copytree - import click -from aea.cli.common import logger +from aea.cli.common import Context, logger, PublicIdParameter from aea.cli.registry.utils import ( request_api, load_yaml, - clean_tarfiles, - get_item_source_path, - get_item_target_path + clean_tarfiles ) -from aea.configurations.base import PublicId def _remove_pycache(source_dir: str): @@ -49,7 +44,7 @@ def _compress_dir(output_filename: str, source_dir: str): @clean_tarfiles -def push_item(item_type: str, item_name: str) -> None: +def push_item(ctx: Context, item_type: str, item_id: PublicIdParameter) -> None: """ Push item to the Registry. @@ -59,85 +54,45 @@ def push_item(item_type: str, item_name: str) -> None: :return: None """ item_type_plural = item_type + 's' - cwd = os.getcwd() - items_folder = os.path.join(cwd, item_type_plural) - item_path = os.path.join(items_folder, item_name) + items_folder = os.path.join(ctx.cwd, item_type_plural) + item_path = os.path.join(items_folder, item_id.name) logger.debug( 'Searching for {} {} in {} ...' - .format(item_name, item_type, items_folder) + .format(item_id.name, item_type, items_folder) ) if not os.path.exists(item_path): raise click.ClickException( '{} "{}" not found in {}. Make sure you run push command ' 'from a correct folder.'.format( - item_type.title(), item_name, items_folder + item_type.title(), item_id.name, items_folder ) ) - output_filename = '{}.tar.gz'.format(item_name) + output_filename = '{}.tar.gz'.format(item_id.name) logger.debug( 'Compressing {} {} to {} ...' - .format(item_name, item_type, output_filename) + .format(item_id.name, item_type, output_filename) ) _compress_dir(output_filename, item_path) - output_filepath = os.path.join(cwd, output_filename) + output_filepath = os.path.join(ctx.cwd, output_filename) item_config_filepath = os.path.join(item_path, '{}.yaml'.format(item_type)) - logger.debug('Reading {} {} config ...'.format(item_name, item_type)) + logger.debug('Reading {} {} config ...'.format(item_id.name, item_type)) item_config = load_yaml(item_config_filepath) data = { - 'name': item_name, + 'name': item_id.name, 'description': item_config['description'], 'version': item_config['version'] } path = '/{}/create'.format(item_type_plural) - logger.debug('Pushing {} {} to Registry ...'.format(item_name, item_type)) + logger.debug('Pushing {} {} to Registry ...'.format(item_id.name, item_type)) resp = request_api( 'POST', path, data=data, auth=True, filepath=output_filepath ) click.echo( 'Successfully pushed {} {} to the Registry. Public ID: {}'.format( - item_type, item_name, resp['public_id'] + item_type, item_id.name, resp['public_id'] ) ) - - -def _check_package_public_id(source_path, item_type, item_id): - config = load_yaml(os.path.join(source_path, item_type + ".yaml")) - item_author = config.get("author", "") - item_name = config.get("name", "") - item_version = config.get("version", "") - if item_id.name != item_name or item_id.author != item_author or item_id.version != item_version: - raise click.ClickException( - "Version or author do not match. Expected '{}', found '{}'" - .format(item_id, item_author + "/" + item_name + ":" + item_version) - ) - - -def save_item_locally( - item_type: str, item_id: PublicId, packages_path -) -> None: - """ - Save item to local packages. - - :param item_type: str type of item (connection/protocol/skill). - :param item_id: the public id of the item. - :param packages_path: path to packages dir - - :return: None - """ - item_type_plural = item_type + 's' - cwd = os.getcwd() - - source_path = get_item_source_path(cwd, item_type_plural, item_id.name) - target_path = get_item_target_path( - item_type_plural, item_id.name, packages_path - ) - _check_package_public_id(source_path, item_type, item_id) - copytree(source_path, target_path) - click.echo( - '{} "{}" successfully saved in packages folder.' - .format(item_type.title(), item_id) - ) diff --git a/aea/cli/registry/utils.py b/aea/cli/registry/utils.py index b80b49404b..d0c8bbd042 100644 --- a/aea/cli/registry/utils.py +++ b/aea/cli/registry/utils.py @@ -28,8 +28,7 @@ import yaml from aea.cli.common import ( - logger, AEAConfigException, Context, DEFAULT_REGISTRY_PATH, - DEFAULT_AEA_CONFIG_FILE + logger, AEAConfigException ) from aea.cli.registry.settings import ( REGISTRY_API_URL, @@ -288,60 +287,3 @@ def wrapper(*args, **kwargs): return result return wrapper - - -def get_item_source_path( - cwd: str, item_type_plural: str, item_name: str -) -> str: - """ - Get the item source path. - - :param cwd: the current working directory - :param item_type_plural: the item type (plural) - :param item_name: the item name - :return: the item source path - """ - source_path = os.path.join(cwd, item_type_plural, item_name) - if not os.path.exists(source_path): - raise click.ClickException( - 'Item "{}" not found in {}.'.format(item_name, cwd) - ) - return source_path - - -def get_item_target_path( - item_type_plural: str, item_name: str, packages_path: str -) -> str: - """ - Get the item target path. - - :param item_type_plural: the item type (plural) - :param item_name: the item name - :param packages_path: str path to packages dir - - :return: the item target path - """ - target_path = os.path.join(packages_path, item_type_plural, item_name) - if os.path.exists(target_path): - raise click.ClickException( - 'Item "{}" already exists in packages folder.'.format(item_name) - ) - return target_path - - -def get_default_registry_path(click_ctx: Context) -> str: - """ - Get agent's default registry path (packages path). - - :param click_ctx context object of click command. - - :return: str agent's default registry path. - """ - try: - with open(DEFAULT_AEA_CONFIG_FILE, mode="r", encoding="utf-8") as f: - agent_config = click_ctx.agent_loader.load(f) - registry_path = agent_config.registry_path - except FileNotFoundError: - registry_path = os.path.join(click_ctx.cwd, DEFAULT_REGISTRY_PATH) - - return registry_path diff --git a/aea/cli/remove.py b/aea/cli/remove.py index b64702c94d..4a93b7de29 100644 --- a/aea/cli/remove.py +++ b/aea/cli/remove.py @@ -43,6 +43,7 @@ def _remove_item(ctx: Context, item_type, item): The parameter 'item' can be either the public id (e.g. 'fetchai/default:0.1.0') or the name of the package (e.g. 'default'). """ + # allow for removal with both item public id and item name try: item_id = PublicId.from_string(item) item_name = item_id.name diff --git a/aea/cli/scaffold.py b/aea/cli/scaffold.py index 668afcad2c..dfe2bc051e 100644 --- a/aea/cli/scaffold.py +++ b/aea/cli/scaffold.py @@ -28,7 +28,7 @@ from jsonschema import ValidationError from aea import AEA_DIR -from aea.cli.common import Context, pass_ctx, logger, _try_to_load_agent_config +from aea.cli.common import Context, pass_ctx, logger, _try_to_load_agent_config, DEFAULT_VERSION from aea.configurations.base import PublicId, DEFAULT_AEA_CONFIG_FILE # these variables are being used dynamically from aea.configurations.base import DEFAULT_CONNECTION_CONFIG_FILE, DEFAULT_PROTOCOL_CONFIG_FILE, DEFAULT_SKILL_CONFIG_FILE # noqa: F401 @@ -41,6 +41,30 @@ def scaffold(ctx: Context): _try_to_load_agent_config(ctx) +@scaffold.command() +@click.argument('connection_name', type=str, required=True) +@pass_ctx +def connection(ctx: Context, connection_name: str) -> None: + """Add a connection scaffolding to the configuration file and agent.""" + _scaffold_item(ctx, "connection", connection_name) + + +@scaffold.command() +@click.argument('protocol_name', type=str, required=True) +@pass_ctx +def protocol(ctx: Context, protocol_name: str): + """Add a protocol scaffolding to the configuration file and agent.""" + _scaffold_item(ctx, "protocol", protocol_name) + + +@scaffold.command() +@click.argument('skill_name', type=str, required=True) +@pass_ctx +def skill(ctx: Context, skill_name: str): + """Add a skill scaffolding to the configuration file and agent.""" + _scaffold_item(ctx, "skill", skill_name) + + def _scaffold_item(ctx: Context, item_type, item_name): """Add an item scaffolding to the configuration file and agent.""" existing_id_list = getattr(ctx.agent_config, "{}s".format(item_type)) @@ -61,20 +85,18 @@ def _scaffold_item(ctx: Context, item_type, item_name): agent_name = ctx.agent_config.agent_name logger.info("Adding {} scaffold '{}' to the agent '{}'...".format(item_type, item_name, agent_name)) + # create the item folder Path(item_type_plural).mkdir(exist_ok=True) - - # create the connection folder dest = Path(os.path.join(item_type_plural, item_name)) - # copy the skill package into the agent's supported skills. + # copy the item package into the agent project. src = Path(os.path.join(AEA_DIR, item_type_plural, "scaffold")) logger.debug("Copying {} modules. src={} dst={}".format(item_type, src, dest)) - shutil.copytree(src, dest) - # add the connection to the configurations. + # add the item to the configurations. logger.debug("Registering the {} into {}".format(item_type, DEFAULT_AEA_CONFIG_FILE)) - existing_id_list.add(PublicId("fetchai", item_name, "0.1.0")) + existing_id_list.add(PublicId("fetchai", item_name, DEFAULT_VERSION)) ctx.agent_loader.dump(ctx.agent_config, open(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w")) # ensure the name in the yaml and the name of the folder are the same @@ -83,38 +105,16 @@ def _scaffold_item(ctx: Context, item_type, item_name): config.name = item_name loader.dump(config, open(config_filepath, "w")) + # TODO: add user as author to config, update name of item in config + except FileExistsError: logger.error("A {} with this name already exists. Please choose a different name and try again.".format(item_type)) sys.exit(1) except ValidationError: - logger.error("Error when validating the skill configuration file.") + logger.error("Error when validating the {} configuration file.".format(item_type)) shutil.rmtree(os.path.join(item_type_plural, item_name), ignore_errors=True) sys.exit(1) except Exception as e: logger.exception(e) shutil.rmtree(os.path.join(item_type_plural, item_name), ignore_errors=True) sys.exit(1) - - -@scaffold.command() -@click.argument('connection_name', type=str, required=True) -@pass_ctx -def connection(ctx: Context, connection_name: str) -> None: - """Add a connection scaffolding to the configuration file and agent.""" - _scaffold_item(ctx, "connection", connection_name) - - -@scaffold.command() -@click.argument('protocol_name', type=str, required=True) -@pass_ctx -def protocol(ctx: Context, protocol_name: str): - """Add a protocol scaffolding to the configuration file and agent.""" - _scaffold_item(ctx, "protocol", protocol_name) - - -@scaffold.command() -@click.argument('skill_name', type=str, required=True) -@pass_ctx -def skill(ctx: Context, skill_name: str): - """Add a skill scaffolding to the configuration file and agent.""" - _scaffold_item(ctx, "skill", skill_name) diff --git a/aea/cli/search.py b/aea/cli/search.py index 6b53f670d4..b78d8948d7 100644 --- a/aea/cli/search.py +++ b/aea/cli/search.py @@ -26,7 +26,7 @@ from aea import AEA_DIR from aea.cli.common import Context, pass_ctx, DEFAULT_REGISTRY_PATH, logger, retrieve_details, ConfigLoader, \ - format_items, format_skills + format_items, format_skills, _try_to_load_agent_config from aea.cli.registry.utils import request_api from aea.configurations.base import DEFAULT_CONNECTION_CONFIG_FILE, DEFAULT_SKILL_CONFIG_FILE, \ DEFAULT_PROTOCOL_CONFIG_FILE, DEFAULT_AEA_CONFIG_FILE @@ -51,14 +51,15 @@ def search(ctx: Context, registry): # if we are in an agent directory, try to load the configuration file. # otherwise, use the default path (i.e. 'packages/' in the current directory.) try: - path = Path(DEFAULT_AEA_CONFIG_FILE) - fp = open(str(path), mode="r", encoding="utf-8") - agent_config = ctx.agent_loader.load(fp) - registry_directory = agent_config.registry_path + _try_to_load_agent_config(ctx, exit_on_except=False) + # path = Path(DEFAULT_AEA_CONFIG_FILE) + # fp = open(str(path), mode="r", encoding="utf-8") + # agent_config = ctx.agent_loader.load(fp) + registry_directory = ctx.agent_config.registry_path except Exception: registry_directory = os.path.join(ctx.cwd, DEFAULT_REGISTRY_PATH) - ctx.set_config("registry", registry_directory) + ctx.set_config("registry_directory", registry_directory) logger.debug("Using registry {}".format(registry_directory)) @@ -68,6 +69,7 @@ def _is_invalid_item(name, dir_path, config_path): def _get_details_from_dir(loader: ConfigLoader, root_path: str, sub_dir_name: str, config_filename: str, results: List[Dict]): + """Get the details from the directory.""" for r in Path(root_path).glob(sub_dir_name + "/*/"): dir_path = os.path.join(root_path, sub_dir_name, r.name) config_path = os.path.join(root_path, sub_dir_name, r.name, config_filename) @@ -97,7 +99,7 @@ def connections(ctx: Context, query): click.echo(format_items(resp)) return - registry = cast(str, ctx.config.get("registry")) + registry = cast(str, ctx.config.get("registry_directory")) result = [] # type: List[Dict] _get_details_from_dir(ctx.connection_loader, AEA_DIR, "connections", DEFAULT_CONNECTION_CONFIG_FILE, result) _get_details_from_dir(ctx.connection_loader, registry, "connections", DEFAULT_CONNECTION_CONFIG_FILE, result) @@ -124,7 +126,7 @@ def protocols(ctx: Context, query): click.echo(format_items(resp)) return - registry = cast(str, ctx.config.get("registry")) + registry = cast(str, ctx.config.get("registry_directory")) result = [] # type: List[Dict] _get_details_from_dir(ctx.protocol_loader, AEA_DIR, "protocols", DEFAULT_PROTOCOL_CONFIG_FILE, result) _get_details_from_dir(ctx.protocol_loader, registry, "protocols", DEFAULT_PROTOCOL_CONFIG_FILE, result) @@ -151,7 +153,7 @@ def skills(ctx: Context, query): click.echo(format_skills(resp)) return - registry = cast(str, ctx.config.get("registry")) + registry = cast(str, ctx.config.get("registry_directory")) result: List[Dict] = [] _get_details_from_dir(ctx.skill_loader, AEA_DIR, "skills", DEFAULT_SKILL_CONFIG_FILE, result) _get_details_from_dir(ctx.skill_loader, registry, "skills", DEFAULT_SKILL_CONFIG_FILE, result) @@ -177,7 +179,7 @@ def agents(ctx: Context, query): click.echo(format_items(resp)) return else: - registry = cast(str, ctx.config.get("registry")) + registry = cast(str, ctx.config.get("registry_directory")) result = [] # type: List[Dict] _get_details_from_dir(ctx.agent_loader, registry, "agents", DEFAULT_AEA_CONFIG_FILE, result) diff --git a/tests/test_cli/test_common.py b/tests/test_cli/test_common.py index 921557fbca..9baf806600 100644 --- a/tests/test_cli/test_common.py +++ b/tests/test_cli/test_common.py @@ -18,9 +18,10 @@ # ------------------------------------------------------------------------------ """This test module contains the tests for cli.common module.""" -from unittest import TestCase +from unittest import TestCase, mock +from click import ClickException -from aea.cli.common import format_items, format_skills +from aea.cli.common import format_items, format_skills, try_get_item_source_path, try_get_item_target_path class FormatItemsTestCase(TestCase): @@ -75,3 +76,43 @@ def test_format_skills_positive(self): '------------------------------\n' ) self.assertEqual(result, expected_result) + + +@mock.patch('aea.cli.common.os.path.join', return_value='some-path') +class TryGetItemSourcePathTestCase(TestCase): + """Test case for try_get_item_source_path method.""" + + @mock.patch('aea.cli.common.os.path.exists', return_value=True) + def test_get_item_source_path_positive(self, exists_mock, join_mock): + """Test for get_item_source_path positive result.""" + result = try_get_item_source_path('cwd', 'skills', 'skill-name') + expected_result = 'some-path' + self.assertEqual(result, expected_result) + join_mock.assert_called_once_with('cwd', 'skills', 'skill-name') + exists_mock.assert_called_once_with('some-path') + + @mock.patch('aea.cli.common.os.path.exists', return_value=False) + def test_get_item_source_path_not_exists(self, exists_mock, join_mock): + """Test for get_item_source_path item already exists.""" + with self.assertRaises(ClickException): + try_get_item_source_path('cwd', 'skills', 'skill-name') + + +@mock.patch('aea.cli.common.os.path.join', return_value='some-path') +class TryGetItemTargetPathTestCase(TestCase): + """Test case for try_get_item_target_path method.""" + + @mock.patch('aea.cli.common.os.path.exists', return_value=False) + def test_get_item_target_path_positive(self, exists_mock, join_mock): + """Test for get_item_source_path positive result.""" + result = try_get_item_target_path('skills', 'skill-name', 'packages') + expected_result = 'some-path' + self.assertEqual(result, expected_result) + join_mock.assert_called_once_with('packages', 'skills', 'skill-name') + exists_mock.assert_called_once_with('some-path') + + @mock.patch('aea.cli.common.os.path.exists', return_value=True) + def test_get_item_target_path_already_exists(self, exists_mock, join_mock): + """Test for get_item_target_path item already exists.""" + with self.assertRaises(ClickException): + try_get_item_target_path('skills', 'skill-name', 'packages_path') diff --git a/tests/test_cli/test_fetch.py b/tests/test_cli/test_fetch.py new file mode 100644 index 0000000000..81819ecfd6 --- /dev/null +++ b/tests/test_cli/test_fetch.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 2018-2019 Fetch.AI Limited +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ +"""This test module contains the tests for CLI Registry fetch methods.""" + +from unittest import mock, TestCase + +from aea.cli.fetch import _fetch_agent_locally + + +@mock.patch('aea.cli.fetch.copy_tree') +@mock.patch('aea.cli.fetch.os.path.join', return_value='joined-path') +@mock.patch('aea.cli.fetch.os.getcwd', return_value='cwd') +@mock.patch( + 'aea.cli.fetch.try_get_agent_source_path', return_value='path' +) +class FetchAgentLocallyTestCase(TestCase): + """Test case for fetch_agent_locally method.""" + + def test_fetch_agent_locally_positive( + self, + _get_agent_source_path_mock, + getcwd_mock, + join_mock, + copy_tree + ): + """Test for fetch_agent_locally method positive result.""" + _fetch_agent_locally(mock, 'author/name:1.0.0') + copy_tree.assert_called_once_with('path', 'joined-path') diff --git a/tests/test_cli/test_publish.py b/tests/test_cli/test_publish.py new file mode 100644 index 0000000000..adbfa4354b --- /dev/null +++ b/tests/test_cli/test_publish.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 2018-2019 Fetch.AI Limited +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ +"""Test module for Registry publish methods.""" + +from unittest import TestCase, mock + +from aea.cli.publish import _save_agent_locally + + +@mock.patch('aea.cli.registry.publish.copyfile') +@mock.patch('aea.cli.registry.publish.os.makedirs') +@mock.patch('aea.cli.registry.publish.os.path.exists', return_value=False) +@mock.patch( + 'aea.cli.registry.publish.get_item_target_path', + return_value='target-dir' +) +@mock.patch( + 'aea.cli.registry.publish._load_agent_config', + return_value={'agent_name': 'agent-name'} +) +@mock.patch('aea.cli.registry.publish.os.path.join', return_value='joined-path') +@mock.patch('aea.cli.registry.publish.os.getcwd', return_value='cwd') +class SaveAgentLocallyTestCase(TestCase): + """Test case for save_agent_locally method.""" + + def test_save_agent_locally_positive( + self, + getcwd_mock, + path_join_mock, + _load_agent_config_mock, + get_item_target_path_mock, + path_exists_mock, + makedirs_mock, + copyfile_mock + ): + """Test for save_agent_locally positive result.""" + _save_agent_locally(mock) + makedirs_mock.assert_called_once_with('target-dir', exist_ok=True) + copyfile_mock.assert_called_once_with('joined-path', 'joined-path') diff --git a/tests/test_cli/test_push.py b/tests/test_cli/test_push.py new file mode 100644 index 0000000000..6252be3c71 --- /dev/null +++ b/tests/test_cli/test_push.py @@ -0,0 +1,114 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 2018-2019 Fetch.AI Limited +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ +"""Test module for Registry push methods.""" + +from unittest import TestCase, mock + +from click import ClickException +from click.testing import CliRunner + +from aea.cli import cli +from aea.cli.push import _save_item_locally +from aea.configurations.base import PublicId +from tests.conftest import CLI_LOG_OPTION + + +@mock.patch('aea.cli.registry.push.copytree') +@mock.patch('aea.cli.registry.push.os.getcwd', return_value='cwd') +class SaveItemLocallyTestCase(TestCase): + """Test case for save_item_locally method.""" + + @mock.patch( + 'aea.cli.registry.push.get_item_target_path', return_value='target' + ) + @mock.patch( + 'aea.cli.registry.push.get_item_source_path', return_value='source' + ) + @mock.patch( + 'aea.cli.registry.push.load_yaml', return_value={"author": "fetchai", "version": "0.1.0", "name": "skill_name"} + ) + def test_save_item_locally_positive( + self, + load_yaml_mock, + get_item_source_path_mock, + get_item_target_path_mock, + getcwd_mock, + copy_tree_mock, + ): + """Test for save_item_locally positive result.""" + item_type = 'skill' + item_id = PublicId.from_string('fetchai/skill_name:0.1.0') + _save_item_locally('packages_path', item_type, item_id) + get_item_source_path_mock.assert_called_once_with( + 'cwd', 'skills', item_id.name + ) + get_item_target_path_mock.assert_called_once_with( + 'skills', item_id.name, 'packages_path' + ) + getcwd_mock.assert_called_once() + copy_tree_mock.assert_called_once_with('source', 'target') + + +@mock.patch('aea.cli.registry.push.copytree') +@mock.patch('aea.cli.registry.push.os.getcwd', return_value='cwd') +class SaveItemLocallyFailsTestCase(TestCase): + """Test case for save_item_locally method.""" + + @mock.patch( + 'aea.cli.registry.push.get_item_target_path', return_value='target' + ) + @mock.patch( + 'aea.cli.registry.push.get_item_source_path', return_value='source' + ) + @mock.patch( + 'aea.cli.registry.push.load_yaml', return_value={"author": "fetchai", "version": "0.1.0", "name": "skill_name"} + ) + def test_save_item_locally_positive( + self, + load_yaml_mock, + get_item_source_path_mock, + get_item_target_path_mock, + getcwd_mock, + copy_tree_mock, + ): + """Test for save_item_locally - item not found.""" + with self.assertRaises(ClickException): + item_type = 'skill' + item_id = PublicId.from_string('non_existing_author/skill_name:0.1.0') + _save_item_locally('packages_path', item_type, item_id) + + +class TestPushLocalFailsArgumentNotPublicId: + """Test the case when we try a local push with a non public id.""" + + @classmethod + def setup_class(cls): + """Set the tests up.""" + cls.runner = CliRunner() + cls.result = cls.runner.invoke(cli, [*CLI_LOG_OPTION, "push", "--local", "connection", "oef"], + standalone_mode=False) + + def test_exit_code_2(self): + """Test the exit code is 2 (i.e. bad usage).""" + assert self.result.exit_code == 1 + assert self.result.exception.exit_code == 2 + + @classmethod + def teardown_class(cls): + """Tear the tests down.""" diff --git a/tests/test_cli/test_registry/test_fetch.py b/tests/test_cli/test_registry/test_fetch.py index 1eda92e0cc..cb59b60364 100644 --- a/tests/test_cli/test_registry/test_fetch.py +++ b/tests/test_cli/test_registry/test_fetch.py @@ -21,9 +21,7 @@ from unittest import mock, TestCase from click import ClickException -from aea.cli.registry.fetch import ( - fetch_agent, _get_agent_source_path, fetch_agent_locally -) +from aea.cli.registry.fetch import fetch_agent def _raise_exception(): @@ -125,42 +123,3 @@ def test_fetch_agent_with_dependencies_unable_to_fetch( extract_mock.assert_not_called() fetch_package_mock.assert_called_once() rmtree_mock.assert_called_once() - - -@mock.patch('aea.cli.registry.fetch.os.path.join', return_value='joined-path') -class GetAgentSourcePathTestCase(TestCase): - """Test case for _get_agent_source_path method.""" - - @mock.patch('aea.cli.registry.fetch.os.path.exists', return_value=True) - def test__get_agent_source_path_positive(self, exists_mock, join_mock): - """Test for _get_agent_source_path method positive result.""" - result = _get_agent_source_path('agent-name') - expected_result = 'joined-path' - self.assertEqual(result, expected_result) - - @mock.patch('aea.cli.registry.fetch.os.path.exists', return_value=False) - def test__get_agent_source_path_not_exists(self, exists_mock, join_mock): - """Test for _get_agent_source_path method not exists.""" - with self.assertRaises(ClickException): - _get_agent_source_path('agent-name') - - -@mock.patch('aea.cli.registry.fetch.copy_tree') -@mock.patch('aea.cli.registry.fetch.os.path.join', return_value='joined-path') -@mock.patch('aea.cli.registry.fetch.os.getcwd', return_value='cwd') -@mock.patch( - 'aea.cli.registry.fetch._get_agent_source_path', return_value='path' -) -class FetchAgentLocallyTestCase(TestCase): - """Test case for fetch_agent_locally method.""" - - def test_fetch_agent_locally_positive( - self, - _get_agent_source_path_mock, - getcwd_mock, - join_mock, - copy_tree - ): - """Test for fetch_agent_locally method positive result.""" - fetch_agent_locally('author/name:1.0.0') - copy_tree.assert_called_once_with('path', 'joined-path') diff --git a/tests/test_cli/test_registry/test_publish.py b/tests/test_cli/test_registry/test_publish.py index 0b9991a663..1f90e0a98c 100644 --- a/tests/test_cli/test_registry/test_publish.py +++ b/tests/test_cli/test_registry/test_publish.py @@ -23,7 +23,7 @@ from click import ClickException from aea.cli.registry.publish import ( - publish_agent, _load_agent_config, save_agent_locally + publish_agent, _load_agent_config ) @@ -96,35 +96,3 @@ def test__load_agent_config_path_not_exists( _load_agent_config('path') load_yaml_mock.assert_not_called() - - -@mock.patch('aea.cli.registry.publish.copyfile') -@mock.patch('aea.cli.registry.publish.os.makedirs') -@mock.patch('aea.cli.registry.publish.os.path.exists', return_value=False) -@mock.patch( - 'aea.cli.registry.publish.get_item_target_path', - return_value='target-dir' -) -@mock.patch( - 'aea.cli.registry.publish._load_agent_config', - return_value={'agent_name': 'agent-name'} -) -@mock.patch('aea.cli.registry.publish.os.path.join', return_value='joined-path') -@mock.patch('aea.cli.registry.publish.os.getcwd', return_value='cwd') -class SaveAgentLocallyTestCase(TestCase): - """Test case for save_agent_locally method.""" - - def test_save_agent_locally_positive( - self, - getcwd_mock, - path_join_mock, - _load_agent_config_mock, - get_item_target_path_mock, - path_exists_mock, - makedirs_mock, - copyfile_mock - ): - """Test for save_agent_locally positive result.""" - save_agent_locally('packages_path') - makedirs_mock.assert_called_once_with('target-dir', exist_ok=True) - copyfile_mock.assert_called_once_with('joined-path', 'joined-path') diff --git a/tests/test_cli/test_registry/test_push.py b/tests/test_cli/test_registry/test_push.py index 0a2d42a69d..d2e7a1618e 100644 --- a/tests/test_cli/test_registry/test_push.py +++ b/tests/test_cli/test_registry/test_push.py @@ -22,16 +22,11 @@ from unittest import TestCase, mock from click import ClickException -from click.testing import CliRunner -from aea.cli import cli from aea.cli.registry.push import ( push_item, _remove_pycache, - save_item_locally, ) -from aea.configurations.base import PublicId -from tests.conftest import CLI_LOG_OPTION @mock.patch('aea.cli.registry.utils._rm_tarfiles') @@ -107,88 +102,3 @@ def test_remove_pycache_no_pycache(self, path_exists_mock, rmtree_mock): source_dir = 'somedir' _remove_pycache(source_dir) rmtree_mock.assert_not_called() - - -@mock.patch('aea.cli.registry.push.copytree') -@mock.patch('aea.cli.registry.push.os.getcwd', return_value='cwd') -class SaveItemLocallyTestCase(TestCase): - """Test case for save_item_locally method.""" - - @mock.patch( - 'aea.cli.registry.push.get_item_target_path', return_value='target' - ) - @mock.patch( - 'aea.cli.registry.push.get_item_source_path', return_value='source' - ) - @mock.patch( - 'aea.cli.registry.push.load_yaml', return_value={"author": "fetchai", "version": "0.1.0", "name": "skill_name"} - ) - def test_save_item_locally_positive( - self, - load_yaml_mock, - get_item_source_path_mock, - get_item_target_path_mock, - getcwd_mock, - copy_tree_mock, - ): - """Test for save_item_locally positive result.""" - item_type = 'skill' - item_id = PublicId.from_string('fetchai/skill_name:0.1.0') - save_item_locally(item_type, item_id, 'packages_path') - get_item_source_path_mock.assert_called_once_with( - 'cwd', 'skills', item_id.name - ) - get_item_target_path_mock.assert_called_once_with( - 'skills', item_id.name, 'packages_path' - ) - getcwd_mock.assert_called_once() - copy_tree_mock.assert_called_once_with('source', 'target') - - -@mock.patch('aea.cli.registry.push.copytree') -@mock.patch('aea.cli.registry.push.os.getcwd', return_value='cwd') -class SaveItemLocallyFailsTestCase(TestCase): - """Test case for save_item_locally method.""" - - @mock.patch( - 'aea.cli.registry.push.get_item_target_path', return_value='target' - ) - @mock.patch( - 'aea.cli.registry.push.get_item_source_path', return_value='source' - ) - @mock.patch( - 'aea.cli.registry.push.load_yaml', return_value={"author": "fetchai", "version": "0.1.0", "name": "skill_name"} - ) - def test_save_item_locally_positive( - self, - load_yaml_mock, - get_item_source_path_mock, - get_item_target_path_mock, - getcwd_mock, - copy_tree_mock, - ): - """Test for save_item_locally - item not found.""" - with self.assertRaises(ClickException): - item_type = 'skill' - item_id = PublicId.from_string('non_existing_author/skill_name:0.1.0') - save_item_locally(item_type, item_id, 'packages_path') - - -class TestPushLocalFailsArgumentNotPublicId: - """Test the case when we try a local push with a non public id.""" - - @classmethod - def setup_class(cls): - """Set the tests up.""" - cls.runner = CliRunner() - cls.result = cls.runner.invoke(cli, [*CLI_LOG_OPTION, "push", "--local", "connection", "oef"], - standalone_mode=False) - - def test_exit_code_2(self): - """Test the exit code is 2 (i.e. bad usage).""" - assert self.result.exit_code == 1 - assert self.result.exception.exit_code == 2 - - @classmethod - def teardown_class(cls): - """Tear the tests down.""" diff --git a/tests/test_cli/test_registry/test_utils.py b/tests/test_cli/test_registry/test_utils.py index 0a000df30e..b66b021ec6 100644 --- a/tests/test_cli/test_registry/test_utils.py +++ b/tests/test_cli/test_registry/test_utils.py @@ -28,8 +28,7 @@ from aea.cli.common import AEAConfigException from aea.cli.registry.utils import ( fetch_package, request_api, download_file, extract, _init_config_folder, - write_cli_config, read_cli_config, get_item_source_path, - get_item_target_path + write_cli_config, read_cli_config ) from aea.cli.registry.settings import REGISTRY_API_URL from aea.configurations.base import PublicId @@ -279,43 +278,3 @@ def test_read_cli_config_file_not_found(self): """Test for read_cli_config method bad yaml behavior.""" with self.assertRaises(AEAConfigException): read_cli_config() - - -@mock.patch('aea.cli.registry.utils.os.path.join', return_value='some-path') -class GetItemSourcePathTestCase(TestCase): - """Test case for get_item_source_path method.""" - - @mock.patch('aea.cli.registry.utils.os.path.exists', return_value=True) - def test_get_item_source_path_positive(self, exists_mock, join_mock): - """Test for get_item_source_path positive result.""" - result = get_item_source_path('cwd', 'skills', 'skill-name') - expected_result = 'some-path' - self.assertEqual(result, expected_result) - join_mock.assert_called_once_with('cwd', 'skills', 'skill-name') - exists_mock.assert_called_once_with('some-path') - - @mock.patch('aea.cli.registry.utils.os.path.exists', return_value=False) - def test_get_item_source_path_not_exists(self, exists_mock, join_mock): - """Test for get_item_source_path item already exists.""" - with self.assertRaises(ClickException): - get_item_source_path('cwd', 'skills', 'skill-name') - - -@mock.patch('aea.cli.registry.utils.os.path.join', return_value='some-path') -class GetItemTargetPathTestCase(TestCase): - """Test case for get_item_target_path method.""" - - @mock.patch('aea.cli.registry.utils.os.path.exists', return_value=False) - def test_get_item_target_path_positive(self, exists_mock, join_mock): - """Test for get_item_source_path positive result.""" - result = get_item_target_path('skills', 'skill-name', 'packages') - expected_result = 'some-path' - self.assertEqual(result, expected_result) - join_mock.assert_called_once_with('packages', 'skills', 'skill-name') - exists_mock.assert_called_once_with('some-path') - - @mock.patch('aea.cli.registry.utils.os.path.exists', return_value=True) - def test_get_item_target_path_already_exists(self, exists_mock, join_mock): - """Test for get_item_target_path item already exists.""" - with self.assertRaises(ClickException): - get_item_target_path('skills', 'skill-name', 'packages_path') diff --git a/tests/test_cli/test_scaffold/test_connection.py b/tests/test_cli/test_scaffold/test_connection.py index f2d484adc7..391c5af08d 100644 --- a/tests/test_cli/test_scaffold/test_connection.py +++ b/tests/test_cli/test_scaffold/test_connection.py @@ -228,7 +228,7 @@ def test_configuration_file_not_valid(self): The expected message is: 'Cannot find connection: '{connection_name}'' """ - self.mocked_logger_error.assert_called_once_with("Error when validating the skill configuration file.") + self.mocked_logger_error.assert_called_once_with("Error when validating the connection configuration file.") def test_resource_directory_does_not_exists(self): """Test that the resource directory does not exist. diff --git a/tests/test_cli/test_scaffold/test_protocols.py b/tests/test_cli/test_scaffold/test_protocols.py index a800ca8ac3..e6bd957b24 100644 --- a/tests/test_cli/test_scaffold/test_protocols.py +++ b/tests/test_cli/test_scaffold/test_protocols.py @@ -234,7 +234,7 @@ def test_configuration_file_not_valid(self): The expected message is: 'Cannot find protocol: '{protocol_name}' """ - self.mocked_logger_error.assert_called_once_with("Error when validating the skill configuration file.") + self.mocked_logger_error.assert_called_once_with("Error when validating the protocol configuration file.") def test_resource_directory_does_not_exists(self): """Test that the resource directory does not exist. From 7d0183e9a5a6743902a0f988a8f977787601b83d Mon Sep 17 00:00:00 2001 From: panasevychol Date: Fri, 10 Jan 2020 15:25:33 +0200 Subject: [PATCH 4/7] Refactoring: private method _try_to_load_agent_config changed to public, a lot of tests fixed + minor changes. --- aea/cli/add.py | 4 +- aea/cli/common.py | 16 ++++-- aea/cli/config.py | 4 +- aea/cli/core.py | 8 +-- aea/cli/install.py | 4 +- aea/cli/list.py | 4 +- aea/cli/publish.py | 4 +- aea/cli/push.py | 4 +- aea/cli/registry/push.py | 2 +- aea/cli/remove.py | 4 +- aea/cli/run.py | 4 +- aea/cli/scaffold.py | 4 +- aea/cli/search.py | 4 +- tests/test_cli/test_common.py | 2 +- tests/test_cli/test_fetch.py | 10 ++-- tests/test_cli/test_publish.py | 23 +++----- tests/test_cli/test_push.py | 60 +++++--------------- tests/test_cli/test_registry/test_fetch.py | 40 ++++--------- tests/test_cli/test_registry/test_publish.py | 4 +- tests/test_cli/test_registry/test_push.py | 18 ++++-- tests/test_cli/tools_for_testing.py | 42 ++++++++++++++ 21 files changed, 135 insertions(+), 130 deletions(-) create mode 100644 tests/test_cli/tools_for_testing.py diff --git a/aea/cli/add.py b/aea/cli/add.py index 4818bcafda..363b277708 100644 --- a/aea/cli/add.py +++ b/aea/cli/add.py @@ -30,7 +30,7 @@ from jsonschema import ValidationError from aea import AEA_DIR -from aea.cli.common import Context, pass_ctx, logger, _try_to_load_agent_config, PublicIdParameter +from aea.cli.common import Context, pass_ctx, logger, try_to_load_agent_config, PublicIdParameter from aea.cli.registry.utils import fetch_package from aea.configurations.base import DEFAULT_AEA_CONFIG_FILE, DEFAULT_CONNECTION_CONFIG_FILE, DEFAULT_SKILL_CONFIG_FILE, \ DEFAULT_PROTOCOL_CONFIG_FILE, PublicId @@ -43,7 +43,7 @@ def add(ctx: Context, registry): """Add a resource to the agent.""" if registry: ctx.set_config("is_registry", True) - _try_to_load_agent_config(ctx) + try_to_load_agent_config(ctx) def _find_connection_locally(ctx, connection_public_id, click_context): diff --git a/aea/cli/common.py b/aea/cli/common.py index ad1feed915..f990fbb994 100644 --- a/aea/cli/common.py +++ b/aea/cli/common.py @@ -102,12 +102,20 @@ def get_dependencies(self) -> Dependencies: pass_ctx = click.make_pass_decorator(Context) -def _try_to_load_agent_config(ctx: Context, exit_on_except: bool = True): +def try_to_load_agent_config(ctx: Context, exit_on_except: bool = True) -> None: + """ + Load agent config to a click context object. + + :param ctx: click command context object. + :param exit_on_except: bool option to exit on exception (default = True). + + :return None + """ try: path = Path(DEFAULT_AEA_CONFIG_FILE) - fp = open(str(path), mode="r", encoding="utf-8") - ctx.agent_config = ctx.agent_loader.load(fp) - logging.config.dictConfig(ctx.agent_config.logging_config) + with open(str(path), mode="r", encoding="utf-8") as fp: + ctx.agent_config = ctx.agent_loader.load(fp) + logging.config.dictConfig(ctx.agent_config.logging_config) except FileNotFoundError: if exit_on_except: logger.error("Agent configuration file '{}' not found in the current directory.".format(DEFAULT_AEA_CONFIG_FILE)) diff --git a/aea/cli/config.py b/aea/cli/config.py index 5aa7e42e0c..4a269ed283 100644 --- a/aea/cli/config.py +++ b/aea/cli/config.py @@ -25,7 +25,7 @@ import click import yaml -from aea.cli.common import Context, pass_ctx, _try_to_load_agent_config, logger +from aea.cli.common import Context, pass_ctx, try_to_load_agent_config, logger from aea.configurations.base import DEFAULT_AEA_CONFIG_FILE, DEFAULT_SKILL_CONFIG_FILE, DEFAULT_PROTOCOL_CONFIG_FILE, \ DEFAULT_CONNECTION_CONFIG_FILE from aea.configurations.loader import ConfigLoader, ConfigurationType @@ -113,7 +113,7 @@ def _get_parent_object(obj: dict, dotted_path: List[str]): @pass_ctx def config(ctx: Context): """Read or modify a configuration.""" - _try_to_load_agent_config(ctx) + try_to_load_agent_config(ctx) @config.command() diff --git a/aea/cli/core.py b/aea/cli/core.py index 540dfdd856..7f37eee972 100644 --- a/aea/cli/core.py +++ b/aea/cli/core.py @@ -29,7 +29,7 @@ import aea from aea.cli.add import add -from aea.cli.common import Context, pass_ctx, logger, _try_to_load_agent_config +from aea.cli.common import Context, pass_ctx, logger, try_to_load_agent_config from aea.cli.config import config from aea.cli.create import create from aea.cli.fetch import fetch @@ -73,7 +73,7 @@ def delete(ctx: Context, agent_name): os.chdir(agent_name) fp = open(DEFAULT_AEA_CONFIG_FILE, mode="r", encoding="utf-8") ctx.agent_config = ctx.agent_loader.load(fp) - _try_to_load_agent_config(ctx) + try_to_load_agent_config(ctx) except Exception: logger.error("The name provided is not an AEA project.") sys.exit(1) @@ -94,7 +94,7 @@ def delete(ctx: Context, agent_name): @pass_ctx def freeze(ctx: Context): """Get the dependencies.""" - _try_to_load_agent_config(ctx) + try_to_load_agent_config(ctx) for dependency_name, dependency_data in sorted(ctx.get_dependencies().items(), key=lambda x: x[0]): print(dependency_name + dependency_data.get("version", "")) @@ -148,7 +148,7 @@ def _can_write(path) -> bool: @pass_ctx def add_key(ctx: Context, type_, file): """Add a private key to the wallet.""" - _try_to_load_agent_config(ctx) + try_to_load_agent_config(ctx) _validate_private_key_path(file, type_) try: ctx.agent_config.private_key_paths.create(type_, PrivateKeyPathConfig(type_, file)) diff --git a/aea/cli/install.py b/aea/cli/install.py index 2cd0f8fc70..b56d965f45 100644 --- a/aea/cli/install.py +++ b/aea/cli/install.py @@ -25,7 +25,7 @@ import click -from aea.cli.common import Context, pass_ctx, logger, _try_to_load_agent_config +from aea.cli.common import Context, pass_ctx, logger, try_to_load_agent_config from aea.configurations.base import Dependency @@ -68,7 +68,7 @@ def _install_from_requirement(file: str): @pass_ctx def install(ctx: Context, requirement: Optional[str]): """Install the dependencies.""" - _try_to_load_agent_config(ctx) + try_to_load_agent_config(ctx) if requirement: logger.debug("Installing the dependencies in '{}'...".format(requirement)) diff --git a/aea/cli/list.py b/aea/cli/list.py index c47ea3b052..849b94fe70 100644 --- a/aea/cli/list.py +++ b/aea/cli/list.py @@ -23,7 +23,7 @@ import click -from aea.cli.common import Context, pass_ctx, _try_to_load_agent_config, retrieve_details, format_items +from aea.cli.common import Context, pass_ctx, try_to_load_agent_config, retrieve_details, format_items from aea.configurations.base import DEFAULT_CONNECTION_CONFIG_FILE, DEFAULT_SKILL_CONFIG_FILE, \ DEFAULT_PROTOCOL_CONFIG_FILE @@ -32,7 +32,7 @@ @pass_ctx def list(ctx: Context): """List the installed resources.""" - _try_to_load_agent_config(ctx) + try_to_load_agent_config(ctx) @list.command() diff --git a/aea/cli/publish.py b/aea/cli/publish.py index 5a27213eb8..047ce8cb16 100644 --- a/aea/cli/publish.py +++ b/aea/cli/publish.py @@ -22,7 +22,7 @@ import os from shutil import copyfile -from aea.cli.common import pass_ctx, Context, _try_to_load_agent_config, try_get_item_target_path, DEFAULT_AEA_CONFIG_FILE +from aea.cli.common import pass_ctx, Context, try_to_load_agent_config, try_get_item_target_path, DEFAULT_AEA_CONFIG_FILE from aea.cli.registry.publish import publish_agent @@ -33,7 +33,7 @@ @pass_ctx def publish(ctx: Context, registry): """Publish Agent to Registry.""" - _try_to_load_agent_config(ctx) + try_to_load_agent_config(ctx) if not registry: # TODO: check agent dependencies are available in local packages dir. _save_agent_locally(ctx) diff --git a/aea/cli/push.py b/aea/cli/push.py index ca7422144d..db4c3e5b84 100644 --- a/aea/cli/push.py +++ b/aea/cli/push.py @@ -21,7 +21,7 @@ import click from shutil import copytree -from aea.cli.common import pass_ctx, Context, PublicIdParameter, try_get_item_target_path, try_get_item_source_path, _try_to_load_agent_config +from aea.cli.common import pass_ctx, Context, PublicIdParameter, try_get_item_target_path, try_get_item_source_path, try_to_load_agent_config from aea.cli.registry.push import push_item from aea.configurations.base import PublicId @@ -33,7 +33,7 @@ @pass_ctx def push(ctx: Context, registry): """Push item to Registry or save it in local packages.""" - _try_to_load_agent_config(ctx) + try_to_load_agent_config(ctx) ctx.set_config("registry", registry) diff --git a/aea/cli/registry/push.py b/aea/cli/registry/push.py index 6fe18cb420..a672634854 100644 --- a/aea/cli/registry/push.py +++ b/aea/cli/registry/push.py @@ -84,7 +84,7 @@ def push_item(ctx: Context, item_type: str, item_id: PublicIdParameter) -> None: data = { 'name': item_id.name, 'description': item_config['description'], - 'version': item_config['version'] + 'version': item_id.version } path = '/{}/create'.format(item_type_plural) logger.debug('Pushing {} {} to Registry ...'.format(item_id.name, item_type)) diff --git a/aea/cli/remove.py b/aea/cli/remove.py index 4a93b7de29..6122484512 100644 --- a/aea/cli/remove.py +++ b/aea/cli/remove.py @@ -25,7 +25,7 @@ import click -from aea.cli.common import Context, pass_ctx, logger, _try_to_load_agent_config +from aea.cli.common import Context, pass_ctx, logger, try_to_load_agent_config from aea.configurations.base import DEFAULT_AEA_CONFIG_FILE, PublicId @@ -33,7 +33,7 @@ @pass_ctx def remove(ctx: Context): """Remove a resource from the agent.""" - _try_to_load_agent_config(ctx) + try_to_load_agent_config(ctx) def _remove_item(ctx: Context, item_type, item): diff --git a/aea/cli/run.py b/aea/cli/run.py index 99c1319624..6bd4e9e973 100644 --- a/aea/cli/run.py +++ b/aea/cli/run.py @@ -29,7 +29,7 @@ from click import pass_context from aea.aea import AEA -from aea.cli.common import Context, logger, _try_to_load_agent_config, _try_to_load_protocols, \ +from aea.cli.common import Context, logger, try_to_load_agent_config, _try_to_load_protocols, \ AEAConfigException, _load_env_file, ConnectionsOption from aea.cli.install import install from aea.configurations.base import AgentConfig, DEFAULT_AEA_CONFIG_FILE, PrivateKeyPathConfig, \ @@ -185,7 +185,7 @@ def _setup_connection(connection_name: str, address: str, ctx: Context) -> Conne def run(click_context, connection_names: List[str], env_file: str, install_deps: bool): """Run the agent.""" ctx = cast(Context, click_context.obj) - _try_to_load_agent_config(ctx) + try_to_load_agent_config(ctx) _load_env_file(env_file) agent_name = cast(str, ctx.agent_config.agent_name) diff --git a/aea/cli/scaffold.py b/aea/cli/scaffold.py index dfe2bc051e..d84e301486 100644 --- a/aea/cli/scaffold.py +++ b/aea/cli/scaffold.py @@ -28,7 +28,7 @@ from jsonschema import ValidationError from aea import AEA_DIR -from aea.cli.common import Context, pass_ctx, logger, _try_to_load_agent_config, DEFAULT_VERSION +from aea.cli.common import Context, pass_ctx, logger, try_to_load_agent_config, DEFAULT_VERSION from aea.configurations.base import PublicId, DEFAULT_AEA_CONFIG_FILE # these variables are being used dynamically from aea.configurations.base import DEFAULT_CONNECTION_CONFIG_FILE, DEFAULT_PROTOCOL_CONFIG_FILE, DEFAULT_SKILL_CONFIG_FILE # noqa: F401 @@ -38,7 +38,7 @@ @pass_ctx def scaffold(ctx: Context): """Scaffold a resource for the agent.""" - _try_to_load_agent_config(ctx) + try_to_load_agent_config(ctx) @scaffold.command() diff --git a/aea/cli/search.py b/aea/cli/search.py index b78d8948d7..9fe513ba6d 100644 --- a/aea/cli/search.py +++ b/aea/cli/search.py @@ -26,7 +26,7 @@ from aea import AEA_DIR from aea.cli.common import Context, pass_ctx, DEFAULT_REGISTRY_PATH, logger, retrieve_details, ConfigLoader, \ - format_items, format_skills, _try_to_load_agent_config + format_items, format_skills, try_to_load_agent_config from aea.cli.registry.utils import request_api from aea.configurations.base import DEFAULT_CONNECTION_CONFIG_FILE, DEFAULT_SKILL_CONFIG_FILE, \ DEFAULT_PROTOCOL_CONFIG_FILE, DEFAULT_AEA_CONFIG_FILE @@ -51,7 +51,7 @@ def search(ctx: Context, registry): # if we are in an agent directory, try to load the configuration file. # otherwise, use the default path (i.e. 'packages/' in the current directory.) try: - _try_to_load_agent_config(ctx, exit_on_except=False) + try_to_load_agent_config(ctx, exit_on_except=False) # path = Path(DEFAULT_AEA_CONFIG_FILE) # fp = open(str(path), mode="r", encoding="utf-8") # agent_config = ctx.agent_loader.load(fp) diff --git a/tests/test_cli/test_common.py b/tests/test_cli/test_common.py index 9baf806600..9e8dee71d4 100644 --- a/tests/test_cli/test_common.py +++ b/tests/test_cli/test_common.py @@ -105,7 +105,7 @@ class TryGetItemTargetPathTestCase(TestCase): @mock.patch('aea.cli.common.os.path.exists', return_value=False) def test_get_item_target_path_positive(self, exists_mock, join_mock): """Test for get_item_source_path positive result.""" - result = try_get_item_target_path('skills', 'skill-name', 'packages') + result = try_get_item_target_path('packages', 'skills', 'skill-name') expected_result = 'some-path' self.assertEqual(result, expected_result) join_mock.assert_called_once_with('packages', 'skills', 'skill-name') diff --git a/tests/test_cli/test_fetch.py b/tests/test_cli/test_fetch.py index 81819ecfd6..5817d26922 100644 --- a/tests/test_cli/test_fetch.py +++ b/tests/test_cli/test_fetch.py @@ -22,23 +22,23 @@ from aea.cli.fetch import _fetch_agent_locally +from tests.test_cli.tools_for_testing import ContextMock, PublicIdMock + @mock.patch('aea.cli.fetch.copy_tree') @mock.patch('aea.cli.fetch.os.path.join', return_value='joined-path') -@mock.patch('aea.cli.fetch.os.getcwd', return_value='cwd') @mock.patch( - 'aea.cli.fetch.try_get_agent_source_path', return_value='path' + 'aea.cli.fetch.try_get_item_source_path', return_value='path' ) class FetchAgentLocallyTestCase(TestCase): """Test case for fetch_agent_locally method.""" def test_fetch_agent_locally_positive( self, - _get_agent_source_path_mock, - getcwd_mock, + try_get_item_source_path_mock, join_mock, copy_tree ): """Test for fetch_agent_locally method positive result.""" - _fetch_agent_locally(mock, 'author/name:1.0.0') + _fetch_agent_locally(ContextMock(), PublicIdMock()) copy_tree.assert_called_once_with('path', 'joined-path') diff --git a/tests/test_cli/test_publish.py b/tests/test_cli/test_publish.py index adbfa4354b..c1c20fce77 100644 --- a/tests/test_cli/test_publish.py +++ b/tests/test_cli/test_publish.py @@ -22,34 +22,29 @@ from aea.cli.publish import _save_agent_locally +from tests.test_cli.tools_for_testing import ContextMock -@mock.patch('aea.cli.registry.publish.copyfile') -@mock.patch('aea.cli.registry.publish.os.makedirs') -@mock.patch('aea.cli.registry.publish.os.path.exists', return_value=False) + +@mock.patch('aea.cli.publish.copyfile') +@mock.patch('aea.cli.publish.os.makedirs') +@mock.patch('aea.cli.publish.os.path.exists', return_value=False) @mock.patch( - 'aea.cli.registry.publish.get_item_target_path', + 'aea.cli.publish.try_get_item_target_path', return_value='target-dir' ) -@mock.patch( - 'aea.cli.registry.publish._load_agent_config', - return_value={'agent_name': 'agent-name'} -) -@mock.patch('aea.cli.registry.publish.os.path.join', return_value='joined-path') -@mock.patch('aea.cli.registry.publish.os.getcwd', return_value='cwd') +@mock.patch('aea.cli.publish.os.path.join', return_value='joined-path') class SaveAgentLocallyTestCase(TestCase): """Test case for save_agent_locally method.""" def test_save_agent_locally_positive( self, - getcwd_mock, path_join_mock, - _load_agent_config_mock, - get_item_target_path_mock, + try_get_item_target_path_mock, path_exists_mock, makedirs_mock, copyfile_mock ): """Test for save_agent_locally positive result.""" - _save_agent_locally(mock) + _save_agent_locally(ContextMock()) makedirs_mock.assert_called_once_with('target-dir', exist_ok=True) copyfile_mock.assert_called_once_with('joined-path', 'joined-path') diff --git a/tests/test_cli/test_push.py b/tests/test_cli/test_push.py index 6252be3c71..2b34385a82 100644 --- a/tests/test_cli/test_push.py +++ b/tests/test_cli/test_push.py @@ -26,74 +26,42 @@ from aea.cli import cli from aea.cli.push import _save_item_locally from aea.configurations.base import PublicId + from tests.conftest import CLI_LOG_OPTION +from tests.test_cli.tools_for_testing import ContextMock, PublicIdMock -@mock.patch('aea.cli.registry.push.copytree') -@mock.patch('aea.cli.registry.push.os.getcwd', return_value='cwd') +@mock.patch('aea.cli.push.copytree') class SaveItemLocallyTestCase(TestCase): """Test case for save_item_locally method.""" @mock.patch( - 'aea.cli.registry.push.get_item_target_path', return_value='target' - ) - @mock.patch( - 'aea.cli.registry.push.get_item_source_path', return_value='source' + 'aea.cli.push.try_get_item_target_path', return_value='target' ) @mock.patch( - 'aea.cli.registry.push.load_yaml', return_value={"author": "fetchai", "version": "0.1.0", "name": "skill_name"} + 'aea.cli.push.try_get_item_source_path', return_value='source' ) def test_save_item_locally_positive( self, - load_yaml_mock, - get_item_source_path_mock, - get_item_target_path_mock, - getcwd_mock, + try_get_item_source_path_mock, + try_get_item_target_path_mock, copy_tree_mock, ): """Test for save_item_locally positive result.""" item_type = 'skill' - item_id = PublicId.from_string('fetchai/skill_name:0.1.0') - _save_item_locally('packages_path', item_type, item_id) - get_item_source_path_mock.assert_called_once_with( + item_id = PublicIdMock() + _save_item_locally(ContextMock(), item_type, PublicIdMock()) + try_get_item_source_path_mock.assert_called_once_with( 'cwd', 'skills', item_id.name ) - get_item_target_path_mock.assert_called_once_with( - 'skills', item_id.name, 'packages_path' + try_get_item_target_path_mock.assert_called_once_with( + ContextMock.agent_config.registry_path, + item_type + 's', + item_id.name, ) - getcwd_mock.assert_called_once() copy_tree_mock.assert_called_once_with('source', 'target') -@mock.patch('aea.cli.registry.push.copytree') -@mock.patch('aea.cli.registry.push.os.getcwd', return_value='cwd') -class SaveItemLocallyFailsTestCase(TestCase): - """Test case for save_item_locally method.""" - - @mock.patch( - 'aea.cli.registry.push.get_item_target_path', return_value='target' - ) - @mock.patch( - 'aea.cli.registry.push.get_item_source_path', return_value='source' - ) - @mock.patch( - 'aea.cli.registry.push.load_yaml', return_value={"author": "fetchai", "version": "0.1.0", "name": "skill_name"} - ) - def test_save_item_locally_positive( - self, - load_yaml_mock, - get_item_source_path_mock, - get_item_target_path_mock, - getcwd_mock, - copy_tree_mock, - ): - """Test for save_item_locally - item not found.""" - with self.assertRaises(ClickException): - item_type = 'skill' - item_id = PublicId.from_string('non_existing_author/skill_name:0.1.0') - _save_item_locally('packages_path', item_type, item_id) - - class TestPushLocalFailsArgumentNotPublicId: """Test the case when we try a local push with a non public id.""" diff --git a/tests/test_cli/test_registry/test_fetch.py b/tests/test_cli/test_registry/test_fetch.py index cb59b60364..5e076df639 100644 --- a/tests/test_cli/test_registry/test_fetch.py +++ b/tests/test_cli/test_registry/test_fetch.py @@ -23,6 +23,11 @@ from aea.cli.registry.fetch import fetch_agent +from tests.test_cli.tools_for_testing import ( + ContextMock, + PublicIdMock +) + def _raise_exception(): raise Exception() @@ -33,7 +38,6 @@ def _raise_exception(): return_value='filepath' ) @mock.patch('aea.cli.registry.fetch.extract') -@mock.patch('aea.cli.registry.fetch.os.getcwd', return_value='cwd') class TestFetchAgent(TestCase): """Test case for fetch_package method.""" @@ -49,16 +53,13 @@ class TestFetchAgent(TestCase): def test_fetch_agent_positive( self, request_api_mock, - getcwd_mock, extract_mock, download_file_mock, ): """Test for fetch_agent method positive result.""" - public_id = 'author/name:0.1.0' - - fetch_agent(public_id) + fetch_agent(ContextMock(), PublicIdMock()) request_api_mock.assert_called_with( - 'GET', '/agents/author/name/0.1.0' + 'GET', '/agents/author/name/1.0.0' ) download_file_mock.assert_called_once_with('url', 'cwd') extract_mock.assert_called_once_with('filepath', 'cwd/name') @@ -77,16 +78,13 @@ def test_fetch_agent_with_dependencies_positive( self, request_api_mock, fetch_package_mock, - getcwd_mock, extract_mock, download_file_mock, ): """Test for fetch_agent method with dependencies positive result.""" - public_id = 'author/name:0.1.0' - - fetch_agent(public_id) + fetch_agent(ContextMock(), PublicIdMock()) request_api_mock.assert_called_with( - 'GET', '/agents/author/name/0.1.0' + 'GET', '/agents/author/name/1.0.0' ) download_file_mock.assert_called_once_with('url', 'cwd') extract_mock.assert_called_once_with('filepath', 'cwd/name') @@ -103,23 +101,7 @@ def test_fetch_agent_with_dependencies_positive( } ) @mock.patch('aea.cli.registry.fetch.rmtree') - def test_fetch_agent_with_dependencies_unable_to_fetch( - self, - rmtree_mock, - request_api_mock, - fetch_package_mock, - getcwd_mock, - extract_mock, - ): + def test_fetch_agent_with_dependencies_unable_to_fetch(self, *mocks): """Test for fetch_agent method positive result.""" - public_id = 'author/name:0.1.0' - with self.assertRaises(ClickException): - fetch_agent(public_id) - - request_api_mock.assert_called_with( - 'GET', '/agents/author/name/0.1.0' - ) - extract_mock.assert_not_called() - fetch_package_mock.assert_called_once() - rmtree_mock.assert_called_once() + fetch_agent(ContextMock(), PublicIdMock()) diff --git a/tests/test_cli/test_registry/test_publish.py b/tests/test_cli/test_registry/test_publish.py index 1f90e0a98c..490b30da9d 100644 --- a/tests/test_cli/test_registry/test_publish.py +++ b/tests/test_cli/test_registry/test_publish.py @@ -26,6 +26,8 @@ publish_agent, _load_agent_config ) +from tests.test_cli.tools_for_testing import ContextMock + @mock.patch('aea.cli.registry.utils._rm_tarfiles') @mock.patch('aea.cli.registry.publish.os.getcwd', return_value='cwd') @@ -57,7 +59,7 @@ def test_push_item_positive( _rm_tarfiles_mock ): """Test for publish_agent positive result.""" - publish_agent() + publish_agent(ContextMock()) request_api_mock.assert_called_once_with( 'POST', '/agents/create', diff --git a/tests/test_cli/test_registry/test_push.py b/tests/test_cli/test_registry/test_push.py index d2e7a1618e..72d1d85710 100644 --- a/tests/test_cli/test_registry/test_push.py +++ b/tests/test_cli/test_registry/test_push.py @@ -28,6 +28,11 @@ _remove_pycache, ) +from tests.test_cli.tools_for_testing import ( + ContextMock, + PublicIdMock +) + @mock.patch('aea.cli.registry.utils._rm_tarfiles') @mock.patch('aea.cli.registry.push.os.getcwd', return_value='cwd') @@ -53,17 +58,20 @@ def test_push_item_positive( rm_tarfiles_mock ): """Test for push_item positive result.""" - push_item('some-type', 'item-name') + public_id = PublicIdMock( + name='some-name', author='some-author', version='1.0.0' + ) + push_item(ContextMock(), 'some-type', public_id) request_api_mock.assert_called_once_with( 'POST', '/some-types/create', data={ - 'name': 'item-name', + 'name': 'some-name', 'description': 'some-description', - 'version': 'some-version', + 'version': '1.0.0', }, auth=True, - filepath='cwd/item-name.tar.gz' + filepath='cwd/some-name.tar.gz' ) @mock.patch('aea.cli.registry.push.os.path.exists', return_value=False) @@ -78,7 +86,7 @@ def test_push_item_item_not_found( ): """Test for push_item - item not found.""" with self.assertRaises(ClickException): - push_item('some-type', 'item-name') + push_item(ContextMock(), 'some-type', PublicIdMock()) request_api_mock.assert_not_called() diff --git a/tests/test_cli/tools_for_testing.py b/tests/test_cli/tools_for_testing.py new file mode 100644 index 0000000000..356d129516 --- /dev/null +++ b/tests/test_cli/tools_for_testing.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 2018-2019 Fetch.AI Limited +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ +"""Tools used for CLI registry testing.""" + + +class AgentConfigMock: + """An object to mock Agent config.""" + + registry_path = 'registry' + name = 'name' + + +class ContextMock: + """An object to mock Click Context.""" + + cwd = 'cwd' + agent_config = AgentConfigMock() + + +class PublicIdMock: + """An object to mock PublicId.""" + + def __init__(self, name='name', author='author', version='1.0.0'): + self.name = name + self.author = author + self.version = version From aa8ee71dd65cca9565cadae0e33d8b5ff2871e33 Mon Sep 17 00:00:00 2001 From: panasevychol Date: Fri, 10 Jan 2020 15:38:45 +0200 Subject: [PATCH 5/7] Getting version on push moved back to old code, test fixed. --- aea/cli/registry/push.py | 2 +- tests/test_cli/test_registry/test_push.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/aea/cli/registry/push.py b/aea/cli/registry/push.py index a672634854..6fe18cb420 100644 --- a/aea/cli/registry/push.py +++ b/aea/cli/registry/push.py @@ -84,7 +84,7 @@ def push_item(ctx: Context, item_type: str, item_id: PublicIdParameter) -> None: data = { 'name': item_id.name, 'description': item_config['description'], - 'version': item_id.version + 'version': item_config['version'] } path = '/{}/create'.format(item_type_plural) logger.debug('Pushing {} {} to Registry ...'.format(item_id.name, item_type)) diff --git a/tests/test_cli/test_registry/test_push.py b/tests/test_cli/test_registry/test_push.py index 72d1d85710..6b716b4221 100644 --- a/tests/test_cli/test_registry/test_push.py +++ b/tests/test_cli/test_registry/test_push.py @@ -68,7 +68,7 @@ def test_push_item_positive( data={ 'name': 'some-name', 'description': 'some-description', - 'version': '1.0.0', + 'version': 'some-version', }, auth=True, filepath='cwd/some-name.tar.gz' From 85e9b44e1f248bba926ec003c8cae2bad34bb7d6 Mon Sep 17 00:00:00 2001 From: panasevychol Date: Fri, 10 Jan 2020 15:59:01 +0200 Subject: [PATCH 6/7] Chenged to use DEFAULT_VERSION in tests. --- tests/test_cli/constants.py | 5 +++++ tests/test_cli/test_registry/test_fetch.py | 12 ++++++------ tests/test_cli/test_registry/test_push.py | 2 +- tests/test_cli/tools_for_testing.py | 8 +++++++- 4 files changed, 19 insertions(+), 8 deletions(-) diff --git a/tests/test_cli/constants.py b/tests/test_cli/constants.py index f06de0f104..af030f3b1f 100644 --- a/tests/test_cli/constants.py +++ b/tests/test_cli/constants.py @@ -18,4 +18,9 @@ # ------------------------------------------------------------------------------ """Constants used for CLI testing.""" +from aea.cli.common import DEFAULT_VERSION + + FORMAT_ITEMS_SAMPLE_OUTPUT = 'Correct items' + +DEFAULT_TESTING_VERSION = DEFAULT_VERSION diff --git a/tests/test_cli/test_registry/test_fetch.py b/tests/test_cli/test_registry/test_fetch.py index 5e076df639..471a006f5a 100644 --- a/tests/test_cli/test_registry/test_fetch.py +++ b/tests/test_cli/test_registry/test_fetch.py @@ -59,7 +59,7 @@ def test_fetch_agent_positive( """Test for fetch_agent method positive result.""" fetch_agent(ContextMock(), PublicIdMock()) request_api_mock.assert_called_with( - 'GET', '/agents/author/name/1.0.0' + 'GET', '/agents/author/name/{}'.format(PublicIdMock.DEFAULT_VERSION) ) download_file_mock.assert_called_once_with('url', 'cwd') extract_mock.assert_called_once_with('filepath', 'cwd/name') @@ -69,9 +69,9 @@ def test_fetch_agent_positive( 'aea.cli.registry.fetch.request_api', return_value={ 'file': 'url', - 'connections': ['public/id:1.0.0'], - 'protocols': ['public/id:1.0.0'], - 'skills': ['public/id:1.0.0'] + 'connections': ['public/id:{}'.format(PublicIdMock.DEFAULT_VERSION)], + 'protocols': ['public/id:{}'.format(PublicIdMock.DEFAULT_VERSION)], + 'skills': ['public/id:{}'.format(PublicIdMock.DEFAULT_VERSION)] } ) def test_fetch_agent_with_dependencies_positive( @@ -84,7 +84,7 @@ def test_fetch_agent_with_dependencies_positive( """Test for fetch_agent method with dependencies positive result.""" fetch_agent(ContextMock(), PublicIdMock()) request_api_mock.assert_called_with( - 'GET', '/agents/author/name/1.0.0' + 'GET', '/agents/author/name/{}'.format(PublicIdMock.DEFAULT_VERSION) ) download_file_mock.assert_called_once_with('url', 'cwd') extract_mock.assert_called_once_with('filepath', 'cwd/name') @@ -95,7 +95,7 @@ def test_fetch_agent_with_dependencies_positive( 'aea.cli.registry.fetch.request_api', return_value={ 'file': 'url', - 'connections': ['public/id:1.0.0'], + 'connections': ['public/id:{}'.format(PublicIdMock.DEFAULT_VERSION)], 'protocols': [], 'skills': [] } diff --git a/tests/test_cli/test_registry/test_push.py b/tests/test_cli/test_registry/test_push.py index 6b716b4221..1c4c7eb7aa 100644 --- a/tests/test_cli/test_registry/test_push.py +++ b/tests/test_cli/test_registry/test_push.py @@ -59,7 +59,7 @@ def test_push_item_positive( ): """Test for push_item positive result.""" public_id = PublicIdMock( - name='some-name', author='some-author', version='1.0.0' + name='some-name', author='some-author', version='{}'.format(PublicIdMock.DEFAULT_VERSION) ) push_item(ContextMock(), 'some-type', public_id) request_api_mock.assert_called_once_with( diff --git a/tests/test_cli/tools_for_testing.py b/tests/test_cli/tools_for_testing.py index 356d129516..200f0f92a8 100644 --- a/tests/test_cli/tools_for_testing.py +++ b/tests/test_cli/tools_for_testing.py @@ -18,6 +18,8 @@ # ------------------------------------------------------------------------------ """Tools used for CLI registry testing.""" +from tests.test_cli.constants import DEFAULT_TESTING_VERSION + class AgentConfigMock: """An object to mock Agent config.""" @@ -36,7 +38,11 @@ class ContextMock: class PublicIdMock: """An object to mock PublicId.""" - def __init__(self, name='name', author='author', version='1.0.0'): + DEFAULT_VERSION = DEFAULT_TESTING_VERSION + + def __init__( + self, name='name', author='author', version=DEFAULT_TESTING_VERSION + ): self.name = name self.author = author self.version = version From c71d80c29569e8ff1ab7c679599c11e0615845b9 Mon Sep 17 00:00:00 2001 From: panasevychol Date: Fri, 10 Jan 2020 16:47:12 +0200 Subject: [PATCH 7/7] Flake8 issues fixed. --- tests/test_cli/test_push.py | 2 -- tests/test_cli/tools_for_testing.py | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_cli/test_push.py b/tests/test_cli/test_push.py index 2b34385a82..76ad9121a5 100644 --- a/tests/test_cli/test_push.py +++ b/tests/test_cli/test_push.py @@ -20,12 +20,10 @@ from unittest import TestCase, mock -from click import ClickException from click.testing import CliRunner from aea.cli import cli from aea.cli.push import _save_item_locally -from aea.configurations.base import PublicId from tests.conftest import CLI_LOG_OPTION from tests.test_cli.tools_for_testing import ContextMock, PublicIdMock diff --git a/tests/test_cli/tools_for_testing.py b/tests/test_cli/tools_for_testing.py index 200f0f92a8..b9ea54c7fe 100644 --- a/tests/test_cli/tools_for_testing.py +++ b/tests/test_cli/tools_for_testing.py @@ -43,6 +43,7 @@ class PublicIdMock: def __init__( self, name='name', author='author', version=DEFAULT_TESTING_VERSION ): + """Init the Public ID mock object.""" self.name = name self.author = author self.version = version