feat: Enhance Data Components and Add SelectData Functionality (#3715)

## Changes Overview

This PR introduces several enhancements to our data handling components and removes some legacy code:

1. **CreateData and UpdateData Components**:
   - Added text key name validation
   - Enhanced UpdateData to support updating and appending multiple data points
   - Implemented optional text key validator for dynamically loaded data
   - Updated component names, descriptions, and default values

2. **New SelectData Component**:
   - Implemented SelectDataComponent for data selection from a list
   - Added inputs for data list and index selection
   - Implemented error handling for out-of-range index selection

3. **Code Cleanup**:
   - Removed legacy post_code_processing methods from CreateDataComponent and UpdateDataComponent
   - Removed corresponding test cases

4. **Testing**:
   - Added unit tests for CreateData and UpdateData components
   - Updated test file names for consistency
This commit is contained in:
Edwin Jose 2024-09-22 14:19:51 -04:00 • committed by GitHub
commit ab2df9ef3d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 401 additions and 49 deletions

View file

@ -0,0 +1,117 @@
import pytest
from langflow.components.prototypes.CreateData import CreateDataComponent
from langflow.schema import Data
@pytest.fixture
def create_data_component():
return CreateDataComponent()
def test_update_build_config(create_data_component):
build_config = {
"number_of_fields": {
"type": "int",
"value": 2,
},
"text_key": {
"type": "str",
"value": "",
},
"text_key_validator": {
"type": "bool",
"value": False,
},
}
updated_config = create_data_component.update_build_config(
build_config=build_config, field_value=3, field_name="number_of_fields"
)
assert "field_1_key" in updated_config
assert "field_2_key" in updated_config
assert "field_3_key" in updated_config
assert updated_config["number_of_fields"]["value"] == 3
def test_update_build_config_exceed_limit(create_data_component):
build_config = {
"number_of_fields": {
"type": "int",
"value": 2,
},
"text_key": {
"type": "str",
"value": "",
},
"text_key_validator": {
"type": "bool",
"value": False,
},
}
with pytest.raises(
ValueError, match="Number of fields cannot exceed 15. Try using a Component to combine two Data."
):
create_data_component.update_build_config(build_config, 16, "number_of_fields")
@pytest.mark.asyncio
async def test_build_data(create_data_component):
create_data_component._attributes = {
"field_1_key": {"key1": "value1"},
"field_2_key": {"key2": "value2"},
}
create_data_component.text_key = "key1"
create_data_component.text_key_validator = False
result = await create_data_component.build_data()
assert isinstance(result, Data)
assert result.data == {"key1": "value1", "key2": "value2"}
assert result.text_key == "key1"
def test_get_data(create_data_component):
create_data_component._attributes = {
"field_1_key": {"key1": "value1"},
"field_2_key": {"key2": "value2"},
}
result = create_data_component.get_data()
assert result == {"key1": "value1", "key2": "value2"}
def test_validate_text_key_valid(create_data_component):
# Arrange
create_data_component._attributes = {
"field_1_key": {"key1": "value1"},
"field_2_key": {"key2": "value2"},
}
create_data_component.text_key = "key1"
# Act & Assert
try:
create_data_component.validate_text_key()
except ValueError:
pytest.fail("validate_text_key() raised ValueError unexpectedly!")
# Additional assertions
assert create_data_component.text_key == "key1"
assert "key1" in create_data_component.get_data()
def test_validate_text_key_invalid(create_data_component):
# Arrange
create_data_component._attributes = {
"field_1_key": {"key1": "value1"},
"field_2_key": {"key2": "value2"},
}
create_data_component.text_key = "invalid_key"
# Act & Assert
with pytest.raises(ValueError) as exc_info:
create_data_component.validate_text_key()
# Check for the exact error message
expected_error_message = f"Text Key: '{create_data_component.text_key}' not found in the Data keys: '{', '.join(create_data_component.get_data().keys())}'"
assert str(exc_info.value) == expected_error_message

View file

@ -0,0 +1,105 @@
import pytest
from langflow.components.prototypes.UpdateData import UpdateDataComponent
from langflow.schema import Data
@pytest.fixture
def update_data_component():
return UpdateDataComponent()
def test_update_build_config(update_data_component):
build_config = {
"number_of_fields": {
"type": "int",
"value": 2,
},
"text_key": {
"type": "str",
"value": "",
},
"text_key_validator": {
"type": "bool",
"value": False,
},
}
updated_config = update_data_component.update_build_config(
build_config=build_config, field_value=3, field_name="number_of_fields"
)
assert "field_1_key" in updated_config
assert "field_2_key" in updated_config
assert "field_3_key" in updated_config
assert updated_config["number_of_fields"]["value"] == 3
def test_update_build_config_exceed_limit(update_data_component):
build_config = {
"number_of_fields": {
"type": "int",
"value": 2,
},
"text_key": {
"type": "str",
"value": "",
},
"text_key_validator": {
"type": "bool",
"value": False,
},
}
with pytest.raises(
ValueError, match="Number of fields cannot exceed 15. Try using a Component to combine two Data."
):
update_data_component.update_build_config(build_config, 16, "number_of_fields")
@pytest.mark.asyncio
async def test_build_data(update_data_component):
update_data_component._attributes = {
"field_1_key": {"key1": "new_value1"},
"field_2_key": {"key3": "value3"},
}
update_data_component.text_key = "key1"
update_data_component.text_key_validator = False
update_data_component.old_data = Data(data={"key1": "old_value1", "key2": "value2"}, text_key="key2")
result = await update_data_component.build_data()
assert isinstance(result, Data)
assert result.data == {"key1": "new_value1", "key2": "value2", "key3": "value3"}
assert result.text_key == "key1"
def test_get_data(update_data_component):
update_data_component._attributes = {
"field_1_key": {"key1": "value1"},
"field_2_key": {"key2": "value2"},
}
result = update_data_component.get_data()
assert result == {"key1": "value1", "key2": "value2"}
def test_validate_text_key_valid(update_data_component):
data = Data(data={"key1": "value1", "key2": "value2"}, text_key="key1")
update_data_component.text_key = "key1"
try:
update_data_component.validate_text_key(data)
except ValueError:
pytest.fail("validate_text_key() raised ValueError unexpectedly!")
def test_validate_text_key_invalid(update_data_component):
data = Data(data={"key1": "value1", "key2": "value2"}, text_key="key1")
update_data_component.text_key = "invalid_key"
with pytest.raises(ValueError) as exc_info:
update_data_component.validate_text_key(data)
expected_error_message = (
f"Text Key: {update_data_component.text_key} not found in the Data keys: {','.join(data.data.keys())}"
)
assert str(exc_info.value) == expected_error_message