Fix mypy (#2204)
* mypy github action * fix endpoints.py mypy lint * directly run poetry run mypy * line based mypy error suppression * switch to use make lint * fix ruff issues * fix EmbedComponent lint * fix prompt.py's lint
This commit is contained in:
parent
45c2f8a9b6
commit
8ccb9e7597
20 changed files with 40 additions and 59 deletions
19
.github/workflows/lint-py.yml
vendored
19
.github/workflows/lint-py.yml
vendored
|
|
@ -32,21 +32,6 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
poetry env use ${{ matrix.python-version }}
|
poetry env use ${{ matrix.python-version }}
|
||||||
poetry install
|
poetry install
|
||||||
- name: Get .mypy_cache to speed up mypy
|
make lint
|
||||||
uses: actions/cache@v4
|
|
||||||
env:
|
env:
|
||||||
SEGMENT_DOWNLOAD_TIMEOUT_MIN: "2"
|
GITHUB_TOKEN: ${{ secrets.github_token }}
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
./.mypy_cache
|
|
||||||
key: ${{ runner.os }}-mypy-${{ hashFiles('**/pyproject.toml') }}
|
|
||||||
- name: Run linters
|
|
||||||
uses: wearerequired/lint-action@v2
|
|
||||||
with:
|
|
||||||
github_token: ${{ secrets.github_token }}
|
|
||||||
# Enable linters
|
|
||||||
git_email: "gabriel@langflow.org"
|
|
||||||
mypy: true
|
|
||||||
mypy_args: '--namespace-packages -p "langflow"'
|
|
||||||
mypy_command_prefix: "poetry run"
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ async def simple_run_flow(
|
||||||
if input_request.output_type == "debug"
|
if input_request.output_type == "debug"
|
||||||
or (
|
or (
|
||||||
vertex.is_output
|
vertex.is_output
|
||||||
and (input_request.output_type == "any" or input_request.output_type in vertex.id.lower())
|
and (input_request.output_type == "any" or input_request.output_type in vertex.id.lower()) # type: ignore
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
task_result, session_id = await run_graph_internal(
|
task_result, session_id = await run_graph_internal(
|
||||||
|
|
@ -230,7 +230,7 @@ async def webhook_run_flow(
|
||||||
session_id=data_dict.get("session_id"),
|
session_id=data_dict.get("session_id"),
|
||||||
)
|
)
|
||||||
logger.debug("Starting background task")
|
logger.debug("Starting background task")
|
||||||
background_tasks.add_task(
|
background_tasks.add_task( # type: ignore
|
||||||
simple_run_flow,
|
simple_run_flow,
|
||||||
db=db,
|
db=db,
|
||||||
flow=flow,
|
flow=flow,
|
||||||
|
|
@ -325,8 +325,6 @@ async def experimental_run_flow(
|
||||||
session_id=session_id,
|
session_id=session_id,
|
||||||
inputs=inputs,
|
inputs=inputs,
|
||||||
outputs=outputs,
|
outputs=outputs,
|
||||||
artifacts=artifacts,
|
|
||||||
session_service=session_service,
|
|
||||||
stream=stream,
|
stream=stream,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -508,9 +506,8 @@ def get_config():
|
||||||
try:
|
try:
|
||||||
from langflow.services.deps import get_settings_service
|
from langflow.services.deps import get_settings_service
|
||||||
|
|
||||||
settings_service: "SettingsService" = get_settings_service()
|
settings_service: "SettingsService" = get_settings_service() # type: ignore
|
||||||
return settings_service.settings.model_dump()
|
return settings_service.settings.model_dump()
|
||||||
except Exception as exc:
|
except Exception as 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
|
||||||
raise HTTPException(status_code=500, detail=str(exc)) from exc
|
|
||||||
|
|
|
||||||
|
|
@ -109,10 +109,10 @@ async def download_profile_picture(
|
||||||
try:
|
try:
|
||||||
extension = file_name.split(".")[-1]
|
extension = file_name.split(".")[-1]
|
||||||
config_dir = get_storage_service().settings_service.settings.config_dir
|
config_dir = get_storage_service().settings_service.settings.config_dir
|
||||||
config_path = Path(config_dir)
|
config_path = Path(config_dir) # type: ignore
|
||||||
folder_path = config_path / "profile_pictures" / folder_name
|
folder_path = config_path / "profile_pictures" / folder_name
|
||||||
content_type = build_content_type_from_extension(extension)
|
content_type = build_content_type_from_extension(extension)
|
||||||
file_content = await storage_service.get_file(flow_id=folder_path, file_name=file_name)
|
file_content = await storage_service.get_file(flow_id=folder_path, file_name=file_name) # type: ignore
|
||||||
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:
|
||||||
|
|
@ -123,13 +123,13 @@ async def download_profile_picture(
|
||||||
async def list_profile_pictures(storage_service: StorageService = Depends(get_storage_service)):
|
async def list_profile_pictures(storage_service: StorageService = Depends(get_storage_service)):
|
||||||
try:
|
try:
|
||||||
config_dir = get_storage_service().settings_service.settings.config_dir
|
config_dir = get_storage_service().settings_service.settings.config_dir
|
||||||
config_path = Path(config_dir)
|
config_path = Path(config_dir) # type: ignore
|
||||||
|
|
||||||
people_path = config_path / "profile_pictures/People"
|
people_path = config_path / "profile_pictures/People"
|
||||||
space_path = config_path / "profile_pictures/Space"
|
space_path = config_path / "profile_pictures/Space"
|
||||||
|
|
||||||
people = await storage_service.list_files(flow_id=people_path)
|
people = await storage_service.list_files(flow_id=people_path) # type: ignore
|
||||||
space = await storage_service.list_files(flow_id=space_path)
|
space = await storage_service.list_files(flow_id=space_path) # type: ignore
|
||||||
|
|
||||||
files = [Path("People") / i for i in people]
|
files = [Path("People") / i for i in people]
|
||||||
files += [Path("Space") / i for i in space]
|
files += [Path("Space") / i for i in space]
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ def create_flow(
|
||||||
# based on the highest number found
|
# based on the highest number found
|
||||||
if session.exec(select(Flow).where(Flow.name == flow.name).where(Flow.user_id == current_user.id)).first():
|
if session.exec(select(Flow).where(Flow.name == flow.name).where(Flow.user_id == current_user.id)).first():
|
||||||
flows = session.exec(
|
flows = session.exec(
|
||||||
select(Flow).where(Flow.name.like(f"{flow.name} (%")).where(Flow.user_id == current_user.id)
|
select(Flow).where(Flow.name.like(f"{flow.name} (%")).where(Flow.user_id == current_user.id) # type: ignore
|
||||||
).all()
|
).all()
|
||||||
if flows:
|
if flows:
|
||||||
numbers = [int(flow.name.split("(")[1].split(")")[0]) for flow in flows]
|
numbers = [int(flow.name.split("(")[1].split(")")[0]) for flow in flows]
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ async def update_message(
|
||||||
try:
|
try:
|
||||||
message_dict = message.model_dump(exclude_none=True)
|
message_dict = message.model_dump(exclude_none=True)
|
||||||
message_dict.pop("index", None)
|
message_dict.pop("index", None)
|
||||||
monitor_service.update_message(message_id=message_id, **message_dict)
|
monitor_service.update_message(message_id=message_id, **message_dict) # type: ignore
|
||||||
return MessageModelResponse(index=message_id, **message_dict)
|
return MessageModelResponse(index=message_id, **message_dict)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ def build_records_from_result_data(result_data: ResultData, get_final_results_on
|
||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
for message in messages:
|
for message in messages: # type: ignore
|
||||||
message_dict = message if isinstance(message, dict) else message.model_dump()
|
message_dict = message if isinstance(message, dict) else message.model_dump()
|
||||||
if get_final_results_only:
|
if get_final_results_only:
|
||||||
result_data_dict = result_data.model_dump()
|
result_data_dict = result_data.model_dump()
|
||||||
|
|
|
||||||
|
|
@ -82,9 +82,9 @@ class ChatComponent(CustomComponent):
|
||||||
if not return_message:
|
if not return_message:
|
||||||
message_text = message.text
|
message_text = message.text
|
||||||
else:
|
else:
|
||||||
message_text = message
|
message_text = message # type: ignore
|
||||||
|
|
||||||
self.status = message_text
|
self.status = message_text
|
||||||
if session_id and isinstance(message, Message) and isinstance(message.text, str):
|
if session_id and isinstance(message, Message) and isinstance(message.text, str):
|
||||||
self.store_message(message)
|
self.store_message(message)
|
||||||
return message_text
|
return message_text # type: ignore
|
||||||
|
|
|
||||||
|
|
@ -78,9 +78,9 @@ class LCModelComponent(CustomComponent):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
status_message = f"Response: {content}"
|
status_message = f"Response: {content}" # type: ignore
|
||||||
else:
|
else:
|
||||||
status_message = f"Response: {message.content}"
|
status_message = f"Response: {message.content}" # type: ignore
|
||||||
return status_message
|
return status_message
|
||||||
|
|
||||||
def get_chat_result(
|
def get_chat_result(
|
||||||
|
|
@ -102,11 +102,11 @@ class LCModelComponent(CustomComponent):
|
||||||
messages.append(input_value.to_lc_message())
|
messages.append(input_value.to_lc_message())
|
||||||
else:
|
else:
|
||||||
messages.append(HumanMessage(content=input_value))
|
messages.append(HumanMessage(content=input_value))
|
||||||
inputs = messages or {}
|
inputs = messages or {} # type: ignore
|
||||||
if stream:
|
if stream:
|
||||||
return runnable.stream(inputs)
|
return runnable.stream(inputs) # type: ignore
|
||||||
else:
|
else:
|
||||||
message = runnable.invoke(inputs)
|
message = runnable.invoke(inputs) # type: ignore
|
||||||
result = message.content
|
result = message.content
|
||||||
if isinstance(message, AIMessage):
|
if isinstance(message, AIMessage):
|
||||||
status_message = self.build_status_message(message)
|
status_message = self.build_status_message(message)
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ class EmbedComponent(CustomComponent):
|
||||||
def build_config(self):
|
def build_config(self):
|
||||||
return {"texts": {"display_name": "Texts"}, "embbedings": {"display_name": "Embeddings"}}
|
return {"texts": {"display_name": "Texts"}, "embbedings": {"display_name": "Embeddings"}}
|
||||||
|
|
||||||
def build(self, texts: list[str], embbedings: Embeddings) -> Embeddings:
|
def build(self, texts: list[str], embbedings: Embeddings) -> Record:
|
||||||
vectors = Record(vector=embbedings.embed_documents(texts))
|
vectors = Record(vector=embbedings.embed_documents(texts))
|
||||||
self.status = vectors
|
self.status = vectors
|
||||||
return vectors
|
return vectors
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ class MemoryComponent(BaseMemoryComponent):
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_messages(self, **kwargs) -> list[Message]:
|
def get_messages(self, **kwargs) -> list[Message]: # type: ignore
|
||||||
# Validate kwargs by checking if it contains the correct keys
|
# Validate kwargs by checking if it contains the correct keys
|
||||||
if "sender" not in kwargs:
|
if "sender" not in kwargs:
|
||||||
kwargs["sender"] = None
|
kwargs["sender"] = None
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ class PromptComponent(CustomComponent):
|
||||||
|
|
||||||
async def build(
|
async def build(
|
||||||
self,
|
self,
|
||||||
template: Prompt,
|
template: str,
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) -> Prompt:
|
) -> Prompt:
|
||||||
prompt = await Prompt.from_template_and_variables(template, kwargs)
|
prompt = await Prompt.from_template_and_variables(template, kwargs)
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ class SelfQueryRetrieverComponent(CustomComponent):
|
||||||
input_text = query
|
input_text = query
|
||||||
else:
|
else:
|
||||||
raise ValueError(f"Query type {type(query)} not supported.")
|
raise ValueError(f"Query type {type(query)} not supported.")
|
||||||
documents = self_query_retriever.invoke(input=input_text)
|
documents = self_query_retriever.invoke(input=input_text) # type: ignore
|
||||||
records = [Record.from_document(document) for document in documents]
|
records = [Record.from_document(document) for document in documents]
|
||||||
self.status = records
|
self.status = records # type: ignore
|
||||||
return records
|
return records # type: ignore
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,6 @@ class Prompt(Record):
|
||||||
if isinstance(value, Message):
|
if isinstance(value, Message):
|
||||||
content_dicts = await value.get_file_content_dicts()
|
content_dicts = await value.get_file_content_dicts()
|
||||||
contents.extend(content_dicts)
|
contents.extend(content_dicts)
|
||||||
prompt_template = ChatPromptTemplate.from_messages([HumanMessage(content=contents)])
|
prompt_template = ChatPromptTemplate.from_messages([HumanMessage(content=contents)]) # type: ignore
|
||||||
instance.prompt = prompt_template.to_json()
|
instance.prompt = prompt_template.to_json()
|
||||||
return instance
|
return instance
|
||||||
|
|
|
||||||
|
|
@ -153,7 +153,6 @@ class ContractEdge(Edge):
|
||||||
sender_name=target.params.get("sender_name", ""),
|
sender_name=target.params.get("sender_name", ""),
|
||||||
message=target.params.get(INPUT_FIELD_NAME, {}),
|
message=target.params.get(INPUT_FIELD_NAME, {}),
|
||||||
session_id=target.params.get("session_id", ""),
|
session_id=target.params.get("session_id", ""),
|
||||||
artifacts=target.artifacts,
|
|
||||||
flow_id=target.graph.flow_id,
|
flow_id=target.graph.flow_id,
|
||||||
)
|
)
|
||||||
return self.result
|
return self.result
|
||||||
|
|
|
||||||
|
|
@ -389,9 +389,9 @@ class Vertex:
|
||||||
if any(isinstance(self._raw_params.get(key), Vertex) for key in new_params):
|
if any(isinstance(self._raw_params.get(key), Vertex) for key in new_params):
|
||||||
return
|
return
|
||||||
if not overwrite:
|
if not overwrite:
|
||||||
for key in new_params.copy():
|
for key in new_params.copy(): # type: ignore
|
||||||
if key not in self._raw_params:
|
if key not in self._raw_params:
|
||||||
new_params.pop(key)
|
new_params.pop(key) # type: ignore
|
||||||
self._raw_params.update(new_params)
|
self._raw_params.update(new_params)
|
||||||
self.params = self._raw_params.copy()
|
self.params = self._raw_params.copy()
|
||||||
self.updated_raw_params = True
|
self.updated_raw_params = True
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@ class Message(BaseModel):
|
||||||
if is_image_file(file):
|
if is_image_file(file):
|
||||||
new_files.append(Image(path=file))
|
new_files.append(Image(path=file))
|
||||||
else:
|
else:
|
||||||
new_files.append(file)
|
new_files.append(file) # type: ignore
|
||||||
self.files = new_files
|
self.files = new_files # type: ignore
|
||||||
|
|
||||||
def to_lc_message(
|
def to_lc_message(
|
||||||
self,
|
self,
|
||||||
|
|
@ -58,7 +58,7 @@ class Message(BaseModel):
|
||||||
if self.files:
|
if self.files:
|
||||||
contents = [{"type": "text", "text": self.text}]
|
contents = [{"type": "text", "text": self.text}]
|
||||||
contents.extend(self.get_file_content_dicts())
|
contents.extend(self.get_file_content_dicts())
|
||||||
human_message = HumanMessage(content=contents)
|
human_message = HumanMessage(content=contents) # type: ignore
|
||||||
else:
|
else:
|
||||||
human_message = HumanMessage(
|
human_message = HumanMessage(
|
||||||
content=[{"type": "text", "text": self.text}],
|
content=[{"type": "text", "text": self.text}],
|
||||||
|
|
@ -66,7 +66,7 @@ class Message(BaseModel):
|
||||||
|
|
||||||
return human_message
|
return human_message
|
||||||
|
|
||||||
return AIMessage(content=self.text)
|
return AIMessage(content=self.text) # type: ignore
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def from_record(cls, record: "Record") -> "Message":
|
def from_record(cls, record: "Record") -> "Message":
|
||||||
|
|
|
||||||
|
|
@ -133,9 +133,9 @@ class Record(BaseModel):
|
||||||
contents = [{"type": "text", "text": text}]
|
contents = [{"type": "text", "text": text}]
|
||||||
for file_path in files:
|
for file_path in files:
|
||||||
image_template = ImagePromptTemplate()
|
image_template = ImagePromptTemplate()
|
||||||
image_prompt_value: ImagePromptValue = image_template.invoke(input={"path": file_path})
|
image_prompt_value: ImagePromptValue = image_template.invoke(input={"path": file_path}) # type: ignore
|
||||||
contents.append({"type": "image_url", "image_url": image_prompt_value.image_url})
|
contents.append({"type": "image_url", "image_url": image_prompt_value.image_url})
|
||||||
human_message = HumanMessage(content=contents)
|
human_message = HumanMessage(content=contents) # type: ignore
|
||||||
else:
|
else:
|
||||||
human_message = HumanMessage(
|
human_message = HumanMessage(
|
||||||
content=[{"type": "text", "text": text}],
|
content=[{"type": "text", "text": text}],
|
||||||
|
|
@ -143,7 +143,7 @@ class Record(BaseModel):
|
||||||
|
|
||||||
return human_message
|
return human_message
|
||||||
|
|
||||||
return AIMessage(content=text)
|
return AIMessage(content=text) # type: ignore
|
||||||
|
|
||||||
def __getattr__(self, key):
|
def __getattr__(self, key):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -107,8 +107,8 @@ async def get_current_user_by_jwt(
|
||||||
with warnings.catch_warnings():
|
with warnings.catch_warnings():
|
||||||
warnings.simplefilter("ignore")
|
warnings.simplefilter("ignore")
|
||||||
payload = jwt.decode(token, secret_key, algorithms=[settings_service.auth_settings.ALGORITHM])
|
payload = jwt.decode(token, secret_key, algorithms=[settings_service.auth_settings.ALGORITHM])
|
||||||
user_id: UUID = payload.get("sub")
|
user_id: UUID = payload.get("sub") # type: ignore
|
||||||
token_type: str = payload.get("type")
|
token_type: str = payload.get("type") # type: ignore
|
||||||
if expires := payload.get("exp", None):
|
if expires := payload.get("exp", None):
|
||||||
expires_datetime = datetime.fromtimestamp(expires, timezone.utc)
|
expires_datetime = datetime.fromtimestamp(expires, timezone.utc)
|
||||||
if datetime.now(timezone.utc) > expires_datetime:
|
if datetime.now(timezone.utc) > expires_datetime:
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ class VariableService(Service):
|
||||||
# credential = session.query(Variable).filter(Variable.user_id == user_id, Variable.name == name).first()
|
# credential = session.query(Variable).filter(Variable.user_id == user_id, Variable.name == name).first()
|
||||||
variable = session.exec(select(Variable).where(Variable.user_id == user_id, Variable.name == name)).first()
|
variable = session.exec(select(Variable).where(Variable.user_id == user_id, Variable.name == name)).first()
|
||||||
|
|
||||||
if variable.type == "Credential" and field == "session_id":
|
if variable.type == "Credential" and field == "session_id": # type: ignore
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
f"variable {name} of type 'Credential' cannot be used in a Session ID field "
|
f"variable {name} of type 'Credential' cannot be used in a Session ID field "
|
||||||
"because its purpose is to prevent the exposure of values."
|
"because its purpose is to prevent the exposure of values."
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ class ChatOutputResponse(BaseModel):
|
||||||
):
|
):
|
||||||
"""Build chat output response from message."""
|
"""Build chat output response from message."""
|
||||||
content = message.content
|
content = message.content
|
||||||
return cls(message=content, sender=sender, sender_name=sender_name)
|
return cls(message=content, sender=sender, sender_name=sender_name) # type: ignore
|
||||||
|
|
||||||
@model_validator(mode="after")
|
@model_validator(mode="after")
|
||||||
def validate_message(self):
|
def validate_message(self):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue