Skip to content
Closed
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
10 changes: 10 additions & 0 deletions packages/gooddata-sdk/src/gooddata_sdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@
TokenCredentialsFromEnvVar,
TokenCredentialsFromFile,
)
from gooddata_sdk.catalog.knowledge.declarative_model.knowledge_document import (
CatalogCreateKnowledgeDocumentRequest,
CatalogCreateKnowledgeDocumentResponse,
CatalogDeleteKnowledgeDocumentResponse,
CatalogKnowledgeDocumentMetadata,
CatalogListKnowledgeDocumentsResponse,
CatalogUpsertKnowledgeDocumentRequest,
CatalogUpsertKnowledgeDocumentResponse,
)
from gooddata_sdk.catalog.knowledge.service import CatalogKnowledgeService
from gooddata_sdk.catalog.export.request import (
ExportCustomLabel,
ExportCustomMetric,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# (C) 2024 GoodData Corporation
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# (C) 2024 GoodData Corporation
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
# (C) 2024 GoodData Corporation
from __future__ import annotations

from typing import Any

import attrs

from gooddata_api_client.model.create_knowledge_document_request_dto import CreateKnowledgeDocumentRequestDto
from gooddata_api_client.model.create_knowledge_document_response_dto import CreateKnowledgeDocumentResponseDto
from gooddata_api_client.model.delete_knowledge_document_response_dto import DeleteKnowledgeDocumentResponseDto
from gooddata_api_client.model.knowledge_document_metadata_dto import KnowledgeDocumentMetadataDto
from gooddata_api_client.model.list_knowledge_documents_response_dto import ListKnowledgeDocumentsResponseDto
from gooddata_api_client.model.upsert_knowledge_document_request_dto import UpsertKnowledgeDocumentRequestDto
from gooddata_api_client.model.upsert_knowledge_document_response_dto import UpsertKnowledgeDocumentResponseDto


@attrs.define(kw_only=True)
class CatalogKnowledgeDocumentMetadata:
"""Metadata for a knowledge document stored in GoodData."""

filename: str
num_chunks: int
created_at: str
created_by: str
updated_at: str
updated_by: str
scopes: list[str] = attrs.field(factory=list)
workspace_id: str | None = None
title: str | None = None
is_disabled: bool | None = None

@classmethod
def from_api(cls, dto: KnowledgeDocumentMetadataDto) -> CatalogKnowledgeDocumentMetadata:
kwargs: dict[str, Any] = {}
if hasattr(dto, "workspace_id") and dto.get("workspace_id") is not None:
kwargs["workspace_id"] = dto["workspace_id"]
if hasattr(dto, "title") and dto.get("title") is not None:
kwargs["title"] = dto["title"]
if hasattr(dto, "is_disabled") and dto.get("is_disabled") is not None:
kwargs["is_disabled"] = dto["is_disabled"]
scopes = dto.get("scopes") or []
return cls(
filename=dto["filename"],
num_chunks=dto["num_chunks"],
created_at=dto["created_at"],
created_by=dto["created_by"],
updated_at=dto["updated_at"],
updated_by=dto["updated_by"],
scopes=scopes,
**kwargs,
)


@attrs.define(kw_only=True)
class CatalogCreateKnowledgeDocumentRequest:
"""Request to create a new knowledge document (fails if already exists)."""

filename: str
content: str
title: str | None = None
scopes: list[str] = attrs.field(factory=list)
page_boundaries: list[int] = attrs.field(factory=list)

def as_api_model(self) -> CreateKnowledgeDocumentRequestDto:
kwargs: dict[str, Any] = {}
if self.title is not None:
kwargs["title"] = self.title
if self.scopes:
kwargs["scopes"] = self.scopes
if self.page_boundaries:
kwargs["page_boundaries"] = self.page_boundaries
return CreateKnowledgeDocumentRequestDto(
filename=self.filename,
content=self.content,
_check_type=False,
**kwargs,
)


@attrs.define(kw_only=True)
class CatalogCreateKnowledgeDocumentResponse:
"""Response from creating a knowledge document."""

filename: str
message: str
num_chunks: int
success: bool

@classmethod
def from_api(cls, dto: CreateKnowledgeDocumentResponseDto) -> CatalogCreateKnowledgeDocumentResponse:
return cls(
filename=dto["filename"],
message=dto["message"],
num_chunks=dto["num_chunks"],
success=dto["success"],
)


@attrs.define(kw_only=True)
class CatalogUpsertKnowledgeDocumentRequest:
"""Request to upsert a knowledge document (create or update)."""

filename: str
content: str
title: str | None = None
scopes: list[str] = attrs.field(factory=list)
page_boundaries: list[int] = attrs.field(factory=list)

def as_api_model(self) -> UpsertKnowledgeDocumentRequestDto:
kwargs: dict[str, Any] = {}
if self.title is not None:
kwargs["title"] = self.title
if self.scopes:
kwargs["scopes"] = self.scopes
if self.page_boundaries:
kwargs["page_boundaries"] = self.page_boundaries
return UpsertKnowledgeDocumentRequestDto(
filename=self.filename,
content=self.content,
_check_type=False,
**kwargs,
)


@attrs.define(kw_only=True)
class CatalogUpsertKnowledgeDocumentResponse:
"""Response from upserting a knowledge document."""

filename: str
message: str
num_chunks: int
success: bool

@classmethod
def from_api(cls, dto: UpsertKnowledgeDocumentResponseDto) -> CatalogUpsertKnowledgeDocumentResponse:
return cls(
filename=dto["filename"],
message=dto["message"],
num_chunks=dto["num_chunks"],
success=dto["success"],
)


@attrs.define(kw_only=True)
class CatalogListKnowledgeDocumentsResponse:
"""Response from listing knowledge documents."""

documents: list[CatalogKnowledgeDocumentMetadata] = attrs.field(factory=list)
next_page_token: str | None = None
total_count: int | None = None

@classmethod
def from_api(cls, dto: ListKnowledgeDocumentsResponseDto) -> CatalogListKnowledgeDocumentsResponse:
raw_docs = dto.get("documents") or []
documents = [CatalogKnowledgeDocumentMetadata.from_api(d) for d in raw_docs]
kwargs: dict[str, Any] = {}
if dto.get("next_page_token") is not None:
kwargs["next_page_token"] = dto["next_page_token"]
if dto.get("total_count") is not None:
kwargs["total_count"] = dto["total_count"]
return cls(documents=documents, **kwargs)


@attrs.define(kw_only=True)
class CatalogDeleteKnowledgeDocumentResponse:
"""Response from deleting a knowledge document."""

message: str
success: bool

@classmethod
def from_api(cls, dto: DeleteKnowledgeDocumentResponseDto) -> CatalogDeleteKnowledgeDocumentResponse:
return cls(
message=dto["message"],
success=dto["success"],
)
128 changes: 128 additions & 0 deletions packages/gooddata-sdk/src/gooddata_sdk/catalog/knowledge/service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# (C) 2024 GoodData Corporation
from __future__ import annotations

from gooddata_api_client.exceptions import NotFoundException

from gooddata_sdk.catalog.catalog_service_base import CatalogServiceBase
from gooddata_sdk.catalog.knowledge.declarative_model.knowledge_document import (
CatalogCreateKnowledgeDocumentRequest,
CatalogCreateKnowledgeDocumentResponse,
CatalogDeleteKnowledgeDocumentResponse,
CatalogKnowledgeDocumentMetadata,
CatalogListKnowledgeDocumentsResponse,
CatalogUpsertKnowledgeDocumentRequest,
CatalogUpsertKnowledgeDocumentResponse,
)
from gooddata_sdk.client import GoodDataApiClient


class CatalogKnowledgeService(CatalogServiceBase):
"""Service for managing knowledge documents in GoodData workspaces."""

def __init__(self, api_client: GoodDataApiClient) -> None:
super().__init__(api_client)

def create_document(
self,
workspace_id: str,
request: CatalogCreateKnowledgeDocumentRequest,
) -> CatalogCreateKnowledgeDocumentResponse:
"""Create a new knowledge document (strict create, rejects duplicates).

Args:
workspace_id (str): Workspace identifier.
request (CatalogCreateKnowledgeDocumentRequest): Document creation request.

Returns:
CatalogCreateKnowledgeDocumentResponse: Response with document metadata.
"""
response = self._actions_api.create_document(
workspace_id,
request.as_api_model(),
_check_return_type=False,
)
return CatalogCreateKnowledgeDocumentResponse.from_api(response)

def upsert_document(
self,
workspace_id: str,
request: CatalogUpsertKnowledgeDocumentRequest,
) -> CatalogUpsertKnowledgeDocumentResponse:
"""Upsert a knowledge document (create or update).

Args:
workspace_id (str): Workspace identifier.
request (CatalogUpsertKnowledgeDocumentRequest): Document upsert request.

Returns:
CatalogUpsertKnowledgeDocumentResponse: Response with document metadata.
"""
response = self._actions_api.upsert_document(
workspace_id,
request.as_api_model(),
_check_return_type=False,
)
return CatalogUpsertKnowledgeDocumentResponse.from_api(response)

def get_document(
self,
workspace_id: str,
filename: str,
) -> CatalogKnowledgeDocumentMetadata:
"""Get metadata for a single knowledge document.

Args:
workspace_id (str): Workspace identifier.
filename (str): Document filename.

Returns:
CatalogKnowledgeDocumentMetadata: Document metadata.

Raises:
NotFoundException: If the document does not exist.
"""
response = self._actions_api.get_document(
workspace_id,
filename,
_check_return_type=False,
)
return CatalogKnowledgeDocumentMetadata.from_api(response)

def list_documents(
self,
workspace_id: str,
) -> CatalogListKnowledgeDocumentsResponse:
"""List all knowledge documents in a workspace.

Args:
workspace_id (str): Workspace identifier.

Returns:
CatalogListKnowledgeDocumentsResponse: Response containing list of document metadata.
"""
response = self._actions_api.list_documents(
workspace_id,
_check_return_type=False,
)
return CatalogListKnowledgeDocumentsResponse.from_api(response)

def delete_document(
self,
workspace_id: str,
filename: str,
) -> CatalogDeleteKnowledgeDocumentResponse:
"""Delete a knowledge document.

Args:
workspace_id (str): Workspace identifier.
filename (str): Document filename.

Returns:
CatalogDeleteKnowledgeDocumentResponse: Response confirming deletion.
"""
response = self._actions_api.delete_document(
workspace_id,
filename,
_check_return_type=False,
)
return CatalogDeleteKnowledgeDocumentResponse.from_api(response)
6 changes: 6 additions & 0 deletions packages/gooddata-sdk/src/gooddata_sdk/sdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from gooddata_sdk.catalog.appearance.service import CatalogAppearanceService
from gooddata_sdk.catalog.data_source.service import CatalogDataSourceService
from gooddata_sdk.catalog.export.service import ExportService
from gooddata_sdk.catalog.knowledge.service import CatalogKnowledgeService
from gooddata_sdk.catalog.organization.service import CatalogOrganizationService
from gooddata_sdk.catalog.permission.service import CatalogPermissionService
from gooddata_sdk.catalog.user.service import CatalogUserService
Expand Down Expand Up @@ -89,6 +90,7 @@ def __init__(self, client: GoodDataApiClient) -> None:
self._support = SupportService(self._client)
self._catalog_permission = CatalogPermissionService(self._client)
self._export = ExportService(self._client)
self._catalog_knowledge = CatalogKnowledgeService(self._client)

@property
def catalog_appearance(self) -> CatalogAppearanceService:
Expand Down Expand Up @@ -138,6 +140,10 @@ def catalog_permission(self) -> CatalogPermissionService:
def export(self) -> ExportService:
return self._export

@property
def catalog_knowledge(self) -> CatalogKnowledgeService:
return self._catalog_knowledge

@property
def client(self) -> GoodDataApiClient:
return self._client
Empty file.
Loading
Loading