-
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
main
branch 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
.