* python version updated from 3.9 into 3.12 * x2text-service updated with uv and python version 3.12 * x2text-service docker file updated * Unstract packages updated with uv * Runner updated with uv * Promptservice updated with uv * Platform service updated with uv * backend service updated with uv * root pyproject.toml file updated * sdk version updated in services * unstract package modules updated based on sdk version: * docker file update * pdm lock workflow modified to support uv * Docs updated based on uv support * lock automation updated * snowflake module version updated into 3.14.0 * tox updated to support UV * tox updated to support UV * tox updated with pytest * tox updated with pytest-md-report * tox updated with module requirements * python migration from 3.9 to 3.12 * tox updated with module requirements * runner updated * Commit uv.lock changes * runner updated * Commit uv.lock changes * pytest.ini added * x2text-service docker file updated * pytest.ini removed * environment updated to test * docformatter commented on pre-commit * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * some pre-commit issues ignored * some pre-commit issues ignored * some pre-commit issues ignored * some pre-commit issues ignored * some pre-commit issues ignored * pre-commit updates * un used import removed from platfrom service controller * tox issue fixed * tox issue fixed * docker files updated * backend dockerfile updated * open installation issue fixed * Tools docker file updated with base python version 3.12 * python version updated into min 3.12 in pyproject.toml * linting issue fixed * uv version upgraded into 0.6.14 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * migrations excluded from ruff * added PoethePoet task runner * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * feat: Added poe tasks for services (#1248) * Added poe tasks for services * reverted FE change made by mistake * updated tool-sidecar to uv and python to 3.12.9 * minor updates in pyproject descreption * feat: platform-service logging improvements (#1255) feat: Used flask util from core to improve logging in platform-service, added core as a dependency to platform-service: * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix: Platform-service build issue and numpy issue with Python 3.12 (#1258) * fix: Platform-service build and numpy issue with Py 3.12 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix: Removed backend dockerfile install statements for numpy --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> * minor: Handled scenario when cost is not calculated due to no usage * minor: Corrected content shown for workflow input * fix: Minor fixes, used gthread for prompt-service, runner * Commit uv.lock changes * Removed unused line in tool dockerfile --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Chandrasekharan M <chandrasekharan@zipstack.com> Co-authored-by: Chandrasekharan M <117059509+chandrasekharan-zipstack@users.noreply.github.com> Co-authored-by: ali-zipstack <muhammad.ali@zipstack.com>
234 lines
6.9 KiB
Python
234 lines
6.9 KiB
Python
from abc import ABC, abstractmethod
|
|
from dataclasses import asdict, dataclass, field
|
|
from typing import Any
|
|
from urllib.parse import urlencode, urljoin
|
|
|
|
from django.conf import settings
|
|
from pipeline_v2.models import Pipeline
|
|
from utils.request import HTTPMethod
|
|
|
|
from api_v2.constants import ApiExecution
|
|
from api_v2.models import APIDeployment
|
|
from api_v2.postman_collection.constants import CollectionKey
|
|
|
|
|
|
@dataclass
|
|
class HeaderItem:
|
|
key: str
|
|
value: str
|
|
|
|
|
|
@dataclass
|
|
class FormDataItem:
|
|
key: str
|
|
type: str
|
|
src: str | None = None
|
|
value: str | None = None
|
|
|
|
def __post_init__(self) -> None:
|
|
if self.type == "file":
|
|
if self.src is None:
|
|
raise ValueError("src must be provided for type 'file'")
|
|
elif self.type == "text":
|
|
if self.value is None:
|
|
raise ValueError("value must be provided for type 'text'")
|
|
else:
|
|
raise ValueError(f"Unsupported type for form data: {self.type}")
|
|
|
|
|
|
@dataclass
|
|
class BodyItem:
|
|
formdata: list[FormDataItem]
|
|
mode: str = "formdata"
|
|
|
|
|
|
@dataclass
|
|
class RequestItem:
|
|
method: HTTPMethod
|
|
url: str
|
|
header: list[HeaderItem]
|
|
body: BodyItem | None = None
|
|
|
|
|
|
@dataclass
|
|
class PostmanItem:
|
|
name: str
|
|
request: RequestItem
|
|
|
|
|
|
@dataclass
|
|
class PostmanInfo:
|
|
name: str = "Unstract's API deployment"
|
|
schema: str = CollectionKey.POSTMAN_COLLECTION_V210
|
|
description: str = "Contains APIs meant for using the deployed Unstract API"
|
|
|
|
|
|
class APIBase(ABC):
|
|
@abstractmethod
|
|
def get_form_data_items(self) -> list[FormDataItem]:
|
|
pass
|
|
|
|
@abstractmethod
|
|
def get_api_endpoint(self) -> str:
|
|
pass
|
|
|
|
@abstractmethod
|
|
def get_postman_items(self) -> list[PostmanItem]:
|
|
pass
|
|
|
|
@abstractmethod
|
|
def get_api_key(self) -> str:
|
|
pass
|
|
|
|
def get_execute_body(self) -> BodyItem:
|
|
form_data_items = self.get_form_data_items()
|
|
return BodyItem(formdata=form_data_items)
|
|
|
|
def get_create_api_request(self) -> RequestItem:
|
|
header_list = [
|
|
HeaderItem(key="Authorization", value=f"Bearer {self.get_api_key()}")
|
|
]
|
|
abs_api_endpoint = urljoin(settings.WEB_APP_ORIGIN_URL, self.get_api_endpoint())
|
|
return RequestItem(
|
|
method=HTTPMethod.POST,
|
|
header=header_list,
|
|
body=self.get_execute_body(),
|
|
url=abs_api_endpoint,
|
|
)
|
|
|
|
|
|
@dataclass
|
|
class APIDeploymentDto(APIBase):
|
|
display_name: str
|
|
description: str
|
|
api_endpoint: str
|
|
api_key: str
|
|
|
|
def get_postman_info(self) -> PostmanInfo:
|
|
return PostmanInfo(name=self.display_name, description=self.description)
|
|
|
|
def get_form_data_items(self) -> list[FormDataItem]:
|
|
return [
|
|
FormDataItem(
|
|
key=ApiExecution.FILES_FORM_DATA, type="file", src="/path_to_file"
|
|
),
|
|
FormDataItem(
|
|
key=ApiExecution.TIMEOUT_FORM_DATA,
|
|
type="text",
|
|
value=ApiExecution.MAXIMUM_TIMEOUT_IN_SEC,
|
|
),
|
|
FormDataItem(key=ApiExecution.INCLUDE_METADATA, type="text", value="False"),
|
|
FormDataItem(key=ApiExecution.INCLUDE_METRICS, type="text", value="False"),
|
|
]
|
|
|
|
def get_api_key(self) -> str:
|
|
return self.api_key
|
|
|
|
def get_api_endpoint(self) -> str:
|
|
return self.api_endpoint
|
|
|
|
def _get_status_api_request(self) -> RequestItem:
|
|
header_list = [HeaderItem(key="Authorization", value=f"Bearer {self.api_key}")]
|
|
status_query_param = {
|
|
"execution_id": CollectionKey.STATUS_EXEC_ID_DEFAULT,
|
|
ApiExecution.INCLUDE_METADATA: "False",
|
|
ApiExecution.INCLUDE_METRICS: "False",
|
|
}
|
|
status_query_str = urlencode(status_query_param)
|
|
abs_api_endpoint = urljoin(settings.WEB_APP_ORIGIN_URL, self.api_endpoint)
|
|
status_url = urljoin(abs_api_endpoint, "?" + status_query_str)
|
|
return RequestItem(method=HTTPMethod.GET, header=header_list, url=status_url)
|
|
|
|
def get_postman_items(self) -> list[PostmanItem]:
|
|
postman_item_list = [
|
|
PostmanItem(
|
|
name=CollectionKey.EXECUTE_API_KEY,
|
|
request=self.get_create_api_request(),
|
|
),
|
|
PostmanItem(
|
|
name=CollectionKey.STATUS_API_KEY,
|
|
request=self._get_status_api_request(),
|
|
),
|
|
]
|
|
return postman_item_list
|
|
|
|
|
|
@dataclass
|
|
class PipelineDto(APIBase):
|
|
pipeline_name: str
|
|
api_endpoint: str
|
|
api_key: str
|
|
|
|
def get_postman_info(self) -> PostmanInfo:
|
|
return PostmanInfo(name=self.pipeline_name, description="")
|
|
|
|
def get_form_data_items(self) -> list[FormDataItem]:
|
|
return []
|
|
|
|
def get_api_endpoint(self) -> str:
|
|
return self.api_endpoint
|
|
|
|
def get_api_key(self) -> str:
|
|
return self.api_key
|
|
|
|
def get_postman_items(self) -> list[PostmanItem]:
|
|
postman_item_list = [
|
|
PostmanItem(
|
|
name=CollectionKey.EXECUTE_PIPELINE_API_KEY,
|
|
request=self.get_create_api_request(),
|
|
)
|
|
]
|
|
return postman_item_list
|
|
|
|
|
|
@dataclass
|
|
class PostmanCollection:
|
|
info: PostmanInfo
|
|
item: list[PostmanItem] = field(default_factory=list)
|
|
|
|
@classmethod
|
|
def create(
|
|
cls,
|
|
instance: APIDeployment | Pipeline,
|
|
api_key: str = CollectionKey.AUTH_QUERY_PARAM_DEFAULT,
|
|
) -> "PostmanCollection":
|
|
"""Creates a PostmanCollection instance.
|
|
|
|
This instance can help represent Postman collections (v2 format) that
|
|
can be used to easily invoke workflows deployed as APIs
|
|
|
|
Args:
|
|
instance (APIDeployment): API deployment to generate collection for
|
|
api_key (str, optional): Active API key used to authenticate requests for
|
|
deployed APIs. Defaults to CollectionKey.AUTH_QUERY_PARAM_DEFAULT.
|
|
|
|
Returns:
|
|
PostmanCollection: Instance representing PostmanCollection
|
|
"""
|
|
data_object: APIBase
|
|
if isinstance(instance, APIDeployment):
|
|
data_object = APIDeploymentDto(
|
|
display_name=instance.display_name,
|
|
description=instance.description,
|
|
api_endpoint=instance.api_endpoint,
|
|
api_key=api_key,
|
|
)
|
|
elif isinstance(instance, Pipeline):
|
|
data_object = PipelineDto(
|
|
pipeline_name=instance.pipeline_name,
|
|
api_endpoint=instance.api_endpoint,
|
|
api_key=api_key,
|
|
)
|
|
postman_info: PostmanInfo = data_object.get_postman_info()
|
|
postman_item_list = data_object.get_postman_items()
|
|
return cls(info=postman_info, item=postman_item_list)
|
|
|
|
def to_dict(self) -> dict[str, Any]:
|
|
"""Convert PostmanCollection instance to a dict.
|
|
|
|
Returns:
|
|
dict[str, Any]: PostmanCollection as a dict
|
|
"""
|
|
collection_dict = asdict(self)
|
|
return collection_dict
|