Skip to content

Commit 480fc4b

Browse files
committed
Raise error for invalid value in return annotation.
1 parent 2bd471f commit 480fc4b

File tree

3 files changed

+27
-1
lines changed

3 files changed

+27
-1
lines changed

docs/source/changes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ releases are available on [PyPI](https://pypi.org/project/pytask) and
1313
- {pull}`485` adds missing steps to unconfigure pytask after the job is done which
1414
caused flaky tests.
1515
- {pull}`486` adds default names to {class}`~pytask.PPathNode`.
16+
- {pull}`488` raises an error when an invalid value is used in a return annotation.
1617

1718
## 0.4.2 - 2023-11-8
1819

src/_pytask/collect.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@ def pytask_collect_task(
308308

309309

310310
@hookimpl(trylast=True)
311-
def pytask_collect_node(session: Session, path: Path, node_info: NodeInfo) -> PNode:
311+
def pytask_collect_node(session: Session, path: Path, node_info: NodeInfo) -> PNode: # noqa: C901
312312
"""Collect a node of a task as a :class:`pytask.PNode`.
313313
314314
Strings are assumed to be paths. This might be a strict assumption, but since this
@@ -375,6 +375,18 @@ def pytask_collect_node(session: Session, path: Path, node_info: NodeInfo) -> PN
375375

376376
return PathNode(name=name, path=node)
377377

378+
# Allowing a PythonNode as a return is a poor fallback, because it cannot be used.
379+
# Probably, the user made a mistake like writing a custom node that does not
380+
# strictly follow the protocol or some other misspecification.
381+
if node_info.arg_name == "return":
382+
msg = (
383+
"The return annotation of the task holds an invalid value. Please, use a "
384+
"node or a value that can be parsed to a node. Maybe you used a node that "
385+
"does not follow the 'pytask.PNode' protocol. This is the value: "
386+
f"{node_info.value!r}"
387+
)
388+
raise ValueError(msg)
389+
378390
node_name = create_name_of_python_node(node_info)
379391
return PythonNode(value=node, name=node_name, node_info=node_info)
380392

tests/test_collect.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,3 +641,16 @@ def task_example() -> Annotated[str, {node}]:
641641
assert session.exit_code == ExitCode.OK
642642
assert tmp_path.joinpath("file.txt").exists()
643643
assert session.tasks[0].produces["return"].name == tmp_path.name + "/file.txt"
644+
645+
646+
def test_error_when_return_annotation_cannot_be_parsed(runner, tmp_path):
647+
source = """
648+
from typing_extensions import Annotated
649+
650+
def task_example() -> Annotated[int, 1]: ...
651+
"""
652+
tmp_path.joinpath("task_example.py").write_text(textwrap.dedent(source))
653+
654+
result = runner.invoke(cli, [tmp_path.as_posix()])
655+
assert result.exit_code == ExitCode.COLLECTION_FAILED
656+
assert "The return annotation of the task" in result.output

0 commit comments

Comments
 (0)