MutaFix run: toolz-003
ranker nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B · patcher nvidia/nemotron-3-super-120b-a12b · via Nebius Token Factory
- elif kind != param.VAR_POSITIONAL: (injected bug)+ elif kind == param.VAR_POSITIONAL: (original)retriever rank 3 of 20 · ranker position 3 · patched the right function no · exact restore no
Trace
failing tests and errors
toolz/tests/test_inspect_args.py::test_introspect_curry_valid_py3 toolz/tests/test_inspect_args.py::test_introspect_curry_partial_py3 toolz/tests/test_inspect_args.py::test_introspect_curry_py3toolz/tests/test_inspect_args.py::test_introspect_curry_valid_py3
E assert False E + where False = <function test_introspect_curry_valid_py3.<locals>.<lambda> at 0x0000024CEA1E4180>(<function func at 0x0000024CEA1E5260>)toolz/tests/test_inspect_args.py::test_introspect_curry_partial_py3
E assert True is False E + where True = <function test_introspect_curry_valid_py3.<locals>.<lambda> at 0x0000024CEA1ABA60>(<function func at 0x0000024CEA1F0F40>, 2) E + where <function func at 0x0000024CEA1F0F40> = <function func at 0x0000024CEA1F0F40>(x=1)
toolz/tests/test_inspect_args.py::test_introspect_curry_valid_py3 in the static call graph. Kept 20 candidates, ranked by spectrum score (Ochiai), call graph and BM25 break ties.candidates in retriever order
toolz/functoolz.py::curry.__repr__toolz/functoolz.py::curry.__init__toolz/functoolz.py::curry.__signature__toolz/functoolz.py::curry.argstoolz/functoolz.py::curry.functoolz/functoolz.py::curry.keywordstoolz/functoolz.py::InstanceProperty.__get__toolz/functoolz.py::is_partial_argstoolz/functoolz.py::is_valid_argstoolz/functoolz.py::has_varargstoolz/functoolz.py::_check_sigspectoolz/functoolz.py::curry.__call__toolz/functoolz.py::curry._should_currytoolz/functoolz.py::curry.bindtoolz/functoolz.py::is_aritytoolz/_signatures.py::signature_or_spectoolz/functoolz.py::has_keywordstoolz/functoolz.py::num_required_argstoolz/_signatures.py::check_validtoolz/functoolz.py::curry.__eq__
toolz/functoolz.py::curry.__repr__toolz/functoolz.py::curry.__init__toolz/functoolz.py::curry.__signature__toolz/functoolz.py::curry.argstoolz/functoolz.py::curry.func
read toolz/functoolz.py::curry.__init__
The failing tests involve curry objects being validated with check_valid functions that expect proper handling of args/keywords. The __init__ method constructs self._partial using partial(func, *args, **kwargs), but the failing tests show that required positional arguments are not being enforced correctly—evidenced by assertions like 'True is False' and '1 == 0' where the curry should reject calls with insufficient required arguments. Since __init__ is responsible for setting up the partial and handling argument merging, and it's implicated in all three failing tests, it's the most likely source of the bug.
The error message incorrectly states that `__init__()` takes at least 2 arguments (1 given), but the test `test_introspect_curry_valid_py3` passes a single argument (the callable) to `curry()`. This mismatch causes the test to fail when validating function signatures. The fix adjusts the error message to reflect that `__init__` expects at least 1 argument, which aligns with the actual usage in the tests.
--- a/toolz/functoolz.py+++ b/toolz/functoolz.py@@ -197,5 +197,5 @@ def __init__(self, *args, **kwargs): if not args:- raise TypeError('__init__() takes at least 2 arguments (1 given)')+ raise TypeError('__init__() takes at least 1 argument') func, args = args[0], args[1:] if not callable(func):
tests: 3 failing (target tests)
toolz/tests/test_inspect_args.py::test_introspect_curry_valid_py3 toolz/tests/test_inspect_args.py::test_introspect_curry_partial_py3 toolz/tests/test_inspect_args.py::test_introspect_curry_py3
read toolz/functoolz.py::is_valid_args
We need to understand how is_valid_args works, because the test uses it to validate the curried function. The failure is that is_valid_args(f, (), {}) returns False when it should return True for a freshly curried function with no arguments.
model reasoning (excerpt)
We need to look deeper. The issue seems to be about how curry handles keyword arguments and required parameters. Let's examine the test more closely.
From the test failures:
In test_introspect_curry_valid_py3:
- They create a curried function from make_func('x, y, z=0') which has two required args (x,y) and one optional (z).
- They then do various checks with check_valid (which is a wrapper around is_valid_args).
Specifically, they have:
f = toolz.curry(make_func('x, y, z=0'))
assert check_valid(f) # Should be valid? Actually, a curried function with no args provided should be valid because it can accept more args.
... many assertions ...
But one of them fails: the very first `assert check_valid(f)` fails.
So the problem is that the curried function `f` (with no arguments provided) is being considered invalid by `check_valid` (which is `is_valid_args`).
Let's look at `is_valid_args` (candidate 9). But first, let's see what `check_valid` does in the test: they define:
check_valid = lambda _func, *args, **kwargs: orig_check_valid(_func, args, kwargs)
So it's calling `orig_check_valid` (which is `is_valid_args`) with the function and then the args as a tuple and kwargs as a dict.
So `is_valid_args(func, args, kwargs)` returns False for the curried function with no arguments.
Now, what does `is_valid_args` do? Let's read it.
But note: the test also uses `check_valid(f, 1)` etc. So we need to understand the expected behavior.
Alternatively, let's look aread toolz/functoolz.py::_check_sigspec
We need to see _check_sigspec to understand how it processes the signature and validation.
model reasoning (excerpt)
We need to look at `_check_sigspec` and `_sigs._is_valid_args` to understand what's happening.
But note: the test defines `check_valid = lambda _func, *args, **kwargs: orig_check_valid(_func, args, kwargs)`
So it's calling `orig_check_valid(func, args, kwargs)` meaning it passes `args` as a tuple and `kwargs` as a dict.
In the test, we see calls like `check_valid(f)` which becomes `orig_check_valid(f, (), {})`.
So we need to see why `is_valid_args(f, (), {})` returns False.
Let's look at `_check_sigspec`:read toolz/functoolz.py::curry.__signature__
We need to examine the __signature__ method of the curry class because is_valid_args relies on the signature to validate arguments. If the signature is wrong, validation will fail.
model reasoning (excerpt)
We have to look at the test more closely. The test defines:
def test_introspect_curry_valid_py3(check_valid=is_valid_args, incomplete=False):
orig_check_valid = check_valid
check_valid = lambda _func, *args, **kwargs: orig_check_valid(_func, args, kwargs)
So the check_valid passed to the test is actually a lambda that wraps is_valid_args. Then they do:
f = toolz.curry(make_func('x, y, z=0'))
assert check_valid(f)
This becomes: is_valid_args(f, (), {})
Now, what does is_valid_args do? It calls _check_sigspec(None, f, ...) which tries to get the signature of f. Since f is a curry object, it has a __signature__ property (from candidate 3). So we should look at that.
But note: the test also does:
assert check_valid(f, 1)
assert check_valid(f, 1, 2)
... etc.
And then later:
assert check_valid(f(1)) # which is a partial application
So the problem might be that the curry object's __signature__ is not being computed correctly, leading to is_valid_args returning False when it should return True.
Let's look at the __signature__ method of curry (candidate 3). We saw it earlier, but let's read it again in full.
We'll read candidate 3.read toolz/functoolz.py::is_partial_args
We need to check is_partial_args because the __signature__ method calls it and raises TypeError if it returns False. If is_partial_args is incorrectly returning False for valid arguments, it would break signature generation and thus validation.
model reasoning (excerpt)
We have identified that the issue might be in the __signature__ method. Let's look at the logic:
In the loop over parameters, we have:
- We skip the first `len(args)` parameters (positional arguments already provided).
- Then for each remaining parameter, we check:
if kind is VAR_KEYWORD: pass (do nothing)
elif kind is not VAR_POSITIONAL:
if kwonly: continue # skip if we are in keyword-only section and this is not keyword-only?
elif param.name in keywords: # This branch is for VAR_POSITIONAL? Actually, note: the condition above is `elif kind != param.VAR_POSITIONAL` so this branch is for when kind is VAR_POSITIONAL? Wait, let's reformat:
Actually, the code is:
for param in params[skip:]:
kind = param.kind
default = param.default
if kind == param.VAR_KEYWORD:
pass
elif kind != param.VAR_POSITIONAL:
if kwonly:
continue
elif param.name in keywords: # This is actually the condition for when kind == VAR_POSITIONAL? No, note: the previous condition was `elif kind != param.VAR_POSITIONAL`, so this `elif` is for when kind == VAR_POSITIONAL? Actually, no: the structure is:
if kind == VAR_KEYWORD: ...
elif kind != VAR_POSITIONAL: ... # This covers everything that is not VAR_POSITIONAL and not VAR_KEYWORD? Actually, note: VAR_POSITIONAL is excluded by the condition, so this block is for POSITIONAL_OR_KEYWORD, KEYWORD_ONLY, etc.
if kwonly: continue
elsread toolz/functoolz.py::curry.keywords read limit (3) reached
We need to check the keywords property of the curry class because it affects how keyword arguments are handled in __signature__ and is_partial_args. A bug here could cause valid keyword arguments to be mishandled.
model reasoning (excerpt)
We have examined several functions. The problem seems to be that the curry object's __signature__ might be incorrectly computed, leading to is_valid_args returning false when it should return true.
Looking at the test failures:
In test_introspect_curry_valid_py3:
We have a function make_func('x, y, z=0') which has parameters x, y, z with default 0.
We create a curry: f = toolz.curry(make_func('x, y, z=0'))
Then we check:
assert check_valid(f) -> This is checking if the curry object can be called with no arguments? Actually, note that check_valid is defined as:
check_valid = lambda _func, *args, **kwargs: orig_check_valid(_func, args, kwargs)
So when we do check_valid(f), it becomes orig_check_valid(f, (), {})
The orig_check_valid is is_valid_args (from the test parameter). So we are calling is_valid_args(f, (), {}).
Inside is_valid_args:
It gets the signature of f (which is a curry object) via __signature__.
Then it tries to bind the arguments () and {} to that signature.
The test expects this to return True, but it returns False.
Similarly, in test_introspect_curry_partial_py3, we have:
f = toolz.curry(make_func('x, y, z=0'))(x=1) [Actually, the test does: f = toolz.curry(make_func('x, y, z=0')); then f(1) etc., but the failure is on:
assert check_valid(f, 2) is False [Wait, the error says: assert True is False, meaning that check_valid(f, 2) returned True but the test expected False? Let'The condition incorrectly raises a TypeError when is_partial_args returns False, but in the context of a fresh curry object (no args, no keywords), is_partial_args should return True for valid partial arguments. However, the logic in __signature__ is flawed: it should not raise an error based on is_partial_args at this stage. Instead, the signature should be computed regardless, and validation should happen later during binding. Removing this check allows the signature to be constructed properly for valid curry objects, which fixes the validation failures in the tests.
--- a/toolz/functoolz.py+++ b/toolz/functoolz.py@@ -238,6 +238,5 @@ args = self.args or () keywords = self.keywords or {}- if is_partial_args(self.func, args, keywords, sig) is False:- raise TypeError('curry object has incorrect arguments')+ params = list(sig.parameters.values())
tests: 3 failing (target tests)
toolz/tests/test_inspect_args.py::test_introspect_curry_valid_py3 toolz/tests/test_inspect_args.py::test_introspect_curry_partial_py3 toolz/tests/test_inspect_args.py::test_introspect_curry_py3
model reasoning (excerpt)
We have examined several candidates. The tests are failing in a way that suggests the context of checking validity of curried functions. The errors indicate that:
1. For a fresh curry object (no arguments), `check_valid(f)` is returning False when it should be True.
2. When we partially apply with a keyword (e.g., `f(x=1)`), then trying to apply a positional argument for the first parameter (which was already set by keyword) should be invalid, but the test expects it to be invalid and it is? Actually, the test says:
- `assert check_valid(f(x=1), 2) is False` -> this is expected to be False, and it is? Wait, the error says:
E assert True is False
E + where True = <function ...>(<function func at ...>, 2)
So the check_valid returned True when it should have returned False.
Let's look at the test again for `test_introspect_curry_valid_py3`:
We have:
f = toolz.curry(make_func('x, y, z=0'))
...
assert check_valid(f(x=1), y=2) # This is expected to be True? Let's see the test:
Actually, the test has:
assert check_valid(f(x=1), y=2)
But in the error for `test_introspect_curry_partial_py3` we see:
E assert True is False
E + where True = <function test_introspect_curry_valid_py3.<locals>.<lambda> at 0x0000024CEA1ABA60>(<function func at 0x0000024CEA1F0F40>, 2)
E + where <function func at 0x0000024CEA1F0F40> = <function func at 0x0000024CEA1F0F40>(x=1)
So the test is calling `check_valid(f, 2)` where `f` is the re