From 8306a5bbd88e859b6ff11de751ce7a37175152c9 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 22 Dec 2023 10:39:17 -0300 Subject: [PATCH] Remove import validation for typing module --- src/backend/langflow/api/v1/endpoints.py | 6 ++-- .../custom_component/custom_component.py | 36 +++---------------- .../langflow/interface/custom/utils.py | 22 ++++-------- src/backend/langflow/utils/validate.py | 15 ++++---- 4 files changed, 20 insertions(+), 59 deletions(-) diff --git a/src/backend/langflow/api/v1/endpoints.py b/src/backend/langflow/api/v1/endpoints.py index 99b7d5427..9bf081163 100644 --- a/src/backend/langflow/api/v1/endpoints.py +++ b/src/backend/langflow/api/v1/endpoints.py @@ -16,7 +16,7 @@ from langflow.api.v1.schemas import ( ) from langflow.interface.custom.custom_component import CustomComponent from langflow.interface.custom.directory_reader import DirectoryReader -from langflow.interface.custom.utils import build_custom_component_template, create_and_validate_component +from langflow.interface.custom.utils import build_custom_component_template from langflow.processing.process import process_graph_cached, process_tweaks from langflow.services.auth.utils import api_key_security, get_current_active_user from langflow.services.cache.utils import save_uploaded_file @@ -270,7 +270,7 @@ async def custom_component( raw_code: CustomComponentCode, user: User = Depends(get_current_active_user), ): - component = create_and_validate_component(raw_code.code) + component = CustomComponent(code=raw_code.code) built_frontend_node = build_custom_component_template(component, user_id=user.id) @@ -300,7 +300,7 @@ async def custom_component_update( raw_code: CustomComponentCode, user: User = Depends(get_current_active_user), ): - component = create_and_validate_component(raw_code.code) + component = CustomComponent(code=raw_code.code) component_node = build_custom_component_template(component, user_id=user.id, update_field=raw_code.field) # Update the field diff --git a/src/backend/langflow/interface/custom/custom_component/custom_component.py b/src/backend/langflow/interface/custom/custom_component/custom_component.py index b26764b9c..15e7cd845 100644 --- a/src/backend/langflow/interface/custom/custom_component/custom_component.py +++ b/src/backend/langflow/interface/custom/custom_component/custom_component.py @@ -5,10 +5,11 @@ from uuid import UUID import yaml from cachetools import TTLCache, cachedmethod from fastapi import HTTPException + from langflow.interface.custom.code_parser.utils import ( extract_inner_type_from_generic_alias, - extract_union_types_from_generic_alias) -from langflow.interface.custom.directory_reader import DirectoryReader + extract_union_types_from_generic_alias, +) from langflow.services.database.models.flow import Flow from langflow.services.database.utils import session_getter from langflow.services.deps import get_credential_service, get_db_service @@ -46,34 +47,6 @@ class CustomComponent(Component): def build_config(self): return self.field_config - def _class_template_validation(self, code: str): - TYPE_HINT_LIST = ["Optional", "Prompt", "PromptTemplate", "LLMChain"] - - if not code: - raise HTTPException( - status_code=400, - detail={ - "error": self.ERROR_CODE_NULL, - "traceback": "", - }, - ) - - reader = DirectoryReader("", False) - - for type_hint in TYPE_HINT_LIST: - if reader._is_type_hint_used_in_args(type_hint, code) and not reader._is_type_hint_imported( - type_hint, code - ): - error_detail = { - "error": "Type hint Error", - "traceback": f"Type hint '{type_hint}' is used but not imported in the code.", - } - raise HTTPException(status_code=400, detail=error_detail) - return True - - def validate(self) -> bool: - return self._class_template_validation(self.code) if self.code else False - @property def tree(self): return self.get_code_tree(self.code or "") @@ -206,8 +179,7 @@ class CustomComponent(Component): return validate.create_function(self.code, self.function_entrypoint_name) async def load_flow(self, flow_id: str, tweaks: Optional[dict] = None) -> Any: - from langflow.processing.process import (build_sorted_vertices, - process_tweaks) + from langflow.processing.process import build_sorted_vertices, process_tweaks db_service = get_db_service() with session_getter(db_service) as session: diff --git a/src/backend/langflow/interface/custom/utils.py b/src/backend/langflow/interface/custom/utils.py index 3744e48be..86c55b0ae 100644 --- a/src/backend/langflow/interface/custom/utils.py +++ b/src/backend/langflow/interface/custom/utils.py @@ -11,12 +11,13 @@ from langflow.field_typing.range_spec import RangeSpec from langflow.interface.custom.code_parser.utils import extract_inner_type from langflow.interface.custom.custom_component import CustomComponent from langflow.interface.custom.directory_reader.utils import ( - build_custom_component_list_from_path, determine_component_name, - merge_nested_dicts_with_renaming) + build_custom_component_list_from_path, + determine_component_name, + merge_nested_dicts_with_renaming, +) from langflow.interface.importing.utils import eval_custom_component_code from langflow.template.field.base import TemplateField -from langflow.template.frontend_node.custom_components import \ - CustomComponentFrontendNode +from langflow.template.frontend_node.custom_components import CustomComponentFrontendNode from langflow.utils.util import get_base_classes from loguru import logger @@ -174,9 +175,7 @@ def get_field_dict(field: Union[TemplateField, dict]): return field -def run_build_config( - custom_component: CustomComponent, user_id: Optional[Union[str, UUID]] = None, update_field=None -): +def run_build_config(custom_component: CustomComponent, user_id: Optional[Union[str, UUID]] = None, update_field=None): """Build the field configuration for a custom component""" try: @@ -343,12 +342,6 @@ def build_custom_components(settings_service): return custom_components_from_file -def create_and_validate_component(code: str) -> CustomComponent: - component = CustomComponent(code=code) - component.validate() - return component - - def update_field_dict(field_dict): """Update the field dictionary by calling options() or value() if they are callable""" if "options" in field_dict and callable(field_dict["options"]): @@ -378,6 +371,3 @@ def build_component(component): component_name = determine_component_name(component) component_template = create_component_template(component) return component_name, component_template - - - diff --git a/src/backend/langflow/utils/validate.py b/src/backend/langflow/utils/validate.py index 785055dba..6e6226568 100644 --- a/src/backend/langflow/utils/validate.py +++ b/src/backend/langflow/utils/validate.py @@ -2,7 +2,7 @@ import ast import contextlib import importlib from types import FunctionType -from typing import Dict +from typing import Dict, List, Optional, Union from langflow.field_typing.constants import CUSTOM_COMPONENT_SUPPORTED_TYPES @@ -260,14 +260,13 @@ def get_default_imports(code_string): """ Returns a dictionary of default imports for the dynamic class constructor. """ - typing_module = importlib.import_module("typing") - default_imports = { - "Optional": typing_module.Optional, - "List": typing_module.List, - "Dict": typing_module.Dict, - "Union": typing_module.Union, - } + default_imports = { + "Optional": Optional, + "List": List, + "Dict": Dict, + "Union": Union, + } langflow_imports = list(CUSTOM_COMPONENT_SUPPORTED_TYPES.keys()) necessary_imports = find_names_in_code(code_string, langflow_imports) langflow_module = importlib.import_module("langflow.field_typing")