Skip to content

Commit 8cb375a

Browse files
authored
Error on Parameter default kwarg usage for inputs (#1197)
**Pull Request Checklist** - [x] Fixes #812 - [x] Tests added - [x] Documentation/examples added - [x] [Good commit messages](https://cbea.ms/git-commit/) and/or PR title **Description of PR** Currently, using the `default` kwarg for a `Parameter` in an input Annotation or Hera's Pydantic `Input` class logs a warning message, added in #1102. This PR makes the code path raise an error, which can be supressed using the `suppress_parameter_default_error` experimental feature flag for 1 minor version until it is removed. --------- Signed-off-by: Elliot Gunton <elliotgunton@gmail.com>
1 parent 3e58f22 commit 8cb375a

10 files changed

Lines changed: 40 additions & 20 deletions

File tree

docs/examples/workflows/experimental/new_dag_decorator_params.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545

4646

4747
class ConcatInput(Input):
48-
word_a: Annotated[str, Parameter(name="word_a", default="")]
48+
word_a: Annotated[str, Parameter(name="word_a")] = ""
4949
word_b: str
5050
concat_config: ConcatConfig = ConcatConfig(reverse=False)
5151

docs/examples/workflows/experimental/new_steps_decorator_with_parallel_steps.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030

3131

3232
class ConcatInput(Input):
33-
word_a: Annotated[str, Parameter(name="word_a", default="")]
33+
word_a: Annotated[str, Parameter(name="word_a")] = ""
3434
word_b: str
3535

3636

docs/user-guides/script-annotations.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ def echo_all(
4545
```
4646

4747
The fields allowed in the `Parameter` annotations are: `name`, `enum`, and `description`, `name` will be set to the
48-
variable name if not provided (when exporting to YAML or viewing in the Argo UI, the `name` variable will be used).
48+
variable name if not provided (when exporting to YAML or viewing in the Argo UI, the `name` variable will be used). A
49+
`default` must be set using standard Python syntax, i.e. `x: int = 42`.
4950

5051
## Artifacts
5152

examples/workflows/experimental/new_dag_decorator_params.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class ConcatConfig(BaseModel):
3535

3636

3737
class ConcatInput(Input):
38-
word_a: Annotated[str, Parameter(name="word_a", default="")]
38+
word_a: Annotated[str, Parameter(name="word_a")] = ""
3939
word_b: str
4040
concat_config: ConcatConfig = ConcatConfig(reverse=False)
4141

examples/workflows/experimental/new_steps_decorator_with_parallel_steps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def setup() -> SetupOutput:
2020

2121

2222
class ConcatInput(Input):
23-
word_a: Annotated[str, Parameter(name="word_a", default="")]
23+
word_a: Annotated[str, Parameter(name="word_a")] = ""
2424
word_b: str
2525

2626

src/hera/shared/_global_config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ def _set_defaults(cls, values):
202202
_SCRIPT_ANNOTATIONS_FLAG = "script_annotations"
203203
_SCRIPT_PYDANTIC_IO_FLAG = "script_pydantic_io"
204204
_DECORATOR_SYNTAX_FLAG = "decorator_syntax"
205+
_SUPPRESS_PARAMETER_DEFAULT_ERROR_FLAG = "suppress_parameter_default_error"
205206

206207
# A dictionary where each key is a flag that has a list of flags which supersede it, hence
207208
# the given flag key can also be switched on by any of the flags in the list. Using simple flat lists

src/hera/workflows/io/_io_mixins.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
else:
88
from typing_extensions import Self
99

10-
from pydantic.fields import FieldInfo
1110

12-
from hera.shared._pydantic import _PYDANTIC_VERSION, get_field_annotations, get_fields
11+
from hera.shared import global_config
12+
from hera.shared._global_config import _SUPPRESS_PARAMETER_DEFAULT_ERROR_FLAG
13+
from hera.shared._pydantic import _PYDANTIC_VERSION, FieldInfo, get_field_annotations, get_fields
1314
from hera.shared._type_util import get_workflow_annotation
1415
from hera.shared.serialization import MISSING, serialize
1516
from hera.workflows._context import _context
@@ -87,8 +88,14 @@ def _get_parameters(cls, object_override: Optional[Self] = None) -> List[Paramet
8788
if param.default is not None:
8889
warnings.warn(
8990
"Using the default field for Parameters in Annotations is deprecated since v5.16"
90-
"and will be removed in a future minor version, use a Python default value instead"
91+
"and will be removed in a future minor version, use a Python default value instead. "
9192
)
93+
if not global_config.experimental_features[_SUPPRESS_PARAMETER_DEFAULT_ERROR_FLAG]:
94+
raise ValueError(
95+
"default cannot be set via the Parameter's default, use a Python default value instead. "
96+
"You can suppress this error by setting "
97+
f'global_config.experimental_features["{_SUPPRESS_PARAMETER_DEFAULT_ERROR_FLAG}"] = True'
98+
)
9299
if object_override:
93100
param.default = serialize(getattr(object_override, field))
94101
elif field_info.default is not None and field_info.default != PydanticUndefined: # type: ignore

src/hera/workflows/script.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
from hera.shared._global_config import (
4444
_SCRIPT_ANNOTATIONS_FLAG,
4545
_SCRIPT_PYDANTIC_IO_FLAG,
46+
_SUPPRESS_PARAMETER_DEFAULT_ERROR_FLAG,
4647
_flag_enabled,
4748
)
4849
from hera.shared._pydantic import _PYDANTIC_VERSION, root_validator, validator
@@ -511,15 +512,17 @@ class will be used as inputs, rather than the class itself.
511512
artifacts.append(new_object)
512513
elif isinstance(new_object, Parameter):
513514
if new_object.default is not None:
515+
# TODO: in 5.18 remove the flag check and `warn`, and raise the ValueError directly (minus "flag" text)
514516
warnings.warn(
515517
"Using the default field for Parameters in Annotations is deprecated since v5.16"
516-
"and will be removed in a future minor version, use a Python default value instead"
518+
"and will be removed in a future minor version, use a Python default value instead. "
517519
)
518-
# TODO: raise error if override flag not enabled in 5.17:
519-
# if not global_config.experimental_features["..."]:
520-
# raise ValueError(
521-
# "default cannot be set via the Parameter's default, use a Python default value instead"
522-
# )
520+
if not global_config.experimental_features[_SUPPRESS_PARAMETER_DEFAULT_ERROR_FLAG]:
521+
raise ValueError(
522+
"default cannot be set via the Parameter's default, use a Python default value instead"
523+
"You can suppress this error by setting "
524+
f'global_config.experimental_features["{_SUPPRESS_PARAMETER_DEFAULT_ERROR_FLAG}"] = True'
525+
)
523526
if func_param.default != inspect.Parameter.empty:
524527
# TODO: remove this check in 5.18:
525528
if new_object.default is not None:

tests/test_decorators.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,9 @@ def test_dag_is_runnable():
229229
)
230230

231231

232-
def test_steps_with_parallel_steps_is_runnable():
232+
def test_steps_with_parallel_steps_is_runnable(global_config_fixture):
233233
"""The steps function, even with a parallel context, should be runnable as Python code."""
234+
global_config_fixture.experimental_features["suppress_parameter_default_error"] = True
234235
from tests.workflow_decorators.steps import WorkerInput, WorkerOutput, worker
235236

236237
assert worker(WorkerInput(value_a="hello", value_b="world")) == WorkerOutput(

tests/test_script_annotations.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ def test_double_default_throws_a_value_error(global_config_fixture):
6868
"""Test asserting that it is not possible to define default in the annotation and normal Python."""
6969

7070
# GIVEN
71+
global_config_fixture.experimental_features["suppress_parameter_default_error"] = True
72+
7173
@script()
7274
def echo_int(an_int: Annotated[int, Parameter(default=1)] = 2):
7375
print(an_int)
@@ -83,13 +85,14 @@ def echo_int(an_int: Annotated[int, Parameter(default=1)] = 2):
8385
assert "default cannot be set via both the function parameter default and the Parameter's default" in str(e.value)
8486

8587

86-
@pytest.mark.skip(reason="Code change required in next Hera version")
87-
def test_parameter_default_throws_a_value_error(global_config_fixture):
88-
"""Test asserting that it is not possible to define default in the annotation."""
88+
def test_parameter_default_without_suppression_throws_a_value_error(global_config_fixture):
89+
"""Test asserting that it is not possible to define default in the annotation and normal Python."""
8990

9091
# GIVEN
92+
global_config_fixture.experimental_features["suppress_parameter_default_error"] = False
93+
9194
@script()
92-
def echo_int(an_int: Annotated[int, Parameter(default=1)] = 2):
95+
def echo_int(an_int: Annotated[int, Parameter(default=1)]):
9396
print(an_int)
9497

9598
global_config_fixture.experimental_features["script_annotations"] = True
@@ -100,7 +103,11 @@ def echo_int(an_int: Annotated[int, Parameter(default=1)] = 2):
100103

101104
w.to_dict()
102105

103-
assert "default cannot be set via the Parameter's default, use a Python default value instead" in str(e.value)
106+
assert (
107+
"default cannot be set via the Parameter's default, use a Python default value instead"
108+
"You can suppress this error by setting "
109+
'global_config.experimental_features["suppress_parameter_default_error"] = True'
110+
) in str(e.value)
104111

105112

106113
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)