Skip to content

Commit 09d4e32

Browse files
authored
refactor: extract get_call_args to eliminate duplicate parameter matching (#448)
* refactor: extract get_call_args to eliminate duplicate parameter matching Reduces 18 lines of duplicated sync/async parameter matching logic to 4 lines. The helper function centralize signature inspection and argument selection. * test: add call-args flow to cover all main function signature types Add comprehensive test coverage for the get_call_args refactor: - no_params: def main() - context_only: def main(context: Context) - inputs_only: def main(inputs) - two_params: def main(inputs, context: Context) - async_two_params: async def main(inputs, context: Context)
1 parent 5d96505 commit 09d4e32

File tree

14 files changed

+134
-16
lines changed

14 files changed

+134
-16
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,3 +163,4 @@ cython_debug/
163163
.pdm-python
164164

165165
node_modules
166+
.claude/

executor/python_executor/block.py

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,25 @@ def output_return_object(obj, context: Context):
7878
else:
7979
context.finish(error=f"return object needs to be a dictionary, but get type: {type(obj)}")
8080

81+
82+
def get_call_args(fn, context: Context) -> tuple:
83+
"""
84+
Determine the arguments to pass to a block function based on its signature.
85+
Returns a tuple of positional arguments.
86+
"""
87+
signature = inspect.signature(fn)
88+
params_count = len(signature.parameters)
89+
90+
if params_count == 0:
91+
return ()
92+
elif params_count == 1:
93+
first_param = list(signature.parameters.values())[0]
94+
if first_param.annotation is Context:
95+
return (context,)
96+
return (context.inputs,)
97+
else:
98+
return (context.inputs, context)
99+
81100
logger = logging.getLogger(EXECUTOR_NAME)
82101

83102
async def run_block(message, mainframe: Mainframe, session_dir: str, tmp_dir: str, package_name: str, pkg_dir: str):
@@ -145,28 +164,15 @@ async def run_block(message, mainframe: Mainframe, session_dir: str, tmp_dir: st
145164
return
146165

147166
try:
148-
signature = inspect.signature(fn)
149-
params_count = len(signature.parameters)
167+
args = get_call_args(fn, context)
150168
result = None
151169
traceback_str = None
152170

153171
try:
154172
if inspect.iscoroutinefunction(fn):
155-
if params_count == 0:
156-
result = await fn()
157-
elif params_count == 1:
158-
only_context_param = list(signature.parameters.values())[0].annotation is Context
159-
result = await fn(context) if only_context_param else await fn(context.inputs)
160-
else:
161-
result = await fn(context.inputs, context)
173+
result = await fn(*args)
162174
else:
163-
if params_count == 0:
164-
result = fn()
165-
elif params_count == 1:
166-
only_context_param = list(signature.parameters.values())[0].annotation is Context
167-
result = fn(context) if only_context_param else fn(context.inputs)
168-
else:
169-
result = fn(context.inputs, context)
175+
result = fn(*args)
170176
except ExitFunctionException as e:
171177
if e.args[0] is not None:
172178
context.finish(error="block call exit with message: " + str(e.args[0]))

flow-examples/test/flow.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,19 @@ describe(
259259
expect(latestFinished?.data.result?.output).toBe(9);
260260
});
261261

262+
it("run call-args flow", async () => {
263+
files.delete("call-args");
264+
const { code, events } = await run("call-args");
265+
expect(code).toBe(0);
266+
267+
const finishedEvents = events.filter(e => e.event === "BlockFinished");
268+
expect(finishedEvents.length).toBe(5);
269+
270+
// Verify the chain executed in order
271+
const lastFinished = finishedEvents[finishedEvents.length - 1];
272+
expect(lastFinished?.data.stacks?.[0].node_id).toBe("async_two_params");
273+
});
274+
262275
it("run additional-block flow", async () => {
263276
files.delete("additional-block");
264277
const { code, events } = await run("additional-block");
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from oocana import Context
2+
3+
4+
async def main(inputs, context: Context):
5+
value = inputs.get("input", "default")
6+
context.send_message(f"async_two_params received: {value}")
7+
return {"output": f"async_two_params:{value}"}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
executor:
2+
name: python
3+
options:
4+
entry: __init__.py
5+
inputs_def:
6+
- handle: input
7+
outputs_def:
8+
- handle: output
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from oocana import Context
2+
3+
4+
def main(context: Context):
5+
value = context.inputs.get("input", "default")
6+
return {"output": f"context_only:{value}"}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
executor:
2+
name: python
3+
options:
4+
entry: __init__.py
5+
inputs_def:
6+
- handle: input
7+
outputs_def:
8+
- handle: output
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
def main(inputs):
2+
value = inputs.get("input", "default")
3+
return {"output": f"inputs_only:{value}"}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
executor:
2+
name: python
3+
options:
4+
entry: __init__.py
5+
inputs_def:
6+
- handle: input
7+
outputs_def:
8+
- handle: output
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
def main():
2+
return {"output": "no_params_ok"}

0 commit comments

Comments
 (0)