From 78e6ee1a8aed70b0a847f2169204900b454bd24b Mon Sep 17 00:00:00 2001 From: Edwin Jose Date: Thu, 24 Oct 2024 13:52:52 -0400 Subject: [PATCH] fix: Solves Issues with Set Function in Component Class and Enhance Input Handling (#4258) * Enhance Component Input Handling and Add Unit Tests Enhance component input handling and add unit tests for mixed input scenarios. * [autofix.ci] apply automated fixes * fix: handle JSON serialization for lists and dicts in _process_connection_or_parameters - Updated the _process_connection_or_parameters function to handle lists and dictionaries properly. - Ensured that each element in a list is checked for serializability and converted to a string if necessary. - Added logic to convert dictionaries to JSON strings, handling non-serializable contents by converting them to strings. - This change prevents JSON serialization errors when processing component parameters. * reverting the changes * [autofix.ci] apply automated fixes * Update component.py updates _process_connection_or_parameters to handles situations where the list is not all component. Also handles any serialisation isseus caused by _process_connection_or_parameters * [autofix.ci] apply automated fixes * Update component.py update make sure it is not a list str | int | float | bool | type(None) Serialisation removed --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- .../langflow/base/tools/component_tool.py | 2 + .../custom/custom_component/component.py | 3 +- .../test_componet_set_functionality.py | 49 +++++++++++++++++++ 3 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 src/backend/tests/unit/custom/component/test_componet_set_functionality.py diff --git a/src/backend/base/langflow/base/tools/component_tool.py b/src/backend/base/langflow/base/tools/component_tool.py index 0cc08b54d..fcbb0444e 100644 --- a/src/backend/base/langflow/base/tools/component_tool.py +++ b/src/backend/base/langflow/base/tools/component_tool.py @@ -47,6 +47,8 @@ def build_description(component: Component, output: Output) -> str: def _build_output_function(component: Component, output_method: Callable): def output_function(*args, **kwargs): + # set the component with the arguments + # set functionality was updatedto handle list of components and other values separately component.set(*args, **kwargs) return output_method() diff --git a/src/backend/base/langflow/custom/custom_component/component.py b/src/backend/base/langflow/custom/custom_component/component.py index feed7ee6b..b2343c6c4 100644 --- a/src/backend/base/langflow/custom/custom_component/component.py +++ b/src/backend/base/langflow/custom/custom_component/component.py @@ -442,7 +442,8 @@ class Component(CustomComponent): def _process_connection_or_parameters(self, key, value) -> None: # if value is a list of components, we need to process each component - if isinstance(value, list): + # Note this update make sure it is not a list str | int | float | bool | type(None) + if isinstance(value, list) and not any(isinstance(val, str | int | float | bool | type(None)) for val in value): for val in value: self._process_connection_or_parameter(key, val) else: diff --git a/src/backend/tests/unit/custom/component/test_componet_set_functionality.py b/src/backend/tests/unit/custom/component/test_componet_set_functionality.py new file mode 100644 index 000000000..d6591f40f --- /dev/null +++ b/src/backend/tests/unit/custom/component/test_componet_set_functionality.py @@ -0,0 +1,49 @@ +import pytest +from langflow.custom import Component +from langflow.inputs.inputs import MessageTextInput, StrInput + + +@pytest.fixture +def setup_component(): + # Create a sample component for testing + component = Component() + # Define inputs for the component + component.inputs = [ + MessageTextInput(name="list_message_input", is_list=True), # Input for a mock component + StrInput(name="mixed_input"), # Input for a mixed list + ] + return component + + +def test_set_with_mixed_list_input(setup_component): + component = setup_component + # Create a mock component to include in the list + mock_component = Component() + message_input_1 = "message data1" + message_input_2 = "message data2" + data = {"mixed_input": [message_input_1, message_input_2], "list_message_input": [message_input_1, mock_component]} + component.set(**data) + + # Assert that the mixed input was set correctly + assert hasattr(component, "mixed_input") + assert len(component.mixed_input) == 2 + assert component.mixed_input[0] == message_input_1 + assert component.mixed_input[1] == message_input_2 + assert component.list_message_input[0] == message_input_1 + assert component.list_message_input[1] == mock_component + + +def test_set_with_message_text_input_list(setup_component): + component = setup_component + # Create a list of MessageTextInput instances + message_input_1 = "message data1" + message_input_2 = "message data2" + data = {"mixed_input": [message_input_1, message_input_2], "list_message_input": [message_input_1, message_input_2]} + # Set a list containing MessageTextInput instances + component.set(**data) + + # Assert that the mixed input was set correctly + assert hasattr(component, "mixed_input") + assert len(component.list_message_input) == 2 + assert component.list_message_input[0] == message_input_1 + assert component.list_message_input[1] == message_input_2