Merge branch 'feature/store' of github.com:logspace-ai/langflow into feature/store
This commit is contained in:
commit
24e9693c53
5 changed files with 28 additions and 36 deletions
|
|
@ -1,13 +1,15 @@
|
||||||
|
import warnings
|
||||||
from typing import Annotated, Any, Dict, List, Optional, Union
|
from typing import Annotated, Any, Dict, List, Optional, Union
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||||
from httpx import HTTPStatusError
|
from httpx import HTTPStatusError
|
||||||
|
|
||||||
from langflow.services.auth import utils as auth_utils
|
from langflow.services.auth import utils as auth_utils
|
||||||
from langflow.services.database.models.user.user import User
|
from langflow.services.database.models.user.user import User
|
||||||
from langflow.services.deps import get_settings_service, get_store_service
|
from langflow.services.deps import get_settings_service, get_store_service
|
||||||
from langflow.services.store.schema import (
|
from langflow.services.store.schema import (
|
||||||
ComponentResponse,
|
CreateComponentResponse,
|
||||||
DownloadComponentResponse,
|
DownloadComponentResponse,
|
||||||
ListComponentResponse,
|
ListComponentResponse,
|
||||||
ListComponentResponseModel,
|
ListComponentResponseModel,
|
||||||
|
|
@ -59,8 +61,8 @@ def check_if_store_has_api_key(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@router.post("/components/", response_model=ComponentResponse, status_code=201)
|
@router.post("/components/", response_model=CreateComponentResponse, status_code=201)
|
||||||
def create_component(
|
async def create_component(
|
||||||
component: StoreComponentCreate,
|
component: StoreComponentCreate,
|
||||||
store_service: StoreService = Depends(get_store_service),
|
store_service: StoreService = Depends(get_store_service),
|
||||||
store_api_Key: str = Depends(get_user_store_api_key),
|
store_api_Key: str = Depends(get_user_store_api_key),
|
||||||
|
|
@ -68,6 +70,11 @@ def create_component(
|
||||||
try:
|
try:
|
||||||
# Verify if this is the latest version of Langflow
|
# Verify if this is the latest version of Langflow
|
||||||
# If not, raise an error
|
# If not, raise an error
|
||||||
|
if not component.last_tested_version:
|
||||||
|
# Get the local version of Langflow
|
||||||
|
from langflow import __version__ as current_version
|
||||||
|
|
||||||
|
component.last_tested_version = current_version
|
||||||
langflow_version = get_lf_version_from_pypi()
|
langflow_version = get_lf_version_from_pypi()
|
||||||
if langflow_version is None:
|
if langflow_version is None:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -76,12 +83,14 @@ def create_component(
|
||||||
)
|
)
|
||||||
elif langflow_version != component.last_tested_version:
|
elif langflow_version != component.last_tested_version:
|
||||||
# If the user is using an older version of Langflow, we need to raise an error
|
# If the user is using an older version of Langflow, we need to raise an error
|
||||||
raise ValueError(
|
# raise ValueError(
|
||||||
|
warnings.warn(
|
||||||
f"Your version of Langflow ({component.last_tested_version}) is outdated."
|
f"Your version of Langflow ({component.last_tested_version}) is outdated."
|
||||||
" Please update to the latest version ({langflow_version}) and try again."
|
f" Please update to the latest version ({langflow_version}) and try again."
|
||||||
)
|
)
|
||||||
|
|
||||||
return store_service.upload(store_api_Key, component)
|
result = await store_service.upload(store_api_Key, component)
|
||||||
|
return result
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
raise HTTPException(status_code=400, detail=str(exc))
|
raise HTTPException(status_code=400, detail=str(exc))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
from datetime import datetime
|
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
|
|
@ -15,24 +14,8 @@ class UsersLikesResponse(BaseModel):
|
||||||
liked_by_user: Optional[bool]
|
liked_by_user: Optional[bool]
|
||||||
|
|
||||||
|
|
||||||
class ComponentResponse(BaseModel):
|
class CreateComponentResponse(BaseModel):
|
||||||
id: UUID
|
id: UUID
|
||||||
status: Optional[str]
|
|
||||||
sort: Optional[int]
|
|
||||||
user_name: Optional[str]
|
|
||||||
date_created: Optional[datetime]
|
|
||||||
user_updated: Optional[UUID]
|
|
||||||
date_updated: Optional[datetime]
|
|
||||||
is_component: Optional[bool]
|
|
||||||
name: Optional[str]
|
|
||||||
description: Optional[str]
|
|
||||||
data: Optional[dict]
|
|
||||||
tags: Optional[List[int]]
|
|
||||||
liked_by_count: Optional[int]
|
|
||||||
downloads_count: Optional[int]
|
|
||||||
parent: Optional[UUID] = None
|
|
||||||
metadata: Optional[dict]
|
|
||||||
last_tested_version: Optional[str]
|
|
||||||
|
|
||||||
|
|
||||||
class TagsIdResponse(BaseModel):
|
class TagsIdResponse(BaseModel):
|
||||||
|
|
@ -88,6 +71,5 @@ class StoreComponentCreate(BaseModel):
|
||||||
tags: Optional[List[str]]
|
tags: Optional[List[str]]
|
||||||
parent: Optional[UUID] = None
|
parent: Optional[UUID] = None
|
||||||
is_component: Optional[bool]
|
is_component: Optional[bool]
|
||||||
metadata: Optional[dict]
|
last_tested_version: Optional[str] = None
|
||||||
last_tested_version: Optional[str]
|
|
||||||
public: Optional[bool] = False
|
public: Optional[bool] = False
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,19 @@
|
||||||
import json
|
import json
|
||||||
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
from httpx import HTTPError, HTTPStatusError
|
from httpx import HTTPError, HTTPStatusError
|
||||||
|
from loguru import logger
|
||||||
|
|
||||||
from langflow.services.base import Service
|
from langflow.services.base import Service
|
||||||
from langflow.services.store.schema import (
|
from langflow.services.store.schema import (
|
||||||
ComponentResponse,
|
CreateComponentResponse,
|
||||||
DownloadComponentResponse,
|
DownloadComponentResponse,
|
||||||
ListComponentResponse,
|
ListComponentResponse,
|
||||||
StoreComponentCreate,
|
StoreComponentCreate,
|
||||||
)
|
)
|
||||||
from langflow.services.store.utils import process_tags_for_post
|
from langflow.services.store.utils import process_tags_for_post
|
||||||
from loguru import logger
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from langflow.services.settings.service import SettingsService
|
from langflow.services.settings.service import SettingsService
|
||||||
|
|
@ -74,7 +75,7 @@ class StoreService(Service):
|
||||||
|
|
||||||
async def _get(
|
async def _get(
|
||||||
self, url: str, api_key: Optional[str] = None, params: Optional[Dict[str, Any]] = None
|
self, url: str, api_key: Optional[str] = None, params: Optional[Dict[str, Any]] = None
|
||||||
) -> List[Dict[str, Any]]:
|
) -> Union[List[Dict[str, Any]], Dict[str, Any]]:
|
||||||
"""Utility method to perform GET requests."""
|
"""Utility method to perform GET requests."""
|
||||||
if api_key:
|
if api_key:
|
||||||
headers = {"Authorization": f"Bearer {api_key}"}
|
headers = {"Authorization": f"Bearer {api_key}"}
|
||||||
|
|
@ -257,7 +258,7 @@ class StoreService(Service):
|
||||||
|
|
||||||
return DownloadComponentResponse(**component)
|
return DownloadComponentResponse(**component)
|
||||||
|
|
||||||
async def upload(self, api_key: str, component_data: StoreComponentCreate) -> ComponentResponse:
|
async def upload(self, api_key: str, component_data: StoreComponentCreate) -> CreateComponentResponse:
|
||||||
headers = {"Authorization": f"Bearer {api_key}"}
|
headers = {"Authorization": f"Bearer {api_key}"}
|
||||||
component_dict = component_data.dict(exclude_unset=True)
|
component_dict = component_data.dict(exclude_unset=True)
|
||||||
# Parent is a UUID, but the store expects a string
|
# Parent is a UUID, but the store expects a string
|
||||||
|
|
@ -273,7 +274,7 @@ class StoreService(Service):
|
||||||
response = await client.post(self.components_url, headers=headers, json=component_dict)
|
response = await client.post(self.components_url, headers=headers, json=component_dict)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
component = response.json()["data"]
|
component = response.json()["data"]
|
||||||
return ComponentResponse(**component)
|
return CreateComponentResponse(**component)
|
||||||
except HTTPError as exc:
|
except HTTPError as exc:
|
||||||
if response:
|
if response:
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -568,7 +568,7 @@ export async function saveFlowStore(
|
||||||
is_component: newFlow.is_component,
|
is_component: newFlow.is_component,
|
||||||
parent: newFlow.parent,
|
parent: newFlow.parent,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
public: publicFlow,
|
status: publicFlow ? "public" : "private",
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response.status !== 201) {
|
if (response.status !== 201) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# FILEPATH: /Users/ogabrielluiz/Projects/langflow2/tests/test_store_service.py
|
# FILEPATH: /Users/ogabrielluiz/Projects/langflow2/tests/test_store_service.py
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from unittest.mock import patch, Mock
|
from unittest.mock import Mock, patch
|
||||||
|
|
||||||
from langflow.services.deps import get_store_service
|
from langflow.services.deps import get_store_service
|
||||||
|
|
||||||
|
|
@ -9,7 +9,7 @@ from langflow.services.deps import get_store_service
|
||||||
@patch("langflow.services.store.service.httpx")
|
@patch("langflow.services.store.service.httpx")
|
||||||
def test_search_components(mock_httpx: Mock, client):
|
def test_search_components(mock_httpx: Mock, client):
|
||||||
# Mock the response from the HTTP GET request
|
# Mock the response from the HTTP GET request
|
||||||
from langflow.services.store.schema import ComponentResponse
|
from langflow.services.store.schema import CreateComponentResponse
|
||||||
|
|
||||||
mock_response = Mock()
|
mock_response = Mock()
|
||||||
mock_response.json.return_value = {
|
mock_response.json.return_value = {
|
||||||
|
|
@ -54,4 +54,4 @@ def test_search_components(mock_httpx: Mock, client):
|
||||||
|
|
||||||
# Assert that the search method returns a list of ComponentResponse objects
|
# Assert that the search method returns a list of ComponentResponse objects
|
||||||
assert len(components) == 2
|
assert len(components) == 2
|
||||||
assert all(isinstance(component, ComponentResponse) for component in components)
|
assert all(isinstance(component, CreateComponentResponse) for component in components)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue