-
Notifications
You must be signed in to change notification settings - Fork 11
Description
- I have checked that this issue has not already been reported.
- I have confirmed this bug exists on the latest version of pytask.
- (optional) I have confirmed this bug exists on the
mainbranch of pytask.
Code Sample, a copy-pastable example
import pytask
from pathlib import Path
from bandgetouw.config import BLD
for id_ in ("unique_id", "another_one"):
def some_fun(some_data):
assert isinstance(some_data, str)
print(some_data)
return some_data
pytask.task(
id=id_,
produces=Path(BLD / "test" / f"{id_}.txt"),
kwargs={"some_data": "stuff"}
)(some_fun)Problem description
This is the output when I run pytask -s:
Collected 10 tasks.
stuff
stuff
╭─────────────────────────────────────┬─────────╮
│ Task │ Outcome │
├─────────────────────────────────────┼─────────┤
│ task_test.py::some_fun[another_one] │ F │
│ task_test.py::some_fun[unique_id] │ F │
╰─────────────────────────────────────┴─────────╯
──────────────────────────────────────── Failures ────────────────────────────────────────
──────────────────── Task task_test.py::some_fun[another_one] failed ─────────────────────
TypeError: 'PathNode' can only save 'str' and 'bytes', not <class 'NoneType'>
───────────────────── Task task_test.py::some_fun[unique_id] failed ──────────────────────
TypeError: 'PathNode' can only save 'str' and 'bytes', not <class 'NoneType'>
──────────────────────────────────────────────────────────────────────────────────────────
╭──────────────── Summary ─────────────────╮
│ 10 Collected tasks │
│ 8 Skipped because unchanged (80.0%) │
│ 2 Failed (20.0%) │
╰──────────────────────────────────────────╯
───────────────────────────────── Failed in 0.03 seconds ─────────────────────────────────
Expected Output
The tasks should succeed and the PathNode should've save "stuff" to the two output files.
Instead, PathNode.save fails because it cannot save the NoneType.
I've traced back the problem to the execute method of the Task class in _pytask.nodes:
There, the function (in this case some_fun) is called: return self.function(**kwargs).
I inspected the return value of self.function(**kwargs)), and it is indeed None. Obviously, I was expecting that value to be the string from some_fun.
In my particular case, my function is a simple lambda wrapper around a function (related to this issue) defined elsewhere called xrn_task. I have been able to work around this issue with the following hack in the Task class:
def execute(self, **kwargs: Any) -> None:
"""Execute the task."""
if "xrn_task" in inspect.getsource(self.function):
from bandgetouw.tasks import xrn_task
return xrn_task(**kwargs)
else:
return self.function(**kwargs)
Additionally, I'm not sure why the return type hint of the execute method is None.