Skip to content

Commit

Permalink
Merge pull request #612 from fetchai/bugfix/local-save-path
Browse files Browse the repository at this point in the history
Local push and publish commands re-implemented to use context generat…
  • Loading branch information
DavidMinarsch authored Jan 10, 2020
2 parents b0f3d7f + c71d80c commit aab127c
Show file tree
Hide file tree
Showing 30 changed files with 553 additions and 500 deletions.
4 changes: 2 additions & 2 deletions aea/cli/add.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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):
Expand Down
63 changes: 55 additions & 8 deletions aea/cli/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -101,18 +102,28 @@ 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) -> 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:
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):
Expand Down Expand Up @@ -248,3 +259,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
4 changes: 2 additions & 2 deletions aea/cli/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down
10 changes: 5 additions & 5 deletions aea/cli/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -67,13 +67,13 @@ 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)
_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)
Expand All @@ -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", ""))

Expand Down Expand Up @@ -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))
Expand Down
4 changes: 2 additions & 2 deletions aea/cli/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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
Expand Down
35 changes: 30 additions & 5 deletions aea/cli/fetch.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,44 @@

"""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')
@click.option(
'--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
4 changes: 2 additions & 2 deletions aea/cli/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -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))
Expand Down
4 changes: 2 additions & 2 deletions aea/cli/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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()
Expand Down
32 changes: 29 additions & 3 deletions aea/cli/publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,43 @@

"""Implementation of the 'aea publish' subcommand."""
import click
import os
from shutil import copyfile

from aea.cli.registry.publish import publish_agent, save_agent_locally
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')
@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."""
try_to_load_agent_config(ctx)
if not registry:
save_agent_locally()
# 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))
Loading

0 comments on commit aab127c

Please sign in to comment.