|
17 | 17 | from .transformations import PipelineElement |
18 | 18 |
|
19 | 19 |
|
| 20 | +def _require_annotated_dataframe_return(func, *, decorator_name: str) -> None: |
| 21 | + """ |
| 22 | + Ensure a decorated function is annotated as returning an :class:`AnnotatedDataFrame`. |
| 23 | +
|
| 24 | + The annotation is accepted both as the class itself and as the string ``'AnnotatedDataFrame'``, |
| 25 | + since a module using ``from __future__ import annotations`` (PEP 563) only ever hands over |
| 26 | + strings - the transformer is perfectly valid in that case. |
| 27 | +
|
| 28 | + :param func: the function being decorated |
| 29 | + :param decorator_name: name of the calling decorator, for the error message |
| 30 | + :raise RuntimeError: if the function is not annotated as returning an ``AnnotatedDataFrame`` |
| 31 | + """ |
| 32 | + return_type = inspect.signature(func).return_annotation |
| 33 | + if return_type not in (AnnotatedDataFrame, "AnnotatedDataFrame"): |
| 34 | + raise RuntimeError( |
| 35 | + f"{decorator_name}: decorator requires 'AnnotatedDataFrame' to be returned by" |
| 36 | + f" function - but was '{return_type}'" |
| 37 | + ) |
| 38 | + |
| 39 | + |
20 | 40 | def _get_dataframe(*args, **kwargs) -> AnnotatedDataFrame: |
21 | 41 | """ |
22 | 42 | Extract the dataframe from positional or keyword arguments |
@@ -169,11 +189,7 @@ def output(requirements: dict[str, Any], exclusive: bool = False): |
169 | 189 | ) |
170 | 190 |
|
171 | 191 | def decorator(func): |
172 | | - return_type = inspect.signature(func).return_annotation |
173 | | - if return_type != AnnotatedDataFrame and return_type != 'AnnotatedDataFrame': |
174 | | - raise RuntimeError( |
175 | | - f"output: decorator requires 'AnnotatedDataFrame' to be returned by function - but was '{return_type}'" |
176 | | - ) |
| 192 | + _require_annotated_dataframe_return(func, decorator_name="output") |
177 | 193 |
|
178 | 194 | setattr(func, DECORATED_OUTPUT_SPECS, required_output_specs) |
179 | 195 | setattr(func, DECORATED_OUTPUT_EXCLUSIVE, exclusive) |
@@ -262,11 +278,7 @@ def artifacts(requirements: dict[str, Any]): |
262 | 278 | required_artifact_specs = ArtifactSpecification(requirements=requirements) |
263 | 279 |
|
264 | 280 | def decorator(func): |
265 | | - return_type = inspect.signature(func).return_annotation |
266 | | - if return_type != AnnotatedDataFrame: |
267 | | - raise RuntimeError( |
268 | | - "artifacts: decorator requires 'AnnotatedDataFrame' to be returned by function" |
269 | | - ) |
| 281 | + _require_annotated_dataframe_return(func, decorator_name="artifacts") |
270 | 282 |
|
271 | 283 | setattr(func, DECORATED_ARTIFACT_SPECS, required_artifact_specs) |
272 | 284 |
|
|
0 commit comments