mirror of https://github.com/langgenius/dify.git
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
|
||||
|
||||
|
||||
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:
|
||||
if value is None:
|
||||
return False
|
||||
|
|
@ -324,18 +363,8 @@ def _assert_greater_than(*, value: object, expected: object) -> bool:
|
|||
if not isinstance(value, (int, float)):
|
||||
raise ValueError("Invalid actual value type: number")
|
||||
|
||||
if isinstance(value, int):
|
||||
if not isinstance(expected, (int, float, str)):
|
||||
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
|
||||
value, expected = _normalize_numeric_values(value, expected)
|
||||
return value > expected
|
||||
|
||||
|
||||
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)):
|
||||
raise ValueError("Invalid actual value type: number")
|
||||
|
||||
if isinstance(value, int):
|
||||
if not isinstance(expected, (int, float, str)):
|
||||
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
|
||||
value, expected = _normalize_numeric_values(value, expected)
|
||||
return value < expected
|
||||
|
||||
|
||||
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)):
|
||||
raise ValueError("Invalid actual value type: number")
|
||||
|
||||
if isinstance(value, int):
|
||||
if not isinstance(expected, (int, float, str)):
|
||||
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
|
||||
value, expected = _normalize_numeric_values(value, expected)
|
||||
return value >= expected
|
||||
|
||||
|
||||
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)):
|
||||
raise ValueError("Invalid actual value type: number")
|
||||
|
||||
if isinstance(value, int):
|
||||
if not isinstance(expected, (int, float, str)):
|
||||
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
|
||||
value, expected = _normalize_numeric_values(value, expected)
|
||||
return value <= expected
|
||||
|
||||
|
||||
def _assert_null(*, value: object) -> bool:
|
||||
|
|
|
|||
|
|
@ -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