mirror of
https://github.com/langgenius/dify.git
synced 2026-04-29 04:26:30 +08:00
fix: fix numeric type conversion issue in if-else condition comparison (#28155)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
c5b6219006
commit
06466cb73a
@ -265,6 +265,45 @@ def _assert_not_empty(*, value: object) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _normalize_numeric_values(value: int | float, expected: object) -> tuple[int | float, int | float]:
|
||||||
|
"""
|
||||||
|
Normalize value and expected to compatible numeric types for comparison.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
value: The actual numeric value (int or float)
|
||||||
|
expected: The expected value (int, float, or str)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
A tuple of (normalized_value, normalized_expected) with compatible types
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ValueError: If expected cannot be converted to a number
|
||||||
|
"""
|
||||||
|
if not isinstance(expected, (int, float, str)):
|
||||||
|
raise ValueError(f"Cannot convert {type(expected)} to number")
|
||||||
|
|
||||||
|
# Convert expected to appropriate numeric type
|
||||||
|
if isinstance(expected, str):
|
||||||
|
# Try to convert to float first to handle decimal strings
|
||||||
|
try:
|
||||||
|
expected_float = float(expected)
|
||||||
|
except ValueError as e:
|
||||||
|
raise ValueError(f"Cannot convert '{expected}' to number") from e
|
||||||
|
|
||||||
|
# If value is int and expected is a whole number, keep as int comparison
|
||||||
|
if isinstance(value, int) and expected_float.is_integer():
|
||||||
|
return value, int(expected_float)
|
||||||
|
else:
|
||||||
|
# Otherwise convert value to float for comparison
|
||||||
|
return float(value) if isinstance(value, int) else value, expected_float
|
||||||
|
elif isinstance(expected, float):
|
||||||
|
# If expected is already float, convert int value to float
|
||||||
|
return float(value) if isinstance(value, int) else value, expected
|
||||||
|
else:
|
||||||
|
# expected is int
|
||||||
|
return value, expected
|
||||||
|
|
||||||
|
|
||||||
def _assert_equal(*, value: object, expected: object) -> bool:
|
def _assert_equal(*, value: object, expected: object) -> bool:
|
||||||
if value is None:
|
if value is None:
|
||||||
return False
|
return False
|
||||||
@ -324,18 +363,8 @@ def _assert_greater_than(*, value: object, expected: object) -> bool:
|
|||||||
if not isinstance(value, (int, float)):
|
if not isinstance(value, (int, float)):
|
||||||
raise ValueError("Invalid actual value type: number")
|
raise ValueError("Invalid actual value type: number")
|
||||||
|
|
||||||
if isinstance(value, int):
|
value, expected = _normalize_numeric_values(value, expected)
|
||||||
if not isinstance(expected, (int, float, str)):
|
return value > expected
|
||||||
raise ValueError(f"Cannot convert {type(expected)} to int")
|
|
||||||
expected = int(expected)
|
|
||||||
else:
|
|
||||||
if not isinstance(expected, (int, float, str)):
|
|
||||||
raise ValueError(f"Cannot convert {type(expected)} to float")
|
|
||||||
expected = float(expected)
|
|
||||||
|
|
||||||
if value <= expected:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def _assert_less_than(*, value: object, expected: object) -> bool:
|
def _assert_less_than(*, value: object, expected: object) -> bool:
|
||||||
@ -345,18 +374,8 @@ def _assert_less_than(*, value: object, expected: object) -> bool:
|
|||||||
if not isinstance(value, (int, float)):
|
if not isinstance(value, (int, float)):
|
||||||
raise ValueError("Invalid actual value type: number")
|
raise ValueError("Invalid actual value type: number")
|
||||||
|
|
||||||
if isinstance(value, int):
|
value, expected = _normalize_numeric_values(value, expected)
|
||||||
if not isinstance(expected, (int, float, str)):
|
return value < expected
|
||||||
raise ValueError(f"Cannot convert {type(expected)} to int")
|
|
||||||
expected = int(expected)
|
|
||||||
else:
|
|
||||||
if not isinstance(expected, (int, float, str)):
|
|
||||||
raise ValueError(f"Cannot convert {type(expected)} to float")
|
|
||||||
expected = float(expected)
|
|
||||||
|
|
||||||
if value >= expected:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def _assert_greater_than_or_equal(*, value: object, expected: object) -> bool:
|
def _assert_greater_than_or_equal(*, value: object, expected: object) -> bool:
|
||||||
@ -366,18 +385,8 @@ def _assert_greater_than_or_equal(*, value: object, expected: object) -> bool:
|
|||||||
if not isinstance(value, (int, float)):
|
if not isinstance(value, (int, float)):
|
||||||
raise ValueError("Invalid actual value type: number")
|
raise ValueError("Invalid actual value type: number")
|
||||||
|
|
||||||
if isinstance(value, int):
|
value, expected = _normalize_numeric_values(value, expected)
|
||||||
if not isinstance(expected, (int, float, str)):
|
return value >= expected
|
||||||
raise ValueError(f"Cannot convert {type(expected)} to int")
|
|
||||||
expected = int(expected)
|
|
||||||
else:
|
|
||||||
if not isinstance(expected, (int, float, str)):
|
|
||||||
raise ValueError(f"Cannot convert {type(expected)} to float")
|
|
||||||
expected = float(expected)
|
|
||||||
|
|
||||||
if value < expected:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def _assert_less_than_or_equal(*, value: object, expected: object) -> bool:
|
def _assert_less_than_or_equal(*, value: object, expected: object) -> bool:
|
||||||
@ -387,18 +396,8 @@ def _assert_less_than_or_equal(*, value: object, expected: object) -> bool:
|
|||||||
if not isinstance(value, (int, float)):
|
if not isinstance(value, (int, float)):
|
||||||
raise ValueError("Invalid actual value type: number")
|
raise ValueError("Invalid actual value type: number")
|
||||||
|
|
||||||
if isinstance(value, int):
|
value, expected = _normalize_numeric_values(value, expected)
|
||||||
if not isinstance(expected, (int, float, str)):
|
return value <= expected
|
||||||
raise ValueError(f"Cannot convert {type(expected)} to int")
|
|
||||||
expected = int(expected)
|
|
||||||
else:
|
|
||||||
if not isinstance(expected, (int, float, str)):
|
|
||||||
raise ValueError(f"Cannot convert {type(expected)} to float")
|
|
||||||
expected = float(expected)
|
|
||||||
|
|
||||||
if value > expected:
|
|
||||||
return False
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def _assert_null(*, value: object) -> bool:
|
def _assert_null(*, value: object) -> bool:
|
||||||
|
|||||||
52
api/tests/unit_tests/core/workflow/utils/test_condition.py
Normal file
52
api/tests/unit_tests/core/workflow/utils/test_condition.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
from core.workflow.runtime import VariablePool
|
||||||
|
from core.workflow.utils.condition.entities import Condition
|
||||||
|
from core.workflow.utils.condition.processor import ConditionProcessor
|
||||||
|
|
||||||
|
|
||||||
|
def test_number_formatting():
|
||||||
|
condition_processor = ConditionProcessor()
|
||||||
|
variable_pool = VariablePool()
|
||||||
|
variable_pool.add(["test_node_id", "zone"], 0)
|
||||||
|
variable_pool.add(["test_node_id", "one"], 1)
|
||||||
|
variable_pool.add(["test_node_id", "one_one"], 1.1)
|
||||||
|
# 0 <= 0.95
|
||||||
|
assert (
|
||||||
|
condition_processor.process_conditions(
|
||||||
|
variable_pool=variable_pool,
|
||||||
|
conditions=[Condition(variable_selector=["test_node_id", "zone"], comparison_operator="≤", value="0.95")],
|
||||||
|
operator="or",
|
||||||
|
).final_result
|
||||||
|
== True
|
||||||
|
)
|
||||||
|
|
||||||
|
# 1 >= 0.95
|
||||||
|
assert (
|
||||||
|
condition_processor.process_conditions(
|
||||||
|
variable_pool=variable_pool,
|
||||||
|
conditions=[Condition(variable_selector=["test_node_id", "one"], comparison_operator="≥", value="0.95")],
|
||||||
|
operator="or",
|
||||||
|
).final_result
|
||||||
|
== True
|
||||||
|
)
|
||||||
|
|
||||||
|
# 1.1 >= 0.95
|
||||||
|
assert (
|
||||||
|
condition_processor.process_conditions(
|
||||||
|
variable_pool=variable_pool,
|
||||||
|
conditions=[
|
||||||
|
Condition(variable_selector=["test_node_id", "one_one"], comparison_operator="≥", value="0.95")
|
||||||
|
],
|
||||||
|
operator="or",
|
||||||
|
).final_result
|
||||||
|
== True
|
||||||
|
)
|
||||||
|
|
||||||
|
# 1.1 > 0
|
||||||
|
assert (
|
||||||
|
condition_processor.process_conditions(
|
||||||
|
variable_pool=variable_pool,
|
||||||
|
conditions=[Condition(variable_selector=["test_node_id", "one_one"], comparison_operator=">", value="0")],
|
||||||
|
operator="or",
|
||||||
|
).final_result
|
||||||
|
== True
|
||||||
|
)
|
||||||
Loading…
Reference in New Issue
Block a user