diff --git a/pyproject.toml b/pyproject.toml index a02ecbe..1037366 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,8 +1,8 @@ [tool.poetry] name = "retrack" -version = "2.5.0" +version = "2.5.1" description = "A business rules engine" -authors = ["Gabriel Guarisa ", "Nathalia Trotte "] +authors = ["Gabriel Guarisa "] license = "MIT" readme = "README.md" repository = "https://github.com/pier-digital/retrack" diff --git a/retrack/nodes/base.py b/retrack/nodes/base.py index 0ef84d2..680039f 100644 --- a/retrack/nodes/base.py +++ b/retrack/nodes/base.py @@ -44,6 +44,17 @@ def cast_int_to_str(v: typing.Any, info: pydantic.ValidationInfo) -> str: ] +def cast_empty_string_to_none(v: str, info: pydantic.ValidationInfo) -> typing.Any: + if v == "": + return None + return v + + +OptionalCastedToNoneStringType = typing.Annotated[ + typing.Optional[str], pydantic.BeforeValidator(cast_empty_string_to_none) +] + + class OutputConnectionItemModel(pydantic.BaseModel): node: CastedToStringType input_: str = pydantic.Field(alias="input") diff --git a/retrack/nodes/inputs.py b/retrack/nodes/inputs.py index 72db14f..e0db7ff 100644 --- a/retrack/nodes/inputs.py +++ b/retrack/nodes/inputs.py @@ -7,6 +7,7 @@ InputConnectionModel, NodeKind, OutputConnectionModel, + OptionalCastedToNoneStringType, ) ################################################ @@ -16,7 +17,7 @@ class InputMetadataModel(pydantic.BaseModel): name: str - default: typing.Optional[str] = None + default: OptionalCastedToNoneStringType = None ################################################ diff --git a/retrack/nodes/outputs.py b/retrack/nodes/outputs.py index 9aee712..5bf75dc 100644 --- a/retrack/nodes/outputs.py +++ b/retrack/nodes/outputs.py @@ -3,7 +3,12 @@ import pandas as pd import pydantic -from retrack.nodes.base import BaseNode, InputConnectionModel, NodeKind +from retrack.nodes.base import ( + BaseNode, + InputConnectionModel, + NodeKind, + OptionalCastedToNoneStringType, +) from retrack.utils import constants ################################################ @@ -12,7 +17,7 @@ class OutputMetadataModel(pydantic.BaseModel): - message: typing.Optional[str] = None + message: OptionalCastedToNoneStringType = None ################################################ diff --git a/tests/conftest.py b/tests/conftest.py index 04827ad..c5e3d8e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,7 @@ import pytest -@pytest.fixture +@pytest.fixture(scope="function") def valid_input_dict_before_validation() -> dict: return { "id": 1, diff --git a/tests/test_nodes/test_input.py b/tests/test_nodes/test_input.py index 7a44c38..d1a770c 100644 --- a/tests/test_nodes/test_input.py +++ b/tests/test_nodes/test_input.py @@ -7,3 +7,10 @@ def test_input_node( input_node = Input(**valid_input_dict_before_validation) assert input_node.model_dump(by_alias=True) == valid_input_dict_after_validation + + +def test_input_with_empty_string_as_default(valid_input_dict_before_validation): + valid_input_dict_before_validation["data"]["default"] = "" + input_node = Input(**valid_input_dict_before_validation) + + assert input_node.data.default is None