Spaces:
Running
Running
Support for multiple outputs in a dict.
Browse files
lynxkite-app/web/src/workspace/nodes/LynxKiteNode.tsx
CHANGED
|
@@ -42,10 +42,12 @@ function getHandles(inputs: any[], outputs: any[]) {
|
|
| 42 |
e.index = counts[e.position];
|
| 43 |
counts[e.position]++;
|
| 44 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
for (const e of handles) {
|
| 46 |
e.offsetPercentage = (100 * (e.index + 1)) / (counts[e.position] + 1);
|
| 47 |
-
const simpleHorizontal = counts.top === 0 && counts.bottom === 0 && handles.length <= 2;
|
| 48 |
-
const simpleVertical = counts.left === 0 && counts.right === 0 && handles.length <= 2;
|
| 49 |
e.showLabel = !simpleHorizontal && !simpleVertical;
|
| 50 |
}
|
| 51 |
return handles;
|
|
|
|
| 42 |
e.index = counts[e.position];
|
| 43 |
counts[e.position]++;
|
| 44 |
}
|
| 45 |
+
const simpleHorizontal =
|
| 46 |
+
counts.top === 0 && counts.bottom === 0 && counts.left <= 1 && counts.right <= 1;
|
| 47 |
+
const simpleVertical =
|
| 48 |
+
counts.left === 0 && counts.right === 0 && counts.top <= 1 && counts.bottom <= 1;
|
| 49 |
for (const e of handles) {
|
| 50 |
e.offsetPercentage = (100 * (e.index + 1)) / (counts[e.position] + 1);
|
|
|
|
|
|
|
| 51 |
e.showLabel = !simpleHorizontal && !simpleVertical;
|
| 52 |
}
|
| 53 |
return handles;
|
lynxkite-graph-analytics/src/lynxkite_graph_analytics/core.py
CHANGED
|
@@ -161,11 +161,15 @@ def disambiguate_edges(ws: workspace.Workspace):
|
|
| 161 |
seen.add((edge.target, edge.targetHandle))
|
| 162 |
|
| 163 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 164 |
@ops.register_executor(ENV)
|
| 165 |
async def execute(ws: workspace.Workspace):
|
| 166 |
-
catalog
|
| 167 |
disambiguate_edges(ws)
|
| 168 |
-
outputs = {}
|
| 169 |
nodes = {node.id: node for node in ws.nodes}
|
| 170 |
todo = set(nodes.keys())
|
| 171 |
progress = True
|
|
@@ -173,8 +177,12 @@ async def execute(ws: workspace.Workspace):
|
|
| 173 |
progress = False
|
| 174 |
for id in list(todo):
|
| 175 |
node = nodes[id]
|
| 176 |
-
|
| 177 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 178 |
# All inputs for this node are ready, we can compute the output.
|
| 179 |
todo.remove(id)
|
| 180 |
progress = True
|
|
@@ -187,7 +195,9 @@ async def await_if_needed(obj):
|
|
| 187 |
return obj
|
| 188 |
|
| 189 |
|
| 190 |
-
async def _execute_node(
|
|
|
|
|
|
|
| 191 |
params = {**node.data.params}
|
| 192 |
op = catalog.get(node.data.title)
|
| 193 |
if not op:
|
|
@@ -196,7 +206,9 @@ async def _execute_node(node, ws, catalog, outputs):
|
|
| 196 |
node.publish_started()
|
| 197 |
# TODO: Handle multi-inputs.
|
| 198 |
input_map = {
|
| 199 |
-
edge.targetHandle: outputs[edge.source
|
|
|
|
|
|
|
| 200 |
}
|
| 201 |
# Convert inputs types to match operation signature.
|
| 202 |
try:
|
|
@@ -228,8 +240,12 @@ async def _execute_node(node, ws, catalog, outputs):
|
|
| 228 |
traceback.print_exc()
|
| 229 |
result = ops.Result(error=str(e))
|
| 230 |
result.input_metadata = [_get_metadata(i) for i in inputs]
|
| 231 |
-
if result.output
|
| 232 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
node.publish_result(result)
|
| 234 |
|
| 235 |
|
|
|
|
| 161 |
seen.add((edge.target, edge.targetHandle))
|
| 162 |
|
| 163 |
|
| 164 |
+
# Outputs are tracked by node ID and output ID.
|
| 165 |
+
Outputs = dict[(str, str), typing.Any]
|
| 166 |
+
|
| 167 |
+
|
| 168 |
@ops.register_executor(ENV)
|
| 169 |
async def execute(ws: workspace.Workspace):
|
| 170 |
+
catalog = ops.CATALOGS[ws.env]
|
| 171 |
disambiguate_edges(ws)
|
| 172 |
+
outputs: Outputs = {}
|
| 173 |
nodes = {node.id: node for node in ws.nodes}
|
| 174 |
todo = set(nodes.keys())
|
| 175 |
progress = True
|
|
|
|
| 177 |
progress = False
|
| 178 |
for id in list(todo):
|
| 179 |
node = nodes[id]
|
| 180 |
+
inputs_done = [
|
| 181 |
+
(edge.source, edge.sourceHandle) in outputs
|
| 182 |
+
for edge in ws.edges
|
| 183 |
+
if edge.target == id
|
| 184 |
+
]
|
| 185 |
+
if all(inputs_done):
|
| 186 |
# All inputs for this node are ready, we can compute the output.
|
| 187 |
todo.remove(id)
|
| 188 |
progress = True
|
|
|
|
| 195 |
return obj
|
| 196 |
|
| 197 |
|
| 198 |
+
async def _execute_node(
|
| 199 |
+
node: workspace.WorkspaceNode, ws: workspace.Workspace, catalog: ops.Catalog, outputs: Outputs
|
| 200 |
+
):
|
| 201 |
params = {**node.data.params}
|
| 202 |
op = catalog.get(node.data.title)
|
| 203 |
if not op:
|
|
|
|
| 206 |
node.publish_started()
|
| 207 |
# TODO: Handle multi-inputs.
|
| 208 |
input_map = {
|
| 209 |
+
edge.targetHandle: outputs[edge.source, edge.sourceHandle]
|
| 210 |
+
for edge in ws.edges
|
| 211 |
+
if edge.target == node.id
|
| 212 |
}
|
| 213 |
# Convert inputs types to match operation signature.
|
| 214 |
try:
|
|
|
|
| 240 |
traceback.print_exc()
|
| 241 |
result = ops.Result(error=str(e))
|
| 242 |
result.input_metadata = [_get_metadata(i) for i in inputs]
|
| 243 |
+
if isinstance(result.output, dict):
|
| 244 |
+
for k, v in result.output.items():
|
| 245 |
+
outputs[node.id, k] = v
|
| 246 |
+
elif result.output is not None:
|
| 247 |
+
[k] = op.outputs
|
| 248 |
+
outputs[node.id, k.name] = result.output
|
| 249 |
node.publish_result(result)
|
| 250 |
|
| 251 |
|