From 204b4e10e007bcc0f1080a7eca4e40dbec7f3307 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 20 Jan 2025 09:53:31 -0300 Subject: [PATCH] refactor: add utility methods for getting display name and improve error messages (#5653) * feat: add methods to access inputs' and outputs' display_name - Updated error messages to use display names for inputs and outputs, improving clarity. - Introduced utility methods for building consistent error messages related to inputs, outputs, and components. - Added public methods to retrieve user-friendly display names for inputs and outputs. - Refactored existing error handling to utilize the new messaging methods for better maintainability. * refactor: enhance error message formatting for inputs, outputs, and components - Updated error message formatting to place input, output, and component names at the beginning for better visibility, especially when messages are truncated. - Changed the format of error messages to use square brackets for consistency and improved readability. - Ensured that utility methods for building error messages maintain a user-friendly approach. * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- .../custom/custom_component/component.py | 113 +++++++++++++++--- 1 file changed, 99 insertions(+), 14 deletions(-) diff --git a/src/backend/base/langflow/custom/custom_component/component.py b/src/backend/base/langflow/custom/custom_component/component.py index b8d94fe5d..29ed354ec 100644 --- a/src/backend/base/langflow/custom/custom_component/component.py +++ b/src/backend/base/langflow/custom/custom_component/component.py @@ -389,7 +389,7 @@ class Component(CustomComponent): """ for input_ in inputs: if input_.name is None: - msg = "Input name cannot be None." + msg = self.build_component_error_message("Input name cannot be None") raise ValueError(msg) self._inputs[input_.name] = deepcopy(input_) @@ -546,22 +546,21 @@ class Component(CustomComponent): # If multiple matches are found, raise an error indicating ambiguity if len(matching_pairs) > 1: matching_pairs_str = self._build_error_string_from_matching_pairs(matching_pairs) - msg = ( - f"There are multiple outputs from {value.__class__.__name__} " - f"that can connect to inputs in {self.__class__.__name__}: {matching_pairs_str}" + msg = self.build_component_error_message( + f"There are multiple outputs from {value.display_name} that can connect to inputs: {matching_pairs_str}" ) + raise ValueError(msg) # If no matches are found, raise an error indicating no suitable output if not matching_pairs: - msg = ( - f"No matching output from {value.__class__.__name__} found for input '{input_name}' " - f"in {self.__class__.__name__}." - ) + msg = self.build_input_error_message(input_name, f"No matching output from {value.display_name} found") raise ValueError(msg) # Get the matching output and input pair output, input_ = matching_pairs[0] # Ensure that the output method is a valid method name (string) if not isinstance(output.method, str): - msg = f"Method {output.method} is not a valid output of {value.__class__.__name__}" + msg = self.build_component_error_message( + f"Method {output.method} is not a valid output of {value.display_name}" + ) raise TypeError(msg) return getattr(value, output.method) @@ -685,19 +684,21 @@ class Component(CustomComponent): input_value = self._inputs[name].value if isinstance(input_value, Component): methods = ", ".join([f"'{output.method}'" for output in input_value.outputs]) - msg = ( - f"You set {input_value.display_name} as value for `{name}`. " - f"You should pass one of the following: {methods}" + msg = self.build_input_error_message( + name, + f"You set {input_value.display_name} as value. You should pass one of the following: {methods}", ) raise ValueError(msg) if callable(input_value) and hasattr(input_value, "__self__"): - msg = f"Input {name} is connected to {input_value.__self__.display_name}.{input_value.__name__}" + msg = self.build_input_error_message( + name, f"Input is connected to {input_value.__self__.display_name}.{input_value.__name__}" + ) raise ValueError(msg) self._inputs[name].value = value if hasattr(self._inputs[name], "load_from_db"): self._inputs[name].load_from_db = False else: - msg = f"Input {name} not found in {self.__class__.__name__}" + msg = self.build_component_error_message(f"Input {name} not found") raise ValueError(msg) def _validate_outputs(self) -> None: @@ -1252,3 +1253,87 @@ class Component(CustomComponent): description=TOOLS_METADATA_INFO, ), ) + + def get_input_display_name(self, input_name: str) -> str: + """Get the display name of an input. + + This is a public utility method that subclasses can use to get user-friendly + display names for inputs when building error messages or UI elements. + + Usage: + msg = f"Input {self.get_input_display_name(input_name)} not found" + + Args: + input_name (str): The name of the input. + + Returns: + str: The display name of the input, or the input name if not found. + """ + if input_name in self._inputs: + return getattr(self._inputs[input_name], "display_name", input_name) + return input_name + + def get_output_display_name(self, output_name: str) -> str: + """Get the display name of an output. + + This is a public utility method that subclasses can use to get user-friendly + display names for outputs when building error messages or UI elements. + + Args: + output_name (str): The name of the output. + + Returns: + str: The display name of the output, or the output name if not found. + """ + if output_name in self._outputs_map: + return getattr(self._outputs_map[output_name], "display_name", output_name) + return output_name + + def build_input_error_message(self, input_name: str, message: str) -> str: + """Build an error message for an input. + + This is a public utility method that subclasses can use to create consistent, + user-friendly error messages that reference inputs by their display names. + The input name is placed at the beginning to ensure it's visible even if the message is truncated. + + Args: + input_name (str): The name of the input. + message (str): The error message. + + Returns: + str: The formatted error message with display name. + """ + display_name = self.get_input_display_name(input_name) + return f"[Input: {display_name}] {message}" + + def build_output_error_message(self, output_name: str, message: str) -> str: + """Build an error message for an output. + + This is a public utility method that subclasses can use to create consistent, + user-friendly error messages that reference outputs by their display names. + The output name is placed at the beginning to ensure it's visible even if the message is truncated. + + Args: + output_name (str): The name of the output. + message (str): The error message. + + Returns: + str: The formatted error message with display name. + """ + display_name = self.get_output_display_name(output_name) + return f"[Output: {display_name}] {message}" + + def build_component_error_message(self, message: str) -> str: + """Build an error message for the component. + + This is a public utility method that subclasses can use to create consistent, + user-friendly error messages that reference the component by its display name. + The component name is placed at the beginning to ensure it's visible even if the message is truncated. + + Args: + message (str): The error message. + + Returns: + str: The formatted error message with component display name. + """ + return f"[Component: {self.display_name or self.__class__.__name__}] {message}"