Beispiel #1
0
def registry_logout() -> None:
    """
    Logout from Registry account.

    :return: None
    """
    request_api("POST", "/rest-auth/logout/")
Beispiel #2
0
 def test_request_api_500(self, request_mock):
     """Test for request_api method 500 server response."""
     resp_mock = mock.Mock()
     resp_mock.status_code = 500
     request_mock.return_value = resp_mock
     with self.assertRaises(ClickException):
         request_api("GET", "/path")
Beispiel #3
0
 def test_request_api_unexpected_response(self, request_mock):
     """Test for fetch_package method unexpected sever response."""
     resp_mock = mock.Mock()
     resp_mock.status_code = 500
     request_mock.return_value = resp_mock
     with self.assertRaises(ClickException):
         request_api('GET', '/path')
Beispiel #4
0
 def test_request_api_403(self, request_mock):
     """Test for fetch_package method not authorized sever response."""
     resp_mock = mock.Mock()
     resp_mock.status_code = 403
     request_mock.return_value = resp_mock
     with self.assertRaises(ClickException):
         request_api('GET', '/path')
Beispiel #5
0
 def test_request_api_409(self, request_mock):
     """Test for request_api method conflict server response."""
     resp_mock = mock.Mock()
     resp_mock.status_code = 409
     resp_mock.json = lambda: {"detail": "some"}
     request_mock.return_value = resp_mock
     with self.assertRaises(ClickException):
         request_api("GET", "/path")
Beispiel #6
0
 def test_request_api_unexpected_response(self, request_mock):
     """Test for request_api method unexpected server response."""
     resp_mock = mock.Mock()
     resp_mock.status_code = 501  # not implemented status
     resp_mock.json = _raise_json_decode_error
     request_mock.return_value = resp_mock
     with self.assertRaises(ClickException):
         request_api("GET", "/path")
Beispiel #7
0
def registry_reset_password(email: str) -> None:
    """
    Request Registry to reset password.

    :param email: user email.

    :return: None.
    """
    request_api("POST", "/rest-auth/password/reset/", data={"email": email})
Beispiel #8
0
def search_items(ctx: Context, item_type: str, query: str,
                 page: int) -> Tuple[List[Dict], int]:
    """
    Search items by query and click.echo results.

    :param ctx: Context object.
    :param item_type: item type.
    :param query: query string.

    :return: (List of items, int items total count).
    """
    click.echo('Searching for "{}"...'.format(query))
    item_type_plural = item_type + "s"
    if ctx.config.get("is_local"):
        results = _search_items_locally(ctx, item_type_plural)
        count = len(results)
    else:
        resp = cast(
            JSONLike,
            request_api(
                "GET",
                "/{}".format(item_type_plural),
                params={
                    "search": query,
                    "page": page
                },
            ),
        )
        results = cast(List[Dict], resp["results"])
        count = cast(int, resp["count"])
    return results, count
def register(username: str, email: str, password: str,
             password_confirmation: str) -> str:
    """
    Register new Registry account and automatically login if successful.

    :param username: str username.
    :param email: str email.
    :param password: str password.
    :param password_confirmation: str password confirmation.

    :return: str auth token.
    """
    data = {
        "username": username,
        "email": email,
        "password1": password,
        "password2": password_confirmation,
    }
    resp_json, status_code = request_api(
        "POST",
        "/rest-auth/registration/",
        data=data,
        handle_400=False,
        return_code=True,
    )
    if status_code == 400:
        errors: List[str] = []
        for key in ("username", "email", "password1", "password2"):
            param_errors = resp_json.get(key)
            if param_errors:
                errors.extend(param_errors)

        raise ClickException("Errors occured during registration.\n" +
                             "\n".join(errors))
    return resp_json["key"]
Beispiel #10
0
def publish_agent(ctx: Context):
    """Publish an agent."""
    try_to_load_agent_config(ctx)
    check_is_author_logged_in(ctx.agent_config.author)

    name = ctx.agent_config.agent_name
    agent_config_path = os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE)
    output_tar = os.path.join(ctx.cwd, "{}.tar.gz".format(name))
    _compress(output_tar, agent_config_path)

    data = {
        "name": name,
        "description": ctx.agent_config.description,
        "version": ctx.agent_config.version,
        "connections": ctx.agent_config.connections,
        "protocols": ctx.agent_config.protocols,
        "skills": ctx.agent_config.skills,
    }

    path = "/agents/create"
    logger.debug("Publishing agent {} to Registry ...".format(name))
    resp = request_api("POST",
                       path,
                       data=data,
                       is_auth=True,
                       filepath=output_tar)
    click.echo(
        "Successfully published agent {} to the Registry. Public ID: {}".
        format(name, resp["public_id"]))
Beispiel #11
0
def fetch_agent(ctx: Context, public_id: PublicId) -> None:
    """
    Fetch Agent from Registry.

    :param public_id: str public ID of desirable Agent.

    :return: None
    """
    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"]

    target_folder = os.path.join(ctx.cwd, name)
    os.makedirs(target_folder, exist_ok=True)

    click.echo("Fetching dependencies...")
    for item_type in ("connection", "skill", "protocol"):
        item_type_plural = item_type + "s"
        for item_public_id in resp[item_type_plural]:
            item_public_id = PublicId.from_str(item_public_id)
            try:
                fetch_package(item_type, item_public_id, target_folder)
            except Exception as e:
                rmtree(target_folder)
                raise click.ClickException(
                    'Unable to fetch dependency for agent "{}", aborting. {}'.format(
                        name, e
                    )
                )
    click.echo("Dependencies successfully fetched.")

    filepath = download_file(file_url, ctx.cwd)
    extract(filepath, target_folder)
    click.echo("Agent {} successfully fetched to {}.".format(name, target_folder))
Beispiel #12
0
def fetch_package(obj_type: str, public_id: PublicId, cwd: str,
                  dest: str) -> Path:
    """
    Fetch a package (connection/contract/protocol/skill) from Registry.

    :param obj_type: str type of object you want to fetch:
        'connection', 'protocol', 'skill'
    :param public_id: str public ID of object.
    :param cwd: str path to current working directory.

    :return: package path
    """
    logger.debug("Fetching {obj_type} {public_id} from Registry...".format(
        public_id=public_id, obj_type=obj_type))
    author, name, version = public_id.author, public_id.name, public_id.version
    item_type_plural = obj_type + "s"  # used for API and folder paths

    api_path = "/{}/{}/{}/{}".format(item_type_plural, author, name, version)
    resp = request_api("GET", api_path)
    file_url = resp["file"]

    logger.debug("Downloading {obj_type} {public_id}...".format(
        public_id=public_id, obj_type=obj_type))
    filepath = download_file(file_url, cwd)

    # next code line is needed because the items are stored in tarball packages as folders
    dest = os.path.split(dest)[
        0]  # TODO: replace this hotfix with a proper solution
    logger.debug("Extracting {obj_type} {public_id}...".format(
        public_id=public_id, obj_type=obj_type))
    extract(filepath, dest)
    click.echo("Successfully fetched {obj_type}: {public_id}.".format(
        public_id=public_id, obj_type=obj_type))
    package_path = os.path.join(dest, public_id.name)
    return Path(package_path)
Beispiel #13
0
def protocols(ctx: Context, query):
    """Search for Protocols."""
    if ctx.config.get("is_registry"):
        click.echo('Searching for "{}"...'.format(query))
        resp = request_api("GET", "/protocols", params={"search": query})
        if len(resp) == 0:
            click.echo("No protocols found.")  # pragma: no cover
        else:
            click.echo("Protocols found:\n")
            click.echo(_format_items(resp))
        return

    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,
    )

    print("Available protocols:")
    print(_format_items(sorted(result, key=lambda k: k["name"])))
Beispiel #14
0
def publish_agent(ctx: Context):
    """Publish an agent."""
    try_to_load_agent_config(ctx)
    check_is_author_logged_in(ctx.agent_config.author)

    name = ctx.agent_config.agent_name
    config_file_source_path = os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE)
    output_tar = os.path.join(ctx.cwd, "{}.tar.gz".format(name))

    with tempfile.TemporaryDirectory() as temp_dir:
        package_dir = os.path.join(temp_dir, name)
        os.makedirs(package_dir)
        config_file_target_path = os.path.join(package_dir, DEFAULT_AEA_CONFIG_FILE)
        shutil.copy(config_file_source_path, config_file_target_path)

        _compress(output_tar, package_dir)

    data = {
        "name": name,
        "description": ctx.agent_config.description,
        "version": ctx.agent_config.version,
        "connections": ctx.agent_config.connections,
        "contracts": ctx.agent_config.contracts,
        "protocols": ctx.agent_config.protocols,
        "skills": ctx.agent_config.skills,
    }

    path = "/agents/create"
    logger.debug("Publishing agent {} to Registry ...".format(name))
    resp = request_api("POST", path, data=data, is_auth=True, filepath=output_tar)
    click.echo(
        "Successfully published agent {} to the Registry. Public ID: {}".format(
            name, resp["public_id"]
        )
    )
def download_package(package_id: PackageId, destination_path: str) -> None:
    """Download a package into a directory."""
    api_path = f"/{package_id.package_type.to_plural()}/{package_id.author}/{package_id.name}/{package_id.public_id.LATEST_VERSION}"
    resp = cast(JSONLike, request_api("GET", api_path))
    file_url = cast(str, resp["file"])
    filepath = download_file(file_url, destination_path)
    extract(filepath, destination_path)
Beispiel #16
0
def fetch_agent(
    click_context, public_id: PublicId, alias: Optional[str] = None
) -> None:
    """
    Fetch Agent from Registry.

    :param ctx: Context
    :param public_id: str public ID of desirable Agent.
    :param click_context: the click context.
    :param alias: an optional alias.
    :return: None
    """
    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"]

    ctx = cast(Context, click_context.obj)
    filepath = download_file(file_url, ctx.cwd)

    folder_name = name if alias is None else alias
    aea_folder = os.path.join(ctx.cwd, folder_name)
    ctx.clean_paths.append(aea_folder)

    extract(filepath, ctx.cwd)

    if alias is not None:
        os.rename(name, alias)

    ctx.cwd = aea_folder
    try_to_load_agent_config(ctx)

    if alias is not None:
        ctx.agent_config.agent_name = alias
        ctx.agent_loader.dump(
            ctx.agent_config, open(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w")
        )

    click.echo("Fetching dependencies...")
    for item_type in ("connection", "contract", "skill", "protocol"):
        item_type_plural = item_type + "s"

        # initialize fetched agent with empty folders for custom packages
        custom_items_folder = os.path.join(ctx.cwd, item_type_plural)
        os.makedirs(custom_items_folder)

        config = getattr(ctx.agent_config, item_type_plural)
        for item_public_id in config:
            try:
                _add_item(click_context, item_type, item_public_id)
            except Exception as e:
                raise click.ClickException(
                    'Unable to fetch dependency for agent "{}", aborting. {}'.format(
                        name, e
                    )
                )
    click.echo("Dependencies successfully fetched.")
    click.echo("Agent {} successfully fetched to {}.".format(name, aea_folder))
Beispiel #17
0
def push_item(ctx: Context, item_type: str, item_id: PublicId) -> None:
    """
    Push item to the Registry.

    :param item_type: str type of item (connection/protocol/skill).
    :param item_id: str item name.

    :return: None
    """
    item_type_plural = item_type + "s"

    items_folder = os.path.join(ctx.cwd, item_type_plural)
    item_path = os.path.join(items_folder, item_id.name)

    item_config_filepath = os.path.join(item_path, "{}.yaml".format(item_type))
    logger.debug("Reading {} {} config ...".format(item_id.name, item_type))
    item_config = load_yaml(item_config_filepath)
    check_is_author_logged_in(item_config["author"])

    logger.debug("Searching for {} {} in {} ...".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_id.name,
                                            items_folder))

    output_filename = "{}.tar.gz".format(item_id.name)
    logger.debug("Compressing {} {} to {} ...".format(item_id.name, item_type,
                                                      output_filename))
    _compress_dir(output_filename, item_path)
    output_filepath = os.path.join(ctx.cwd, output_filename)

    data = {
        "name": item_id.name,
        "description": item_config["description"],
        "version": item_config["version"],
    }

    # dependencies
    for key in ["connections", "contracts", "protocols", "skills"]:
        deps_list = item_config.get(key)
        if deps_list:
            data.update({key: deps_list})

    path = "/{}/create".format(item_type_plural)
    logger.debug("Pushing {} {} to Registry ...".format(
        item_id.name, item_type))
    resp = request_api("POST",
                       path,
                       data=data,
                       is_auth=True,
                       filepath=output_filepath)
    click.echo(
        "Successfully pushed {} {} to the Registry. Public ID: {}".format(
            item_type, item_id.name, resp["public_id"]))
Beispiel #18
0
    def test_request_api_201(self, request_mock):
        """Test for request_api method 201 server response."""
        expected_result = {"correct": "json"}

        resp_mock = mock.Mock()
        resp_mock.json = lambda: expected_result
        resp_mock.status_code = 201
        request_mock.return_value = resp_mock
        result = request_api("GET", "/path")
        self.assertEqual(result, expected_result)
Beispiel #19
0
    def test_request_api_with_file_positive(self, request_mock):
        """Test for request_api method with file positive result."""
        expected_result = {"correct": "json"}

        resp_mock = mock.Mock()
        resp_mock.json = lambda: expected_result
        resp_mock.status_code = 200
        request_mock.return_value = resp_mock

        result = request_api("GET", "/path", filepath="filepath")
        self.assertEqual(result, expected_result)
Beispiel #20
0
def registry_login(username: str, password: str) -> str:
    """
    Login into Registry account.

    :param username: str username.
    :param password: str password.

    :return: str token
    """
    resp = request_api(
        "POST", "/rest-auth/login/", data={"username": username, "password": password}
    )
    return resp["key"]
Beispiel #21
0
    def test_request_api_positive(self, request_mock):
        """Test for request_api method positive result."""
        expected_result = {"correct": "json"}

        resp_mock = mock.Mock()
        resp_mock.json = lambda: expected_result
        resp_mock.status_code = 200
        request_mock.return_value = resp_mock

        result = request_api("GET", "/path")
        request_mock.assert_called_once_with(
            method="GET",
            params=None,
            data=None,
            files=None,
            headers={},
            url=REGISTRY_API_URL + "/path",
        )
        self.assertEqual(result, expected_result)

        result = request_api("GET", "/path", return_code=True)
        self.assertEqual(result, (expected_result, 200))
Beispiel #22
0
    def test_request_api_with_auth_positive(self,
                                            get_or_create_cli_config_mock,
                                            request_mock):
        """Test for request_api method with auth positive result."""
        expected_result = {"correct": "json"}

        resp_mock = mock.Mock()
        resp_mock.json = lambda: expected_result
        resp_mock.status_code = 200
        request_mock.return_value = resp_mock

        result = request_api("GET", "/path", is_auth=True)
        self.assertEqual(result, expected_result)
Beispiel #23
0
def agents(ctx: Context, query):
    """Search for Agents."""
    click.echo('Searching for "{}"...'.format(query))
    if ctx.config.get("is_local"):
        results = _search_items(ctx, "agents")
    else:
        results = request_api("GET", "/agents", params={"search": query})

    if not len(results):
        click.echo("No agents found.")  # pragma: no cover
    else:
        click.echo("Agents found:\n")
        click.echo(_format_items(results))
Beispiel #24
0
    def test_request_api_positive(self, request_mock):
        """Test for fetch_package method positive result."""
        expected_result = {'correct': 'json'}

        resp_mock = mock.Mock()
        resp_mock.json = lambda: expected_result
        resp_mock.status_code = 200
        request_mock.return_value = resp_mock

        result = request_api('GET', '/path')
        request_mock.assert_called_once_with(method='GET',
                                             params=None,
                                             url=REGISTRY_API_URL + '/path')
        self.assertEqual(result, expected_result)
Beispiel #25
0
def publish_agent(ctx: Context) -> None:
    """Publish an agent."""
    try_to_load_agent_config(ctx)
    check_is_author_logged_in(ctx.agent_config.author)

    name = ctx.agent_config.agent_name
    config_file_source_path = os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE)
    readme_source_path = os.path.join(ctx.cwd, DEFAULT_README_FILE)
    output_tar = os.path.join(ctx.cwd, "{}.tar.gz".format(name))

    with tempfile.TemporaryDirectory() as temp_dir:
        package_dir = os.path.join(temp_dir, name)
        os.makedirs(package_dir)
        config_file_target_path = os.path.join(package_dir, DEFAULT_AEA_CONFIG_FILE)
        shutil.copy(config_file_source_path, config_file_target_path)
        if is_readme_present(readme_source_path):
            readme_file_target_path = os.path.join(package_dir, DEFAULT_README_FILE)
            shutil.copy(readme_source_path, readme_file_target_path)

        _compress(output_tar, package_dir)

    data = {
        "name": name,
        "description": ctx.agent_config.description,
        "version": ctx.agent_config.version,
        CONNECTIONS: ctx.agent_config.connections,
        CONTRACTS: ctx.agent_config.contracts,
        PROTOCOLS: ctx.agent_config.protocols,
        SKILLS: ctx.agent_config.skills,
    }

    files = {}
    try:
        files["file"] = open(output_tar, "rb")
        if is_readme_present(readme_source_path):
            files["readme"] = open(readme_source_path, "rb")
        path = "/agents/create"
        logger.debug("Publishing agent {} to Registry ...".format(name))
        resp = cast(
            JSONLike, request_api("POST", path, data=data, is_auth=True, files=files)
        )
    finally:
        for fd in files.values():
            fd.close()
    click.echo(
        "Successfully published agent {} to the Registry. Public ID: {}".format(
            name, resp["public_id"]
        )
    )
Beispiel #26
0
    def test_request_api_with_files_positive(self, request_mock):
        """Test for request_api method with file positive result."""
        expected_result = {"correct": "json"}

        resp_mock = mock.Mock()
        resp_mock.json = lambda: expected_result
        resp_mock.status_code = 200
        request_mock.return_value = resp_mock

        test_files = {
            "file": open("file.tar.gz", "rb"),
            "readme": open("file.md", "rb"),
        }
        result = request_api("GET", "/path", files=test_files)
        self.assertEqual(result, expected_result)
Beispiel #27
0
def search_items(ctx: Context, item_type: str, query: str) -> List:
    """
    Search items by query and click.echo results.

    :param ctx: Context object.
    :param item_type: item type.
    :param query: query string.

    :return: None
    """
    click.echo('Searching for "{}"...'.format(query))
    item_type_plural = item_type + "s"
    if ctx.config.get("is_local"):
        return _search_items_locally(ctx, item_type_plural)
    else:
        return request_api("GET",
                           "/{}".format(item_type_plural),
                           params={"search": query})
Beispiel #28
0
def agents(ctx: Context, query):
    """Search for Agents."""
    if ctx.config.get("is_registry"):
        resp = request_api("GET", "/agents", params={"search": query})
        if len(resp) == 0:
            click.echo("No agents found.")  # pragma: no cover
        else:
            click.echo("Agents found:\n")
            click.echo(_format_items(resp))
        return
    else:
        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
        )

        print("Available agents:")
        print(_format_items(sorted(result, key=lambda k: k["name"])))
Beispiel #29
0
def connections(ctx: Context, query):
    """Search for Connections."""
    if ctx.config.get("is_registry"):
        click.echo('Searching for "{}"...'.format(query))
        resp = request_api('GET', '/connections', params={'search': query})
        if not len(resp):
            click.echo('No connections found.')
        else:
            click.echo('Connections found:\n')
            click.echo(format_items(resp))
        return

    registry = cast(str, ctx.config.get("registry"))
    result: 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)

    print("Available connections:")
    print(format_items(sorted(result, key=lambda k: k['name'])))
Beispiel #30
0
def fetch_agent(ctx: Context, public_id: PublicId, click_context) -> None:
    """
    Fetch Agent from Registry.

    :param public_id: str public ID of desirable Agent.

    :return: None
    """
    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"]

    filepath = download_file(file_url, ctx.cwd)
    extract(filepath, ctx.cwd)

    target_folder = os.path.join(ctx.cwd, name)
    ctx.cwd = target_folder
    try_to_load_agent_config(ctx)

    click.echo("Fetching dependencies...")
    for item_type in ("connection", "contract", "skill", "protocol"):
        item_type_plural = item_type + "s"

        # initialize fetched agent with empty folders for custom packages
        custom_items_folder = os.path.join(ctx.cwd, item_type_plural)
        os.makedirs(custom_items_folder)

        config = getattr(ctx.agent_config, item_type_plural)
        for item_public_id in config:
            try:
                _add_item(click_context, item_type, item_public_id)
            except Exception as e:
                rmtree(target_folder)
                raise click.ClickException(
                    'Unable to fetch dependency for agent "{}", aborting. {}'.
                    format(name, e))
    click.echo("Dependencies successfully fetched.")
    click.echo("Agent {} successfully fetched to {}.".format(
        name, target_folder))