Files
unstract/backend/api_v2/postman_collection/dto.py
Jaseem Jas ba1df894d2 Python 3.9 to 3.12 (#1231)
* 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>
2025-04-24 16:07:02 +05:30

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