feat: add convert component with dynamic output support (#7773)
* Create convertor.py * [autofix.ci] apply automated fixes * convert component * [autofix.ci] apply automated fixes * add Type_conversion base class with dispatchers for performance based conversion * fix lint issues * add type_convertor test * [autofix.ci] apply automated fixes * update tests * fix tests * update with auto conversion methods * update function to component file * feat: enhance input validation for Data, DataFrame, and Message types * test: add unit tests for DataInput, MessageInput, and DataFrameInput data conversion * updated changes to use type classes * [autofix.ci] apply automated fixes * add convert logic * update converts * Update converter.py * [autofix.ci] apply automated fixes * revert converter.py * Update inputs.py * Update test_inputs.py * update to logic * Update test_type_convertor_component.py * update converter * [autofix.ci] apply automated fixes * refactor: rename conversion functions for clarity Updated function names for converting inputs to Message, Data, and DataFrame types to improve readability and consistency. The changes include renaming `get_message_converter` to `convert_to_message`, `get_data_converter` to `convert_to_data`, and `get_dataframe_converter` to `convert_to_dataframe`. Additionally, added a check for dictionary input in the data conversion function. * fix: add TYPE_CHECKING for conditional imports in message.py Introduced TYPE_CHECKING to optimize imports for the DataFrame type, ensuring that the import only occurs during type checking. This change enhances performance and maintains compatibility with static type checkers. * refactor: simplify data conversion methods in Message class Removed unnecessary parameters from the `to_data` and `to_dataframe` methods in the Message class, enhancing clarity and reducing complexity. The methods now directly use instance attributes, improving code readability and maintainability. * refactor: enhance DataFrame methods for clarity and type safety Updated the `to_data` and `to_message` methods in the DataFrame class to improve clarity and type safety. The `to_data` method now directly converts the DataFrame to a Data object without parameters, and the `to_message` method uses the instance's data directly. Added TYPE_CHECKING for conditional imports to optimize performance and maintain compatibility with static type checkers. * refactor: streamline Data class methods for improved clarity Refactored the `to_message` and `to_dataframe` methods in the Data class to eliminate unnecessary parameters and directly utilize instance attributes. This change enhances code readability and maintainability while ensuring type safety with the appropriate imports for Message and DataFrame. Additionally, updated the logic to access instance data more intuitively. * refactor: simplify conversion method calls by removing redundant arguments * rename test file * refactor: remove obsolete test file for data conversion * refactor: add support for converting dictionary to DataFrame --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org> Co-authored-by: Carlos Coelho <80289056+carlosrcoelho@users.noreply.github.com> Co-authored-by: Yuqi Tang <yuqi.tang@datastax.com>
This commit is contained in:
parent
d50c90522e
commit
360836800d
7 changed files with 293 additions and 6 deletions
|
|
@ -0,0 +1,115 @@
|
|||
import pandas as pd
|
||||
import pytest
|
||||
from langflow.components.processing.converter import TypeConverterComponent
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.dataframe import DataFrame
|
||||
from langflow.schema.message import Message
|
||||
|
||||
from tests.base import ComponentTestBaseWithoutClient
|
||||
|
||||
|
||||
class TestTypeConverterComponent(ComponentTestBaseWithoutClient):
|
||||
@pytest.fixture
|
||||
def component_class(self):
|
||||
"""Return the component class to test."""
|
||||
return TypeConverterComponent
|
||||
|
||||
@pytest.fixture
|
||||
def file_names_mapping(self):
|
||||
"""Return an empty list since this component doesn't have version-specific files."""
|
||||
return []
|
||||
|
||||
# Message to other types
|
||||
def test_message_to_message(self, component_class):
|
||||
"""Test converting Message to Message."""
|
||||
component = component_class(input_data=Message(text="Hello World"), output_type="Message")
|
||||
result = component.convert_to_message()
|
||||
assert isinstance(result, Message)
|
||||
assert result.text == "Hello World"
|
||||
|
||||
def test_message_to_data(self, component_class):
|
||||
"""Test converting Message to Data."""
|
||||
component = component_class(input_data=Message(text="Hello"), output_type="Data")
|
||||
result = component.convert_to_data()
|
||||
assert isinstance(result, Data)
|
||||
assert "text" in result.data
|
||||
assert result.data["text"] == "Hello"
|
||||
|
||||
def test_message_to_dataframe(self, component_class):
|
||||
"""Test converting Message to DataFrame."""
|
||||
component = component_class(input_data=Message(text="Hello"), output_type="DataFrame")
|
||||
result = component.convert_to_dataframe()
|
||||
assert isinstance(result, DataFrame)
|
||||
assert "text" in result.columns
|
||||
assert result.iloc[0]["text"] == "Hello"
|
||||
|
||||
# Data to other types
|
||||
def test_data_to_message(self, component_class):
|
||||
"""Test converting Data to Message."""
|
||||
component = component_class(input_data=Data(data={"text": "Hello World"}), output_type="Message")
|
||||
result = component.convert_to_message()
|
||||
assert isinstance(result, Message)
|
||||
assert result.text == "Hello World"
|
||||
|
||||
def test_data_to_data(self, component_class):
|
||||
"""Test converting Data to Data."""
|
||||
component = component_class(input_data=Data(data={"key": "value"}), output_type="Data")
|
||||
result = component.convert_to_data()
|
||||
assert isinstance(result, Data)
|
||||
assert result.data == {"key": "value"}
|
||||
|
||||
def test_data_to_dataframe(self, component_class):
|
||||
"""Test converting Data to DataFrame."""
|
||||
component = component_class(input_data=Data(data={"text": "Hello World"}), output_type="DataFrame")
|
||||
result = component.convert_to_dataframe()
|
||||
assert isinstance(result, DataFrame)
|
||||
assert "text" in result.columns
|
||||
assert result.iloc[0]["text"] == "Hello World"
|
||||
|
||||
# DataFrame to other types
|
||||
def test_dataframe_to_message(self, component_class):
|
||||
"""Test converting DataFrame to Message."""
|
||||
df_data = pd.DataFrame({"col1": ["Hello"], "col2": ["World"]})
|
||||
component = component_class(input_data=DataFrame(data=df_data), output_type="Message")
|
||||
result = component.convert_to_message()
|
||||
assert isinstance(result, Message)
|
||||
assert result.text == "| col1 | col2 |\n|:-------|:-------|\n| Hello | World |"
|
||||
|
||||
def test_dataframe_to_data(self, component_class):
|
||||
"""Test converting DataFrame to Data."""
|
||||
df_data = pd.DataFrame({"col1": ["Hello"]})
|
||||
component = component_class(input_data=DataFrame(data=df_data), output_type="Data")
|
||||
result = component.convert_to_data()
|
||||
assert isinstance(result, Data)
|
||||
assert isinstance(result.data, dict)
|
||||
|
||||
def test_dataframe_to_dataframe(self, component_class):
|
||||
"""Test converting DataFrame to DataFrame."""
|
||||
df_data = pd.DataFrame({"col1": ["Hello"], "col2": ["World"]})
|
||||
component = component_class(input_data=DataFrame(data=df_data), output_type="DataFrame")
|
||||
result = component.convert_to_dataframe()
|
||||
assert isinstance(result, DataFrame)
|
||||
assert "col1" in result.columns
|
||||
assert "col2" in result.columns
|
||||
assert result.iloc[0]["col1"] == "Hello"
|
||||
assert result.iloc[0]["col2"] == "World"
|
||||
|
||||
def test_update_outputs(self, component_class):
|
||||
"""Test the update_outputs method."""
|
||||
component = component_class(input_data=Message(text="Hello"), output_type="Message")
|
||||
frontend_node = {"outputs": []}
|
||||
|
||||
# Test with Message output
|
||||
updated = component.update_outputs(frontend_node, "output_type", "Message")
|
||||
assert len(updated["outputs"]) == 1
|
||||
assert updated["outputs"][0]["name"] == "message_output"
|
||||
|
||||
# Test with Data output
|
||||
updated = component.update_outputs(frontend_node, "output_type", "Data")
|
||||
assert len(updated["outputs"]) == 1
|
||||
assert updated["outputs"][0]["name"] == "data_output"
|
||||
|
||||
# Test with DataFrame output
|
||||
updated = component.update_outputs(frontend_node, "output_type", "DataFrame")
|
||||
assert len(updated["outputs"]) == 1
|
||||
assert updated["outputs"][0]["name"] == "dataframe_output"
|
||||
Loading…
Add table
Add a link
Reference in a new issue