from typing import Any from dify_graph.variables import SegmentType from .enums import Operation def is_operation_supported(*, variable_type: SegmentType, operation: Operation): match operation: case Operation.OVER_WRITE | Operation.CLEAR: return True case Operation.SET: return variable_type in { SegmentType.OBJECT, SegmentType.STRING, SegmentType.NUMBER, SegmentType.INTEGER, SegmentType.FLOAT, SegmentType.BOOLEAN, } case Operation.ADD | Operation.SUBTRACT | Operation.MULTIPLY | Operation.DIVIDE: # Only number variable can be added, subtracted, multiplied or divided return variable_type in {SegmentType.NUMBER, SegmentType.INTEGER, SegmentType.FLOAT} case Operation.APPEND | Operation.EXTEND | Operation.REMOVE_FIRST | Operation.REMOVE_LAST: # Only array variable can be appended or extended # Only array variable can have elements removed return variable_type.is_array_type() def is_variable_input_supported(*, operation: Operation): if operation in {Operation.SET, Operation.ADD, Operation.SUBTRACT, Operation.MULTIPLY, Operation.DIVIDE}: return False return True def is_constant_input_supported(*, variable_type: SegmentType, operation: Operation): match variable_type: case SegmentType.STRING | SegmentType.OBJECT | SegmentType.BOOLEAN: return operation in {Operation.OVER_WRITE, Operation.SET} case SegmentType.NUMBER | SegmentType.INTEGER | SegmentType.FLOAT: return operation in { Operation.OVER_WRITE, Operation.SET, Operation.ADD, Operation.SUBTRACT, Operation.MULTIPLY, Operation.DIVIDE, } case _: return False def is_input_value_valid(*, variable_type: SegmentType, operation: Operation, value: Any): if operation in {Operation.CLEAR, Operation.REMOVE_FIRST, Operation.REMOVE_LAST}: return True match variable_type: case SegmentType.STRING: return isinstance(value, str) case SegmentType.BOOLEAN: return isinstance(value, bool) case SegmentType.NUMBER | SegmentType.INTEGER | SegmentType.FLOAT: if not isinstance(value, int | float): return False if operation == Operation.DIVIDE and value == 0: return False return True case SegmentType.OBJECT: return isinstance(value, dict) # Array & Append case SegmentType.ARRAY_ANY if operation == Operation.APPEND: return isinstance(value, str | float | int | dict) case SegmentType.ARRAY_STRING if operation == Operation.APPEND: return isinstance(value, str) case SegmentType.ARRAY_NUMBER if operation == Operation.APPEND: return isinstance(value, int | float) case SegmentType.ARRAY_OBJECT if operation == Operation.APPEND: return isinstance(value, dict) case SegmentType.ARRAY_BOOLEAN if operation == Operation.APPEND: return isinstance(value, bool) # Array & Extend / Overwrite case SegmentType.ARRAY_ANY if operation in {Operation.EXTEND, Operation.OVER_WRITE}: return isinstance(value, list) and all(isinstance(item, str | float | int | dict) for item in value) case SegmentType.ARRAY_STRING if operation in {Operation.EXTEND, Operation.OVER_WRITE}: return isinstance(value, list) and all(isinstance(item, str) for item in value) case SegmentType.ARRAY_NUMBER if operation in {Operation.EXTEND, Operation.OVER_WRITE}: return isinstance(value, list) and all(isinstance(item, int | float) for item in value) case SegmentType.ARRAY_OBJECT if operation in {Operation.EXTEND, Operation.OVER_WRITE}: return isinstance(value, list) and all(isinstance(item, dict) for item in value) case SegmentType.ARRAY_BOOLEAN if operation in {Operation.EXTEND, Operation.OVER_WRITE}: return isinstance(value, list) and all(isinstance(item, bool) for item in value) case _: return False