예제 #1
0
def get_type_info(
        # Basic config
        config_name: str = typer.Argument(None, help=CONFIG_ARG_HELP),
        graph_name: str = typer.Argument(None, help=GRAPH_ARG_HELP),
        # Types to query
        vertex_type_names: List[str] = typer.Option(
            [],
            "--vertex",
            help="Vertex type name to query. Specify * to query all."),
        edge_type_names: List[str] = typer.Option(
            [],
            "--edge",
            help="Vertex type name to query. Specify * to query all.")):
    """Get a set of types, either vertices or edges. If no optioans are given, all types are returned."""
    conn = get_initialized_tg_connection(config_name=config_name,
                                         graph_name=graph_name,
                                         require_graph=True)
    results = {}
    query_all = (not vertex_type_names) and (not edge_type_names)
    if vertex_type_names or query_all:
        vertex_types = resolve_multiple_args(vertex_type_names)
        if query_all:
            vertex_types = "*"
        results.update(conn.getVertexStats(vertex_types))
    if edge_type_names or query_all:
        edge_types = resolve_multiple_args(edge_type_names)
        if query_all:
            edge_types = "*"
        results.update(conn.getEdgeStats(edge_types))
    cli.print_to_console(results)
예제 #2
0
def __get_config_interactive__() -> TgcliConfiguration:
    """Retrieves a configuration from the user interactively

    :return: A TgcliConfiguration that corresponds to the input
    """
    cli.print_to_console("Adding a TigerGraph configuration")
    server_address = cli.get_input_str(
        "Server Address (ex. https://xyz.i.tgcloud.io)").strip()
    client_version = cli.get_input_str(
        "Client Version (3.0.0, 2.6.0, 2.5.2, 2.5.0, 2.4.1, 2.4.0, 2.3.2)"
    ).strip()
    restpp_port = cli.get_input_str("REST++ Port",
                                    default=DEFAULT_RESTPP_PORT).strip()
    gs_port = cli.get_input_str("GS Port", default=DEFAULT_GS_PORT).strip()
    use_auth = cli.get_input_bool("Use Auth (This is usually true)",
                                  default=True)
    server_username = cli.get_input_str("Username",
                                        default="tigergraph").strip()
    server_password = cli.get_input_str("Password",
                                        default="tigergraph",
                                        hide_input=True)
    name = cli.get_input_str(
        "Name (Alphanumeric & Underscore Allowed)").strip()
    name = __clean_config_name__(name)
    return TgcliConfiguration(name=name,
                              server=server_address,
                              username=server_username,
                              password=server_password,
                              client_version=client_version,
                              restpp_port=restpp_port,
                              gs_port=gs_port,
                              use_auth=use_auth)
예제 #3
0
def reinit_dependencies(config_name: str = typer.Argument(
    ..., help=CONFIG_ARG_HELP),
                        graph_name: str = typer.Option("",
                                                       "--graph",
                                                       help=GRAPH_ARG_HELP)):
    """Force download dependencies for the configuration. If a graph name is specified, a new secret will be
    generated for the graph.
    """
    _ = get_initialized_tg_connection(config_name=config_name,
                                      graph_name=graph_name,
                                      clean_init=True)
    cli.print_to_console("Done")
예제 #4
0
def add_config():
    """Adds a configuration - only supports interactive input for now"""
    new_config = __get_config_interactive__()
    curr_configs = get_configs()
    if curr_configs.get(new_config.name, None):
        # Make sure that we want to overwrite
        if not cli.get_input_bool(
                prompt=
                f"Configuration {new_config.name} already exists. Do you want to overwrite it?"
        ):
            cli.terminate(message="Add configuration cancelled.")
        # Overwriting a configuration may need a reinitialization of dependencies
        cli.print_to_console(
            f"Configuration {new_config.name} already exists. You may need to run "
            f"tgcli reinit-dependencies to update dependencies to reflect this new configuration."
        )
    curr_configs[new_config.name] = new_config
    save_configs(curr_configs)
    cli.print_to_console(
        f"Configuration {new_config.name} added for server {new_config.server}"
    )
예제 #5
0
def run_gsql(
        config_name: str = typer.Argument(None, help=CONFIG_ARG_HELP),
        graph_name: str = typer.Argument(None, help=GRAPH_ARG_HELP),
        inline_command: str = typer.Option(None,
                                           "--command",
                                           help="Inline GSQL command"),
        file_command: Path = typer.Option(
            None,
            "--file",
            help="Filepath to load a GSQL command from.",
            exists=True,
            file_okay=True,
            dir_okay=False,
            readable=True,
            resolve_path=True),
        launch_editor: bool = typer.Option(
            False,
            "--editor",
            help="Launch an interactive editor to load the GSQL command")):
    """Run a GSQL query against a configuration through an inline command, file, or interactive editor"""
    conn = get_initialized_tg_connection(config_name=config_name,
                                         graph_name=graph_name)
    options = []
    if graph_name:
        options = ["-g", graph_name]
    command = None
    # Get the GSQL command depending on the flag
    if inline_command:
        command = inline_command
    elif file_command:
        with open(file_command, "r") as cmd_file:
            command = cmd_file.read()
    elif launch_editor:
        command = cli.get_input_from_editor("")
    command = command.strip()
    if not command:
        cli.terminate(message="No command specified.", is_err=True)
    output = conn.gsql(command, options=options)
    cli.print_to_console(output)
예제 #6
0
def delete_config(name: str):
    """Delete a configuration with the given name."""
    try:
        all_configs = get_configs(raise_on_nonexistent=True)
    except TgcliConfigurationError as e:
        # No configuration files found - or error while retrieving the files
        cli.print_to_console(e.message, is_err=True)
        cli.print_to_console(
            "Please add a valid configuration using tgcli config add",
            is_err=True)
        return
    if not all_configs[name]:
        cli.print_to_console(f"Configuration {name} not found.", is_err=True)
        return
    if cli.get_input_bool(f"Are you sure you want to delete {name}?"):
        # Delete all the associated initialization files
        delete_dependencies(all_configs[name])
        # Delete the dictionary associated with the config
        del all_configs[name]
        save_configs(all_configs)
        cli.print_to_console(f"{name} deleted.")
예제 #7
0
def load_vertices(
        # Basic config
        config_name: str = typer.Argument(None, help=CONFIG_ARG_HELP),
        graph_name: str = typer.Argument(None, help=GRAPH_ARG_HELP),
        # Required attributes
        vertex_type: str = typer.Option(...,
                                        "--type",
                                        help="Vertex type to map data to.",
                                        prompt="Vertex type"),
        vertex_id_col: str = typer.Option(
            ...,
            "--id",
            help="Column name to set as the ID of the vertex",
            prompt="Column name for ID"),
        # No prompt here - must be provided via CLI (string split into chars because of typer processing)
        attrs: List[str] = typer.
    Option(
        [],
        "--attr",
        help=
        "Column name of an vertex attribute, multiple can be specified by using the flag multiple times. "
        "If no values are provided, all columns will be used.",
    ),
        # Data sources
        csv_filepath: Path = typer.Option(
            None,
            "--csv",
            help="CSV filepath to load vertices from.",
            exists=True,
            file_okay=True,
            dir_okay=False,
            readable=True,
            resolve_path=True),
        pickle_filepath: Path = typer.Option(
            None,
            "--pickle",
            help="Pickle filepath to load vertices from.",
            exists=True,
            file_okay=True,
            dir_okay=False,
            readable=True,
            resolve_path=True),
        json_filepath: Path = typer.Option(
            None,
            "--json",
            help="JSON filepath to load vertices from.",
            exists=True,
            file_okay=True,
            dir_okay=False,
            readable=True,
            resolve_path=True)):
    """Loads a set of vertices from a given datasource."""
    conn = get_initialized_tg_connection(config_name=config_name,
                                         graph_name=graph_name,
                                         require_graph=True)
    num_upserted: int = 0
    vertex_attributes = None
    df = None
    if attrs:
        vertex_attributes = {val: val for val in attrs}
    if csv_filepath:
        df = __get_df__(csv_filepath, "csv")
    elif pickle_filepath:
        df = __get_df__(pickle_filepath, "pickle")
    elif json_filepath:
        df = __get_df__(json_filepath, "json")
    if df is not None:
        num_upserted = conn.upsertVertexDataframe(df=df,
                                                  vertexType=vertex_type,
                                                  v_id=vertex_id_col,
                                                  attributes=vertex_attributes)
    else:
        cli.terminate(
            message="No vertices loaded. Please specify a data source.")
    cli.print_to_console(
        f"Vertex load success. {num_upserted} vertices added.")
예제 #8
0
def load_edges(
        # Basic config
        config_name: str = typer.Argument(None, help=CONFIG_ARG_HELP),
        graph_name: str = typer.Argument(None, help=GRAPH_ARG_HELP),
        # Required items
        source_vertex_type: str = typer.Option(
            ...,
            "--source-type",
            help="Type name of the source vertex",
            prompt="Source vertex type"),
        source_vertex_id_col: str = typer.Option(
            ...,
            "--source-id",
            help="Column name for the source vertex ID",
            prompt="Source vertex ID column name"),
        target_vertex_type: str = typer.Option(
            ...,
            "--target-type",
            help="Type name of the target vertex",
            prompt="Target vertex type"),
        target_vertex_id_col: str = typer.Option(
            ...,
            "--target-id",
            help="Column name for the target vertex ID",
            prompt="Target vertex ID column name"),
        edge_type: str = typer.Option(...,
                                      "--edge-type",
                                      help="Type name of the edge",
                                      prompt="Edge type"),
        # No prompt here - must be provided via CLI (string split into chars because of typer processing)
        edge_attrs: List[str] = typer.
    Option(
        [],
        "--edge-attr",
        help=
        "Column name of an edge attribute, multiple can be specified by using the flag multiple times. "
        "If none are provided, all columns except for the source and target vertex ID columns are used.",
    ),
        # Data sources
        csv_filepath: Path = typer.Option(
            None,
            "--csv",
            help="CSV filepath to load vertices from.",
            exists=True,
            file_okay=True,
            dir_okay=False,
            readable=True,
            resolve_path=True),
        pickle_filepath: Path = typer.Option(
            None,
            "--pickle",
            help="Pickle filepath to load vertices from.",
            exists=True,
            file_okay=True,
            dir_okay=False,
            readable=True,
            resolve_path=True),
        json_filepath: Path = typer.Option(
            None,
            "--json",
            help="JSON filepath to load vertices from.",
            exists=True,
            file_okay=True,
            dir_okay=False,
            readable=True,
            resolve_path=True)):
    """Loads a set of edges from a given datasource."""
    conn = get_initialized_tg_connection(config_name=config_name,
                                         graph_name=graph_name,
                                         require_graph=True)
    num_upserted: int = 0
    df = None
    ignore_cols = {source_vertex_id_col, target_vertex_id_col}
    if csv_filepath:
        df = __get_df__(csv_filepath, "csv")
    elif pickle_filepath:
        df = __get_df__(pickle_filepath, "pickle")
    elif json_filepath:
        df = __get_df__(json_filepath, "json")
    if df is not None:
        edge_attributes = {
            val: val
            for val in df.columns if val not in ignore_cols
        }
        if edge_attrs:
            edge_attributes = {val: val for val in edge_attrs}
        num_upserted = conn.upsertEdgesDataframe(
            df=df,
            sourceVertexType=source_vertex_type,
            targetVertexType=target_vertex_type,
            edgeType=edge_type,
            from_id=source_vertex_id_col,
            to_id=target_vertex_id_col,
            attributes=edge_attributes)
    else:
        cli.terminate(message="No edges loaded. Please specify a data source.")
    cli.print_to_console(f"Edge load success. {num_upserted} edges added.")
예제 #9
0
def version():
    cli.print_to_console(__version__)
예제 #10
0
def get_edges(
        # Basic config
        config_name: str = typer.Argument(None, help=CONFIG_ARG_HELP),
        graph_name: str = typer.Argument(None, help=GRAPH_ARG_HELP),
        # Required items
        source_vertex_type: str = typer.Option(
            ..., "--from-type", help="Type of the source vertex."),
        source_vertex_id: str = typer.Option(...,
                                             "--from-id",
                                             help="ID of the source vertex."),
        # Filter by target
        target_vertex_id: str = typer.Option(None,
                                             "--to-id",
                                             help="ID of the target vertex"),
        target_vertex_type: str = typer.
    Option(
        None,
        "--to-type",
        help="Type of the target vertex. Required if '--to-id' is specified."),
        edge_type: str = typer.
    Option(
        None,
        "--edge-type",
        help=
        "Type of the edge. Required if '--to-id' and '--to-type' are specified."
    ),
        # Generic query params
        attributes: List[str] = typer.
    Option(
        [],
        '--attr',
        help=
        "Attributes to return for each edge, multiple can be specified by using the flag multiple times. "
        "See https://docs.tigergraph.com/dev/restpp-api/built-in-endpoints#select."
    ),
        where: List[str] = typer.
    Option(
        [],
        '--where',
        help="A condition to match for returned edges, "
        "multiple can be specified by using the flag multiple times. "
        "Multiple conditions are joined with AND. "
        "See https://docs.tigergraph.com/dev/restpp-api/built-in-endpoints#filter. "
        "For string conditions, the literal can be escaped like so: '--where=gender=\\\"male\\\"'. "
        "Alternatively, string escapes can be replaced by the URL-encoded string '%22'."
    ),
        sort_by_attrs: List[str] = typer.
    Option(
        [],
        '--sort',
        help=
        "Attribute name to sort results by, multiple can be specified by using the flag multiple times. "
        "See https://docs.tigergraph.com/dev/restpp-api/built-in-endpoints#sort."
    ),
        limit: int = typer.Option(
            10, '--limit', help="Maximum number of results to retrieve."),
        timeout: int = typer.Option(60,
                                    '--timeout',
                                    help="Timeout in seconds.")):
    """Get a set of edges"""
    conn = get_initialized_tg_connection(config_name=config_name,
                                         graph_name=graph_name,
                                         require_graph=True)
    if target_vertex_id and (not target_vertex_type or not edge_type):
        cli.terminate(
            message=
            "Target vertex ID is specified but target vertex type or edge type isn't.",
            is_err=True)
    output = conn.getEdges(sourceVertexType=source_vertex_type,
                           sourceVertexId=source_vertex_id,
                           targetVertexType=target_vertex_type,
                           targetVertexId=target_vertex_id,
                           edgeType=edge_type,
                           select=preprocess_list_query(attributes),
                           where=preprocess_list_query(where),
                           sort=preprocess_list_query(sort_by_attrs),
                           limit=limit,
                           timeout=timeout)
    cli.print_to_console(output)
예제 #11
0
def get_schema(config_name: str, graph_name: str):
    """Retrieve the schema for the configuration"""
    conn = get_initialized_tg_connection(config_name=config_name,
                                         graph_name=graph_name)
    output = conn.getSchema()
    cli.print_to_console(output)
예제 #12
0
def get_vertices(
        # Basic config
        config_name: str = typer.Argument(None, help=CONFIG_ARG_HELP),
        graph_name: str = typer.Argument(None, help=GRAPH_ARG_HELP),
        # Required items
        vertex_type: str = typer.Option(...,
                                        "--type",
                                        help="Type of the vertex."),
        # Query by ID's. If given, ID's take precedence over the generic query
        vertex_ids: List[str] = typer.
    Option(
        [],
        "--id",
        help=
        "ID of the vertex to retrieve, multiple can be specified by using the flag multiple times. If "
        "this is specified, other query parameters are ignored."),
        # Generic query params
        attributes: List[str] = typer.
    Option(
        [],
        '--attr',
        help=
        "Attributes to return for each vertex, multiple can be specified by using the flag multiple times. "
        "See https://docs.tigergraph.com/dev/restpp-api/built-in-endpoints#select ."
    ),
        where: List[str] = typer.
    Option(
        [],
        '--where',
        help="A condition to match for returned vertices, "
        "multiple can be specified by using the flag multiple times. "
        "Multiple conditions are joined with AND. "
        "See https://docs.tigergraph.com/dev/restpp-api/built-in-endpoints#filter . "
        "For string conditions, the literal can be escaped like so: '--where=gender=\\\"male\\\"'. "
        "Alternatively, string escapes can be replaced by the URL-encoded string '%22'."
    ),
        sort_by_attrs: List[str] = typer.
    Option(
        [],
        '--sort',
        help=
        "Attribute name to sort results by, multiple can be specified by using the flag multiple times. "
        "See https://docs.tigergraph.com/dev/restpp-api/built-in-endpoints#sort."
    ),
        limit: int = typer.Option(
            10, '--limit', help="Maximum number of results to retrieve."),
        timeout: int = typer.Option(60,
                                    '--timeout',
                                    help="Timeout in seconds.")):
    """Get a set of vertices, either by ID or by query"""
    conn = get_initialized_tg_connection(config_name=config_name,
                                         graph_name=graph_name,
                                         require_graph=True)
    if vertex_ids:
        # Given ID's give precedence
        output = conn.getVerticesById(vertex_type,
                                      resolve_multiple_args(vertex_ids))
    else:
        output = conn.getVertices(vertex_type,
                                  select=preprocess_list_query(attributes),
                                  where=preprocess_list_query(where),
                                  sort=preprocess_list_query(sort_by_attrs),
                                  limit=limit,
                                  timeout=timeout)
    cli.print_to_console(output)
예제 #13
0
def describe_config(config_name: str, show_sensitive: bool):
    """Output all the parameters from a TgcliConfiguration, optionally showing sensitive data."""
    configs = {}
    try:
        configs = get_configs(raise_on_nonexistent=True)
    except TgcliConfigurationError as e:
        cli.terminate(message=e.message, is_err=True)
    config = configs.get(config_name, None)
    if not config:
        cli.terminate(message=f"Configuration {config_name} not found.",
                      is_err=True)
    cli.print_to_console(f"Configuration {config_name}")
    # Print configuration values
    cli.print_to_console(f"Server: {config.server}")
    cli.print_to_console(f"Client Version: {config.client_version}")
    cli.print_to_console(f"REST++ Port: {config.restpp_port}")
    cli.print_to_console(f"GS Port: {config.gs_port}")
    cli.print_to_console(f"Use Auth: {config.use_auth}")
    cli.print_to_console(f"Username: {config.username}")
    # Password
    password = "******"
    if show_sensitive:
        password = config.password
    cli.print_to_console(f"Password: {password}")
    # Secrets
    if show_sensitive:
        for graph_name, secret in config.secrets.items():
            cli.print_to_console(f"Secret ({graph_name}): {secret}")