-
Notifications
You must be signed in to change notification settings - Fork 8.3k
feat: add convert component with dynamic output support #7773
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This pull request introduces the DataTypeConverterComponent to enable conversions between Message, Data, and DataFrame types.
- Added a new component with defined inputs and outputs
- Implemented conversion methods (to_message, to_data, to_dataframe) with error handling
- Integrated dynamic output adjustments based on the selected output type
Comments suppressed due to low confidence (1)
src/backend/base/langflow/components/processing/convertor.py:9
- [nitpick] Consider renaming the file from 'convertor.py' to 'converter.py' for consistency with the class name and common spelling.
class DataTypeConverterComponent(Component):
…ngflow into convert_component
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (4)
src/backend/base/langflow/schema/message.py (1)
282-283: Add missing docstring for theto_datamethod.The method lacks documentation explaining its purpose and return value, as flagged by static analysis.
def to_data(self) -> Data: + """Convert this Message to a Data object. + + Returns: + Data: A Data object containing this message's data. + """ return Data(data=self.data)🧰 Tools
🪛 Pylint (3.3.7)
[convention] 282-282: Missing function or method docstring
(C0116)
src/backend/base/langflow/schema/dataframe.py (1)
192-206: Add docstring and fix line length violation.The method needs documentation and has a line that exceeds the 100-character limit.
def to_message(self) -> Message: + """Convert this DataFrame to a Message with markdown table format. + + Processes the DataFrame by cleaning empty rows, normalizing whitespace, + escaping pipe characters, and converting to markdown table format. + + Returns: + Message: A Message containing the DataFrame as markdown table. + """ from langflow.schema.message import Message # Local import to avoid circular import # Process DataFrame similar to the _safe_convert method # Remove empty rows processed_df = self.dropna(how="all") # Remove empty lines in each cell processed_df = processed_df.replace(r"^\s*$", "", regex=True) # Replace multiple newlines with a single newline processed_df = processed_df.replace(r"\n+", "\n", regex=True) # Replace pipe characters to avoid markdown table issues processed_df = processed_df.replace(r"\|", r"\\|", regex=True) - processed_df = processed_df.map(lambda x: str(x).replace("\n", "<br/>") if isinstance(x, str) else x) + processed_df = processed_df.map( + lambda x: str(x).replace("\n", "<br/>") if isinstance(x, str) else x + ) # Convert to markdown and wrap in a Message return Message(text=processed_df.to_markdown(index=False))🧰 Tools
🪛 Pylint (3.3.7)
[convention] 204-204: Line too long (109/100)
(C0301)
[convention] 192-192: Missing function or method docstring
(C0116)
[warning] 193-193: Redefining name 'Message' from outer scope (line 8)
(W0621)
[warning] 193-193: Reimport 'Message' (imported line 8)
(W0404)
[convention] 193-193: Import outside toplevel (langflow.schema.message.Message)
(C0415)
src/backend/base/langflow/schema/data.py (2)
257-262: Add missing docstring for theto_messagemethod.The method lacks documentation explaining its purpose and behavior.
def to_message(self) -> Message: + """Convert this Data to a Message. + + Uses the text from the configured text_key if available, + otherwise converts the entire data dictionary to string. + + Returns: + Message: A Message containing the text representation. + """ from langflow.schema.message import Message # Local import to avoid circular import if self.text_key in self.data: return Message(text=self.get_text()) return Message(text=str(self.data))🧰 Tools
🪛 Pylint (3.3.7)
[convention] 257-257: Missing function or method docstring
(C0116)
[convention] 258-258: Import outside toplevel (langflow.schema.message.Message)
(C0415)
264-275: Add docstring and improve readability of complex conditional.The method needs documentation and the long conditional affects readability.
def to_dataframe(self) -> DataFrame: + """Convert this Data to a DataFrame. + + If the data contains exactly one key with a list of dictionaries as value, + that list is used as DataFrame data. Otherwise, wraps this Data object + in a single-row DataFrame. + + Returns: + DataFrame: A DataFrame representation of the data. + """ from langflow.schema.dataframe import DataFrame # Local import to avoid circular import data_dict = self.data - # If data contains only one key and the value is a list of dictionaries, convert to DataFrame - if ( - len(data_dict) == 1 - and isinstance(next(iter(data_dict.values())), list) - and all(isinstance(item, dict) for item in next(iter(data_dict.values()))) - ): - return DataFrame(data=next(iter(data_dict.values()))) + # If data contains only one key and the value is a list of dictionaries + if len(data_dict) == 1: + single_value = next(iter(data_dict.values())) + if ( + isinstance(single_value, list) + and all(isinstance(item, dict) for item in single_value) + ): + return DataFrame(data=single_value) return DataFrame(data=[self])🧰 Tools
🪛 Pylint (3.3.7)
[convention] 268-268: Line too long (101/100)
(C0301)
[convention] 264-264: Missing function or method docstring
(C0116)
[convention] 265-265: Import outside toplevel (langflow.schema.dataframe.DataFrame)
(C0415)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/backend/base/langflow/schema/data.py(7 hunks)src/backend/base/langflow/schema/dataframe.py(2 hunks)src/backend/base/langflow/schema/message.py(3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/backend/base/langflow/schema/dataframe.py (2)
src/backend/base/langflow/schema/message.py (2)
Message(38-288)to_data(282-283)src/backend/base/langflow/schema/data.py (2)
Data(23-275)to_message(257-262)
src/backend/base/langflow/schema/message.py (2)
src/backend/base/langflow/schema/dataframe.py (2)
DataFrame(11-206)to_data(183-190)src/backend/base/langflow/schema/data.py (2)
Data(23-275)to_dataframe(264-275)
🪛 Pylint (3.3.7)
src/backend/base/langflow/schema/data.py
[convention] 1-1: Missing module docstring
(C0114)
[convention] 268-268: Line too long (101/100)
(C0301)
[convention] 257-257: Missing function or method docstring
(C0116)
[convention] 258-258: Import outside toplevel (langflow.schema.message.Message)
(C0415)
[convention] 264-264: Missing function or method docstring
(C0116)
[convention] 265-265: Import outside toplevel (langflow.schema.dataframe.DataFrame)
(C0415)
src/backend/base/langflow/schema/dataframe.py
[convention] 204-204: Line too long (109/100)
(C0301)
[convention] 192-192: Missing function or method docstring
(C0116)
[warning] 193-193: Redefining name 'Message' from outer scope (line 8)
(W0621)
[warning] 193-193: Reimport 'Message' (imported line 8)
(W0404)
[convention] 193-193: Import outside toplevel (langflow.schema.message.Message)
(C0415)
src/backend/base/langflow/schema/message.py
[convention] 282-282: Missing function or method docstring
(C0116)
[convention] 286-286: Import outside toplevel (langflow.schema.dataframe.DataFrame)
(C0415)
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: Optimize new Python code in this PR
- GitHub Check: Run Ruff Check and Format
- GitHub Check: Update Starter Projects
🔇 Additional comments (2)
src/backend/base/langflow/schema/message.py (1)
285-288: Good implementation of the conversion method.The method correctly operates on
self(addressing previous design issues), uses local import to avoid circular dependencies, and follows the established pattern of wrapping the current instance in a list for DataFrame creation.🧰 Tools
🪛 Pylint (3.3.7)
[convention] 286-286: Import outside toplevel (langflow.schema.dataframe.DataFrame)
(C0415)
src/backend/base/langflow/schema/dataframe.py (1)
183-190: Well-implemented conversion method.The
to_data()method correctly operates onself, includes proper documentation, and follows a logical conversion pattern by wrapping DataFrame records under a 'results' key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (2)
src/backend/base/langflow/components/processing/converter.py (2)
8-17: Add missing type hint for parameter.The function parameter lacks a type hint, which reduces code clarity and IDE support.
The past review correctly identified this issue. The parameter
vneeds a proper type hint:-def convert_to_message(v) -> Message: +def convert_to_message(v: Message | Data | DataFrame | dict) -> Message:
46-49: Add comprehensive class docstring.As identified in past reviews, the class needs proper documentation:
class TypeConverterComponent(Component): + """ + A component for converting between different data types. + + Supports conversion between Message, Data, and DataFrame types with + dynamic output configuration based on the selected output type. + """ display_name = "Type Convert"🧰 Tools
🪛 Pylint (3.3.7)
[convention] 46-46: Missing class docstring
(C0115)
🧹 Nitpick comments (7)
src/backend/tests/unit/components/processing/test_type_converter_component.py (5)
1-9: Add module docstring and verify import consistency.The module is missing a docstring and there's an inconsistency in the import path compared to the implementation file.
+""" +Unit tests for the TypeConverterComponent. + +Tests conversion functionality between Message, Data, and DataFrame types, +as well as dynamic output updating behavior. +""" import pandas as pd import pytest -from langflow.components.processing.converter import TypeConverterComponent +from langflow.components.processing.converter import TypeConverterComponentNote: Verify that the import path matches the actual file location in the implementation.
🧰 Tools
🪛 Pylint (3.3.7)
[convention] 1-1: Missing module docstring
(C0114)
[error] 1-1: Unable to import 'pandas'
(E0401)
[error] 3-3: Unable to import 'langflow.components.processing.converter'
(E0401)
[error] 3-3: No name 'components' in module 'langflow'
(E0611)
[error] 4-4: Unable to import 'langflow.schema.data'
(E0401)
[error] 4-4: No name 'schema' in module 'langflow'
(E0611)
[error] 5-5: Unable to import 'langflow.schema.dataframe'
(E0401)
[error] 5-5: No name 'schema' in module 'langflow'
(E0611)
[error] 6-6: Unable to import 'langflow.schema.message'
(E0401)
[error] 6-6: No name 'schema' in module 'langflow'
(E0611)
11-21: Add class docstring for better test documentation.The test class lacks documentation explaining its purpose and structure.
class TestTypeConverterComponent(ComponentTestBaseWithoutClient): + """Test suite for TypeConverterComponent functionality.""" + @pytest.fixture def component_class(self):🧰 Tools
🪛 Pylint (3.3.7)
[convention] 11-11: Missing class docstring
(C0115)
49-49: Fix line length violations.Multiple lines exceed the 100-character limit as flagged by static analysis.
- component = component_class(input_data=Data(data={"text": "Hello World"}), output_type="Message") + component = component_class( + input_data=Data(data={"text": "Hello World"}), output_type="Message" + ) - component = component_class(input_data=Data(data={"text": "Hello World"}), output_type="DataFrame") + component = component_class( + input_data=Data(data={"text": "Hello World"}), output_type="DataFrame" + )Also applies to: 63-63
🧰 Tools
🪛 Pylint (3.3.7)
[convention] 49-49: Line too long (105/100)
(C0301)
76-76: Verify hardcoded markdown table assertion.The test asserts a specific markdown table format. This creates a brittle test that could break if the DataFrame-to-markdown conversion implementation changes.
Consider making this assertion more flexible:
- assert result.text == "| col1 | col2 |\n|:-------|:-------|\n| Hello | World |" + # Verify it's a valid markdown table containing the expected data + assert "col1" in result.text + assert "col2" in result.text + assert "Hello" in result.text + assert "World" in result.text + assert "|" in result.text # Ensure it's table format
97-115: Enhance test coverage for update_outputs method.The test covers the happy path but misses edge cases and error conditions.
Consider adding additional test cases:
def test_update_outputs_edge_cases(self, component_class): """Test update_outputs with edge cases.""" component = component_class(input_data=Message(text="Hello"), output_type="Message") frontend_node = {"outputs": []} # Test with invalid field_name (should not modify outputs) original_outputs = frontend_node["outputs"].copy() updated = component.update_outputs(frontend_node, "invalid_field", "Message") assert updated["outputs"] == original_outputs # Test with invalid output_type (should handle gracefully) updated = component.update_outputs(frontend_node, "output_type", "InvalidType") # Should either handle gracefully or raise appropriate errorsrc/backend/base/langflow/components/processing/converter.py (2)
1-6: Add missing module docstring.The module lacks documentation explaining its purpose and functionality.
+""" +Type conversion utilities and component for Langflow. + +Provides converter functions and a dynamic component for converting between +Message, Data, and DataFrame types with configurable output selection. +""" from typing import Any🧰 Tools
🪛 Pylint (3.3.7)
[convention] 1-1: Missing module docstring
(C0114)
69-69: Fix multiple line length violations.Several lines exceed the 100-character limit as flagged by static analysis.
- outputs = [Output(display_name="Message Output", name="message_output", method="convert_to_message")] + outputs = [ + Output(display_name="Message Output", name="message_output", method="convert_to_message") + ] - Output(display_name="Message Output", name="message_output", method="convert_to_message").to_dict() + Output( + display_name="Message Output", + name="message_output", + method="convert_to_message" + ).to_dict() - Output(display_name="Data Output", name="data_output", method="convert_to_data").to_dict() + Output( + display_name="Data Output", + name="data_output", + method="convert_to_data" + ).to_dict() - return convert_to_message(self.input_data[0] if isinstance(self.input_data, list) else self.input_data) + input_val = self.input_data[0] if isinstance(self.input_data, list) else self.input_data + return convert_to_message(input_val) - return convert_to_data(self.input_data[0] if isinstance(self.input_data, list) else self.input_data) + input_val = self.input_data[0] if isinstance(self.input_data, list) else self.input_data + return convert_to_data(input_val) - return convert_to_dataframe(self.input_data[0] if isinstance(self.input_data, list) else self.input_data) + input_val = self.input_data[0] if isinstance(self.input_data, list) else self.input_data + return convert_to_dataframe(input_val)Also applies to: 80-80, 84-84, 89-89, 97-97, 101-101, 105-105
🧰 Tools
🪛 Pylint (3.3.7)
[convention] 69-69: Line too long (105/100)
(C0301)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/backend/base/langflow/components/processing/converter.py(1 hunks)src/backend/tests/unit/components/processing/test_type_converter_component.py(1 hunks)
🧰 Additional context used
🪛 Pylint (3.3.7)
src/backend/tests/unit/components/processing/test_type_converter_component.py
[convention] 49-49: Line too long (105/100)
(C0301)
[convention] 63-63: Line too long (107/100)
(C0301)
[convention] 1-1: Missing module docstring
(C0114)
[error] 1-1: Unable to import 'pandas'
(E0401)
[error] 3-3: Unable to import 'langflow.components.processing.converter'
(E0401)
[error] 3-3: No name 'components' in module 'langflow'
(E0611)
[error] 4-4: Unable to import 'langflow.schema.data'
(E0401)
[error] 4-4: No name 'schema' in module 'langflow'
(E0611)
[error] 5-5: Unable to import 'langflow.schema.dataframe'
(E0401)
[error] 5-5: No name 'schema' in module 'langflow'
(E0611)
[error] 6-6: Unable to import 'langflow.schema.message'
(E0401)
[error] 6-6: No name 'schema' in module 'langflow'
(E0611)
[convention] 11-11: Missing class docstring
(C0115)
src/backend/base/langflow/components/processing/converter.py
[convention] 69-69: Line too long (105/100)
(C0301)
[convention] 80-80: Line too long (119/100)
(C0301)
[convention] 84-84: Line too long (110/100)
(C0301)
[convention] 89-89: Line too long (111/100)
(C0301)
[convention] 97-97: Line too long (111/100)
(C0301)
[convention] 101-101: Line too long (108/100)
(C0301)
[convention] 105-105: Line too long (113/100)
(C0301)
[convention] 1-1: Missing module docstring
(C0114)
[convention] 46-46: Missing class docstring
(C0115)
⏰ Context from checks skipped due to timeout of 90000ms (11)
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 2/10
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 10/10
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 1/10
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 4/10
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 7/10
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 5/10
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 8/10
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 9/10
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 6/10
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 3/10
- GitHub Check: Optimize new Python code in this PR
🔇 Additional comments (1)
src/backend/base/langflow/components/processing/converter.py (1)
29-31:Details
❓ Verification inconclusive
Verify Data constructor usage with dict.
The code calls
Data(v)with a dict, but this may not match the expected constructor signature.
🏁 Script executed:
#!/bin/bash # Description: Verify the Data class constructor signature # Expected: Should show how Data class handles dict initialization ast-grep --pattern 'class Data: $$$ def __init__($$$): $$$'Length of output: 69
I couldn’t locate the
Dataclass definition with the initial AST search. Let’s search the repository for anyclass Datadeclarations to confirm how its constructor is defined:
🏁 Script executed:
#!/bin/bash # Find all Python files declaring class Data rg -n "class Data" --glob "*.py"Length of output: 1604
Let’s inspect how
Datais defined to confirm its constructor signature:
🏁 Script executed:
#!/bin/bash # Show class Data definition and its __init__ context rg -n "class Data" -A 50 src/backend/base/langflow/schema/data.pyLength of output: 2087
Let’s verify how
BaseModel.__init__is defined in Pydantic to confirm if positional dicts are supported:
🏁 Script executed:
#!/bin/bash python - << 'EOF' import inspect try: from pydantic import BaseModel print("BaseModel.__init__ signature:", inspect.signature(BaseModel.__init__)) except Exception as e: print("Error importing or inspecting BaseModel:", e) EOFLength of output: 78
Verify Data constructor usage with dict as positional argument
Pydantic’s
BaseModelinitializer only accepts field values as keyword arguments, so callingData(v)wherevis adictmay raise aTypeErroror misassign fields. Please confirm whetherData(v)works as intended or if you should instead pass the dict explicitly:
- File:
src/backend/base/langflow/components/processing/converter.py, lines 29–31- Current code:
if isinstance(v, dict): return Data(v)- Consider one of the following, depending on your intent:
return Data(data=v) # to populate the `data` field # – or – return Data(**v) # if dict keys map directly to model fields
| def convert_to_message(self) -> Message: | ||
| """Convert input to Message type.""" | ||
| return convert_to_message(self.input_data[0] if isinstance(self.input_data, list) else self.input_data) | ||
|
|
||
| def convert_to_data(self) -> Data: | ||
| """Convert input to Data type.""" | ||
| return convert_to_data(self.input_data[0] if isinstance(self.input_data, list) else self.input_data) | ||
|
|
||
| def convert_to_dataframe(self) -> DataFrame: | ||
| """Convert input to DataFrame type.""" | ||
| return convert_to_dataframe(self.input_data[0] if isinstance(self.input_data, list) else self.input_data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Extract common input processing logic to reduce duplication.
All three conversion methods use identical logic to handle list inputs. This violates the DRY principle.
+ def _get_input_value(self):
+ """Extract the actual input value, handling list inputs."""
+ return self.input_data[0] if isinstance(self.input_data, list) else self.input_data
+
def convert_to_message(self) -> Message:
"""Convert input to Message type."""
- return convert_to_message(self.input_data[0] if isinstance(self.input_data, list) else self.input_data)
+ return convert_to_message(self._get_input_value())
def convert_to_data(self) -> Data:
"""Convert input to Data type."""
- return convert_to_data(self.input_data[0] if isinstance(self.input_data, list) else self.input_data)
+ return convert_to_data(self._get_input_value())
def convert_to_dataframe(self) -> DataFrame:
"""Convert input to DataFrame type."""
- return convert_to_dataframe(self.input_data[0] if isinstance(self.input_data, list) else self.input_data)
+ return convert_to_dataframe(self._get_input_value())📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def convert_to_message(self) -> Message: | |
| """Convert input to Message type.""" | |
| return convert_to_message(self.input_data[0] if isinstance(self.input_data, list) else self.input_data) | |
| def convert_to_data(self) -> Data: | |
| """Convert input to Data type.""" | |
| return convert_to_data(self.input_data[0] if isinstance(self.input_data, list) else self.input_data) | |
| def convert_to_dataframe(self) -> DataFrame: | |
| """Convert input to DataFrame type.""" | |
| return convert_to_dataframe(self.input_data[0] if isinstance(self.input_data, list) else self.input_data) | |
| def _get_input_value(self): | |
| """Extract the actual input value, handling list inputs.""" | |
| return self.input_data[0] if isinstance(self.input_data, list) else self.input_data | |
| def convert_to_message(self) -> Message: | |
| """Convert input to Message type.""" | |
| return convert_to_message(self._get_input_value()) | |
| def convert_to_data(self) -> Data: | |
| """Convert input to Data type.""" | |
| return convert_to_data(self._get_input_value()) | |
| def convert_to_dataframe(self) -> DataFrame: | |
| """Convert input to DataFrame type.""" | |
| return convert_to_dataframe(self._get_input_value()) |
🧰 Tools
🪛 Pylint (3.3.7)
[convention] 97-97: Line too long (111/100)
(C0301)
[convention] 101-101: Line too long (108/100)
(C0301)
[convention] 105-105: Line too long (113/100)
(C0301)
🤖 Prompt for AI Agents
In src/backend/base/langflow/components/processing/converter.py around lines 95
to 105, the three conversion methods duplicate the logic to check if input_data
is a list and select the first element. Extract this common input processing
logic into a private helper method that returns the appropriate input element,
then update each conversion method to call this helper before passing the input
to the respective conversion function. This will reduce code duplication and
improve maintainability.
| def update_outputs(self, frontend_node: dict, field_name: str, field_value: Any) -> dict: | ||
| """Dynamically show only the relevant output based on the selected output type.""" | ||
| if field_name == "output_type": | ||
| # Start with empty outputs | ||
| frontend_node["outputs"] = [] | ||
|
|
||
| # Add only the selected output type | ||
| if field_value == "Message": | ||
| frontend_node["outputs"].append( | ||
| Output(display_name="Message Output", name="message_output", method="convert_to_message").to_dict() | ||
| ) | ||
| elif field_value == "Data": | ||
| frontend_node["outputs"].append( | ||
| Output(display_name="Data Output", name="data_output", method="convert_to_data").to_dict() | ||
| ) | ||
| elif field_value == "DataFrame": | ||
| frontend_node["outputs"].append( | ||
| Output( | ||
| display_name="DataFrame Output", name="dataframe_output", method="convert_to_dataframe" | ||
| ).to_dict() | ||
| ) | ||
|
|
||
| return frontend_node |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add error handling for invalid output types.
The update_outputs method doesn't handle the case where an invalid field_value is provided, which could leave the component in an inconsistent state.
def update_outputs(self, frontend_node: dict, field_name: str, field_value: Any) -> dict:
"""Dynamically show only the relevant output based on the selected output type."""
if field_name == "output_type":
# Start with empty outputs
frontend_node["outputs"] = []
# Add only the selected output type
if field_value == "Message":
frontend_node["outputs"].append(
Output(
display_name="Message Output",
name="message_output",
method="convert_to_message"
).to_dict()
)
elif field_value == "Data":
frontend_node["outputs"].append(
Output(
display_name="Data Output",
name="data_output",
method="convert_to_data"
).to_dict()
)
elif field_value == "DataFrame":
frontend_node["outputs"].append(
Output(
display_name="DataFrame Output",
name="dataframe_output",
method="convert_to_dataframe"
).to_dict()
)
+ else:
+ # Handle invalid output type by defaulting to Message
+ frontend_node["outputs"].append(
+ Output(
+ display_name="Message Output",
+ name="message_output",
+ method="convert_to_message"
+ ).to_dict()
+ )
return frontend_node📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def update_outputs(self, frontend_node: dict, field_name: str, field_value: Any) -> dict: | |
| """Dynamically show only the relevant output based on the selected output type.""" | |
| if field_name == "output_type": | |
| # Start with empty outputs | |
| frontend_node["outputs"] = [] | |
| # Add only the selected output type | |
| if field_value == "Message": | |
| frontend_node["outputs"].append( | |
| Output(display_name="Message Output", name="message_output", method="convert_to_message").to_dict() | |
| ) | |
| elif field_value == "Data": | |
| frontend_node["outputs"].append( | |
| Output(display_name="Data Output", name="data_output", method="convert_to_data").to_dict() | |
| ) | |
| elif field_value == "DataFrame": | |
| frontend_node["outputs"].append( | |
| Output( | |
| display_name="DataFrame Output", name="dataframe_output", method="convert_to_dataframe" | |
| ).to_dict() | |
| ) | |
| return frontend_node | |
| def update_outputs(self, frontend_node: dict, field_name: str, field_value: Any) -> dict: | |
| """Dynamically show only the relevant output based on the selected output type.""" | |
| if field_name == "output_type": | |
| # Start with empty outputs | |
| frontend_node["outputs"] = [] | |
| # Add only the selected output type | |
| if field_value == "Message": | |
| frontend_node["outputs"].append( | |
| Output(display_name="Message Output", name="message_output", method="convert_to_message").to_dict() | |
| ) | |
| elif field_value == "Data": | |
| frontend_node["outputs"].append( | |
| Output(display_name="Data Output", name="data_output", method="convert_to_data").to_dict() | |
| ) | |
| elif field_value == "DataFrame": | |
| frontend_node["outputs"].append( | |
| Output( | |
| display_name="DataFrame Output", name="dataframe_output", method="convert_to_dataframe" | |
| ).to_dict() | |
| ) | |
| else: | |
| # Handle invalid output type by defaulting to Message | |
| frontend_node["outputs"].append( | |
| Output(display_name="Message Output", name="message_output", method="convert_to_message").to_dict() | |
| ) | |
| return frontend_node |
🧰 Tools
🪛 Pylint (3.3.7)
[convention] 80-80: Line too long (119/100)
(C0301)
[convention] 84-84: Line too long (110/100)
(C0301)
[convention] 89-89: Line too long (111/100)
(C0301)
🤖 Prompt for AI Agents
In src/backend/base/langflow/components/processing/converter.py around lines 71
to 93, the update_outputs method lacks error handling for invalid output types
in the field_value parameter. To fix this, add a check after the existing
if-elif blocks to handle unexpected field_value values by either raising a
ValueError with a clear message or logging an error and leaving outputs empty.
This ensures the component does not enter an inconsistent state when given
invalid input.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (3)
src/backend/base/langflow/components/processing/converter.py (3)
48-51: Add comprehensive class docstring.This issue was already identified in previous reviews. The class needs a docstring explaining its purpose and functionality.
🧰 Tools
🪛 Pylint (3.3.7)
[convention] 48-48: Missing class docstring
(C0115)
73-95: Add error handling for invalid output types.This issue was already identified in previous reviews. The
update_outputsmethod lacks error handling for invalidfield_valueparameters.🧰 Tools
🪛 Pylint (3.3.7)
[convention] 82-82: Line too long (119/100)
(C0301)
[convention] 86-86: Line too long (110/100)
(C0301)
[convention] 91-91: Line too long (111/100)
(C0301)
97-107: Extract common input processing logic to reduce duplication.This code duplication issue was already identified in previous reviews. All three conversion methods use identical logic to handle list inputs, violating the DRY principle.
🧰 Tools
🪛 Pylint (3.3.7)
[convention] 99-99: Line too long (111/100)
(C0301)
[convention] 103-103: Line too long (108/100)
(C0301)
[convention] 107-107: Line too long (113/100)
(C0301)
🧹 Nitpick comments (3)
src/backend/base/langflow/components/processing/converter.py (3)
1-6: Add module docstring to document the converter functionality.The module is missing a docstring that would help developers understand its purpose and the conversion capabilities it provides.
+""" +Type conversion utilities for converting between Message, Data, and DataFrame types. + +This module provides converter functions and a TypeConverterComponent that enables +dynamic conversion between the core data types used in the Langflow system. +""" from typing import Any🧰 Tools
🪛 Pylint (3.3.7)
[convention] 1-1: Missing module docstring
(C0114)
8-17: Add missing type hints for the parameter.The function is missing proper type hints for the input parameter, which affects code clarity and IDE support.
-def convert_to_message(v) -> Message: +def convert_to_message(v: Message | Data | DataFrame | dict) -> Message:
71-71: Address line length violations for better readability.Multiple lines exceed the 100-character limit, affecting code readability and compliance with style guidelines.
Consider breaking long lines using appropriate line continuation or reformatting:
- outputs = [Output(display_name="Message Output", name="message_output", method="convert_to_message")] + outputs = [ + Output( + display_name="Message Output", + name="message_output", + method="convert_to_message" + ) + ]Apply similar formatting to other long lines in the
update_outputsmethod and conversion methods.Also applies to: 82-82, 86-86, 91-91, 99-99, 103-103, 107-107
🧰 Tools
🪛 Pylint (3.3.7)
[convention] 71-71: Line too long (105/100)
(C0301)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/backend/base/langflow/components/processing/converter.py(1 hunks)
🧰 Additional context used
🪛 Pylint (3.3.7)
src/backend/base/langflow/components/processing/converter.py
[convention] 71-71: Line too long (105/100)
(C0301)
[convention] 82-82: Line too long (119/100)
(C0301)
[convention] 86-86: Line too long (110/100)
(C0301)
[convention] 91-91: Line too long (111/100)
(C0301)
[convention] 99-99: Line too long (111/100)
(C0301)
[convention] 103-103: Line too long (108/100)
(C0301)
[convention] 107-107: Line too long (113/100)
(C0301)
[convention] 1-1: Missing module docstring
(C0114)
[convention] 48-48: Missing class docstring
(C0115)
⏰ Context from checks skipped due to timeout of 90000ms (21)
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 6/10
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 3/10
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 10/10
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 7/10
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 8/10
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 9/10
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 5/10
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 1/10
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 4/10
- GitHub Check: Run Frontend Tests / Playwright Tests - Shard 2/10
- GitHub Check: Lint Backend / Run Mypy (3.10)
- GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 4
- GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 3
- GitHub Check: Run Backend Tests / Integration Tests - Python 3.10
- GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 2
- GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 5
- GitHub Check: Lint Backend / Run Mypy (3.13)
- GitHub Check: Run Backend Tests / Unit Tests - Python 3.10 - Group 1
- GitHub Check: Optimize new Python code in this PR
- GitHub Check: Run Ruff Check and Format
- GitHub Check: Update Starter Projects
🔇 Additional comments (1)
src/backend/base/langflow/components/processing/converter.py (1)
29-30:Details
✅ Verification successful
Verify dictionary handling consistency across converter functions.
The dictionary handling differs between
convert_to_dataandconvert_to_dataframefunctions. Ensure this behavior aligns with the expected data structures.Also applies to: 43-44
🏁 Script executed:
#!/bin/bash # Search for Data and DataFrame constructor usage patterns to verify consistency echo "=== Data constructor usage ===" rg "Data\(" -A 2 -B 2 echo "=== DataFrame constructor usage ===" rg "DataFrame\(" -A 2 -B 2Length of output: 118195
🏁 Script executed:
#!/bin/bash # Locate the convert_to_data and convert_to_dataframe functions grep -R "def convert_to_data" -n src/backend/base/langflow/components/processing/converter.py grep -R "def convert_to_dataframe" -n src/backend/base/langflow/components/processing/converter.py # Show their implementations for review sed -n '1,200p' src/backend/base/langflow/components/processing/converter.py sed -n '200,400p' src/backend/base/langflow/components/processing/converter.pyLength of output: 4447
🏁 Script executed:
#!/bin/bash # Inspect DataFrame implementation to confirm constructor behavior grep -R "class DataFrame" -n src/backend/base/langflow/schema/dataframe.py sed -n '1,200p' src/backend/base/langflow/schema/dataframe.pyLength of output: 7161
🏁 Script executed:
#!/bin/bash # Inspect Data class constructor grep -R "class Data" -n src/backend/base/langflow/schema/data.py sed -n '1,200p' src/backend/base/langflow/schema/data.pyLength of output: 7620
Dictionary conversion behavior is consistent
Bothconvert_to_dataandconvert_to_dataframecorrectly wrap a plaindictinto the respective target type—Data(v)for aDataobject andDataFrame([v])for a single‐rowDataFrame. This aligns with the intended conversion patterns, so no changes are required.
…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 <[email protected]> Co-authored-by: Carlos Coelho <[email protected]> Co-authored-by: Yuqi Tang <[email protected]>
…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 <[email protected]> Co-authored-by: Carlos Coelho <[email protected]> Co-authored-by: Yuqi Tang <[email protected]>
This pull request introduces a new
DataTypeConverterComponentin thesrc/backend/base/langflow/components/processing/convertor.pyfile. This component provides functionality to convert between three data types:Message,Data, andDataFrame. It includes input and output definitions, dynamic output adjustments, and methods for performing the conversions.Key Changes:
New Component:
DataTypeConverterComponentclass:Message,Data, andDataFramedata types. It includes input definitions (HandleInput,TabInput), output definitions (Output), and a dynamic output adjustment method (update_outputs).Conversion Methods:
to_messagemethod:Messagetype, handling cases forData,DataFrame, and fallback scenarios. Includes error handling for JSON serialization and markdown conversion.to_datamethod:Datatype, with support for parsing JSON fromMessagetext and convertingDataFrameto a dictionary. Includes error handling for invalid conversions.to_dataframemethod:DataFrametype, supporting JSON parsing fromMessagetext and converting `DataSummary by CodeRabbit