|
| 1 | +import __future__ |
| 2 | + |
1 | 3 | import json |
2 | 4 | from dataclasses import dataclass |
3 | 5 | from typing import Annotated |
@@ -46,6 +48,35 @@ def execute(self, context: ExecutionContext) -> None: |
46 | 48 | assert TaskMeta.for_task(SimpleTask).executable is True |
47 | 49 |
|
48 | 50 |
|
| 51 | +def _compile_task_with_postponed_return_annotation(return_annotation: str) -> type: |
| 52 | + source = f""" |
| 53 | +class PostponedAnnotationsTask(Task): |
| 54 | + def execute(self, context: ExecutionContext) -> {return_annotation}: |
| 55 | + pass |
| 56 | +""" |
| 57 | + namespace: dict[str, type] = {"Task": Task, "ExecutionContext": ExecutionContext} |
| 58 | + code = compile( |
| 59 | + source, |
| 60 | + filename="<postponed-annotations-test>", |
| 61 | + mode="exec", |
| 62 | + flags=__future__.annotations.compiler_flag, |
| 63 | + dont_inherit=True, |
| 64 | + ) |
| 65 | + exec(code, namespace) # noqa: S102 |
| 66 | + return namespace["PostponedAnnotationsTask"] |
| 67 | + |
| 68 | + |
| 69 | +def test_task_validation_execute_none_return_type_with_postponed_annotations() -> None: |
| 70 | + task_class = _compile_task_with_postponed_return_annotation("None") |
| 71 | + |
| 72 | + assert TaskMeta.for_task(task_class).executable is True |
| 73 | + |
| 74 | + |
| 75 | +def test_task_validation_execute_invalid_return_type_with_postponed_annotations() -> None: |
| 76 | + with pytest.raises(TypeError, match="to not have a return value"): |
| 77 | + _compile_task_with_postponed_return_annotation("int") |
| 78 | + |
| 79 | + |
49 | 80 | def test_task_validation_execute_invalid_signature_no_params() -> None: |
50 | 81 | with pytest.raises(TypeError, match="Expected a function signature of"): |
51 | 82 | # validation happens at class creation time, that's why we create it in a function |
|
0 commit comments