From d460b05a6cdcfaf180ba72ede58350c26631a0a7 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 16 Nov 2023 16:27:27 -0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix(schema.py):=20set=20count=20?= =?UTF-8?q?field=20in=20ListComponentResponseModel=20as=20Optional=20with?= =?UTF-8?q?=20default=20value=20of=200=20to=20handle=20cases=20where=20cou?= =?UTF-8?q?nt=20is=20not=20provided=20=F0=9F=90=9B=20fix(service.py):=20im?= =?UTF-8?q?port=20logger=20from=20loguru=20module=20to=20fix=20logger=20im?= =?UTF-8?q?port=20error=20=E2=9C=A8=20feat(service.py):=20add=20support=20?= =?UTF-8?q?for=20metadata=20in=20=5Fget=20method=20to=20handle=20additiona?= =?UTF-8?q?l=20metadata=20returned=20in=20API=20response=20=E2=9C=A8=20fea?= =?UTF-8?q?t(service.py):=20add=20support=20for=20metadata=20in=20query=5F?= =?UTF-8?q?components=20method=20to=20handle=20additional=20metadata=20ret?= =?UTF-8?q?urned=20in=20API=20response?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/langflow/services/store/schema.py | 2 +- .../langflow/services/store/service.py | 51 +++++++++++-------- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/backend/langflow/services/store/schema.py b/src/backend/langflow/services/store/schema.py index cbd9b3a52..e07e7d384 100644 --- a/src/backend/langflow/services/store/schema.py +++ b/src/backend/langflow/services/store/schema.py @@ -49,7 +49,7 @@ class ListComponentResponse(BaseModel): class ListComponentResponseModel(BaseModel): - count: int + count: Optional[int] = 0 authorized: bool results: Optional[List[ListComponentResponse]] diff --git a/src/backend/langflow/services/store/service.py b/src/backend/langflow/services/store/service.py index cb7fa3058..5da323138 100644 --- a/src/backend/langflow/services/store/service.py +++ b/src/backend/langflow/services/store/service.py @@ -1,9 +1,11 @@ import json -from typing import TYPE_CHECKING, Any, Dict, List, Optional +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple from uuid import UUID import httpx from httpx import HTTPError, HTTPStatusError +from loguru import logger + from langflow.services.base import Service from langflow.services.store.schema import ( CreateComponentResponse, @@ -13,7 +15,6 @@ from langflow.services.store.schema import ( StoreComponentCreate, ) from langflow.services.store.utils import process_tags_for_post, update_components_with_user_data -from loguru import logger if TYPE_CHECKING: from langflow.services.settings.service import SettingsService @@ -29,7 +30,9 @@ async def user_data_context(store_service: "StoreService", api_key: Optional[str # Fetch and set user data to the context variable if api_key: try: - user_data = await store_service._get(f"{store_service.base_url}/users/me", api_key, params={"fields": "id"}) + user_data, _ = await store_service._get( + f"{store_service.base_url}/users/me", api_key, params={"fields": "id"} + ) if isinstance(user_data, list): user_data = user_data[0] user_data_var.set(user_data) @@ -77,7 +80,7 @@ class StoreService(Service): async def _get( self, url: str, api_key: Optional[str] = None, params: Optional[Dict[str, Any]] = None - ) -> List[Dict[str, Any]]: + ) -> Tuple[List[Dict[str, Any]], Dict[str, Any]]: """Utility method to perform GET requests.""" if api_key: headers = {"Authorization": f"Bearer {api_key}"} @@ -91,10 +94,15 @@ class StoreService(Service): raise exc except Exception as exc: raise ValueError(f"GET failed: {exc}") - result = response.json()["data"] + json_response = response.json() + result = json_response["data"] + metadata = {} + if "meta" in json_response: + metadata = json_response["meta"] + if isinstance(result, dict): - return [result] - return result + return [result], metadata + return result, metadata async def call_webhook(self, api_key: str, webhook_url: str, component_id: UUID) -> None: # The webhook is a POST request with the data in the body @@ -128,7 +136,7 @@ class StoreService(Service): api_key = api_key if use_api_key else None - results = await self._get(self.components_url, api_key, params) + results, _ = await self._get(self.components_url, api_key, params) return int(results[0].get("count", 0)) @staticmethod @@ -200,11 +208,12 @@ class StoreService(Service): fields: Optional[List[str]] = None, filter_conditions: Optional[List[Dict[str, Any]]] = None, use_api_key: Optional[bool] = False, - ) -> List[ListComponentResponse]: + ) -> Tuple[List[ListComponentResponse], Dict[str, Any]]: params: Dict[str, Any] = { "page": page, "limit": limit, "fields": ",".join(fields) if fields else ",".join(self.default_fields), + "meta": "filter_count", # !This is DEPRECATED so we should remove it ASAP } # ?aggregate[count]=likes @@ -221,7 +230,7 @@ class StoreService(Service): # so we don't need to risk passing an invalid api_key # and getting 401 api_key = api_key if use_api_key else None - results = await self._get(self.components_url, api_key, params) + results, metadata = await self._get(self.components_url, api_key, params) if isinstance(results, dict): results = [results] results_objects = [ListComponentResponse(**component) for component in results] @@ -229,7 +238,7 @@ class StoreService(Service): # for component in results_objects: # if component.tags: # component.tags = [tags_id.tags_id for tags_id in component.tags] - return results_objects + return results_objects, metadata async def get_liked_by_user_components(self, component_ids: List[UUID], api_key: str) -> List[str]: # Get fields id @@ -249,7 +258,7 @@ class StoreService(Service): } ), } - results = await self._get(self.components_url, api_key, params) + results, _ = await self._get(self.components_url, api_key, params) return [result["id"] for result in results] # Which of the components is parent of the user's components @@ -268,7 +277,7 @@ class StoreService(Service): } ), } - results = await self._get(self.components_url, api_key, params) + results, _ = await self._get(self.components_url, api_key, params) return [result["id"] for result in results] async def download(self, api_key: str, component_id: UUID) -> DownloadComponentResponse: @@ -276,7 +285,7 @@ class StoreService(Service): params = {"fields": ",".join(["id", "name", "description", "data", "is_component"])} if not self.download_webhook_url: raise ValueError("DOWNLOAD_WEBHOOK_URL is not set") - component = await self._get(url, api_key, params) + component, _ = await self._get(url, api_key, params) await self.call_webhook(api_key, self.download_webhook_url, component_id) return DownloadComponentResponse(**component) @@ -311,7 +320,7 @@ class StoreService(Service): async def get_tags(self) -> List[Dict[str, Any]]: url = f"{self.base_url}/items/tags" params = {"fields": ",".join(["id", "name"])} - tags = await self._get(url, api_key=None, params=params) + tags, _ = await self._get(url, api_key=None, params=params) return tags async def get_user_likes(self, api_key: str) -> List[Dict[str, Any]]: @@ -319,7 +328,7 @@ class StoreService(Service): params = { "fields": ",".join(["id", "likes"]), } - likes = await self._get(url, api_key, params) + likes, _ = await self._get(url, api_key, params) return likes async def get_component_likes_count(self, component_id: str, api_key: Optional[str] = None) -> int: @@ -328,7 +337,7 @@ class StoreService(Service): params = { "fields": ",".join(["id", "count(liked_by)"]), } - result = await self._get(url, api_key=api_key, params=params) + result, _ = await self._get(url, api_key=api_key, params=params) if len(result) == 0: raise ValueError("Component not found") likes = result[0]["liked_by_count"] @@ -399,7 +408,7 @@ class StoreService(Service): result: List[ListComponentResponse] = [] authorized = False try: - result = await self.query_components( + result, metadata = await self.query_components( api_key=store_api_Key, page=page, limit=limit, @@ -407,13 +416,15 @@ class StoreService(Service): filter_conditions=filter_conditions, use_api_key=liked or filter_by_user, ) + if metadata: + comp_count = metadata.get("filter_count", 0) except HTTPStatusError as exc: if exc.response.status_code == 403: raise ValueError("You are not authorized to access this public resource") elif exc.response.status_code == 401: raise ValueError("You are not authorized to access this resource. Please check your API key.") try: - if result: + if result and not metadata: if len(result) >= limit: comp_count = await self.count_components( api_key=store_api_Key, @@ -422,7 +433,7 @@ class StoreService(Service): ) else: comp_count = len(result) - else: + elif not metadata: comp_count = 0 except HTTPStatusError as exc: if exc.response.status_code == 403: