-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Bug
rename_arguments creates a double-partial when the input function is a functools.partial, causing the bound positional arguments to be passed twice.
Minimal Reproducible Example
import functools
from dags.signature import rename_arguments
def inner(bound_arg, free_arg):
return f"bound={bound_arg}, free={free_arg}"
func = functools.partial(inner, "BOUND_VALUE")
renamed = rename_arguments(func, mapper={"free_arg": "renamed_free"})
renamed(renamed_free="hello")
# TypeError: inner() got multiple values for argument 'free_arg'
renamed("hello")
# TypeError: inner() takes 2 positional arguments but 3 were givenRoot Cause
In dags/signature.py, rename_arguments lines 274-279:
# Preserve function type
if isinstance(func, functools.partial):
partial_wrapper = functools.partial(
wrapper_rename_arguments, *func.args, **func.keywords
)
out = cast("Callable[P, R]", partial_wrapper)wrapper_rename_arguments already captures func (the partial) in its closure and delegates to it via func(*args, **internal_kwargs). The bound args from the partial are already applied when func is called internally.
The "Preserve function type" block then wraps wrapper_rename_arguments in another functools.partial with the same *func.args, so those args get passed twice: once by the outer partial as positional args, and once by the inner func() call (which is the original partial).
Expected Behavior
rename_arguments should work correctly with functools.partial inputs — renaming only the free (unbound) parameters without duplicating the bound arguments.
dags Version
0.5.0 (also affects current main)