darabos commited on
Commit
2db0d9f
·
1 Parent(s): 56ec4e5

Add "simple" executor.

Browse files
lynxkite-core/src/lynxkite/core/executors/simple.py ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """A LynxKite executor that simply passes the output of one box to the other."""
2
+
3
+ import os
4
+ from .. import ops
5
+ from .. import workspace
6
+ import traceback
7
+ import inspect
8
+ import graphlib
9
+
10
+
11
+ def register(env: str):
12
+ """Registers the one-by-one executor."""
13
+ ops.EXECUTORS[env] = lambda ws: execute(ws, ops.CATALOGS[env])
14
+
15
+
16
+ async def await_if_needed(obj):
17
+ if inspect.isawaitable(obj):
18
+ return await obj
19
+ return obj
20
+
21
+
22
+ async def execute(ws: workspace.Workspace, catalog: ops.Catalog):
23
+ nodes = {n.id: n for n in ws.nodes}
24
+ dependencies = {n: [] for n in nodes}
25
+ in_edges = {n: {} for n in nodes}
26
+ for e in ws.edges:
27
+ dependencies[e.target].append(e.source)
28
+ assert e.targetHandle not in in_edges[e.target], f"Duplicate input for {e.target}"
29
+ in_edges[e.target][e.targetHandle] = e.source, e.sourceHandle
30
+ outputs = {}
31
+ ts = graphlib.TopologicalSorter(dependencies)
32
+ for node_id in ts.static_order():
33
+ node = nodes[node_id]
34
+ op = catalog[node.data.title]
35
+ params = {**node.data.params}
36
+ node.publish_started()
37
+ try:
38
+ inputs = []
39
+ missing = []
40
+ for i in op.inputs.values():
41
+ edges = in_edges[node_id]
42
+ if i.name in edges and edges[i.name] in outputs:
43
+ inputs.append(outputs[edges[i.name]])
44
+ else:
45
+ missing.append(i.name)
46
+ if missing:
47
+ node.publish_error(f"Missing input: {', '.join(missing)}")
48
+ continue
49
+ result = op(*inputs, **params)
50
+ result.output = await await_if_needed(result.output)
51
+ result.display = await await_if_needed(result.display)
52
+ if len(op.outputs) == 1:
53
+ [output] = list(op.outputs.values())
54
+ outputs[node_id, output.name] = result.output
55
+ elif len(op.outputs) > 1:
56
+ assert type(result.output) is dict, "An op with multiple outputs must return a dict"
57
+ for output in op.outputs.values():
58
+ outputs[node_id, output.name] = result.output[output.name]
59
+ node.publish_result(result)
60
+ except Exception as e:
61
+ if not os.environ.get("LYNXKITE_SUPPRESS_OP_ERRORS"):
62
+ traceback.print_exc()
63
+ node.publish_error(e)
64
+ return outputs
lynxkite-pillow-example/src/lynxkite_pillow_example/__init__.py CHANGED
@@ -1,7 +1,7 @@
1
  """Demo for how easily we can provide a UI for popular open-source tools."""
2
 
3
  from lynxkite.core import ops
4
- from lynxkite.core.executors import one_by_one
5
  from PIL import Image, ImageFilter
6
  import base64
7
  import fsspec
@@ -9,7 +9,7 @@ import io
9
 
10
  ENV = "Pillow"
11
  op = ops.op_registration(ENV)
12
- one_by_one.register(ENV, cache=False)
13
 
14
 
15
  @op("Open image")
 
1
  """Demo for how easily we can provide a UI for popular open-source tools."""
2
 
3
  from lynxkite.core import ops
4
+ from lynxkite.core.executors import simple
5
  from PIL import Image, ImageFilter
6
  import base64
7
  import fsspec
 
9
 
10
  ENV = "Pillow"
11
  op = ops.op_registration(ENV)
12
+ simple.register(ENV)
13
 
14
 
15
  @op("Open image")