parent
140cf890e3
commit
f96f2eaf8a
67 changed files with 424 additions and 364 deletions
|
|
@ -216,6 +216,43 @@ directory = "coverage"
|
|||
exclude = ["src/backend/langflow/alembic/*"]
|
||||
line-length = 120
|
||||
|
||||
[tool.ruff.lint]
|
||||
pydocstyle.convention = "google"
|
||||
select = ["ALL"]
|
||||
ignore = [
|
||||
"C90", # McCabe complexity
|
||||
"CPY", # Missing copyright
|
||||
"COM812", # Messes with the formatter
|
||||
"ERA", # Eradicate commented-out code
|
||||
"FIX002", # Line contains TODO
|
||||
"ISC001", # Messes with the formatter
|
||||
"PERF203", # Rarely useful
|
||||
"PLR09", # Too many something (arg, statements, etc)
|
||||
"RUF012", # Pydantic models are currently not well detected. See https://github.com/astral-sh/ruff/issues/13630
|
||||
"TD002", # Missing author in TODO
|
||||
"TD003", # Missing issue link in TODO
|
||||
"TRY301", # A bit too harsh (Abstract `raise` to an inner function)
|
||||
|
||||
# Rules that are TODOs
|
||||
"ANN",
|
||||
]
|
||||
|
||||
# Preview rules that are not yet activated
|
||||
external = ["RUF027"]
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"scripts/*" = [
|
||||
"D1",
|
||||
"INP",
|
||||
"T201",
|
||||
]
|
||||
"src/backend/tests/*" = [
|
||||
"D1",
|
||||
"PLR2004",
|
||||
"S101",
|
||||
"SLF001",
|
||||
]
|
||||
|
||||
[tool.mypy]
|
||||
plugins = ["pydantic.mypy"]
|
||||
follow_imports = "skip"
|
||||
|
|
|
|||
|
|
@ -12,8 +12,10 @@ PYPI_LANGFLOW_NIGHTLY_URL = "https://pypi.org/pypi/langflow-nightly/json"
|
|||
PYPI_LANGFLOW_BASE_URL = "https://pypi.org/pypi/langflow-base/json"
|
||||
PYPI_LANGFLOW_BASE_NIGHTLY_URL = "https://pypi.org/pypi/langflow-base-nightly/json"
|
||||
|
||||
ARGUMENT_NUMBER = 2
|
||||
|
||||
def get_latest_published_version(build_type: str, is_nightly: bool) -> Version:
|
||||
|
||||
def get_latest_published_version(build_type: str, *, is_nightly: bool) -> Version:
|
||||
import requests
|
||||
|
||||
url = ""
|
||||
|
|
@ -25,12 +27,12 @@ def get_latest_published_version(build_type: str, is_nightly: bool) -> Version:
|
|||
msg = f"Invalid build type: {build_type}"
|
||||
raise ValueError(msg)
|
||||
|
||||
res = requests.get(url)
|
||||
res = requests.get(url, timeout=10)
|
||||
try:
|
||||
version_str = res.json()["info"]["version"]
|
||||
except Exception as e:
|
||||
msg = "Got unexpected response from PyPI"
|
||||
raise RuntimeError(msg, e)
|
||||
raise RuntimeError(msg) from e
|
||||
return Version(version_str)
|
||||
|
||||
|
||||
|
|
@ -74,9 +76,9 @@ def create_tag(build_type: str):
|
|||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 2:
|
||||
if len(sys.argv) != ARGUMENT_NUMBER:
|
||||
msg = "Specify base or main"
|
||||
raise Exception(msg)
|
||||
raise ValueError(msg)
|
||||
|
||||
build_type = sys.argv[1]
|
||||
tag = create_tag(build_type)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
|
@ -5,6 +7,7 @@ from pathlib import Path
|
|||
import packaging.version
|
||||
|
||||
BASE_DIR = Path(__file__).parent.parent.parent
|
||||
ARGUMENT_NUMBER = 2
|
||||
|
||||
|
||||
def update_base_dep(pyproject_path: str, new_version: str) -> None:
|
||||
|
|
@ -18,7 +21,7 @@ def update_base_dep(pyproject_path: str, new_version: str) -> None:
|
|||
pattern = re.compile(r'langflow-base = \{ path = "\./src/backend/base", develop = true \}')
|
||||
if not pattern.search(content):
|
||||
msg = f'langflow-base poetry dependency not found in "{filepath}"'
|
||||
raise Exception(msg)
|
||||
raise ValueError(msg)
|
||||
content = pattern.sub(replacement, content)
|
||||
filepath.write_text(content, encoding="utf-8")
|
||||
|
||||
|
|
@ -28,16 +31,13 @@ def verify_pep440(version):
|
|||
|
||||
https://github.com/pypa/packaging/blob/16.7/packaging/version.py#L191
|
||||
"""
|
||||
try:
|
||||
return packaging.version.Version(version)
|
||||
except packaging.version.InvalidVersion:
|
||||
raise
|
||||
return packaging.version.Version(version)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
if len(sys.argv) != 2:
|
||||
if len(sys.argv) != ARGUMENT_NUMBER:
|
||||
msg = "New version not specified"
|
||||
raise Exception(msg)
|
||||
raise ValueError(msg)
|
||||
base_version = sys.argv[1]
|
||||
|
||||
# Strip "v" prefix from version if present
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
BASE_DIR = Path(__file__).parent.parent.parent
|
||||
ARGUMENT_NUMBER = 3
|
||||
|
||||
|
||||
def update_pyproject_name(pyproject_path: str, new_project_name: str) -> None:
|
||||
|
|
@ -15,7 +18,7 @@ def update_pyproject_name(pyproject_path: str, new_project_name: str) -> None:
|
|||
|
||||
if not pattern.search(content):
|
||||
msg = f'Project name not found in "{filepath}"'
|
||||
raise Exception(msg)
|
||||
raise ValueError(msg)
|
||||
content = pattern.sub(new_project_name, content)
|
||||
|
||||
filepath.write_text(content, encoding="utf-8")
|
||||
|
|
@ -39,15 +42,15 @@ def update_uv_dep(pyproject_path: str, new_project_name: str) -> None:
|
|||
# Updates the dependency name for uv
|
||||
if not pattern.search(content):
|
||||
msg = f"{replacement} uv dependency not found in {filepath}"
|
||||
raise Exception(msg)
|
||||
raise ValueError(msg)
|
||||
content = pattern.sub(replacement, content)
|
||||
filepath.write_text(content, encoding="utf-8")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
if len(sys.argv) != 3:
|
||||
if len(sys.argv) != ARGUMENT_NUMBER:
|
||||
msg = "Must specify project name and build type, e.g. langflow-nightly base"
|
||||
raise Exception(msg)
|
||||
raise ValueError(msg)
|
||||
new_project_name = sys.argv[1]
|
||||
build_type = sys.argv[2]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
|
@ -5,6 +7,7 @@ from pathlib import Path
|
|||
import packaging.version
|
||||
|
||||
BASE_DIR = Path(__file__).parent.parent.parent
|
||||
ARGUMENT_NUMBER = 3
|
||||
|
||||
|
||||
def update_pyproject_version(pyproject_path: str, new_version: str) -> None:
|
||||
|
|
@ -17,7 +20,7 @@ def update_pyproject_version(pyproject_path: str, new_version: str) -> None:
|
|||
|
||||
if not pattern.search(content):
|
||||
msg = f'Project version not found in "{filepath}"'
|
||||
raise Exception(msg)
|
||||
raise ValueError(msg)
|
||||
|
||||
content = pattern.sub(new_version, content)
|
||||
|
||||
|
|
@ -29,16 +32,13 @@ def verify_pep440(version):
|
|||
|
||||
https://github.com/pypa/packaging/blob/16.7/packaging/version.py#L191
|
||||
"""
|
||||
try:
|
||||
return packaging.version.Version(version)
|
||||
except packaging.version.InvalidVersion:
|
||||
raise
|
||||
return packaging.version.Version(version)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
if len(sys.argv) != 3:
|
||||
if len(sys.argv) != ARGUMENT_NUMBER:
|
||||
msg = "New version not specified"
|
||||
raise Exception(msg)
|
||||
raise ValueError(msg)
|
||||
new_version = sys.argv[1]
|
||||
|
||||
# Strip "v" prefix from version if present
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
BASE_DIR = Path(__file__).parent.parent.parent
|
||||
ARGUMENT_NUMBER = 2
|
||||
|
||||
|
||||
def update_uv_dep(base_version: str) -> None:
|
||||
|
|
@ -19,7 +22,7 @@ def update_uv_dep(base_version: str) -> None:
|
|||
# Check if the pattern is found
|
||||
if not pattern.search(content):
|
||||
msg = f"{pattern} UV dependency not found in {pyproject_path}"
|
||||
raise Exception(msg)
|
||||
raise ValueError(msg)
|
||||
|
||||
# Replace the matched pattern with the new one
|
||||
content = pattern.sub(replacement, content)
|
||||
|
|
@ -29,9 +32,9 @@ def update_uv_dep(base_version: str) -> None:
|
|||
|
||||
|
||||
def main() -> None:
|
||||
if len(sys.argv) != 2:
|
||||
if len(sys.argv) != ARGUMENT_NUMBER:
|
||||
msg = "specify base version"
|
||||
raise Exception(msg)
|
||||
raise ValueError(msg)
|
||||
base_version = sys.argv[1]
|
||||
base_version = base_version.lstrip("v")
|
||||
update_uv_dep(base_version)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ from pydantic import BaseModel
|
|||
|
||||
from langflow.base.tools.constants import TOOL_OUTPUT_NAME
|
||||
from langflow.custom.tree_visitor import RequiredInputsVisitor
|
||||
from langflow.field_typing import Tool # noqa: TCH001 Needed by add_toolkit_output
|
||||
from langflow.field_typing import Tool # noqa: TCH001 Needed by _add_toolkit_output
|
||||
from langflow.graph.state.model import create_state_model
|
||||
from langflow.helpers.custom import format_type
|
||||
from langflow.schema.artifact import get_artifact_type, post_process_raw
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
"""Version package."""
|
||||
|
|
@ -1,8 +1,11 @@
|
|||
"""Module for package versioning."""
|
||||
|
||||
import contextlib
|
||||
|
||||
|
||||
def get_version() -> str:
|
||||
"""Retrieves the version of the package from a possible list of package names.
|
||||
|
||||
This accounts for after package names are updated for -nightly builds.
|
||||
|
||||
Returns:
|
||||
|
|
@ -32,7 +35,9 @@ def get_version() -> str:
|
|||
|
||||
|
||||
def is_pre_release(v: str) -> bool:
|
||||
"""Returns a boolean indicating whether the version is a pre-release version,
|
||||
"""Returns a boolean indicating whether the version is a pre-release version.
|
||||
|
||||
Returns a boolean indicating whether the version is a pre-release version,
|
||||
as per the definition of a pre-release segment from PEP 440.
|
||||
"""
|
||||
return any(label in v for label in ["a", "b", "rc"])
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ from langflow.services.database.models.vertex_builds.crud import delete_vertex_b
|
|||
from langflow.services.database.utils import session_getter
|
||||
from langflow.services.deps import get_db_service
|
||||
from loguru import logger
|
||||
from pytest import LogCaptureFixture
|
||||
from sqlmodel import Session, SQLModel, create_engine, select
|
||||
from sqlmodel.pool import StaticPool
|
||||
from typer.testing import CliRunner
|
||||
|
|
@ -102,7 +101,7 @@ def _delete_transactions_and_vertex_builds(session, user: User):
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def caplog(caplog: LogCaptureFixture):
|
||||
def caplog(caplog: pytest.LogCaptureFixture):
|
||||
handler_id = logger.add(
|
||||
caplog.handler,
|
||||
format="{message}",
|
||||
|
|
@ -144,7 +143,7 @@ def load_flows_dir():
|
|||
|
||||
|
||||
@pytest.fixture(name="distributed_env")
|
||||
def setup_env(monkeypatch):
|
||||
def _setup_env(monkeypatch):
|
||||
monkeypatch.setenv("LANGFLOW_CACHE_TYPE", "redis")
|
||||
monkeypatch.setenv("LANGFLOW_REDIS_HOST", "result_backend")
|
||||
monkeypatch.setenv("LANGFLOW_REDIS_PORT", "6379")
|
||||
|
|
@ -158,7 +157,11 @@ def setup_env(monkeypatch):
|
|||
|
||||
|
||||
@pytest.fixture(name="distributed_client")
|
||||
def distributed_client_fixture(session: Session, monkeypatch, distributed_env):
|
||||
def distributed_client_fixture(
|
||||
session: Session, # noqa: ARG001
|
||||
monkeypatch,
|
||||
distributed_env, # noqa: ARG001
|
||||
):
|
||||
# Here we load the .env from ../deploy/.env
|
||||
from langflow.core import celery_app
|
||||
|
||||
|
|
@ -273,7 +276,12 @@ def json_memory_chatbot_no_llm():
|
|||
|
||||
|
||||
@pytest.fixture(name="client")
|
||||
async def client_fixture(session: Session, monkeypatch, request, load_flows_dir):
|
||||
async def client_fixture(
|
||||
session: Session, # noqa: ARG001
|
||||
monkeypatch,
|
||||
request,
|
||||
load_flows_dir,
|
||||
):
|
||||
# Set the database url to a test database
|
||||
if "noclient" in request.keywords:
|
||||
yield
|
||||
|
|
@ -296,9 +304,11 @@ async def client_fixture(session: Session, monkeypatch, request, load_flows_dir)
|
|||
db_service.database_url = f"sqlite:///{db_path}"
|
||||
db_service.reload_engine()
|
||||
# app.dependency_overrides[get_session] = get_session_override
|
||||
async with LifespanManager(app, startup_timeout=None, shutdown_timeout=None) as manager:
|
||||
async with AsyncClient(transport=ASGITransport(app=manager.app), base_url="http://testserver/") as client:
|
||||
yield client
|
||||
async with (
|
||||
LifespanManager(app, startup_timeout=None, shutdown_timeout=None) as manager,
|
||||
AsyncClient(transport=ASGITransport(app=manager.app), base_url="http://testserver/") as client,
|
||||
):
|
||||
yield client
|
||||
# app.dependency_overrides.clear()
|
||||
monkeypatch.undo()
|
||||
# clear the temp db
|
||||
|
|
@ -308,7 +318,7 @@ async def client_fixture(session: Session, monkeypatch, request, load_flows_dir)
|
|||
|
||||
# create a fixture for session_getter above
|
||||
@pytest.fixture(name="session_getter")
|
||||
def session_getter_fixture(client):
|
||||
def session_getter_fixture(client): # noqa: ARG001
|
||||
@contextmanager
|
||||
def blank_session_getter(db_service: "DatabaseService"):
|
||||
with Session(db_service.engine) as session:
|
||||
|
|
@ -326,7 +336,7 @@ def runner():
|
|||
async def test_user(client):
|
||||
user_data = UserCreate(
|
||||
username="testuser",
|
||||
password="testpassword",
|
||||
password="testpassword", # noqa: S106
|
||||
)
|
||||
response = await client.post("api/v1/users/", json=user_data.model_dump())
|
||||
assert response.status_code == 201
|
||||
|
|
@ -337,7 +347,7 @@ async def test_user(client):
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def active_user(client):
|
||||
def active_user(client): # noqa: ARG001
|
||||
db_manager = get_db_service()
|
||||
with db_manager.with_session() as session:
|
||||
user = User(
|
||||
|
|
@ -375,7 +385,11 @@ async def logged_in_headers(client, active_user):
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def flow(client, json_flow: str, active_user):
|
||||
def flow(
|
||||
client, # noqa: ARG001
|
||||
json_flow: str,
|
||||
active_user,
|
||||
):
|
||||
from langflow.services.database.models.flow.model import FlowCreate
|
||||
|
||||
loaded_json = json.loads(json_flow)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class TestComponent(CustomComponent):
|
|||
def refresh_values(self):
|
||||
# This is a function that will be called every time the component is updated
|
||||
# and should return a list of random strings
|
||||
return [f"Random {random.randint(1, 100)}" for _ in range(5)]
|
||||
return [f"Random {random.randint(1, 100)}" for _ in range(5)] # noqa: S311
|
||||
|
||||
def build_config(self):
|
||||
return {"param": {"display_name": "Param", "options": self.refresh_values}}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class MultipleOutputsComponent(Component):
|
|||
]
|
||||
|
||||
def certain_output(self) -> int:
|
||||
return randint(0, self.number)
|
||||
return randint(0, self.number) # noqa: S311
|
||||
|
||||
def other_output(self) -> int:
|
||||
return self.certain_output()
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ class TestComponent(CustomComponent):
|
|||
def refresh_values(self):
|
||||
# This is a function that will be called every time the component is updated
|
||||
# and should return a list of random strings
|
||||
return [f"Random {random.randint(1, 100)}" for _ in range(5)]
|
||||
return [f"Random {random.randint(1, 100)}" for _ in range(5)] # noqa: S311
|
||||
|
||||
def build_config(self):
|
||||
return {"param": Input(display_name="Param", options=self.refresh_values)}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import pytest
|
||||
from langflow.schema.message import Message
|
||||
|
||||
from tests.api_keys import get_openai_api_key
|
||||
from tests.integration.utils import download_flow_from_github, run_json_flow
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import pytest
|
||||
|
||||
from tests.integration.utils import run_single_component
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ from langchain_core.documents import Document
|
|||
from langflow.components.embeddings import OpenAIEmbeddingsComponent
|
||||
from langflow.components.vectorstores import AstraVectorStoreComponent
|
||||
from langflow.schema.data import Data
|
||||
|
||||
from tests.api_keys import get_astradb_api_endpoint, get_astradb_application_token, get_openai_api_key
|
||||
from tests.integration.components.mock_components import TextToData
|
||||
from tests.integration.utils import ComponentInputHandle, run_single_component
|
||||
|
|
@ -27,7 +28,7 @@ ALL_COLLECTIONS = [
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def astradb_client(request):
|
||||
def astradb_client():
|
||||
client = AstraDB(api_endpoint=get_astradb_api_endpoint(), token=get_astradb_application_token())
|
||||
yield client
|
||||
for collection in ALL_COLLECTIONS:
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import pytest
|
|||
from langflow.components.helpers.ParseJSONData import ParseJSONDataComponent
|
||||
from langflow.components.inputs import ChatInput
|
||||
from langflow.schema import Data
|
||||
|
||||
from tests.integration.components.mock_components import TextToData
|
||||
from tests.integration.utils import ComponentInputHandle, run_single_component
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import pytest
|
|||
from langflow.components.inputs import ChatInput
|
||||
from langflow.memory import get_messages
|
||||
from langflow.schema.message import Message
|
||||
|
||||
from tests.integration.utils import run_single_component
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import pytest
|
||||
from langflow.components.inputs import TextInputComponent
|
||||
from langflow.schema.message import Message
|
||||
|
||||
from tests.integration.utils import run_single_component
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import pytest
|
|||
from langflow.components.models.OpenAIModel import OpenAIModelComponent
|
||||
from langflow.components.output_parsers.OutputParser import OutputParserComponent
|
||||
from langflow.components.prompts.Prompt import PromptComponent
|
||||
|
||||
from tests.integration.utils import ComponentInputHandle, run_single_component
|
||||
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue