Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ref: Add ALL ruff rules for tests #4183

Merged
merged 1 commit into from
Oct 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
12 changes: 7 additions & 5 deletions scripts/ci/pypi_nightly_tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
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 = ""
Expand All @@ -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)


Expand Down Expand Up @@ -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)
Expand Down
14 changes: 7 additions & 7 deletions scripts/ci/update_lf_base_dependency.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#!/usr/bin/env python

import re
import sys
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:
Expand All @@ -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")

Expand All @@ -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
Expand Down
11 changes: 7 additions & 4 deletions scripts/ci/update_pyproject_name.py
Original file line number Diff line number Diff line change
@@ -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:
Expand All @@ -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")
Expand All @@ -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]

Expand Down
14 changes: 7 additions & 7 deletions scripts/ci/update_pyproject_version.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#!/usr/bin/env python

import re
import sys
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:
Expand All @@ -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)

Expand All @@ -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
Expand Down
9 changes: 6 additions & 3 deletions scripts/ci/update_uv_dependency.py
Original file line number Diff line number Diff line change
@@ -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:
Expand All @@ -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)
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

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
Expand Down
1 change: 1 addition & 0 deletions src/backend/langflow/version/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Version package."""
7 changes: 6 additions & 1 deletion src/backend/langflow/version/version.py
Original file line number Diff line number Diff line change
@@ -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:
Expand Down Expand Up @@ -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"])
38 changes: 26 additions & 12 deletions src/backend/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
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
Expand Down Expand Up @@ -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}",
Expand Down Expand Up @@ -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")
Expand All @@ -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

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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:
Expand All @@ -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
Expand All @@ -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(
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/backend/tests/data/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
Expand Down
Loading
Loading