ref: Add ruff rules for bugbear (B) (#3983)

Add ruff rules for bugbear (B)
This commit is contained in:
Christophe Bornet 2024-10-02 18:55:51 +02:00 • committed by GitHub
commit 7e3d470845
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
86 changed files with 267 additions and 230 deletions

View file

@ -1,10 +1,10 @@
from __future__ import annotations from __future__ import annotations
import uuid import uuid
import warnings
from typing import TYPE_CHECKING, Any from typing import TYPE_CHECKING, Any
from fastapi import HTTPException from fastapi import HTTPException
from loguru import logger
from sqlalchemy import delete from sqlalchemy import delete
from sqlmodel import Session from sqlmodel import Session
@ -101,7 +101,7 @@ async def check_langflow_version(component: StoreComponentCreate):
if langflow_version is None: if langflow_version is None:
raise HTTPException(status_code=500, detail="Unable to verify the latest version of Langflow") raise HTTPException(status_code=500, detail="Unable to verify the latest version of Langflow")
if langflow_version != component.last_tested_version: if langflow_version != component.last_tested_version:
warnings.warn( logger.warning(
f"Your version of Langflow ({component.last_tested_version}) is outdated. " f"Your version of Langflow ({component.last_tested_version}) is outdated. "
f"Please update to the latest version ({langflow_version}) and try again." f"Please update to the latest version ({langflow_version}) and try again."
) )
@ -260,4 +260,4 @@ async def cascade_delete_flow(session: Session, flow: Flow):
session.exec(delete(Flow).where(Flow.id == flow.id)) # type: ignore session.exec(delete(Flow).where(Flow.id == flow.id)) # type: ignore
except Exception as e: except Exception as e:
msg = f"Unable to cascade delete flow: ${flow.id}" msg = f"Unable to cascade delete flow: ${flow.id}"
raise RuntimeError(msg, e) raise RuntimeError(msg, e) from e

View file

@ -134,7 +134,7 @@ async def retrieve_vertices_order(
), ),
) )
if "stream or streaming set to True" in str(exc): if "stream or streaming set to True" in str(exc):
raise HTTPException(status_code=400, detail=str(exc)) raise HTTPException(status_code=400, detail=str(exc)) from exc
logger.error(f"Error checking build status: {exc}") logger.error(f"Error checking build status: {exc}")
logger.exception(exc) logger.exception(exc)
raise HTTPException(status_code=500, detail=str(exc)) from exc raise HTTPException(status_code=500, detail=str(exc)) from exc
@ -202,7 +202,7 @@ async def build_flow(
), ),
) )
if "stream or streaming set to True" in str(exc): if "stream or streaming set to True" in str(exc):
raise HTTPException(status_code=400, detail=str(exc)) raise HTTPException(status_code=400, detail=str(exc)) from exc
logger.error(f"Error checking build status: {exc}") logger.error(f"Error checking build status: {exc}")
logger.exception(exc) logger.exception(exc)
raise HTTPException(status_code=500, detail=str(exc)) from exc raise HTTPException(status_code=500, detail=str(exc)) from exc

View file

@ -176,7 +176,7 @@ async def simple_run_flow_task(
async def simplified_run_flow( async def simplified_run_flow(
background_tasks: BackgroundTasks, background_tasks: BackgroundTasks,
flow: Annotated[FlowRead | None, Depends(get_flow_by_id_or_endpoint_name)], flow: Annotated[FlowRead | None, Depends(get_flow_by_id_or_endpoint_name)],
input_request: SimplifiedAPIRequest = SimplifiedAPIRequest(), input_request: SimplifiedAPIRequest | None = None,
stream: bool = False, stream: bool = False,
api_key_user: UserRead = Depends(api_key_security), api_key_user: UserRead = Depends(api_key_security),
telemetry_service: TelemetryService = Depends(get_telemetry_service), telemetry_service: TelemetryService = Depends(get_telemetry_service),
@ -244,6 +244,7 @@ async def simplified_run_flow(
supporting a wide range of applications by allowing for dynamic input and output configuration along with supporting a wide range of applications by allowing for dynamic input and output configuration along with
performance optimizations through session management and caching. performance optimizations through session management and caching.
""" """
input_request = input_request if input_request is not None else SimplifiedAPIRequest()
if flow is None: if flow is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Flow not found") raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Flow not found")
start_time = time.perf_counter() start_time = time.perf_counter()
@ -379,8 +380,8 @@ async def webhook_run_flow(
async def experimental_run_flow( async def experimental_run_flow(
session: Annotated[Session, Depends(get_session)], session: Annotated[Session, Depends(get_session)],
flow_id: UUID, flow_id: UUID,
inputs: list[InputValueRequest] | None = [InputValueRequest(components=[], input_value="")], inputs: list[InputValueRequest] | None = None,
outputs: list[str] | None = [], outputs: list[str] | None = None,
tweaks: Annotated[Tweaks | None, Body(embed=True)] = None, # noqa: F821 tweaks: Annotated[Tweaks | None, Body(embed=True)] = None, # noqa: F821
stream: Annotated[bool, Body(embed=True)] = False, # noqa: F821 stream: Annotated[bool, Body(embed=True)] = False, # noqa: F821
session_id: Annotated[None | str, Body(embed=True)] = None, # noqa: F821 session_id: Annotated[None | str, Body(embed=True)] = None, # noqa: F821
@ -438,6 +439,8 @@ async def experimental_run_flow(
flow_id_str = str(flow_id) flow_id_str = str(flow_id)
if outputs is None: if outputs is None:
outputs = [] outputs = []
if inputs is None:
inputs = [InputValueRequest(components=[], input_value="")]
artifacts = {} artifacts = {}
if session_id: if session_id:

View file

@ -64,7 +64,7 @@ async def upload_file(
await storage_service.save_file(flow_id=folder, file_name=full_file_name, data=file_content) await storage_service.save_file(flow_id=folder, file_name=full_file_name, data=file_content)
return UploadFileResponse(flowId=flow_id_str, file_path=f"{folder}/{full_file_name}") return UploadFileResponse(flowId=flow_id_str, file_path=f"{folder}/{full_file_name}")
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.get("/download/{flow_id}/{file_name}") @router.get("/download/{flow_id}/{file_name}")
@ -89,7 +89,7 @@ async def download_file(file_name: str, flow_id: UUID, storage_service: StorageS
} }
return StreamingResponse(BytesIO(file_content), media_type=content_type, headers=headers) return StreamingResponse(BytesIO(file_content), media_type=content_type, headers=headers)
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.get("/images/{flow_id}/{file_name}") @router.get("/images/{flow_id}/{file_name}")
@ -111,7 +111,7 @@ async def download_image(file_name: str, flow_id: UUID, storage_service: Storage
file_content = await storage_service.get_file(flow_id=flow_id_str, file_name=file_name) file_content = await storage_service.get_file(flow_id=flow_id_str, file_name=file_name)
return StreamingResponse(BytesIO(file_content), media_type=content_type) return StreamingResponse(BytesIO(file_content), media_type=content_type)
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.get("/profile_pictures/{folder_name}/{file_name}") @router.get("/profile_pictures/{folder_name}/{file_name}")
@ -130,7 +130,7 @@ async def download_profile_picture(
return StreamingResponse(BytesIO(file_content), media_type=content_type) return StreamingResponse(BytesIO(file_content), media_type=content_type)
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.get("/profile_pictures/list") @router.get("/profile_pictures/list")
@ -151,7 +151,7 @@ async def list_profile_pictures(storage_service: StorageService = Depends(get_st
return {"files": files} return {"files": files}
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.get("/list/{flow_id}") @router.get("/list/{flow_id}")
@ -163,7 +163,7 @@ async def list_files(
files = await storage_service.list_files(flow_id=flow_id_str) files = await storage_service.list_files(flow_id=flow_id_str)
return {"files": files} return {"files": files}
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.delete("/delete/{flow_id}/{file_name}") @router.delete("/delete/{flow_id}/{file_name}")
@ -175,4 +175,4 @@ async def delete_file(
await storage_service.delete_file(flow_id=flow_id_str, file_name=file_name) await storage_service.delete_file(flow_id=flow_id_str, file_name=file_name)
return {"message": f"File {file_name} deleted successfully"} return {"message": f"File {file_name} deleted successfully"}
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e

View file

@ -74,7 +74,7 @@ def create_folder(
return new_folder return new_folder
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.get("/", response_model=list[FolderRead], status_code=200) @router.get("/", response_model=list[FolderRead], status_code=200)
@ -91,7 +91,7 @@ def read_folders(
).all() ).all()
return sorted(folders, key=lambda x: x.name != DEFAULT_FOLDER_NAME) return sorted(folders, key=lambda x: x.name != DEFAULT_FOLDER_NAME)
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.get("/{folder_id}", response_model=FolderReadWithFlows, status_code=200) @router.get("/{folder_id}", response_model=FolderReadWithFlows, status_code=200)
@ -110,8 +110,8 @@ def read_folder(
return folder return folder
except Exception as e: except Exception as e:
if "No result found" in str(e): if "No result found" in str(e):
raise HTTPException(status_code=404, detail="Folder not found") raise HTTPException(status_code=404, detail="Folder not found") from e
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.patch("/{folder_id}", response_model=FolderRead, status_code=200) @router.patch("/{folder_id}", response_model=FolderRead, status_code=200)
@ -167,7 +167,7 @@ def update_folder(
return existing_folder return existing_folder
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.delete("/{folder_id}", status_code=204) @router.delete("/{folder_id}", status_code=204)
@ -191,7 +191,7 @@ async def delete_folder(
return Response(status_code=status.HTTP_204_NO_CONTENT) return Response(status_code=status.HTTP_204_NO_CONTENT)
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.get("/download/{folder_id}", response_model=FlowListReadWithFolderName, status_code=200) @router.get("/download/{folder_id}", response_model=FlowListReadWithFolderName, status_code=200)
@ -206,8 +206,8 @@ async def download_file(
return session.exec(select(Folder).where(Folder.id == folder_id, Folder.user_id == current_user.id)).first() return session.exec(select(Folder).where(Folder.id == folder_id, Folder.user_id == current_user.id)).first()
except Exception as e: except Exception as e:
if "No result found" in str(e): if "No result found" in str(e):
raise HTTPException(status_code=404, detail="Folder not found") raise HTTPException(status_code=404, detail="Folder not found") from e
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.post("/upload/", response_model=list[FlowRead], status_code=201) @router.post("/upload/", response_model=list[FlowRead], status_code=201)

View file

@ -29,7 +29,7 @@ async def get_vertex_builds(
vertex_builds = get_vertex_builds_by_flow_id(session, flow_id) vertex_builds = get_vertex_builds_by_flow_id(session, flow_id)
return VertexBuildMapModel.from_list_of_dicts(vertex_builds) return VertexBuildMapModel.from_list_of_dicts(vertex_builds)
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.delete("/builds", status_code=204) @router.delete("/builds", status_code=204)
@ -40,7 +40,7 @@ async def delete_vertex_builds(
try: try:
delete_vertex_builds_by_flow_id(session, flow_id) delete_vertex_builds_by_flow_id(session, flow_id)
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.get("/messages", response_model=list[MessageResponse]) @router.get("/messages", response_model=list[MessageResponse])
@ -68,7 +68,7 @@ async def get_messages(
messages = session.exec(stmt) messages = session.exec(stmt)
return [MessageResponse.model_validate(d, from_attributes=True) for d in messages] return [MessageResponse.model_validate(d, from_attributes=True) for d in messages]
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.delete("/messages", status_code=204) @router.delete("/messages", status_code=204)
@ -81,7 +81,7 @@ async def delete_messages(
session.exec(delete(MessageTable).where(MessageTable.id.in_(message_ids))) # type: ignore session.exec(delete(MessageTable).where(MessageTable.id.in_(message_ids))) # type: ignore
session.commit() session.commit()
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.put("/messages/{message_id}", response_model=MessageRead) @router.put("/messages/{message_id}", response_model=MessageRead)
@ -104,7 +104,7 @@ async def update_message(
except HTTPException as e: except HTTPException as e:
raise e raise e
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.patch("/messages/session/{old_session_id}", response_model=list[MessageResponse]) @router.patch("/messages/session/{old_session_id}", response_model=list[MessageResponse])
@ -137,7 +137,7 @@ async def update_session_id(
except HTTPException as e: except HTTPException as e:
raise e raise e
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.delete("/messages/session/{session_id}", status_code=204) @router.delete("/messages/session/{session_id}", status_code=204)
@ -154,7 +154,7 @@ async def delete_messages_session(
session.commit() session.commit()
return {"message": "Messages deleted successfully"} return {"message": "Messages deleted successfully"}
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e
@router.get("/transactions", response_model=list[TransactionReadResponse]) @router.get("/transactions", response_model=list[TransactionReadResponse])
@ -179,4 +179,4 @@ async def get_transactions(
for t in transactions for t in transactions
] ]
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) raise HTTPException(status_code=500, detail=str(e)) from e

View file

@ -67,7 +67,7 @@ async def check_if_store_has_api_key(
try: try:
is_valid = await store_service.check_api_key(api_key) is_valid = await store_service.check_api_key(api_key)
except Exception as e: except Exception as e:
raise HTTPException(status_code=400, detail=str(e)) raise HTTPException(status_code=400, detail=str(e)) from e
return {"has_api_key": api_key is not None, "is_valid": is_valid} return {"has_api_key": api_key is not None, "is_valid": is_valid}
@ -82,7 +82,7 @@ async def share_component(
await check_langflow_version(component) await check_langflow_version(component)
return await store_service.upload(store_api_key, component) return await store_service.upload(store_api_key, component)
except Exception as exc: except Exception as exc:
raise HTTPException(status_code=400, detail=str(exc)) raise HTTPException(status_code=400, detail=str(exc)) from exc
@router.patch("/components/{component_id}", response_model=CreateComponentResponse, status_code=201) @router.patch("/components/{component_id}", response_model=CreateComponentResponse, status_code=201)
@ -96,7 +96,7 @@ async def update_shared_component(
await check_langflow_version(component) await check_langflow_version(component)
return await store_service.update(store_api_key, component_id, component) return await store_service.update(store_api_key, component_id, component)
except Exception as exc: except Exception as exc:
raise HTTPException(status_code=400, detail=str(exc)) raise HTTPException(status_code=400, detail=str(exc)) from exc
@router.get("/components/", response_model=ListComponentResponseModel) @router.get("/components/", response_model=ListComponentResponseModel)
@ -164,7 +164,7 @@ async def get_tags(
except CustomException as exc: except CustomException as exc:
raise HTTPException(status_code=400, detail=str(exc)) from exc raise HTTPException(status_code=400, detail=str(exc)) from exc
except Exception as exc: except Exception as exc:
raise HTTPException(status_code=500, detail=str(exc)) raise HTTPException(status_code=500, detail=str(exc)) from exc
@router.get("/users/likes", response_model=list[UsersLikesResponse]) @router.get("/users/likes", response_model=list[UsersLikesResponse])
@ -177,7 +177,7 @@ async def get_list_of_components_liked_by_user(
except CustomException as exc: except CustomException as exc:
raise HTTPException(status_code=400, detail=str(exc)) from exc raise HTTPException(status_code=400, detail=str(exc)) from exc
except Exception as exc: except Exception as exc:
raise HTTPException(status_code=500, detail=str(exc)) raise HTTPException(status_code=500, detail=str(exc)) from exc
@router.post("/users/likes/{component_id}", response_model=UsersLikesResponse) @router.post("/users/likes/{component_id}", response_model=UsersLikesResponse)
@ -194,4 +194,4 @@ async def like_component(
except CustomException as exc: except CustomException as exc:
raise HTTPException(status_code=exc.status_code, detail=str(exc)) from exc raise HTTPException(status_code=exc.status_code, detail=str(exc)) from exc
except Exception as exc: except Exception as exc:
raise HTTPException(status_code=500, detail=str(exc)) raise HTTPException(status_code=500, detail=str(exc)) from exc

View file

@ -83,8 +83,8 @@ def update_variable(
variable=variable, variable=variable,
session=session, session=session,
) )
except NoResultFound: except NoResultFound as e:
raise HTTPException(status_code=404, detail="Variable not found") raise HTTPException(status_code=404, detail="Variable not found") from e
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=str(e)) from e raise HTTPException(status_code=500, detail=str(e)) from e

View file

@ -1,12 +1,12 @@
from __future__ import annotations from __future__ import annotations
import re import re
import warnings
from collections.abc import Callable from collections.abc import Callable
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from langchain_core.tools import BaseTool from langchain_core.tools import BaseTool
from langchain_core.tools.structured import StructuredTool from langchain_core.tools.structured import StructuredTool
from loguru import logger
from langflow.base.tools.constants import TOOL_OUTPUT_NAME from langflow.base.tools.constants import TOOL_OUTPUT_NAME
from langflow.io.schema import create_input_schema from langflow.io.schema import create_input_schema
@ -27,7 +27,7 @@ def _get_input_type(input: InputTypes):
def build_description(component: Component, output: Output): def build_description(component: Component, output: Output):
if not output.required_inputs: if not output.required_inputs:
warnings.warn(f"Output {output.name} does not have required inputs defined") logger.warning(f"Output {output.name} does not have required inputs defined")
if output.required_inputs: if output.required_inputs:
args = ", ".join( args = ", ".join(

View file

@ -1,10 +1,10 @@
from __future__ import annotations from __future__ import annotations
import warnings
from typing import Any from typing import Any
from langchain_core.runnables import RunnableConfig from langchain_core.runnables import RunnableConfig
from langchain_core.tools import BaseTool, ToolException from langchain_core.tools import BaseTool, ToolException
from loguru import logger
from pydantic.v1 import BaseModel from pydantic.v1 import BaseModel
from langflow.base.flow_processing.utils import build_data_from_result_data, format_flow_output_data from langflow.base.flow_processing.utils import build_data_from_result_data, format_flow_output_data
@ -45,7 +45,7 @@ class FlowTool(BaseTool):
"""Use the tool.""" """Use the tool."""
args_names = get_arg_names(self.inputs) args_names = get_arg_names(self.inputs)
if len(args_names) == len(args): if len(args_names) == len(args):
kwargs = {arg["arg_name"]: arg_value for arg, arg_value in zip(args_names, args)} kwargs = {arg["arg_name"]: arg_value for arg, arg_value in zip(args_names, args, strict=True)}
elif len(args_names) != len(args) and len(args) != 0: elif len(args_names) != len(args) and len(args) != 0:
msg = "Number of arguments does not match the number of inputs. Pass keyword arguments instead." msg = "Number of arguments does not match the number of inputs. Pass keyword arguments instead."
raise ToolException(msg) raise ToolException(msg)
@ -77,7 +77,7 @@ class FlowTool(BaseTool):
raise ToolException(msg) raise ToolException(msg)
if len(args) == len(args_names): if len(args) == len(args_names):
kwargs = {arg_name["arg_name"]: arg_value for arg_name, arg_value in zip(args_names, args)} kwargs = {arg_name["arg_name"]: arg_value for arg_name, arg_value in zip(args_names, args, strict=True)}
missing_args = [arg["arg_name"] for arg in args_names if arg["arg_name"] not in kwargs] missing_args = [arg["arg_name"] for arg in args_names if arg["arg_name"] not in kwargs]
if missing_args: if missing_args:
@ -101,7 +101,7 @@ class FlowTool(BaseTool):
try: try:
run_id = self.graph.run_id if self.graph else None run_id = self.graph.run_id if self.graph else None
except Exception as e: except Exception as e:
warnings.warn(f"Failed to set run_id: {e}") logger.warning(f"Failed to set run_id: {e}")
run_id = None run_id = None
run_outputs = await run_flow( run_outputs = await run_flow(
tweaks={key: {"input_value": value} for key, value in tweaks.items()}, tweaks={key: {"input_value": value} for key, value in tweaks.items()},

View file

@ -26,7 +26,6 @@ class AssistantsRun(Component):
if field_value is None: if field_value is None:
thread = self.client.beta.threads.create() thread = self.client.beta.threads.create()
self.thread_id = thread.id self.thread_id = thread.id
field_value
build_config["thread_id"] = field_value build_config["thread_id"] = field_value
inputs = [ inputs = [
@ -92,4 +91,4 @@ class AssistantsRun(Component):
except Exception as e: except Exception as e:
print(e) print(e)
msg = f"Error running assistant: {e}" msg = f"Error running assistant: {e}"
raise Exception(msg) raise Exception(msg) from e

View file

@ -94,7 +94,7 @@ class APIRequestComponent(Component):
except Exception as exc: except Exception as exc:
logger.error(f"Error parsing curl: {exc}") logger.error(f"Error parsing curl: {exc}")
msg = f"Error parsing curl: {exc}" msg = f"Error parsing curl: {exc}"
raise ValueError(msg) raise ValueError(msg) from exc
return build_config return build_config
def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None): def update_build_config(self, build_config: dotdict, field_value: Any, field_name: str | None = None):
@ -123,7 +123,7 @@ class APIRequestComponent(Component):
logger.error(f"Error decoding JSON data: {e}") logger.error(f"Error decoding JSON data: {e}")
body = None body = None
msg = f"Error decoding JSON data: {e}" msg = f"Error decoding JSON data: {e}"
raise ValueError(msg) raise ValueError(msg) from e
data = body if body else None data = body if body else None
@ -191,7 +191,10 @@ class APIRequestComponent(Component):
async with httpx.AsyncClient() as client: async with httpx.AsyncClient() as client:
results = await asyncio.gather( results = await asyncio.gather(
*[self.make_request(client, method, u, headers, rec, timeout) for u, rec in zip(urls, bodies)] *[
self.make_request(client, method, u, headers, rec, timeout)
for u, rec in zip(urls, bodies, strict=True)
]
) )
self.status = results self.status = results
return results return results

View file

@ -124,9 +124,9 @@ class ChatLiteLLMModelComponent(LCModelComponent):
litellm.drop_params = True litellm.drop_params = True
litellm.set_verbose = self.verbose litellm.set_verbose = self.verbose
except ImportError: except ImportError as e:
msg = "Could not import litellm python package. " "Please install it with `pip install litellm`" msg = "Could not import litellm python package. " "Please install it with `pip install litellm`"
raise ChatLiteLLMException(msg) raise ChatLiteLLMException(msg) from e
# Remove empty keys # Remove empty keys
if "" in self.kwargs: if "" in self.kwargs:
del self.kwargs[""] del self.kwargs[""]

View file

@ -38,10 +38,10 @@ class ExtractKeyFromDataComponent(CustomComponent):
for key in keys: for key in keys:
try: try:
extracted_keys[key] = getattr(data, key) extracted_keys[key] = getattr(data, key)
except AttributeError: except AttributeError as e:
if not silent_error: if not silent_error:
msg = f"The key '{key}' does not exist in the data." msg = f"The key '{key}' does not exist in the data."
raise KeyError(msg) raise KeyError(msg) from e
return_data = Data(data=extracted_keys) return_data = Data(data=extracted_keys)
self.status = return_data self.status = return_data
return return_data return return_data

View file

@ -22,7 +22,7 @@ class ShouldRunNextComponent(CustomComponent):
prompt = PromptTemplate.from_template(template) prompt = PromptTemplate.from_template(template)
chain = prompt | llm chain = prompt | llm
error_message = "" error_message = ""
for i in range(retries): for _i in range(retries):
result = chain.invoke( result = chain.invoke(
{"question": question, "context": context, "error_message": error_message}, {"question": question, "context": context, "error_message": error_message},
config={"callbacks": self.get_langchain_callbacks()}, config={"callbacks": self.get_langchain_callbacks()},

View file

@ -78,7 +78,7 @@ class GoogleGenerativeAIEmbeddingsComponent(Component):
title=title, title=title,
output_dimensionality=1536, output_dimensionality=1536,
) )
for text, title in zip(batch, titles_batch) for text, title in zip(batch, titles_batch, strict=True)
] ]
try: try:

View file

@ -55,12 +55,12 @@ class HuggingFaceInferenceAPIEmbeddingsComponent(LCEmbeddingsModel):
try: try:
response = requests.get(f"{inference_endpoint}/health", timeout=5) response = requests.get(f"{inference_endpoint}/health", timeout=5)
except requests.RequestException: except requests.RequestException as e:
msg = ( msg = (
f"Inference endpoint '{inference_endpoint}' is not responding. " f"Inference endpoint '{inference_endpoint}' is not responding. "
"Please ensure the URL is correct and the service is running." "Please ensure the URL is correct and the service is running."
) )
raise ValueError(msg) raise ValueError(msg) from e
if response.status_code != 200: if response.status_code != 200:
msg = f"HuggingFace health check failed: {response.status_code}" msg = f"HuggingFace health check failed: {response.status_code}"

View file

@ -52,15 +52,15 @@ class NVIDIAEmbeddingsComponent(LCEmbeddingsModel):
build_config["model"]["value"] = ids[0] build_config["model"]["value"] = ids[0]
except Exception as e: except Exception as e:
msg = f"Error getting model names: {e}" msg = f"Error getting model names: {e}"
raise ValueError(msg) raise ValueError(msg) from e
return build_config return build_config
def build_embeddings(self) -> Embeddings: def build_embeddings(self) -> Embeddings:
try: try:
from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings from langchain_nvidia_ai_endpoints import NVIDIAEmbeddings
except ImportError: except ImportError as e:
msg = "Please install langchain-nvidia-ai-endpoints to use the Nvidia model." msg = "Please install langchain-nvidia-ai-endpoints to use the Nvidia model."
raise ImportError(msg) raise ImportError(msg) from e
try: try:
output = NVIDIAEmbeddings( output = NVIDIAEmbeddings(
model=self.model, model=self.model,

View file

@ -38,9 +38,9 @@ class VertexAIEmbeddingsComponent(LCModelComponent):
def build_embeddings(self) -> Embeddings: def build_embeddings(self) -> Embeddings:
try: try:
from langchain_google_vertexai import VertexAIEmbeddings from langchain_google_vertexai import VertexAIEmbeddings
except ImportError: except ImportError as e:
msg = "Please install the langchain-google-vertexai package to use the VertexAIEmbeddings component." msg = "Please install the langchain-google-vertexai package to use the VertexAIEmbeddings component."
raise ImportError(msg) raise ImportError(msg) from e
from google.oauth2 import service_account from google.oauth2 import service_account

View file

@ -63,7 +63,7 @@ class ParseJSONDataComponent(Component):
to_filter_as_dict.append(json.loads(repair_json(f))) to_filter_as_dict.append(json.loads(repair_json(f)))
except JSONDecodeError as e: except JSONDecodeError as e:
msg = f"Invalid JSON: {e}" msg = f"Invalid JSON: {e}"
raise ValueError(msg) raise ValueError(msg) from e
full_filter_str = json.dumps(to_filter_as_dict) full_filter_str = json.dumps(to_filter_as_dict)

View file

@ -56,11 +56,11 @@ class FirecrawlCrawlApi(CustomComponent):
) -> Data: ) -> Data:
try: try:
from firecrawl.firecrawl import FirecrawlApp # type: ignore from firecrawl.firecrawl import FirecrawlApp # type: ignore
except ImportError: except ImportError as e:
msg = ( msg = (
"Could not import firecrawl integration package. " "Please install it with `pip install firecrawl-py`." "Could not import firecrawl integration package. " "Please install it with `pip install firecrawl-py`."
) )
raise ImportError(msg) raise ImportError(msg) from e
crawler_options_dict = crawlerOptions.__dict__["data"]["text"] if crawlerOptions else {} crawler_options_dict = crawlerOptions.__dict__["data"]["text"] if crawlerOptions else {}
page_options_dict = pageOptions.__dict__["data"]["text"] if pageOptions else {} page_options_dict = pageOptions.__dict__["data"]["text"] if pageOptions else {}

View file

@ -49,11 +49,11 @@ class FirecrawlScrapeApi(CustomComponent):
) -> Data: ) -> Data:
try: try:
from firecrawl.firecrawl import FirecrawlApp # type: ignore from firecrawl.firecrawl import FirecrawlApp # type: ignore
except ImportError: except ImportError as e:
msg = ( msg = (
"Could not import firecrawl integration package. " "Please install it with `pip install firecrawl-py`." "Could not import firecrawl integration package. " "Please install it with `pip install firecrawl-py`."
) )
raise ImportError(msg) raise ImportError(msg) from e
extractor_options_dict = extractorOptions.__dict__["data"]["text"] if extractorOptions else {} extractor_options_dict = extractorOptions.__dict__["data"]["text"] if extractorOptions else {}
page_options_dict = pageOptions.__dict__["data"]["text"] if pageOptions else {} page_options_dict = pageOptions.__dict__["data"]["text"] if pageOptions else {}

View file

@ -114,7 +114,7 @@ class SpiderTool(Component):
raise ValueError(msg) raise ValueError(msg)
except Exception as e: except Exception as e:
msg = f"Error: {str(e)}" msg = f"Error: {str(e)}"
raise Exception(msg) raise Exception(msg) from e
records = [] records = []

View file

@ -52,12 +52,12 @@ class AstraDBChatMemory(LCChatMemoryComponent):
def build_message_history(self) -> BaseChatMessageHistory: def build_message_history(self) -> BaseChatMessageHistory:
try: try:
from langchain_astradb.chat_message_histories import AstraDBChatMessageHistory from langchain_astradb.chat_message_histories import AstraDBChatMessageHistory
except ImportError: except ImportError as e:
msg = ( msg = (
"Could not import langchain Astra DB integration package. " "Could not import langchain Astra DB integration package. "
"Please install it with `pip install langchain-astradb`." "Please install it with `pip install langchain-astradb`."
) )
raise ImportError(msg) raise ImportError(msg) from e
return AstraDBChatMessageHistory( return AstraDBChatMessageHistory(
session_id=self.session_id, session_id=self.session_id,

View file

@ -54,9 +54,9 @@ class CassandraChatMemory(LCChatMemoryComponent):
try: try:
import cassio import cassio
except ImportError: except ImportError as e:
msg = "Could not import cassio integration package. " "Please install it with `pip install cassio`." msg = "Could not import cassio integration package. " "Please install it with `pip install cassio`."
raise ImportError(msg) raise ImportError(msg) from e
from uuid import UUID from uuid import UUID

View file

@ -34,9 +34,9 @@ class ZepChatMemory(LCChatMemoryComponent):
from zep_python.langchain import ZepChatMessageHistory from zep_python.langchain import ZepChatMessageHistory
zep_python.zep_client.API_BASE_PATH = self.api_base_path zep_python.zep_client.API_BASE_PATH = self.api_base_path
except ImportError: except ImportError as e:
msg = "Could not import zep-python package. " "Please install it with `pip install zep-python`." msg = "Could not import zep-python package. " "Please install it with `pip install zep-python`."
raise ImportError(msg) raise ImportError(msg) from e
zep_client = ZepClient(api_url=self.url, api_key=self.api_key) zep_client = ZepClient(api_url=self.url, api_key=self.api_key)
return ZepChatMessageHistory(session_id=self.session_id, zep_client=zep_client) return ZepChatMessageHistory(session_id=self.session_id, zep_client=zep_client)

View file

@ -68,9 +68,9 @@ class AmazonBedrockComponent(LCModelComponent):
def build_model(self) -> LanguageModel: # type: ignore[type-var] def build_model(self) -> LanguageModel: # type: ignore[type-var]
try: try:
from langchain_aws import ChatBedrock from langchain_aws import ChatBedrock
except ImportError: except ImportError as e:
msg = "langchain_aws is not installed. Please install it with `pip install langchain_aws`." msg = "langchain_aws is not installed. Please install it with `pip install langchain_aws`."
raise ImportError(msg) raise ImportError(msg) from e
if self.aws_access_key: if self.aws_access_key:
import boto3 # type: ignore import boto3 # type: ignore

View file

@ -62,9 +62,9 @@ class AnthropicModelComponent(LCModelComponent):
def build_model(self) -> LanguageModel: # type: ignore[type-var] def build_model(self) -> LanguageModel: # type: ignore[type-var]
try: try:
from langchain_anthropic.chat_models import ChatAnthropic from langchain_anthropic.chat_models import ChatAnthropic
except ImportError: except ImportError as e:
msg = "langchain_anthropic is not installed. Please install it with `pip install langchain_anthropic`." msg = "langchain_anthropic is not installed. Please install it with `pip install langchain_anthropic`."
raise ImportError(msg) raise ImportError(msg) from e
model = self.model model = self.model
anthropic_api_key = self.anthropic_api_key anthropic_api_key = self.anthropic_api_key
max_tokens = self.max_tokens max_tokens = self.max_tokens

View file

@ -62,9 +62,9 @@ class GoogleGenerativeAIComponent(LCModelComponent):
def build_model(self) -> LanguageModel: # type: ignore[type-var] def build_model(self) -> LanguageModel: # type: ignore[type-var]
try: try:
from langchain_google_genai import ChatGoogleGenerativeAI from langchain_google_genai import ChatGoogleGenerativeAI
except ImportError: except ImportError as e:
msg = "The 'langchain_google_genai' package is required to use the Google Generative AI model." msg = "The 'langchain_google_genai' package is required to use the Google Generative AI model."
raise ImportError(msg) raise ImportError(msg) from e
google_api_key = self.google_api_key google_api_key = self.google_api_key
model = self.model model = self.model

View file

@ -66,15 +66,15 @@ class NVIDIAModelComponent(LCModelComponent):
build_config["model_name"]["value"] = ids[0] build_config["model_name"]["value"] = ids[0]
except Exception as e: except Exception as e:
msg = f"Error getting model names: {e}" msg = f"Error getting model names: {e}"
raise ValueError(msg) raise ValueError(msg) from e
return build_config return build_config
def build_model(self) -> LanguageModel: # type: ignore[type-var] def build_model(self) -> LanguageModel: # type: ignore[type-var]
try: try:
from langchain_nvidia_ai_endpoints import ChatNVIDIA from langchain_nvidia_ai_endpoints import ChatNVIDIA
except ImportError: except ImportError as e:
msg = "Please install langchain-nvidia-ai-endpoints to use the NVIDIA model." msg = "Please install langchain-nvidia-ai-endpoints to use the NVIDIA model."
raise ImportError(msg) raise ImportError(msg) from e
nvidia_api_key = self.nvidia_api_key nvidia_api_key = self.nvidia_api_key
temperature = self.temperature temperature = self.temperature
model_name: str = self.model_name model_name: str = self.model_name

View file

@ -41,9 +41,9 @@ class ChatVertexAIComponent(LCModelComponent):
def build_model(self) -> LanguageModel: def build_model(self) -> LanguageModel:
try: try:
from langchain_google_vertexai import ChatVertexAI from langchain_google_vertexai import ChatVertexAI
except ImportError: except ImportError as e:
msg = "Please install the langchain-google-vertexai package to use the VertexAIEmbeddings component." msg = "Please install the langchain-google-vertexai package to use the VertexAIEmbeddings component."
raise ImportError(msg) raise ImportError(msg) from e
location = self.location or None location = self.location or None
if self.credentials: if self.credentials:
from google.cloud import aiplatform from google.cloud import aiplatform

View file

@ -1,6 +1,7 @@
import warnings
from typing import Any from typing import Any
from loguru import logger
from langflow.base.langchain_utilities.model import LCToolComponent from langflow.base.langchain_utilities.model import LCToolComponent
from langflow.base.tools.flow_tool import FlowTool from langflow.base.tools.flow_tool import FlowTool
from langflow.field_typing import Tool from langflow.field_typing import Tool
@ -85,7 +86,7 @@ class FlowToolComponent(LCToolComponent):
try: try:
graph.set_run_id(self.graph.run_id) graph.set_run_id(self.graph.run_id)
except Exception as e: except Exception as e:
warnings.warn(f"Failed to set run_id: {e}") logger.warning(f"Failed to set run_id: {e}")
inputs = get_flow_inputs(graph) inputs = get_flow_inputs(graph)
tool = FlowTool( tool = FlowTool(
name=self.name, name=self.name,

View file

@ -47,9 +47,9 @@ class JSONCleaner(Component):
def clean_json(self) -> Message: def clean_json(self) -> Message:
try: try:
from json_repair import repair_json # type: ignore from json_repair import repair_json # type: ignore
except ImportError: except ImportError as e:
msg = "Could not import the json_repair package." "Please install it with `pip install json_repair`." msg = "Could not import the json_repair package." "Please install it with `pip install json_repair`."
raise ImportError(msg) raise ImportError(msg) from e
"""Clean the input JSON string based on provided options and return the cleaned JSON string.""" """Clean the input JSON string based on provided options and return the cleaned JSON string."""
json_str = self.json_str json_str = self.json_str
@ -79,7 +79,7 @@ class JSONCleaner(Component):
return Message(text=result) return Message(text=result)
except Exception as e: except Exception as e:
msg = f"Error cleaning JSON string: {str(e)}" msg = f"Error cleaning JSON string: {str(e)}"
raise ValueError(msg) raise ValueError(msg) from e
def _remove_control_characters(self, s: str) -> str: def _remove_control_characters(self, s: str) -> str:
"""Remove control characters from the string.""" """Remove control characters from the string."""
@ -96,4 +96,4 @@ class JSONCleaner(Component):
return s return s
except json.JSONDecodeError as e: except json.JSONDecodeError as e:
msg = f"Invalid JSON string: {str(e)}" msg = f"Invalid JSON string: {str(e)}"
raise ValueError(msg) raise ValueError(msg) from e

View file

@ -49,7 +49,7 @@ class SQLExecutorComponent(CustomComponent):
database = SQLDatabase.from_uri(database_url) database = SQLDatabase.from_uri(database_url)
except Exception as e: except Exception as e:
msg = f"An error occurred while connecting to the database: {e}" msg = f"An error occurred while connecting to the database: {e}"
raise ValueError(msg) raise ValueError(msg) from e
try: try:
tool = QuerySQLDataBaseTool(db=database) tool = QuerySQLDataBaseTool(db=database)
result = tool.run(query, include_columns=include_columns) result = tool.run(query, include_columns=include_columns)

View file

@ -56,15 +56,15 @@ class NvidiaRerankComponent(LCVectorStoreComponent):
build_config["model"]["value"] = ids[0] build_config["model"]["value"] = ids[0]
except Exception as e: except Exception as e:
msg = f"Error getting model names: {e}" msg = f"Error getting model names: {e}"
raise ValueError(msg) raise ValueError(msg) from e
return build_config return build_config
def build_model(self): def build_model(self):
try: try:
from langchain_nvidia_ai_endpoints import NVIDIARerank from langchain_nvidia_ai_endpoints import NVIDIARerank
except ImportError: except ImportError as e:
msg = "Please install langchain-nvidia-ai-endpoints to use the NVIDIA model." msg = "Please install langchain-nvidia-ai-endpoints to use the NVIDIA model."
raise ImportError(msg) raise ImportError(msg) from e
return NVIDIARerank(api_key=self.api_key, model=self.model, base_url=self.base_url) return NVIDIARerank(api_key=self.api_key, model=self.model, base_url=self.base_url)
def build_base_retriever(self) -> Retriever: # type: ignore[type-var] def build_base_retriever(self) -> Retriever: # type: ignore[type-var]

View file

@ -38,7 +38,7 @@ class GoogleSearchAPIComponent(LCToolComponent):
def _build_wrapper(self): def _build_wrapper(self):
try: try:
from langchain_google_community import GoogleSearchAPIWrapper # type: ignore from langchain_google_community import GoogleSearchAPIWrapper # type: ignore
except ImportError: except ImportError as e:
msg = "Please install langchain-google-community to use GoogleSearchAPIWrapper." msg = "Please install langchain-google-community to use GoogleSearchAPIWrapper."
raise ImportError(msg) raise ImportError(msg) from e
return GoogleSearchAPIWrapper(google_api_key=self.google_api_key, google_cse_id=self.google_cse_id, k=self.k) return GoogleSearchAPIWrapper(google_api_key=self.google_api_key, google_cse_id=self.google_cse_id, k=self.k)

View file

@ -61,9 +61,9 @@ class PythonREPLToolComponent(LCToolComponent):
try: try:
imported_module = importlib.import_module(module) imported_module = importlib.import_module(module)
global_dict[imported_module.__name__] = imported_module global_dict[imported_module.__name__] = imported_module
except ImportError: except ImportError as e:
msg = f"Could not import module {module}" msg = f"Could not import module {module}"
raise ImportError(msg) raise ImportError(msg) from e
return global_dict return global_dict
def build_tool(self) -> Tool: def build_tool(self) -> Tool:

View file

@ -1,4 +1,5 @@
import json import json
from collections.abc import Sequence
from typing import Any from typing import Any
import requests import requests
@ -87,7 +88,7 @@ class SearXNGToolComponent(LCToolComponent):
_max_results: int = 10 _max_results: int = 10
@staticmethod @staticmethod
def search(query: str, categories: list[str] = []) -> list: def search(query: str, categories: Sequence[str] = ()) -> list:
if not SearxSearch._categories and not categories: if not SearxSearch._categories and not categories:
msg = "No categories provided." msg = "No categories provided."
raise ValueError(msg) raise ValueError(msg)

View file

@ -213,11 +213,13 @@ class AstraVectorStoreComponent(LCVectorStoreComponent):
items = list(build_config.items()) items = list(build_config.items())
# Find the index of the key to insert after # Find the index of the key to insert after
for i, (key, value) in enumerate(items): idx = len(items)
for i, (key, _value) in enumerate(items):
if key == field_name: if key == field_name:
idx = i + 1
break break
items.insert(i + 1, (new_field_name, new_parameter)) items.insert(idx, (new_field_name, new_parameter))
# Clear the original dictionary and update with the modified items # Clear the original dictionary and update with the modified items
build_config.clear() build_config.clear()
@ -366,21 +368,21 @@ class AstraVectorStoreComponent(LCVectorStoreComponent):
try: try:
from langchain_astradb import AstraDBVectorStore from langchain_astradb import AstraDBVectorStore
from langchain_astradb.utils.astradb import SetupMode from langchain_astradb.utils.astradb import SetupMode
except ImportError: except ImportError as e:
msg = ( msg = (
"Could not import langchain Astra DB integration package. " "Could not import langchain Astra DB integration package. "
"Please install it with `pip install langchain-astradb`." "Please install it with `pip install langchain-astradb`."
) )
raise ImportError(msg) raise ImportError(msg) from e
try: try:
if not self.setup_mode: if not self.setup_mode:
self.setup_mode = self._inputs["setup_mode"].options[0] self.setup_mode = self._inputs["setup_mode"].options[0]
setup_mode_value = SetupMode[self.setup_mode.upper()] setup_mode_value = SetupMode[self.setup_mode.upper()]
except KeyError: except KeyError as e:
msg = f"Invalid setup mode: {self.setup_mode}" msg = f"Invalid setup mode: {self.setup_mode}"
raise ValueError(msg) raise ValueError(msg) from e
if self.embedding: if self.embedding:
embedding_dict = {"embedding": self.embedding} embedding_dict = {"embedding": self.embedding}

View file

@ -136,9 +136,9 @@ class CassandraVectorStoreComponent(LCVectorStoreComponent):
try: try:
import cassio import cassio
from langchain_community.utilities.cassandra import SetupMode from langchain_community.utilities.cassandra import SetupMode
except ImportError: except ImportError as e:
msg = "Could not import cassio integration package. " "Please install it with `pip install cassio`." msg = "Could not import cassio integration package. " "Please install it with `pip install cassio`."
raise ImportError(msg) raise ImportError(msg) from e
from uuid import UUID from uuid import UUID
@ -234,7 +234,7 @@ class CassandraVectorStoreComponent(LCVectorStoreComponent):
"You should ingest data through Langflow (or LangChain) to query it in Langflow. " "You should ingest data through Langflow (or LangChain) to query it in Langflow. "
"Your collection does not contain a field name 'content'." "Your collection does not contain a field name 'content'."
) )
raise ValueError(msg) raise ValueError(msg) from e
raise e raise e
logger.debug(f"Retrieved documents: {len(docs)}") logger.debug(f"Retrieved documents: {len(docs)}")

View file

@ -125,9 +125,9 @@ class CassandraGraphVectorStoreComponent(LCVectorStoreComponent):
try: try:
import cassio import cassio
from langchain_community.utilities.cassandra import SetupMode from langchain_community.utilities.cassandra import SetupMode
except ImportError: except ImportError as e:
msg = "Could not import cassio integration package. " "Please install it with `pip install cassio`." msg = "Could not import cassio integration package. " "Please install it with `pip install cassio`."
raise ImportError(msg) raise ImportError(msg) from e
database_ref = self.database_ref database_ref = self.database_ref

View file

@ -106,11 +106,11 @@ class ChromaVectorStoreComponent(LCVectorStoreComponent):
try: try:
from chromadb import Client from chromadb import Client
from langchain_chroma import Chroma from langchain_chroma import Chroma
except ImportError: except ImportError as e:
msg = ( msg = (
"Could not import Chroma integration package. " "Please install it with `pip install langchain-chroma`." "Could not import Chroma integration package. " "Please install it with `pip install langchain-chroma`."
) )
raise ImportError(msg) raise ImportError(msg) from e
# Chroma settings # Chroma settings
chroma_settings = None chroma_settings = None
client = None client = None

View file

@ -83,7 +83,7 @@ class ClickhouseVectorStoreComponent(LCVectorStoreComponent):
client.command("SELECT 1") client.command("SELECT 1")
except Exception as e: except Exception as e:
msg = f"Failed to connect to Clickhouse: {e}" msg = f"Failed to connect to Clickhouse: {e}"
raise ValueError(msg) raise ValueError(msg) from e
documents = [] documents = []
for _input in self.ingest_data or []: for _input in self.ingest_data or []:

View file

@ -59,7 +59,7 @@ class CouchbaseVectorStoreComponent(LCVectorStoreComponent):
cluster.wait_until_ready(timedelta(seconds=5)) cluster.wait_until_ready(timedelta(seconds=5))
except Exception as e: except Exception as e:
msg = f"Failed to connect to Couchbase: {e}" msg = f"Failed to connect to Couchbase: {e}"
raise ValueError(msg) raise ValueError(msg) from e
documents = [] documents = []
for _input in self.ingest_data or []: for _input in self.ingest_data or []:

View file

@ -180,28 +180,28 @@ class HCDVectorStoreComponent(LCVectorStoreComponent):
try: try:
from langchain_astradb import AstraDBVectorStore from langchain_astradb import AstraDBVectorStore
from langchain_astradb.utils.astradb import SetupMode from langchain_astradb.utils.astradb import SetupMode
except ImportError: except ImportError as e:
msg = ( msg = (
"Could not import langchain Astra DB integration package. " "Could not import langchain Astra DB integration package. "
"Please install it with `pip install langchain-astradb`." "Please install it with `pip install langchain-astradb`."
) )
raise ImportError(msg) raise ImportError(msg) from e
try: try:
from astrapy.authentication import UsernamePasswordTokenProvider from astrapy.authentication import UsernamePasswordTokenProvider
from astrapy.constants import Environment from astrapy.constants import Environment
except ImportError: except ImportError as e:
msg = "Could not import astrapy integration package. " "Please install it with `pip install astrapy`." msg = "Could not import astrapy integration package. " "Please install it with `pip install astrapy`."
raise ImportError(msg) raise ImportError(msg) from e
try: try:
if not self.setup_mode: if not self.setup_mode:
self.setup_mode = self._inputs["setup_mode"].options[0] self.setup_mode = self._inputs["setup_mode"].options[0]
setup_mode_value = SetupMode[self.setup_mode.upper()] setup_mode_value = SetupMode[self.setup_mode.upper()]
except KeyError: except KeyError as e:
msg = f"Invalid setup mode: {self.setup_mode}" msg = f"Invalid setup mode: {self.setup_mode}"
raise ValueError(msg) raise ValueError(msg) from e
if not isinstance(self.embedding, dict): if not isinstance(self.embedding, dict):
embedding_dict = {"embedding": self.embedding} embedding_dict = {"embedding": self.embedding}

View file

@ -73,11 +73,11 @@ class MilvusVectorStoreComponent(LCVectorStoreComponent):
def build_vector_store(self): def build_vector_store(self):
try: try:
from langchain_milvus.vectorstores import Milvus as LangchainMilvus from langchain_milvus.vectorstores import Milvus as LangchainMilvus
except ImportError: except ImportError as e:
msg = ( msg = (
"Could not import Milvus integration package. " "Please install it with `pip install langchain-milvus`." "Could not import Milvus integration package. " "Please install it with `pip install langchain-milvus`."
) )
raise ImportError(msg) raise ImportError(msg) from e
self.connection_args.update(uri=self.uri, token=self.password) self.connection_args.update(uri=self.uri, token=self.password)
milvus_store = LangchainMilvus( milvus_store = LangchainMilvus(
embedding_function=self.embedding, embedding_function=self.embedding,

View file

@ -38,16 +38,16 @@ class MongoVectorStoreComponent(LCVectorStoreComponent):
def build_vector_store(self) -> MongoDBAtlasVectorSearch: def build_vector_store(self) -> MongoDBAtlasVectorSearch:
try: try:
from pymongo import MongoClient from pymongo import MongoClient
except ImportError: except ImportError as e:
msg = "Please install pymongo to use MongoDB Atlas Vector Store" msg = "Please install pymongo to use MongoDB Atlas Vector Store"
raise ImportError(msg) raise ImportError(msg) from e
try: try:
mongo_client: MongoClient = MongoClient(self.mongodb_atlas_cluster_uri) mongo_client: MongoClient = MongoClient(self.mongodb_atlas_cluster_uri)
collection = mongo_client[self.db_name][self.collection_name] collection = mongo_client[self.db_name][self.collection_name]
except Exception as e: except Exception as e:
msg = f"Failed to connect to MongoDB Atlas: {e}" msg = f"Failed to connect to MongoDB Atlas: {e}"
raise ValueError(msg) raise ValueError(msg) from e
documents = [] documents = []
for _input in self.ingest_data or []: for _input in self.ingest_data or []:

View file

@ -58,9 +58,9 @@ class VectaraVectorStoreComponent(LCVectorStoreComponent):
""" """
try: try:
from langchain_community.vectorstores import Vectara from langchain_community.vectorstores import Vectara
except ImportError: except ImportError as e:
msg = "Could not import Vectara. Please install it with `pip install langchain-community`." msg = "Could not import Vectara. Please install it with `pip install langchain-community`."
raise ImportError(msg) raise ImportError(msg) from e
vectara = Vectara( vectara = Vectara(
vectara_customer_id=self.vectara_customer_id, vectara_customer_id=self.vectara_customer_id,

View file

@ -136,9 +136,9 @@ class VectaraRagComponent(Component):
try: try:
from langchain_community.vectorstores import Vectara from langchain_community.vectorstores import Vectara
from langchain_community.vectorstores.vectara import RerankConfig, SummaryConfig, VectaraQueryConfig from langchain_community.vectorstores.vectara import RerankConfig, SummaryConfig, VectaraQueryConfig
except ImportError: except ImportError as e:
msg = "Could not import Vectara. Please install it with `pip install langchain-community`." msg = "Could not import Vectara. Please install it with `pip install langchain-community`."
raise ImportError(msg) raise ImportError(msg) from e
vectara = Vectara(self.vectara_customer_id, self.vectara_corpus_id, self.vectara_api_key) vectara = Vectara(self.vectara_customer_id, self.vectara_corpus_id, self.vectara_api_key)
rerank_config = RerankConfig(self.reranker, self.reranker_k, self.diversity_bias) rerank_config = RerankConfig(self.reranker, self.reranker_k, self.diversity_bias)

View file

@ -1,7 +1,7 @@
import warnings
from collections.abc import Callable from collections.abc import Callable
import emoji import emoji
from loguru import logger
def validate_icon(value: str, *args, **kwargs): def validate_icon(value: str, *args, **kwargs):
@ -18,7 +18,7 @@ def validate_icon(value: str, *args, **kwargs):
emoji_value = emoji.emojize(value, variant="emoji_type") emoji_value = emoji.emojize(value, variant="emoji_type")
if value == emoji_value: if value == emoji_value:
warnings.warn(f"Invalid emoji. {value} is not a valid emoji.") logger.warning(f"Invalid emoji. {value} is not a valid emoji.")
return value return value
return emoji_value return emoji_value

View file

@ -217,7 +217,7 @@ class CodeParser:
defaults = missing_defaults + default_values defaults = missing_defaults + default_values
return [self.parse_arg(arg, default) for arg, default in zip(node.args.args, defaults)] return [self.parse_arg(arg, default) for arg, default in zip(node.args.args, defaults, strict=True)]
def parse_varargs(self, node: ast.FunctionDef) -> list[dict[str, Any]]: def parse_varargs(self, node: ast.FunctionDef) -> list[dict[str, Any]]:
""" """
@ -238,7 +238,7 @@ class CodeParser:
ast.unparse(default) if default else None for default in node.args.kw_defaults ast.unparse(default) if default else None for default in node.args.kw_defaults
] ]
return [self.parse_arg(arg, default) for arg, default in zip(node.args.kwonlyargs, kw_defaults)] return [self.parse_arg(arg, default) for arg, default in zip(node.args.kwonlyargs, kw_defaults, strict=True)]
def parse_kwargs(self, node: ast.FunctionDef) -> list[dict[str, Any]]: def parse_kwargs(self, node: ast.FunctionDef) -> list[dict[str, Any]]:
""" """

View file

@ -1,10 +1,10 @@
import operator import operator
import warnings
from typing import Any, ClassVar from typing import Any, ClassVar
from uuid import UUID from uuid import UUID
from cachetools import TTLCache, cachedmethod from cachetools import TTLCache, cachedmethod
from fastapi import HTTPException from fastapi import HTTPException
from loguru import logger
from langflow.custom.attributes import ATTR_FUNC_MAPPING from langflow.custom.attributes import ATTR_FUNC_MAPPING
from langflow.custom.code_parser import CodeParser from langflow.custom.code_parser import CodeParser
@ -35,13 +35,13 @@ class BaseComponent:
self.cache = TTLCache(maxsize=1024, ttl=60) self.cache = TTLCache(maxsize=1024, ttl=60)
for key, value in data.items(): for key, value in data.items():
if key == "user_id": if key == "user_id":
setattr(self, "_user_id", value) self._user_id = value
else: else:
setattr(self, key, value) setattr(self, key, value)
def __setattr__(self, key, value): def __setattr__(self, key, value):
if key == "_user_id" and hasattr(self, "_user_id") and getattr(self, "_user_id") is not None: if key == "_user_id" and self._user_id is not None:
warnings.warn("user_id is immutable and cannot be changed.") logger.warning("user_id is immutable and cannot be changed.")
super().__setattr__(key, value) super().__setattr__(key, value)
@cachedmethod(cache=operator.attrgetter("cache")) @cachedmethod(cache=operator.attrgetter("cache"))

View file

@ -113,7 +113,7 @@ class Component(CustomComponent):
def _reset_all_output_values(self): def _reset_all_output_values(self):
if isinstance(self._outputs_map, dict): if isinstance(self._outputs_map, dict):
for output in self._outputs_map.values(): for output in self._outputs_map.values():
setattr(output, "value", UNDEFINED) output.value = UNDEFINED
def _build_state_model(self): def _build_state_model(self):
if self._state_model: if self._state_model:
@ -164,9 +164,9 @@ class Component(CustomComponent):
raise ValueError(msg) raise ValueError(msg)
class_code = inspect.getsource(module) class_code = inspect.getsource(module)
self._code = class_code self._code = class_code
except OSError: except OSError as e:
msg = f"Could not find source code for {self.__class__.__name__}" msg = f"Could not find source code for {self.__class__.__name__}"
raise ValueError(msg) raise ValueError(msg) from e
def set(self, **kwargs): def set(self, **kwargs):
""" """
@ -441,9 +441,9 @@ class Component(CustomComponent):
if callable(value) and self._inherits_from_component(value): if callable(value) and self._inherits_from_component(value):
try: try:
self._method_is_valid_output(value) self._method_is_valid_output(value)
except ValueError: except ValueError as e:
msg = f"Method {value.__name__} is not a valid output of {value.__self__.__class__.__name__}" msg = f"Method {value.__name__} is not a valid output of {value.__self__.__class__.__name__}"
raise ValueError(msg) raise ValueError(msg) from e
self._connect_to_component(key, value, _input) self._connect_to_component(key, value, _input)
else: else:
self._set_parameter_or_attribute(key, value) self._set_parameter_or_attribute(key, value)
@ -569,15 +569,15 @@ class Component(CustomComponent):
for name, value in self._parameters.items(): for name, value in self._parameters.items():
try: try:
template[name]["value"] = value template[name]["value"] = value
except KeyError: except KeyError as e:
close_match = find_closest_match(name, list(template.keys())) close_match = find_closest_match(name, list(template.keys()))
if close_match: if close_match:
msg = ( msg = (
f"Parameter '{name}' not found in {self.__class__.__name__}. " f"Did you mean '{close_match}'?" f"Parameter '{name}' not found in {self.__class__.__name__}. " f"Did you mean '{close_match}'?"
) )
raise ValueError(msg) raise ValueError(msg) from e
msg = f"Parameter {name} not found in {self.__class__.__name__}. " msg = f"Parameter {name} not found in {self.__class__.__name__}. "
raise ValueError(msg) raise ValueError(msg) from e
def _get_method_return_type(self, method_name: str) -> list[str]: def _get_method_return_type(self, method_name: str) -> list[str]:
method = getattr(self, method_name) method = getattr(self, method_name)
@ -594,7 +594,7 @@ class Component(CustomComponent):
#! works and then update this later #! works and then update this later
field_config = self.get_template_config(self) field_config = self.get_template_config(self)
frontend_node = ComponentFrontendNode.from_inputs(**field_config) frontend_node = ComponentFrontendNode.from_inputs(**field_config)
for key, value in self._inputs.items(): for key, _value in self._inputs.items():
frontend_node.set_field_load_from_db_in_template(key, False) frontend_node.set_field_load_from_db_in_template(key, False)
self._map_parameters_on_frontend_node(frontend_node) self._map_parameters_on_frontend_node(frontend_node)

View file

@ -118,7 +118,7 @@ class CustomComponent(BaseComponent):
self._vertex.graph.update_state(name=name, record=value, caller=self._vertex.id) self._vertex.graph.update_state(name=name, record=value, caller=self._vertex.id)
except Exception as e: except Exception as e:
msg = f"Error updating state: {e}" msg = f"Error updating state: {e}"
raise ValueError(msg) raise ValueError(msg) from e
def stop(self, output_name: str | None = None): def stop(self, output_name: str | None = None):
if not output_name and self._vertex and len(self._vertex.outputs) == 1: if not output_name and self._vertex and len(self._vertex.outputs) == 1:
@ -133,7 +133,7 @@ class CustomComponent(BaseComponent):
self.graph.mark_branch(vertex_id=self._vertex.id, output_name=output_name, state="INACTIVE") self.graph.mark_branch(vertex_id=self._vertex.id, output_name=output_name, state="INACTIVE")
except Exception as e: except Exception as e:
msg = f"Error stopping {self.display_name}: {e}" msg = f"Error stopping {self.display_name}: {e}"
raise ValueError(msg) raise ValueError(msg) from e
def append_state(self, name: str, value: Any): def append_state(self, name: str, value: Any):
if not self._vertex: if not self._vertex:
@ -143,7 +143,7 @@ class CustomComponent(BaseComponent):
self._vertex.graph.append_state(name=name, record=value, caller=self._vertex.id) self._vertex.graph.append_state(name=name, record=value, caller=self._vertex.id)
except Exception as e: except Exception as e:
msg = f"Error appending state: {e}" msg = f"Error appending state: {e}"
raise ValueError(msg) raise ValueError(msg) from e
def get_state(self, name: str): def get_state(self, name: str):
if not self._vertex: if not self._vertex:
@ -153,7 +153,7 @@ class CustomComponent(BaseComponent):
return self._vertex.graph.get_state(name=name) return self._vertex.graph.get_state(name=name)
except Exception as e: except Exception as e:
msg = f"Error getting state: {e}" msg = f"Error getting state: {e}"
raise ValueError(msg) raise ValueError(msg) from e
@staticmethod @staticmethod
def resolve_path(path: str) -> str: def resolve_path(path: str) -> str:
@ -278,9 +278,9 @@ class CustomComponent(BaseComponent):
else: else:
try: try:
data_dict[key] = model_dump[key] data_dict[key] = model_dump[key]
except KeyError: except KeyError as e:
msg = f"Key {key} not found in {item}" msg = f"Key {key} not found in {item}"
raise ValueError(msg) raise ValueError(msg) from e
elif isinstance(item, str): elif isinstance(item, str):
data_dict = {"text": item} data_dict = {"text": item}
@ -512,7 +512,7 @@ class CustomComponent(BaseComponent):
return list_flows(user_id=str(self._user_id)) return list_flows(user_id=str(self._user_id))
except Exception as e: except Exception as e:
msg = f"Error listing flows: {e}" msg = f"Error listing flows: {e}"
raise ValueError(msg) raise ValueError(msg) from e
def build(self, *args: Any, **kwargs: Any) -> Any: def build(self, *args: Any, **kwargs: Any) -> Any:
""" """

View file

@ -324,7 +324,7 @@ class DirectoryReader:
tasks = [self.process_file_async(file_path) for file_path in file_paths] tasks = [self.process_file_async(file_path) for file_path in file_paths]
results = await asyncio.gather(*tasks) results = await asyncio.gather(*tasks)
for file_path, (validation_result, result_content) in zip(file_paths, results): for file_path, (validation_result, result_content) in zip(file_paths, results, strict=True):
menu_name = os.path.basename(os.path.dirname(file_path)) menu_name = os.path.basename(os.path.dirname(file_path))
filename = os.path.basename(file_path) filename = os.path.basename(file_path)

View file

@ -2,7 +2,6 @@ import ast
import contextlib import contextlib
import re import re
import traceback import traceback
import warnings
from typing import Any from typing import Any
from uuid import UUID from uuid import UUID
@ -177,7 +176,7 @@ def add_new_custom_field(
field_config["is_list"] = is_list or field_config.get("list", False) or field_contains_list field_config["is_list"] = is_list or field_config.get("list", False) or field_contains_list
if "name" in field_config: if "name" in field_config:
warnings.warn("The 'name' key in field_config is used to build the object and can't be changed.") logger.warning("The 'name' key in field_config is used to build the object and can't be changed.")
required = field_config.pop("required", field_required) required = field_config.pop("required", field_required)
placeholder = field_config.pop("placeholder", "") placeholder = field_config.pop("placeholder", "")

View file

@ -5,7 +5,6 @@ import contextlib
import copy import copy
import json import json
import uuid import uuid
import warnings
from collections import defaultdict, deque from collections import defaultdict, deque
from collections.abc import Generator, Iterable from collections.abc import Generator, Iterable
from datetime import datetime, timezone from datetime import datetime, timezone
@ -263,11 +262,11 @@ class Graph:
input_field = target_vertex.get_input(input_name) input_field = target_vertex.get_input(input_name)
input_types = input_field.input_types input_types = input_field.input_types
input_field_type = str(input_field.field_type) input_field_type = str(input_field.field_type)
except ValueError: except ValueError as e:
input_field = target_vertex.data.get("node", {}).get("template", {}).get(input_name) input_field = target_vertex.data.get("node", {}).get("template", {}).get(input_name)
if not input_field: if not input_field:
msg = f"Input field {input_name} not found in target vertex {target_id}" msg = f"Input field {input_name} not found in target vertex {target_id}"
raise ValueError(msg) raise ValueError(msg) from e
input_types = input_field.get("input_types", []) input_types = input_field.get("input_types", [])
input_field_type = input_field.get("type", "") input_field_type = input_field.get("type", "")
@ -793,7 +792,7 @@ class Graph:
types = [] types = []
for _ in range(len(inputs) - len(types)): for _ in range(len(inputs) - len(types)):
types.append("chat") # default to chat types.append("chat") # default to chat
for run_inputs, components, input_type in zip(inputs, inputs_components, types): for run_inputs, components, input_type in zip(inputs, inputs_components, types, strict=True):
run_outputs = await self._run( run_outputs = await self._run(
inputs=run_inputs, inputs=run_inputs,
input_components=components, input_components=components,
@ -1199,9 +1198,9 @@ class Graph:
"""Returns a vertex by id.""" """Returns a vertex by id."""
try: try:
return self.vertex_map[vertex_id] return self.vertex_map[vertex_id]
except KeyError: except KeyError as e:
msg = f"Vertex {vertex_id} not found" msg = f"Vertex {vertex_id} not found"
raise ValueError(msg) raise ValueError(msg) from e
def get_root_of_group_node(self, vertex_id: str) -> Vertex: def get_root_of_group_node(self, vertex_id: str) -> Vertex:
"""Returns the root of a group node.""" """Returns the root of a group node."""
@ -1646,7 +1645,7 @@ class Graph:
new_edge = self.build_edge(edge) new_edge = self.build_edge(edge)
edges.add(new_edge) edges.add(new_edge)
if self.vertices and not edges: if self.vertices and not edges:
warnings.warn("Graph has vertices but no edges") logger.warning("Graph has vertices but no edges")
return list(cast(Iterable[CycleEdge], edges)) return list(cast(Iterable[CycleEdge], edges))
def build_edge(self, edge: EdgeData) -> CycleEdge | Edge: def build_edge(self, edge: EdgeData) -> CycleEdge | Edge:

View file

@ -62,6 +62,6 @@ def create_state_model_from_graph(graph: BaseModel) -> type[BaseModel]:
] ]
fields = { fields = {
camel_to_snake(vertex.id): state_model_getter camel_to_snake(vertex.id): state_model_getter
for vertex, state_model_getter in zip(graph.vertices, state_model_getters) for vertex, state_model_getter in zip(graph.vertices, state_model_getters, strict=False)
} }
return create_state_model(model_name="GraphStateModel", validate=False, **fields) return create_state_model(model_name="GraphStateModel", validate=False, **fields)

View file

@ -281,14 +281,14 @@ def sort_up_to_vertex(
"""Cuts the graph up to a given vertex and sorts the resulting subgraph.""" """Cuts the graph up to a given vertex and sorts the resulting subgraph."""
try: try:
stop_or_start_vertex = graph[vertex_id] stop_or_start_vertex = graph[vertex_id]
except KeyError: except KeyError as e:
if parent_node_map is None: if parent_node_map is None:
msg = "Parent node map is required to find the root of a group node" msg = "Parent node map is required to find the root of a group node"
raise ValueError(msg) raise ValueError(msg) from e
vertex_id = get_root_of_group_node(graph=graph, vertex_id=vertex_id, parent_node_map=parent_node_map) vertex_id = get_root_of_group_node(graph=graph, vertex_id=vertex_id, parent_node_map=parent_node_map)
if vertex_id not in graph: if vertex_id not in graph:
msg = f"Vertex {vertex_id} not found into graph" msg = f"Vertex {vertex_id} not found into graph"
raise ValueError(msg) raise ValueError(msg) from e
stop_or_start_vertex = graph[vertex_id] stop_or_start_vertex = graph[vertex_id]
visited, excluded = set(), set() visited, excluded = set(), set()

View file

@ -39,7 +39,7 @@ def list_flows(*, user_id: str | None = None) -> list[Data]:
return [flow.to_data() for flow in flows] return [flow.to_data() for flow in flows]
except Exception as e: except Exception as e:
msg = f"Error listing flows: {e}" msg = f"Error listing flows: {e}"
raise ValueError(msg) raise ValueError(msg) from e
async def load_flow( async def load_flow(
@ -161,7 +161,7 @@ def generate_function_for_flow(
# Map original argument names to their corresponding Pythonic variable names in the function # Map original argument names to their corresponding Pythonic variable names in the function
arg_mappings = ", ".join( arg_mappings = ", ".join(
f'"{original_name}": {name}' f'"{original_name}": {name}'
for original_name, name in zip(original_arg_names, [arg.split(":")[0] for arg in args]) for original_name, name in zip(original_arg_names, [arg.split(":")[0] for arg in args], strict=True)
) )
func_body = f""" func_body = f"""

View file

@ -78,7 +78,7 @@ def update_projects_components_with_latest_component_versions(project_data, all_
} }
) )
node_data["template"][key]["value"] = value["value"] node_data["template"][key]["value"] = value["value"]
for key, value in node_data["template"].items(): for key in node_data["template"]:
if key not in latest_template: if key not in latest_template:
node_data["template"][key]["input_types"] = DEFAULT_PROMPT_INTUT_TYPES node_data["template"][key]["input_types"] = DEFAULT_PROMPT_INTUT_TYPES
node_changes_log[node_data["display_name"]].append( node_changes_log[node_data["display_name"]].append(
@ -359,7 +359,7 @@ def load_starter_projects(retries=3, delay=1) -> list[tuple[Path, dict]]:
attempt += 1 attempt += 1
if attempt >= retries: if attempt >= retries:
msg = f"Error loading starter project {file}: {e}" msg = f"Error loading starter project {file}: {e}"
raise ValueError(msg) raise ValueError(msg) from e
time.sleep(delay) # Wait before retrying time.sleep(delay) # Wait before retrying
return starter_projects return starter_projects

View file

@ -108,10 +108,14 @@ class StrInput(BaseInputMixin, ListableInputMixin, DatabaseLoadMixin, MetadataTr
if _info.data.get("input_types") and v.__class__.__name__ not in _info.data.get("input_types"): if _info.data.get("input_types") and v.__class__.__name__ not in _info.data.get("input_types"):
warnings.warn( warnings.warn(
f"Invalid value type {type(v)} for input {_info.data.get('name')}. " f"Invalid value type {type(v)} for input {_info.data.get('name')}. "
f"Expected types: {_info.data.get('input_types')}" f"Expected types: {_info.data.get('input_types')}",
stacklevel=4,
) )
else: else:
warnings.warn(f"Invalid value type {type(v)} for input {_info.data.get('name')}.") warnings.warn(
f"Invalid value type {type(v)} for input {_info.data.get('name')}.",
stacklevel=4,
)
return v return v
@field_validator("value") @field_validator("value")

View file

@ -36,9 +36,7 @@ def update_memory_keys(langchain_object, possible_new_mem_key):
if key not in [langchain_object.memory.memory_key, possible_new_mem_key] if key not in [langchain_object.memory.memory_key, possible_new_mem_key]
][0] ][0]
keys = [input_key, output_key, possible_new_mem_key] for key, attr in [(input_key, "input_key"), (output_key, "output_key"), (possible_new_mem_key, "memory_key")]:
attrs = ["input_key", "output_key", "memory_key"]
for key, attr in zip(keys, attrs):
try: try:
setattr(langchain_object.memory, attr, key) setattr(langchain_object.memory, attr, key)
except ValueError as exc: except ValueError as exc:

View file

@ -28,7 +28,7 @@ def upload(file_path, host, flow_id):
raise Exception(msg) raise Exception(msg)
except Exception as e: except Exception as e:
msg = f"Error uploading file: {e}" msg = f"Error uploading file: {e}"
raise Exception(msg) raise Exception(msg) from e
def upload_file(file_path: str, host: str, flow_id: str, components: list[str], tweaks: dict | None = None): def upload_file(file_path: str, host: str, flow_id: str, components: list[str], tweaks: dict | None = None):
@ -65,7 +65,7 @@ def upload_file(file_path: str, host: str, flow_id: str, components: list[str],
raise ValueError(msg) raise ValueError(msg)
except Exception as e: except Exception as e:
msg = f"Error uploading file: {e}" msg = f"Error uploading file: {e}"
raise ValueError(msg) raise ValueError(msg) from e
def get_flow(url: str, flow_id: str): def get_flow(url: str, flow_id: str):
@ -92,4 +92,4 @@ def get_flow(url: str, flow_id: str):
raise Exception(msg) raise Exception(msg)
except Exception as e: except Exception as e:
msg = f"Error retrieving flow: {e}" msg = f"Error retrieving flow: {e}"
raise Exception(msg) raise Exception(msg) from e

View file

@ -78,7 +78,7 @@ class SizedLogBuffer:
with self._wlock: with self._wlock:
as_list = list(self.buffer) as_list = list(self.buffer)
max_index = -1 max_index = -1
for i, (ts, msg) in enumerate(as_list): for i, (ts, _) in enumerate(as_list):
if ts >= timestamp: if ts >= timestamp:
max_index = i max_index = i
break break

View file

@ -1,4 +1,3 @@
import warnings
from collections.abc import Sequence from collections.abc import Sequence
from uuid import UUID from uuid import UUID
@ -124,7 +123,7 @@ def store_message(
ValueError: If any of the required parameters (session_id, sender, sender_name) is not provided. ValueError: If any of the required parameters (session_id, sender, sender_name) is not provided.
""" """
if not message: if not message:
warnings.warn("No message provided.") logger.warning("No message provided.")
return [] return []
if not message.session_id or not message.sender or not message.sender_name: if not message.session_id or not message.sender or not message.sender_name:

View file

@ -164,10 +164,10 @@ class Data(BaseModel):
if key in {"data", "text_key"} or key.startswith("_"): if key in {"data", "text_key"} or key.startswith("_"):
return super().__getattr__(key) return super().__getattr__(key)
return self.data[key] return self.data[key]
except KeyError: except KeyError as e:
# Fallback to default behavior to raise AttributeError for undefined attributes # Fallback to default behavior to raise AttributeError for undefined attributes
msg = f"'{type(self).__name__}' object has no attribute '{key}'" msg = f"'{type(self).__name__}' object has no attribute '{key}'"
raise AttributeError(msg) raise AttributeError(msg) from e
def __setattr__(self, key, value): def __setattr__(self, key, value):
""" """

View file

@ -29,9 +29,9 @@ class dotdict(dict):
value = dotdict(value) value = dotdict(value)
self[attr] = value # Update self to nest dotdict for future accesses self[attr] = value # Update self to nest dotdict for future accesses
return value return value
except KeyError: except KeyError as e:
msg = f"'dotdict' object has no attribute '{attr}'" msg = f"'dotdict' object has no attribute '{attr}'"
raise AttributeError(msg) raise AttributeError(msg) from e
def __setattr__(self, key, value): def __setattr__(self, key, value):
""" """
@ -57,9 +57,9 @@ class dotdict(dict):
""" """
try: try:
del self[key] del self[key]
except KeyError: except KeyError as e:
msg = f"'dotdict' object has no attribute '{key}'" msg = f"'dotdict' object has no attribute '{key}'"
raise AttributeError(msg) raise AttributeError(msg) from e
def __missing__(self, key): def __missing__(self, key):
""" """

View file

@ -31,9 +31,9 @@ def _timestamp_to_str(timestamp: datetime | str) -> str:
try: try:
datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S") datetime.strptime(timestamp, "%Y-%m-%d %H:%M:%S")
return timestamp return timestamp
except ValueError: except ValueError as e:
msg = f"Invalid timestamp: {timestamp}" msg = f"Invalid timestamp: {timestamp}"
raise ValueError(msg) raise ValueError(msg) from e
return timestamp.strftime("%Y-%m-%d %H:%M:%S") return timestamp.strftime("%Y-%m-%d %H:%M:%S")

View file

@ -23,7 +23,7 @@ class Service(ABC):
return schema return schema
async def teardown(self): async def teardown(self):
pass return
def set_ready(self): def set_ready(self):
self.ready = True self.ready = True

View file

@ -1,7 +1,6 @@
# Path: src/backend/langflow/services/database/models/flow/model.py # Path: src/backend/langflow/services/database/models/flow/model.py
import re import re
import warnings
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import TYPE_CHECKING, Optional from typing import TYPE_CHECKING, Optional
from uuid import UUID, uuid4 from uuid import UUID, uuid4
@ -9,6 +8,7 @@ from uuid import UUID, uuid4
import emoji import emoji
from emoji import purely_emoji # type: ignore from emoji import purely_emoji # type: ignore
from fastapi import HTTPException, status from fastapi import HTTPException, status
from loguru import logger
from pydantic import field_serializer, field_validator from pydantic import field_serializer, field_validator
from sqlalchemy import Text, UniqueConstraint from sqlalchemy import Text, UniqueConstraint
from sqlmodel import JSON, Column, Field, Relationship, SQLModel from sqlmodel import JSON, Column, Field, Relationship, SQLModel
@ -88,8 +88,7 @@ class FlowBase(SQLModel):
emoji_value = emoji.emojize(v, variant="emoji_type") emoji_value = emoji.emojize(v, variant="emoji_type")
if v == emoji_value: if v == emoji_value:
warnings.warn(f"Invalid emoji. {v} is not a valid emoji.") logger.warning(f"Invalid emoji. {v} is not a valid emoji.")
icon = v
icon = emoji_value icon = emoji_value
if purely_emoji(icon): if purely_emoji(icon):

View file

@ -220,7 +220,7 @@ class DatabaseService(Service):
logger.error(f"AutogenerateDiffsDetected: {exc}") logger.error(f"AutogenerateDiffsDetected: {exc}")
if not fix: if not fix:
msg = f"There's a mismatch between the models and the database.\n{exc}" msg = f"There's a mismatch between the models and the database.\n{exc}"
raise RuntimeError(msg) raise RuntimeError(msg) from exc
if fix: if fix:
self.try_downgrade_upgrade_until_success(alembic_cfg) self.try_downgrade_upgrade_until_success(alembic_cfg)

View file

@ -54,9 +54,9 @@ def infer_service_types(factory_class: type[ServiceFactory], available_services=
# Attempt to find a matching enum value # Attempt to find a matching enum value
service_type = ServiceType[type_name] service_type = ServiceType[type_name]
service_types.append(service_type) service_types.append(service_type)
except KeyError: except KeyError as e:
msg = f"No matching ServiceType for parameter type: {param_type.__name__}" msg = f"No matching ServiceType for parameter type: {param_type.__name__}"
raise ValueError(msg) raise ValueError(msg) from e
return service_types return service_types

View file

@ -132,7 +132,7 @@ class ServiceManager:
module = importlib.import_module(module_name) module = importlib.import_module(module_name)
# Find all classes in the module that are subclasses of ServiceFactory # Find all classes in the module that are subclasses of ServiceFactory
for name, obj in inspect.getmembers(module, inspect.isclass): for _, obj in inspect.getmembers(module, inspect.isclass):
if issubclass(obj, ServiceFactory) and obj is not ServiceFactory: if issubclass(obj, ServiceFactory) and obj is not ServiceFactory:
factories.append(obj()) factories.append(obj())
break break

View file

@ -44,7 +44,7 @@ async def user_data_context(store_service: StoreService, api_key: str | None = N
except HTTPStatusError as exc: except HTTPStatusError as exc:
if exc.response.status_code == 403: if exc.response.status_code == 403:
msg = "Invalid API key" msg = "Invalid API key"
raise ValueError(msg) raise ValueError(msg) from exc
try: try:
yield yield
finally: finally:
@ -119,10 +119,10 @@ class StoreService(Service):
if exc.response.status_code in [403, 401]: if exc.response.status_code in [403, 401]:
return False return False
msg = f"Unexpected status code: {exc.response.status_code}" msg = f"Unexpected status code: {exc.response.status_code}"
raise ValueError(msg) raise ValueError(msg) from exc
except Exception as exc: except Exception as exc:
msg = f"Unexpected error: {exc}" msg = f"Unexpected error: {exc}"
raise ValueError(msg) raise ValueError(msg) from exc
async def _get( async def _get(
self, url: str, api_key: str | None = None, params: dict[str, Any] | None = None self, url: str, api_key: str | None = None, params: dict[str, Any] | None = None
@ -137,7 +137,7 @@ class StoreService(Service):
raise exc raise exc
except Exception as exc: except Exception as exc:
msg = f"GET failed: {exc}" msg = f"GET failed: {exc}"
raise ValueError(msg) raise ValueError(msg) from exc
json_response = response.json() json_response = response.json()
result = json_response["data"] result = json_response["data"]
metadata = {} metadata = {}
@ -355,9 +355,9 @@ class StoreService(Service):
# If it is, we need to build the metadata # If it is, we need to build the metadata
try: try:
download_component.metadata = process_component_data(download_component.data.get("nodes", [])) download_component.metadata = process_component_data(download_component.data.get("nodes", []))
except KeyError: except KeyError as e:
msg = "Invalid component data. No nodes found" msg = "Invalid component data. No nodes found"
raise ValueError(msg) raise ValueError(msg) from e
return download_component return download_component
async def upload(self, api_key: str, component_data: StoreComponentCreate) -> CreateComponentResponse: async def upload(self, api_key: str, component_data: StoreComponentCreate) -> CreateComponentResponse:
@ -392,7 +392,7 @@ class StoreService(Service):
except UnboundLocalError: except UnboundLocalError:
pass pass
msg = f"Upload failed: {exc}" msg = f"Upload failed: {exc}"
raise ValueError(msg) raise ValueError(msg) from exc
async def update( async def update(
self, api_key: str, component_id: UUID, component_data: StoreComponentCreate self, api_key: str, component_id: UUID, component_data: StoreComponentCreate
@ -429,7 +429,7 @@ class StoreService(Service):
except UnboundLocalError: except UnboundLocalError:
pass pass
msg = f"Upload failed: {exc}" msg = f"Upload failed: {exc}"
raise ValueError(msg) raise ValueError(msg) from exc
async def get_tags(self) -> list[dict[str, Any]]: async def get_tags(self) -> list[dict[str, Any]]:
url = f"{self.base_url}/items/tags" url = f"{self.base_url}/items/tags"
@ -460,9 +460,9 @@ class StoreService(Service):
# try to convert it to int # try to convert it to int
try: try:
likes = int(likes) likes = int(likes)
except ValueError: except ValueError as e:
msg = f"Unexpected value for likes count: {likes}" msg = f"Unexpected value for likes count: {likes}"
raise ValueError(msg) raise ValueError(msg) from e
return likes return likes
async def like_component(self, api_key: str, component_id: str) -> bool: async def like_component(self, api_key: str, component_id: str) -> bool:
@ -567,10 +567,10 @@ class StoreService(Service):
except HTTPStatusError as exc: except HTTPStatusError as exc:
if exc.response.status_code == 403: if exc.response.status_code == 403:
msg = "You are not authorized to access this public resource" msg = "You are not authorized to access this public resource"
raise ForbiddenError(msg) raise ForbiddenError(msg) from exc
if exc.response.status_code == 401: if exc.response.status_code == 401:
msg = "You are not authorized to access this resource. Please check your API key." msg = "You are not authorized to access this resource. Please check your API key."
raise APIKeyError(msg) raise APIKeyError(msg) from exc
if store_api_key: if store_api_key:
# Now, from the result, we need to get the components # Now, from the result, we need to get the components

View file

@ -1,6 +1,7 @@
from __future__ import annotations from __future__ import annotations
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from collections.abc import Sequence
from typing import TYPE_CHECKING, Any from typing import TYPE_CHECKING, Any
from uuid import UUID from uuid import UUID
@ -40,7 +41,7 @@ class BaseTracer(ABC):
trace_name: str, trace_name: str,
outputs: dict[str, Any] | None = None, outputs: dict[str, Any] | None = None,
error: Exception | None = None, error: Exception | None = None,
logs: list[Log | dict] = [], logs: Sequence[Log | dict] = (),
): ):
raise NotImplementedError raise NotImplementedError

View file

@ -1,6 +1,7 @@
from __future__ import annotations from __future__ import annotations
import os import os
from collections.abc import Sequence
from datetime import datetime from datetime import datetime
from typing import TYPE_CHECKING, Any from typing import TYPE_CHECKING, Any
from uuid import UUID from uuid import UUID
@ -100,7 +101,7 @@ class LangFuseTracer(BaseTracer):
trace_name: str, trace_name: str,
outputs: dict[str, Any] | None = None, outputs: dict[str, Any] | None = None,
error: Exception | None = None, error: Exception | None = None,
logs: list[Log | dict] = [], logs: Sequence[Log | dict] = (),
): ):
end_time = datetime.utcnow() end_time = datetime.utcnow()
if not self._ready: if not self._ready:
@ -111,7 +112,7 @@ class LangFuseTracer(BaseTracer):
_output: dict = {} _output: dict = {}
_output |= outputs if outputs else {} _output |= outputs if outputs else {}
_output |= {"error": str(error)} if error else {} _output |= {"error": str(error)} if error else {}
_output |= {"logs": logs} if logs else {} _output |= {"logs": list(logs)} if logs else {}
content = {"output": _output, "end_time": end_time} content = {"output": _output, "end_time": end_time}
span.update(**content) span.update(**content)

View file

@ -3,6 +3,7 @@ from __future__ import annotations
import os import os
import traceback import traceback
import types import types
from collections.abc import Sequence
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import TYPE_CHECKING, Any from typing import TYPE_CHECKING, Any
from uuid import UUID from uuid import UUID
@ -119,7 +120,7 @@ class LangSmithTracer(BaseTracer):
trace_name: str, trace_name: str,
outputs: dict[str, Any] | None = None, outputs: dict[str, Any] | None = None,
error: Exception | None = None, error: Exception | None = None,
logs: list[Log | dict] = [], logs: Sequence[Log | dict] = (),
): ):
if not self._ready: if not self._ready:
return return

View file

@ -1,5 +1,6 @@
from __future__ import annotations from __future__ import annotations
from collections.abc import Sequence
from typing import TYPE_CHECKING, Any, cast from typing import TYPE_CHECKING, Any, cast
from uuid import UUID from uuid import UUID
@ -103,7 +104,7 @@ class LangWatchTracer(BaseTracer):
trace_name: str, trace_name: str,
outputs: dict[str, Any] | None = None, outputs: dict[str, Any] | None = None,
error: Exception | None = None, error: Exception | None = None,
logs: list[Log | dict] = [], logs: Sequence[Log | dict] = (),
): ):
if not self._ready: if not self._ready:
return return

View file

@ -1,6 +1,7 @@
from __future__ import annotations from __future__ import annotations
import os import os
from collections.abc import Sequence
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
from uuid import UUID from uuid import UUID
@ -165,7 +166,7 @@ class DatabaseVariableService(VariableService, Service):
user_id: UUID | str, user_id: UUID | str,
name: str, name: str,
value: str, value: str,
default_fields: list[str] = [], default_fields: Sequence[str] = (),
_type: str = GENERIC_TYPE, _type: str = GENERIC_TYPE,
session: Session = Depends(get_session), session: Session = Depends(get_session),
): ):
@ -173,7 +174,7 @@ class DatabaseVariableService(VariableService, Service):
name=name, name=name,
type=_type, type=_type,
value=auth_utils.encrypt_api_key(value, settings_service=self.settings_service), value=auth_utils.encrypt_api_key(value, settings_service=self.settings_service),
default_fields=default_fields, default_fields=list(default_fields),
) )
variable = Variable.model_validate(variable_base, from_attributes=True, update={"user_id": user_id}) variable = Variable.model_validate(variable_base, from_attributes=True, update={"user_id": user_id})
session.add(variable) session.add(variable)

View file

@ -53,7 +53,7 @@ class Template(BaseModel):
_input = instantiate_input(input_type, value) _input = instantiate_input(input_type, value)
except Exception as e: except Exception as e:
msg = f"Error instantiating input {input_type}: {e}" msg = f"Error instantiating input {input_type}: {e}"
raise ValueError(msg) raise ValueError(msg) from e
else: else:
_input = Input(**value) _input = Input(**value)

View file

@ -217,9 +217,9 @@ def prepare_global_scope(code, module):
imported_module = importlib.import_module(node.module) imported_module = importlib.import_module(node.module)
for alias in node.names: for alias in node.names:
exec_globals[alias.name] = getattr(imported_module, alias.name) exec_globals[alias.name] = getattr(imported_module, alias.name)
except ModuleNotFoundError: except ModuleNotFoundError as e:
msg = f"Module {node.module} not found. Please install it and try again" msg = f"Module {node.module} not found. Please install it and try again"
raise ModuleNotFoundError(msg) raise ModuleNotFoundError(msg) from e
return exec_globals return exec_globals

View file

@ -74,20 +74,18 @@ def fetch_latest_version(package_name: str, include_prerelease: bool) -> str | N
from packaging import version as pkg_version from packaging import version as pkg_version
package_name = package_name.replace(" ", "-").lower() package_name = package_name.replace(" ", "-").lower()
valid_versions = []
try: try:
response = httpx.get(f"https://pypi.org/pypi/{package_name}/json") response = httpx.get(f"https://pypi.org/pypi/{package_name}/json")
versions = response.json()["releases"].keys() versions = response.json()["releases"].keys()
valid_versions = [v for v in versions if include_prerelease or not is_pre_release(v)] valid_versions = [v for v in versions if include_prerelease or not is_pre_release(v)]
except Exception as e:
logger.exception(e)
finally:
if not valid_versions: if not valid_versions:
return None # Handle case where no valid versions are found return None # Handle case where no valid versions are found
return max(valid_versions, key=lambda v: pkg_version.parse(v)) return max(valid_versions, key=lambda v: pkg_version.parse(v))
except Exception as e:
logger.exception(e)
return None
def get_version_info(): def get_version_info():
return VERSION_INFO return VERSION_INFO

View file

@ -149,8 +149,15 @@ exclude = ["langflow/alembic"]
line-length = 120 line-length = 120
[tool.ruff.lint] [tool.ruff.lint]
flake8-bugbear.extend-immutable-calls = [
"fastapi.Depends",
"fastapi.File",
"fastapi.Query",
"typer.Option",
]
select = [ select = [
"ASYNC", "ASYNC",
"B",
"C4", "C4",
"COM", "COM",
"DJ", "DJ",

View file

@ -11,6 +11,9 @@ from typing import TYPE_CHECKING
import orjson import orjson
import pytest import pytest
from loguru import logger
from pytest import LogCaptureFixture
from base.langflow.components.inputs.ChatInput import ChatInput from base.langflow.components.inputs.ChatInput import ChatInput
from dotenv import load_dotenv from dotenv import load_dotenv
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
@ -79,6 +82,19 @@ def get_text():
assert path.exists(), f"File {path} does not exist. Available files: {list(data_path.iterdir())}" assert path.exists(), f"File {path} does not exist. Available files: {list(data_path.iterdir())}"
@pytest.fixture
def caplog(caplog: LogCaptureFixture):
handler_id = logger.add(
caplog.handler,
format="{message}",
level=0,
filter=lambda record: record["level"].no >= caplog.handler.level,
enqueue=False, # Set to 'True' if your test is spawning child processes.
)
yield caplog
logger.remove(handler_id)
@pytest.fixture() @pytest.fixture()
async def async_client() -> AsyncGenerator: async def async_client() -> AsyncGenerator:
from langflow.main import create_app from langflow.main import create_app

View file

@ -1,6 +1,8 @@
import logging
from collections import deque from collections import deque
import pytest import pytest
from pytest import LogCaptureFixture
from langflow.components.agents.ToolCallingAgent import ToolCallingAgentComponent from langflow.components.agents.ToolCallingAgent import ToolCallingAgentComponent
from langflow.components.inputs.ChatInput import ChatInput from langflow.components.inputs.ChatInput import ChatInput
@ -28,14 +30,16 @@ async def test_graph_not_prepared():
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_graph(): async def test_graph(caplog: LogCaptureFixture):
chat_input = ChatInput() chat_input = ChatInput()
chat_output = ChatOutput() chat_output = ChatOutput()
graph = Graph() graph = Graph()
graph.add_component(chat_input) graph.add_component(chat_input)
graph.add_component(chat_output) graph.add_component(chat_output)
with pytest.warns(UserWarning, match="Graph has vertices but no edges"): caplog.clear()
with caplog.at_level(logging.WARNING):
graph.prepare() graph.prepare()
assert "Graph has vertices but no edges" in caplog.text
@pytest.mark.asyncio @pytest.mark.asyncio