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