def connection(ctx: Context, connection_name): """Remove a connection from the agent.""" agent_name = ctx.agent_config.agent_name logger.info( "Removing connection {connection_name} from the agent {agent_name}...". format(agent_name=agent_name, connection_name=connection_name)) if connection_name not in ctx.agent_config.connections: logger.error("Connection '{}' not found.".format(connection_name)) exit(-1) connection_folder = os.path.join("connections", connection_name) try: shutil.rmtree(connection_folder) except BaseException: logger.exception( "An error occurred while deleting '{}'.".format(connection_folder)) exit(-1) # removing the connection to the configurations. logger.debug( "Removing the connection from {}".format(DEFAULT_AEA_CONFIG_FILE)) if connection_name in ctx.agent_config.connections: ctx.agent_config.connections.remove(connection_name) ctx.agent_loader.dump(ctx.agent_config, open(DEFAULT_AEA_CONFIG_FILE, "w"))
def protocol(ctx: Context, protocol_name): """Remove a protocol from the agent.""" agent_name = ctx.agent_config.agent_name logger.info( "Removing protocol {protocol_name} from the agent {agent_name}...". format(agent_name=agent_name, protocol_name=protocol_name)) if protocol_name not in ctx.agent_config.protocols: logger.error("Protocol '{}' not found.".format(protocol_name)) exit(-1) protocol_folder = os.path.join("protocols", protocol_name) try: shutil.rmtree(protocol_folder) except BaseException: logger.exception("An error occurred.") exit(-1) # removing the protocol to the configurations. logger.debug( "Removing the protocol from {}".format(DEFAULT_AEA_CONFIG_FILE)) if protocol_name in ctx.agent_config.protocols: ctx.agent_config.protocols.remove(protocol_name) ctx.agent_loader.dump(ctx.agent_config, open(DEFAULT_AEA_CONFIG_FILE, "w"))
def _remove_item(ctx: Context, item_type, item_id: PublicId): """Remove an item from the configuration file and agent, given the public id.""" item_name = item_id.name item_type_plural = "{}s".format(item_type) existing_item_ids = getattr(ctx.agent_config, item_type_plural) existing_items_name_to_ids = { public_id.name: public_id for public_id in existing_item_ids } agent_name = ctx.agent_config.agent_name click.echo( "Removing {item_type} '{item_name}' from the agent '{agent_name}'...".format( agent_name=agent_name, item_type=item_type, item_name=item_name ) ) if ( item_id not in existing_items_name_to_ids.keys() and item_id not in existing_item_ids ): logger.error("The {} '{}' is not supported.".format(item_type, item_id)) sys.exit(1) # TODO we assume the item in the agent config are necessarily in the agent projects. item_folder = Path("vendor", item_id.author, item_type_plural, item_name) if not item_folder.exists(): # check if it is present in custom packages. item_folder = Path(item_type_plural, item_name) if not item_folder.exists(): raise click.ClickException( "{} {} not found. Aborting.".format(item_type.title(), item_name) ) elif ( item_folder.exists() and not ctx.agent_config.author == item_id.author ): # pragma: no cover raise click.ClickException( "{} {} author is different from {} agent author. " "Please fix the author field.".format(item_name, item_type, agent_name) ) else: logger.debug( "Removing local {} {}.".format(item_type, item_name) ) # pragma: no cover try: shutil.rmtree(item_folder) except BaseException: logger.exception("An error occurred.") sys.exit(1) # removing the protocol to the configurations. item_public_id = existing_items_name_to_ids[item_name] logger.debug("Removing the {} from {}".format(item_type, DEFAULT_AEA_CONFIG_FILE)) existing_item_ids.remove(item_public_id) ctx.agent_loader.dump(ctx.agent_config, open(DEFAULT_AEA_CONFIG_FILE, "w"))
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) _load_env_file(env_file) agent_name = cast(str, ctx.agent_config.agent_name) _verify_or_create_private_keys(ctx) _verify_ledger_apis_access() private_key_paths = dict([(identifier, config.path) for identifier, config in ctx.agent_config.private_key_paths.read_all()]) ledger_api_configs = dict([ (identifier, (config.addr, config.port)) for identifier, config in ctx.agent_config.ledger_apis.read_all() ]) wallet = Wallet(private_key_paths) ledger_apis = LedgerApis(ledger_api_configs) connection_names = [ctx.agent_config.default_connection ] if connection_names is None else connection_names connections = [] _try_to_load_protocols(ctx) try: for connection_name in connection_names: connection = _setup_connection(connection_name, wallet.public_keys[FETCHAI], ctx) connections.append(connection) except AEAConfigException as e: logger.error(str(e)) sys.exit(1) if install_deps: if Path("requirements.txt").exists(): click_context.invoke(install, requirement="requirements.txt") else: click_context.invoke(install) agent = AEA(agent_name, connections, wallet, ledger_apis, resources=Resources(str(Path(".")))) try: agent.start() except KeyboardInterrupt: logger.info("Interrupted.") # pragma: no cover except Exception as e: logger.exception(e) sys.exit(1) finally: agent.stop()
def _run_aea(aea: AEA) -> None: click.echo(AEA_LOGO + "v" + __version__ + "\n") click.echo("{} starting ...".format(aea.name)) try: aea.start() except KeyboardInterrupt: click.echo(" {} interrupted!".format(aea.name)) # pragma: no cover except Exception as e: logger.exception(e) sys.exit(1) finally: click.echo("{} stopping ...".format(aea.name)) aea.stop()
def protocol(ctx: Context, protocol_name: str): """Add a protocol scaffolding to the configuration file and agent.""" # check if we already have a protocol with the same name logger.debug("Protocols already supported by the agent: {}".format( ctx.agent_config.protocols)) if protocol_name in ctx.agent_config.protocols: logger.error( "A protocol with name '{}' already exists. Aborting...".format( protocol_name)) exit(-1) return try: # create the 'protocols' folder if it doesn't exist: if not os.path.exists("protocols"): os.makedirs("protocols") # create the protocol folder dest = Path(os.path.join("protocols", protocol_name)) # copy the skill package into the agent's supported skills. src = Path(os.path.join(AEA_DIR, "protocols", "scaffold")) logger.info("Copying protocol modules. src={} dst={}".format( src, dest)) try: shutil.copytree(src, dest) except Exception as e: logger.error(e) exit(-1) # add the protocol to the configurations. logger.info( "Registering the protocol into {}".format(DEFAULT_AEA_CONFIG_FILE)) ctx.agent_config.protocols.add(protocol_name) ctx.agent_loader.dump( ctx.agent_config, open(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w")) except OSError: logger.error("Directory already exist. Aborting...") exit(-1) except ValidationError as e: logger.error(str(e)) shutil.rmtree(protocol_name, ignore_errors=True) exit(-1) except Exception as e: logger.exception(e) shutil.rmtree(protocol_name, ignore_errors=True) exit(-1)
def create(click_context, agent_name): """Create an agent.""" ctx = cast(Context, click_context.obj) path = Path(agent_name) logger.info("Initializing AEA project '{}'".format(agent_name)) logger.info("Creating project directory '/{}'".format(agent_name)) # create the agent's directory try: path.mkdir(exist_ok=False) # create a config file inside it 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__, authors="", version="v1", license="", url="", registry_path=DEFAULT_REGISTRY_PATH, description="") agent_config.default_connection = DEFAULT_CONNECTION ctx.agent_loader.dump(agent_config, config_file) # next commands must be done from the agent's directory -> overwrite ctx.cwd ctx.agent_config = agent_config ctx.cwd = agent_config.agent_name logger.info("Default connections:") click_context.invoke(connection, connection_name=DEFAULT_CONNECTION) logger.info("Default skills:") click_context.invoke(skill, skill_name=DEFAULT_SKILL) except OSError: logger.error("Directory already exist. Aborting...") sys.exit(1) except ValidationError as e: logger.error(str(e)) shutil.rmtree(agent_name, ignore_errors=True) sys.exit(1) except Exception as e: logger.exception(e) shutil.rmtree(agent_name, ignore_errors=True) sys.exit(1)
def run(ctx: Context, connection_name: str): """Run the agent.""" _try_to_load_agent_config(ctx) agent_name = cast(str, ctx.agent_config.agent_name) private_key_pem_path = cast(str, ctx.agent_config.private_key_pem_path) if private_key_pem_path == "": private_key_pem_path = _create_temporary_private_key_pem_path() else: _try_validate_private_key_pem_path(private_key_pem_path) crypto = Crypto(private_key_pem_path=private_key_pem_path) public_key = crypto.public_key connection_name = ctx.agent_config.default_connection if connection_name is None else connection_name _try_to_load_protocols(ctx) try: connection = _setup_connection(connection_name, public_key, ctx) except AEAConfigException as e: logger.error(str(e)) exit(-1) return logger.debug("Installing all the dependencies...") for d in ctx.get_dependencies(): logger.debug("Installing {}...".format(d)) try: subp = subprocess.Popen( [sys.executable, "-m", "pip", "install", d]) subp.wait(30.0) except Exception: logger.error( "An error occurred while installing {}. Stopping...".format(d)) exit(-1) mailbox = MailBox(connection) agent = AEA(agent_name, mailbox, private_key_pem_path=private_key_pem_path, directory=str(Path("."))) try: agent.start() except KeyboardInterrupt: logger.info("Interrupted.") except Exception as e: logger.exception(e) finally: agent.stop()
def launch(click_context, agents: List[str]): """Launch many agents.""" agents_directories = list(map(Path, list(OrderedDict.fromkeys(agents)))) agent_processes = [ Process(target=_run_agent, args=(click_context, agent_directory)) for agent_directory in agents_directories ] failed = 0 try: for agent_directory, agent_process in zip(agents_directories, agent_processes): agent_process.start() logger.info("Agent {} started...".format(agent_directory.name)) for agent_process in agent_processes: agent_process.join() failed |= (agent_process.exitcode if agent_process.exitcode is not None else 1) except KeyboardInterrupt: # at this point, the keyboard interrupt has been propagated # to all the child process, hence we just need to 'join' the processes. for agent_directory, agent_process in zip(agents_directories, agent_processes): logger.info("Waiting for agent {} to shut down...".format( agent_directory.name)) agent_process.join(5.0) if agent_process.is_alive(): logger.info("Killing agent {}...".format(agent_directory.name)) agent_process.kill() failed = 1 else: logger.info("Agent {} terminated with exit code {}".format( agent_directory.name, agent_process.exitcode)) failed |= (agent_process.exitcode if agent_process.exitcode is not None else 1) except Exception as e: logger.exception(e) sys.exit(1) sys.exit(1) if failed else sys.exit(0)
def _fingerprint_item(click_context, item_type, item_public_id) -> None: """ Fingerprint components of an item. :param click_context: the click context. :param item_type: the item type. :param item_public_id: the item public id. :return: None """ ctx = cast(Context, click_context.obj) item_type_plural = item_type + "s" click.echo("Fingerprinting {} components of '{}' ...".format( item_type, item_public_id)) # create fingerprints package_dir = Path(ctx.cwd, item_type_plural, item_public_id.name) try: default_config_file_name = _get_default_configuration_file_name_from_type( item_type) config_loader = ConfigLoader.from_configuration_type(item_type) config_file_path = Path(package_dir, default_config_file_name) config = config_loader.load(config_file_path.open()) if not package_dir.exists(): # we only permit non-vendorized packages to be fingerprinted logger.error("Package not found at path {}".format(package_dir)) sys.exit(1) fingerprints_dict = _compute_fingerprint( package_dir, ignore_patterns=config.fingerprint_ignore_patterns ) # type: Dict[str, str] # Load item specification yaml file and add fingerprints config.fingerprint = fingerprints_dict config_loader.dump(config, open(config_file_path, "w")) except Exception as e: logger.exception(e) sys.exit(1)
def skill(ctx: Context, skill_name): """Remove a skill from the agent.""" agent_name = ctx.agent_config.agent_name logger.info("Removing skill '{skill_name}' from the agent '{agent_name}'..." .format(agent_name=agent_name, skill_name=skill_name)) if skill_name not in ctx.agent_config.skills: logger.error("The skill '{}' is not supported.".format(skill_name)) sys.exit(1) skill_folder = os.path.join("skills", skill_name) try: shutil.rmtree(skill_folder) except BaseException: logger.exception("An error occurred.") sys.exit(1) # removing the protocol to the configurations. logger.debug("Removing the skill from {}".format(DEFAULT_AEA_CONFIG_FILE)) if skill_name in ctx.agent_config.skills: ctx.agent_config.skills.remove(skill_name) ctx.agent_loader.dump(ctx.agent_config, open(DEFAULT_AEA_CONFIG_FILE, "w"))
def create(click_context, agent_name): """Create an agent.""" ctx = cast(Context, click_context.obj) path = Path(agent_name) logger.info("Creating agent's directory in '{}'".format(path)) # create the agent's directory try: path.mkdir(exist_ok=False) # create a config file inside it config_file = open(os.path.join(agent_name, DEFAULT_AEA_CONFIG_FILE), "w") agent_config = AgentConfig(agent_name=agent_name, aea_version=aea.__version__, authors="", version="v1", license="", url="", registry_path="../packages", private_key_pem_path="") agent_config.default_connection = DEFAULT_CONNECTION ctx.agent_loader.dump(agent_config, config_file) logger.info("Created config file {}".format(DEFAULT_AEA_CONFIG_FILE)) # next commands must be done from the agent's directory -> overwrite ctx.cwd ctx.agent_config = agent_config ctx.cwd = agent_config.agent_name logger.info("Adding default connection '{}' to the agent...".format(DEFAULT_CONNECTION)) click_context.invoke(connection, connection_name=DEFAULT_CONNECTION) logger.info("Adding default skill '{}' to the agent...".format(DEFAULT_SKILL)) click_context.invoke(skill, skill_name=DEFAULT_SKILL) except OSError: logger.error("Directory already exist. Aborting...") exit(-1) except ValidationError as e: logger.error(str(e)) shutil.rmtree(agent_name, ignore_errors=True) exit(-1) except Exception as e: logger.exception(e) shutil.rmtree(agent_name, ignore_errors=True) exit(-1)
def run(click_context, connection_ids: List[PublicId], env_file: str, is_install_deps: bool): """Run the agent.""" ctx = cast(Context, click_context.obj) _validate_aea(ctx) _prepare_environment(click_context, env_file, is_install_deps) aea = _build_aea(ctx, connection_ids) click.echo(AEA_LOGO + "v" + __version__ + "\n") click.echo("{} starting ...".format(ctx.agent_config.agent_name)) try: aea.start() except KeyboardInterrupt: click.echo(" {} interrupted!".format( ctx.agent_config.agent_name)) # pragma: no cover except Exception as e: logger.exception(e) sys.exit(1) finally: click.echo("{} stopping ...".format(ctx.agent_config.agent_name)) aea.stop()
def _scaffold_item(ctx: Context, item_type, item_name): """Add an item scaffolding to the configuration file and agent.""" existing_item_list = getattr(ctx.agent_config, "{}s".format(item_type)) loader = getattr(ctx, "{}_loader".format(item_type)) default_config_filename = globals()["DEFAULT_{}_CONFIG_FILE".format( item_type.upper())] item_type_plural = item_type + "s" # check if we already have an item with the same name logger.debug("{} already supported by the agent: {}".format( item_type_plural, existing_item_list)) if item_name in existing_item_list: logger.error("A {} with name '{}' already exists. Aborting...".format( item_type, item_name)) sys.exit(1) try: agent_name = ctx.agent_config.agent_name logger.info("Adding {} scaffold '{}' to the agent '{}'...".format( item_type, item_name, agent_name)) 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. 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. logger.debug("Registering the {} into {}".format( item_type, DEFAULT_AEA_CONFIG_FILE)) existing_item_list.add(item_name) 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 config_filepath = os.path.join(ctx.cwd, item_type_plural, item_name, default_config_filename) config = loader.load(open(str(config_filepath))) config.name = item_name loader.dump(config, open(config_filepath, "w")) 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.") 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)
def _generate_item(ctx: Context, item_type, specification_path): """Generate an item based on a specification and add it to the configuration file and agent.""" # # check protocol buffer compiler is installed # res = shutil.which("protoc") # if res is None: # print( # "Please install protocol buffer first! See the following link: https://developers.google.com/protocol-buffers/" # ) # sys.exit(1) # Get existing items existing_id_list = getattr(ctx.agent_config, "{}s".format(item_type)) existing_item_list = [public_id.name for public_id in existing_id_list] item_type_plural = item_type + "s" # Load item specification yaml file try: config_loader = ConfigLoader( "protocol-specification_schema.json", ProtocolSpecification ) protocol_spec = config_loader.load_protocol_specification( open(specification_path) ) except Exception as e: logger.exception(e) sys.exit(1) protocol_directory_path = os.path.join( ctx.cwd, item_type_plural, protocol_spec.name ) # Check if we already have an item with the same name in the agent config logger.debug( "{} already supported by the agent: {}".format( item_type_plural, existing_item_list ) ) if protocol_spec.name in existing_item_list: logger.error( "A {} with name '{}' already exists. Aborting...".format( item_type, protocol_spec.name ) ) sys.exit(1) # Check if we already have a directory with the same name in the resource directory (e.g. protocols) of the agent's directory if os.path.exists(protocol_directory_path): logger.error( "A directory with name '{}' already exists. Aborting...".format( protocol_spec.name ) ) sys.exit(1) try: agent_name = ctx.agent_config.agent_name click.echo( "Generating {} '{}' and adding it to the agent '{}'...".format( item_type, protocol_spec.name, agent_name ) ) output_path = os.path.join(ctx.cwd, item_type_plural) protocol_generator = ProtocolGenerator(protocol_spec, output_path) protocol_generator.generate() # Add the item to the configurations logger.debug( "Registering the {} into {}".format(item_type, DEFAULT_AEA_CONFIG_FILE) ) existing_id_list.add(PublicId("fetchai", protocol_spec.name, DEFAULT_VERSION)) ctx.agent_loader.dump( ctx.agent_config, open(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w") ) 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 Exception as e: logger.exception(e) shutil.rmtree( os.path.join(item_type_plural, protocol_spec.name), ignore_errors=True ) sys.exit(1)
def create(click_context, agent_name, author, local): """Create an agent.""" try: _check_is_parent_folders_are_aea_projects_recursively() except Exception: logger.error( "The current folder is already an AEA project. Please move to the parent folder." ) sys.exit(1) if author is not None: if local: do_init(author, False, False) else: raise click.ClickException( "Author is not set up. Please use 'aea init' to initialize.") config = _get_or_create_cli_config() set_author = config.get(AUTHOR, None) if set_author is None: click.echo( "The AEA configurations are not initialized. Uses `aea init` before continuing or provide optional argument `--author`." ) sys.exit(1) ctx = cast(Context, click_context.obj) path = Path(agent_name) click.echo("Initializing AEA project '{}'".format(agent_name)) click.echo("Creating project directory './{}'".format(agent_name)) # create the agent's directory try: path.mkdir(exist_ok=False) # set up packages directories. _setup_package_folder(Path(agent_name, "protocols")) _setup_package_folder(Path(agent_name, "contracts")) _setup_package_folder(Path(agent_name, "connections")) _setup_package_folder(Path(agent_name, "skills")) # set up a vendor directory Path(agent_name, "vendor").mkdir(exist_ok=False) Path(agent_name, "vendor", "__init__.py").touch(exist_ok=False) # create a config file inside it click.echo("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=set_author, version=DEFAULT_VERSION, license=DEFAULT_LICENSE, registry_path=os.path.join("..", DEFAULT_REGISTRY_PATH), description="", ) agent_config.default_connection = DEFAULT_CONNECTION agent_config.default_ledger = DEFAULT_LEDGER ctx.agent_loader.dump(agent_config, config_file) # next commands must be done from the agent's directory -> overwrite ctx.cwd ctx.agent_config = agent_config ctx.cwd = agent_config.agent_name click.echo("Adding default packages ...") if local: ctx.set_config("is_local", True) _add_item(click_context, "connection", DEFAULT_CONNECTION) _add_item(click_context, "skill", DEFAULT_SKILL) except OSError: logger.error("Directory already exist. Aborting...") sys.exit(1) except ValidationError as e: logger.error(str(e)) shutil.rmtree(agent_name, ignore_errors=True) sys.exit(1) except Exception as e: logger.exception(e) shutil.rmtree(agent_name, ignore_errors=True) sys.exit(1)
def _scaffold_item(ctx: Context, item_type, item_name): """Add an item scaffolding to the configuration file and agent.""" _validate_package_name(item_name) author_name = ctx.agent_config.author loader = getattr(ctx, "{}_loader".format(item_type)) default_config_filename = globals()["DEFAULT_{}_CONFIG_FILE".format( item_type.upper())] item_type_plural = item_type + "s" existing_ids = getattr(ctx.agent_config, "{}s".format(item_type)) existing_ids_only_author_and_name = map(lambda x: (x.author, x.name), existing_ids) # check if we already have an item with the same public id if (author_name, item_name) in existing_ids_only_author_and_name: logger.error("A {} with name '{}' already exists. Aborting...".format( item_type, item_name)) sys.exit(1) try: agent_name = ctx.agent_config.agent_name click.echo("Adding {} scaffold '{}' to the agent '{}'...".format( item_type, item_name, agent_name)) # create the item folder Path(item_type_plural).mkdir(exist_ok=True) dest = Path(os.path.join(item_type_plural, item_name)) # 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 item to the configurations. logger.debug("Registering the {} into {}".format( item_type, DEFAULT_AEA_CONFIG_FILE)) existing_ids.add(PublicId(author_name, 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 config_filepath = Path(ctx.cwd, item_type_plural, item_name, default_config_filename) config = loader.load(config_filepath.open()) config.name = item_name config.author = author_name loader.dump(config, open(config_filepath, "w")) 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 {} 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)
def _generate_item(click_context, item_type, specification_path): """Generate an item based on a specification and add it to the configuration file and agent.""" # check protocol buffer compiler is installed ctx = cast(Context, click_context.obj) res = shutil.which("protoc") if res is None: logger.error( "Please install protocol buffer first! See the following link: https://developers.google.com/protocol-buffers/" ) sys.exit(1) # check black code formatter is installed res = shutil.which("black") if res is None: logger.error( "Please install black code formater first! See the following link: https://black.readthedocs.io/en/stable/installation_and_usage.html" ) sys.exit(1) # Get existing items existing_id_list = getattr(ctx.agent_config, "{}s".format(item_type)) existing_item_list = [public_id.name for public_id in existing_id_list] item_type_plural = item_type + "s" # Load item specification yaml file try: config_loader = ConfigLoader("protocol-specification_schema.json", ProtocolSpecification) protocol_spec = config_loader.load_protocol_specification( open(specification_path)) except Exception as e: logger.exception(e) sys.exit(1) protocol_directory_path = os.path.join(ctx.cwd, item_type_plural, protocol_spec.name) # Check if we already have an item with the same name in the agent config logger.debug("{} already supported by the agent: {}".format( item_type_plural, existing_item_list)) if protocol_spec.name in existing_item_list: logger.error("A {} with name '{}' already exists. Aborting...".format( item_type, protocol_spec.name)) sys.exit(1) # Check if we already have a directory with the same name in the resource directory (e.g. protocols) of the agent's directory if os.path.exists(protocol_directory_path): logger.error( "A directory with name '{}' already exists. Aborting...".format( protocol_spec.name)) sys.exit(1) try: agent_name = ctx.agent_config.agent_name click.echo( "Generating {} '{}' and adding it to the agent '{}'...".format( item_type, protocol_spec.name, agent_name)) output_path = os.path.join(ctx.cwd, item_type_plural) protocol_generator = ProtocolGenerator(protocol_spec, output_path) protocol_generator.generate() # Add the item to the configurations logger.debug("Registering the {} into {}".format( item_type, DEFAULT_AEA_CONFIG_FILE)) existing_id_list.add( PublicId("fetchai", protocol_spec.name, DEFAULT_VERSION)) ctx.agent_loader.dump( ctx.agent_config, open(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w")) 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 ProtocolSpecificationParseError as e: logger.error( "The following error happened while parsing the protocol specification: " + str(e)) shutil.rmtree(os.path.join(item_type_plural, protocol_spec.name), ignore_errors=True) sys.exit(1) except Exception as e: logger.debug("Exception thrown: " + str(e)) logger.error( "There was an error while generating the protocol. The protocol is NOT generated." ) shutil.rmtree(os.path.join(item_type_plural, protocol_spec.name), ignore_errors=True) sys.exit(1) # Run black code formatting try: subp = subprocess.Popen( # nosec [ sys.executable, "-m", "black", os.path.join(item_type_plural, protocol_spec.name), "--quiet", ]) subp.wait(10.0) finally: poll = subp.poll() if poll is None: # pragma: no cover subp.terminate() subp.wait(5) _fingerprint_item(click_context, "protocol", protocol_spec.public_id)