Exemple #1
0
def node(
        title: str = Option("", "--title", "-n", help=_name_help),
        component: str = Option("", "-c", "--component", help=_component_help),
        location: Path = Argument(None),
):
    """Add a new node to a graph

    patterns create node --name='My Node' mynode.py
    """
    if component and location:
        abort("Specify either a component or a node location, not both")

    if component:
        ids = IdLookup(find_nearest_graph=True)
        GraphConfigEditor(ids.graph_file_path).add_component_uses(
            component_key=component).write()
        sprint(f"[success]Added component {component} to graph")
        return

    if not location:
        sprint("[info]Nodes can be python files like [code]ingest.py")
        sprint("[info]Nodes can be sql files like [code]aggregate.sql")
        sprint(
            "[info]You also can add a subgraph like [code]processor/graph.yml")
        message = "Enter a name for the new node file"
        location = prompt_path(message, exists=False)

    if location.exists():
        abort(f"Cannot create node: {location} already exists")

    ids = IdLookup(node_file_path=location, find_nearest_graph=True)
    # Update the graph yaml
    node_file = "/".join(location.absolute().relative_to(
        ids.graph_directory).parts)
    node_title = title or (location.parent.name
                           if location.name == "graph.yml" else location.stem)
    with abort_on_error("Adding node failed"):
        editor = GraphConfigEditor(ids.graph_file_path)
        editor.add_node(
            title=node_title,
            node_file=node_file,
            id=str(random_node_id()),
        )

    # Write to disk last to avoid partial updates
    if location.suffix == ".py":
        location.write_text(_PY_FILE_TEMPLATE)
    elif location.suffix == ".sql":
        location.write_text(_SQL_FILE_TEMPLATE)
    elif location.name == "graph.yml":
        location.parent.mkdir(exist_ok=True, parents=True)
        GraphConfigEditor(location, read=False).set_name(node_title).write()
    else:
        abort("Node file must be graph.yml or end in .py or .sql")
    editor.write()

    sprint(f"\n[success]Created node [b]{location}")
    sprint(
        f"\n[info]Once you've edited the node and are ready to run the graph, "
        f"use [code]patterns upload")
Exemple #2
0
 def add_node(
     self,
     node_file: str,
     schedule: str = None,
     inputs: Dict[str, str] = None,
     outputs: Dict[str, str] = None,
     parameters: Dict[str, Any] = None,
     title: str = None,
     id: Optional[str] = MISSING,
     description: str = None,
     description_file: str = None,
 ) -> GraphConfigEditor:
     if id is MISSING:
         id = random_node_id()
     self.add_function_node_dict(
         {
             "node_file": node_file,
             "schedule": schedule,
             "inputs": inputs,
             "outputs": outputs,
             "parameters": parameters,
             "title": title,
             "id": str(id) if id else id,
             "description": description,
             "description_file": description_file,
         }
     )
     return self
Exemple #3
0
    def add_store(
        self,
        name: str,
        table: bool,
        title: str = None,
        id: Optional[str] = MISSING,
        schema: str = None,
    ):
        if id is MISSING:
            id = random_node_id()
        d = {
            "table" if table else "stream": name,
            "title": title,
            "id": str(id) if id else id,
            "schema": schema,
        }
        d = {k: v for (k, v) in d.items() if v is not None}

        for k in ("table", "stream", "id"):
            if d.get(k) and any(
                it.get(k) == d[k] for it in self._cfg.get("stores", [])
            ):
                raise ValueError(
                    f"{k} '{d[k]}' already defined in the graph configuration"
                )

        if "stores" not in self._cfg:
            self._cfg["stores"] = []
        self._cfg["stores"].append(d)
        return self
Exemple #4
0
def webhook(
        explicit_graph: Path = Option(None,
                                      "--graph",
                                      "-g",
                                      exists=True,
                                      help=_graph_help),
        name: str = Argument(..., help=_webhook_name_help),
):
    """Add a new webhook node to a graph"""
    ids = IdLookup(explicit_graph_path=explicit_graph)

    with abort_on_error("Adding webhook failed"):
        editor = GraphConfigEditor(ids.graph_file_path)
        editor.add_webhook(name, id=random_node_id())
        editor.write()

    sprint(f"\n[success]Created webhook [b]{name}")
    sprint(
        f"\n[info]Once you've deployed the graph, use "
        f"[code]patterns list webhooks[/code] to get the url of the webhook")
Exemple #5
0
 def add_webhook(
     self,
     webhook: str,
     title: str = None,
     id: Optional[str] = MISSING,
     description: str = None,
     description_file: str = None,
 ) -> GraphConfigEditor:
     if id is MISSING:
         id = random_node_id()
     self.add_function_node_dict(
         {
             "webhook": webhook,
             "title": title,
             "id": str(id) if id else id,
             "description": description,
             "description_file": description_file,
         }
     )
     return self
Exemple #6
0
 def add_missing_node_ids(self) -> GraphConfigEditor:
     """Add a random id to any node entry that doesn't specify one"""
     for node in self.all_nodes():
         if "id" not in node:
             node["id"] = random_node_id()
     return self