From ae79bdcac8160a69ece92256701a200a89f83ec9 Mon Sep 17 00:00:00 2001 From: Mara3l Date: Thu, 27 Jul 2023 08:40:33 +0200 Subject: [PATCH] DP-2433: adding exporting documentation --- docs/content/en/docs/execution/_index.html | 7 + .../en/docs/execution/exports/_index.md | 82 ++++++++++ .../en/docs/execution/exports/export_pdf.md | 58 +++++++ .../docs/execution/exports/export_tabular.md | 79 ++++++++++ .../exports/export_tabular_by_insight_id.md | 69 +++++++++ .../gooddata_sdk/catalog/export/request.py | 24 ++- .../gooddata_sdk/catalog/export/service.py | 145 +++++++++++++++++- 7 files changed, 461 insertions(+), 3 deletions(-) create mode 100644 docs/content/en/docs/execution/_index.html create mode 100644 docs/content/en/docs/execution/exports/_index.md create mode 100644 docs/content/en/docs/execution/exports/export_pdf.md create mode 100644 docs/content/en/docs/execution/exports/export_tabular.md create mode 100644 docs/content/en/docs/execution/exports/export_tabular_by_insight_id.md diff --git a/docs/content/en/docs/execution/_index.html b/docs/content/en/docs/execution/_index.html new file mode 100644 index 000000000..f3b86d74c --- /dev/null +++ b/docs/content/en/docs/execution/_index.html @@ -0,0 +1,7 @@ +--- +title: "Execution" +linkTitle: "Execution" +weight: 40 +no_list: true +navigationLabel: true +--- diff --git a/docs/content/en/docs/execution/exports/_index.md b/docs/content/en/docs/execution/exports/_index.md new file mode 100644 index 000000000..d8b1701a6 --- /dev/null +++ b/docs/content/en/docs/execution/exports/_index.md @@ -0,0 +1,82 @@ +--- +title: "Dashboard Export" +linkTitle: "Dashboard Export" +weight: 23 +no_list: true +--- + +Create dashboard exports or automate your pipelines. Can be for [example](#example) be used to report .pdf via e-mail each week. + +## Methods + +* [export_pdf](./export_pdf/) +* [export_tabular](./export_tabular/) +* [export_tabular_by_insight_id](./export_tabular_by_insight_id/) + + +## Example + +```python +from gooddata_sdk import GoodDataSdk +import schedule +import smtplib +from os.path import basename +from email.mime.application import MIMEApplication +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText +from email.utils import COMMASPACE, formatdate + + +# GoodData base URL, e.g. "https://www.example.com" +host = "https://www.example.com" +token = "" +sdk = GoodDataSdk.create(host, token) + + +def send_mail(send_from, send_to, subject, text, files, server): + msg = MIMEMultipart() + msg["From"] = send_from + msg["To"] = send_to + msg["Date"] = formatdate(localtime=True) + msg["Subject"] = subject + + msg.attach(MIMEText(text)) + + # Open CSV / XLSX file(s) and add it to email attachment + for f in files or []: + with open(f, "rb") as fil: + part = MIMEApplication( + fil.read(), + Name=basename(f) + ) + part["Content-Disposition"] = "attachment; filename=\"%s\"" % basename(f) + msg.attach(part) + + smtp = smtplib.SMTP(server) + smtp.sendmail(send_from, send_to, msg.as_string()) + smtp.close() + + +def export_tabular(): + # Export a particular insight in the desired format (CSV / XLSX) + sdk.export.export_tabular_by_insight_id( + workspace_id = "demo", + insight_id = "revenue", + file_format = "CSV", + file_name = "revenue_export.csv" + ) + + send_mail( + send_from = "your@email.com", + send_to = "to@email.com", + subject = "Scheduled export", + text = "Scheduled export of dashboard 'dashboard_overview'", + # Name of exported file from the method call 'export_pdf' + files = "revenue_export.csv", + server = "" + ) + + +# Schedule call to export visualization in CSV and sent via e-email every morning at 8:00. +schedule.every().day.at("8:00").do(export_tabular) +``` diff --git a/docs/content/en/docs/execution/exports/export_pdf.md b/docs/content/en/docs/execution/exports/export_pdf.md new file mode 100644 index 000000000..830fb3813 --- /dev/null +++ b/docs/content/en/docs/execution/exports/export_pdf.md @@ -0,0 +1,58 @@ +--- +title: "export_pdf" +linkTitle: "export_pdf" +weight: 110 +superheading: "export." +--- + +``export_pdf(workspace_id: str, + dashboard_id: str, + file_name: str, + store_path: Union[str, Path] = Path.cwd(), + timeout: float = 60.0, + retry: float = 0.2, + max_retry: float = 5.0, + )`` + +Export a PDF of the specified GoodData Dashboard and save it to the specified file path. + + +{{% parameters-block title="Parameters" %}} +{{< parameter p_name="workspace_id" p_type="string" >}} +The ID of the GoodData Workspace. +{{< /parameter >}} +{{< parameter p_name="dashboard_id" p_type="string" >}} +The ID of the GoodData Dashboard. +{{< /parameter >}} +{{< parameter p_name="file_name" p_type="String" >}} +The name of the PDF file (excluding the file extension). +{{< /parameter >}} +{{< parameter p_name="store_path" p_type="Union[String, Path]" >}} +The name of the PDF file (excluding the file extension). +{{< /parameter >}} +{{< parameter p_name="timeout" p_type="float" >}} +The maximum amount of time (in seconds) to wait for the server to process the export. Defaults to 60.0. +{{< /parameter >}} +{{< parameter p_name="retry" p_type="float" >}} +Initial wait time (in seconds) before retrying to get the exported content. Defaults to 0.2. +{{< /parameter >}} +{{< parameter p_name="max_retry" p_type="float" >}} +The maximum retry wait time (in seconds). Defaults to 5.0. +{{< /parameter >}} +{{% /parameters-block %}} + +{{% parameters-block title="Returns" None="true"%}} +{{% /parameters-block %}} + + +## Example + +```python + +host = "https://www.example.com" +token = "" +sdk = GoodDataSdk.create(host, token) + + +sdk.export.export_pdf(workspace_id="demo", dashboard_id="campaign", file_name="test") +``` diff --git a/docs/content/en/docs/execution/exports/export_tabular.md b/docs/content/en/docs/execution/exports/export_tabular.md new file mode 100644 index 000000000..ecd397aa3 --- /dev/null +++ b/docs/content/en/docs/execution/exports/export_tabular.md @@ -0,0 +1,79 @@ +--- +title: "export_tabular" +linkTitle: "export_tabular" +weight: 110 +superheading: "export." +--- + +``export_tabular(workspace_id: str, + dashboard_id: str, + file_name: str, + store_path: Union[str, Path] = Path.cwd(), + timeout: float = 60.0, + retry: float = 0.2, + max_retry: float = 5.0, + )`` + + Export Tabular (CSV, XLSX) data from the specified GoodData Dashboard report, saved to the specified file path. + + +{{% parameters-block title="Parameters" %}} +{{< parameter p_name="workspace_id" p_type="string" >}} +The ID of the GoodData Workspace. +{{< /parameter >}} +{{< parameter p_name="dashboard_id" p_type="string" >}} +The ID of the GoodData Dashboard. +{{< /parameter >}} +{{< parameter p_name="store_path" p_type="Union[String, Path]" >}} +The path to save the exported tabular data. Defaults to Path.cwd(). +{{< /parameter >}} +{{< parameter p_name="timeout" p_type="float" >}} +The maximum amount of time (in seconds) to wait for the server to process the export. Defaults to 60.0. +{{< /parameter >}} +{{< parameter p_name="retry" p_type="float" >}} +Initial wait time (in seconds) before retrying to get the exported content. Defaults to 0.2. +{{< /parameter >}} +{{< parameter p_name="max_retry" p_type="float" >}} +The maximum retry wait time (in seconds). Defaults to 5.0. +{{< /parameter >}} +{{% /parameters-block %}} + +{{% parameters-block title="Returns" None="true"%}} +{{% /parameters-block %}} + + +## Example + +```python + +host = "https://www.example.com" +token = "" +sdk = GoodDataSdk.create(host, token) + +workspace_id = "demo" +exec_def = ExecutionDefinition( + attributes=[Attribute(local_id="region", label="region"), Attribute(local_id="state", label="state")], + metrics=[ + SimpleMetric(local_id="price", item=ObjId(id="price", type="fact")), + SimpleMetric(local_id="order_amount", item=ObjId(id="order_amount", type="metric")), + ], + filters=[], + dimensions=[["state", "region"], ["measureGroup"]], + ) +execution_result=sdk.compute.for_exec_def(workspace_id, exec_def).result_id +export_request = ExportRequest( + format="CSV", + execution_result=execution_result, + file_name="my_file", + custom_override=ExportCustomOverride( + labels={"region": ExportCustomLabel(title="Custom Title Region")}, + metrics={ + "price": ExportCustomMetric(title="Sum Of Price", format=""), + "order_amount": ExportCustomMetric(title="Order Amount Metric", format="#,##0.00"), + }, + ), + ) + + +sdk.export.export_tabular(workspace_id, export_request, _exports_dir) +``` diff --git a/docs/content/en/docs/execution/exports/export_tabular_by_insight_id.md b/docs/content/en/docs/execution/exports/export_tabular_by_insight_id.md new file mode 100644 index 000000000..26929fcef --- /dev/null +++ b/docs/content/en/docs/execution/exports/export_tabular_by_insight_id.md @@ -0,0 +1,69 @@ +--- +title: "export_tabular_by_insight_id" +linkTitle: "export_tabular_by_insight_id" +weight: 110 +superheading: "export." +--- + +``export_tabular_by_insight_id( + workspace_id: str, + insight_id: str, + file_format: str, + file_name: Optional[str] = None, + settings: Optional[ExportSettings] = None, + store_path: Union[str, Path] = Path.cwd(), + timeout: float = 60.0, + retry: float = 0.2, + max_retry: float = 5.0, + )`` + + Exports the tabular data for an Insight by its ID. + + + +{{% parameters-block title="Parameters" %}} +{{< parameter p_name="workspace_id" p_type="string" >}} +The ID of the GoodData Workspace. +{{< /parameter >}} +{{< parameter p_name="insight_id" p_type="string" >}} +The ID of the GoodData Insight. +{{< /parameter >}} +{{< parameter p_name="file_format" p_type="string" >}} +The format of the file to be exported. +{{< /parameter >}} +{{< parameter p_name="file_name" p_type="String" >}} +The name which the exported file should have. Defaults to None. +{{< /parameter >}} +{{< parameter p_name="settings" p_type="Optional[ExportSettings]" >}} +Any additional settings for the export. Defaults to None. +{{< /parameter >}} +{{< parameter p_name="store_path" p_type="Union[String, Path]" >}} +The path to store the exported file. Defaults to Path.cwd(). +{{< /parameter >}} +{{< parameter p_name="timeout" p_type="float" >}} +The maximum amount of time (in seconds) to wait for the server to process the export. Defaults to 60.0. +{{< /parameter >}} +{{< parameter p_name="retry" p_type="float" >}} +Initial wait time (in seconds) before retrying to get the exported content. Defaults to 0.2. +{{< /parameter >}} +{{< parameter p_name="max_retry" p_type="float" >}} +The maximum retry wait time (in seconds). Defaults to 5.0. +{{< /parameter >}} +{{% /parameters-block %}} + +{{% parameters-block title="Returns" None="true" %}} +{{% /parameters-block %}} + + +## Example + +```python + +host = "https://www.example.com" +token = "" +sdk = GoodDataSdk.create(host, token) + +sdk.export.export_tabular_by_insight_id( + workspace_id="demo", insight_id="campaign_spend", file_format="CSV") + +``` diff --git a/gooddata-sdk/gooddata_sdk/catalog/export/request.py b/gooddata-sdk/gooddata_sdk/catalog/export/request.py index 9766b1821..f6e8abf93 100644 --- a/gooddata-sdk/gooddata_sdk/catalog/export/request.py +++ b/gooddata-sdk/gooddata_sdk/catalog/export/request.py @@ -52,14 +52,26 @@ def client_class() -> Type[ApiSettings]: @attr.s(auto_attribs=True, kw_only=True) class ExportRequest(Base): + """ + ExportRequest class is used to create an export request in the desired format, filename, and settings. + Attributes: + format (str): The format of the output file (CSV, XLSX). + execution_result (str): Execution result id from backend. + file_name (str): The name of the output file. + settings (Optional[Dict[str, bool]]): Optional dictionary containing settings for the export request. + custom_override (Optional[Dict[str, Any]]): Optional dictionary containing custom settings. + """ + format: str - # execution result id from backend execution_result: str file_name: str settings: Optional[ExportSettings] = None custom_override: Optional[ExportCustomOverride] = None def __attrs_post_init__(self) -> None: + """ + Validates that the provided format is supported and raises ValueError if not. + """ supported_formats = ["CSV", "XLSX"] if self.format not in supported_formats: raise ValueError( @@ -68,8 +80,18 @@ def __attrs_post_init__(self) -> None: @staticmethod def client_class() -> Type[TabularExportRequest]: + """ + Returns the appropriate client class for the tabular export request. + Returns: + Type[TabularExportRequest]: TabularExportRequest class + """ return TabularExportRequest @property def file(self) -> str: + """ + Generates the full filename with the format extension. + Returns: + str: Full filename with the format extension. + """ return f"{self.file_name}.{self.format.lower()}" diff --git a/gooddata-sdk/gooddata_sdk/catalog/export/service.py b/gooddata-sdk/gooddata_sdk/catalog/export/service.py index 63fc6afc3..cf1eec3bb 100644 --- a/gooddata-sdk/gooddata_sdk/catalog/export/service.py +++ b/gooddata-sdk/gooddata_sdk/catalog/export/service.py @@ -21,8 +21,37 @@ class ExportService(CatalogServiceBase): + """ + ExportService provides the ability to export PDF and Tabular data from GoodData Dashboards. + Attributes: + _entities_api: + A reference to the entities_api of GoodDataApiClient instance. + _actions_api: + A reference to the actions_api of GoodDataApiClient instance. + Methods: + _get_exported_content: + A static method that gets the exported content using the provided `get_func`. + _create_export: + A static method that creates an export and returns its ID. + _dashboard_id_exists: + Checks if the given dashboard_id exists in the workspace. + _export_common: + Common export method for handling the exports of PDF and Tabular. + export_pdf: + Export a PDF of a GoodData Dashboard. + export_tabular: + Export Tabular data from a GoodData Dashboard. + export_tabular_by_insight_id: + Exports the tabular data of a particular insight id. + """ + def __init__(self, api_client: GoodDataApiClient) -> None: super(ExportService, self).__init__(api_client) + """ + Initializes the ExportService with the GoodDataApiClient instance. + Args: + api_client (GoodDataApiClient): An instance of the GoodData API Client. + """ @staticmethod def _get_exported_content( @@ -33,6 +62,26 @@ def _get_exported_content( retry: float = 0.2, max_retry: float = 5.0, ) -> bytes: + """ + Get the exported content from a server as bytes. + Args: + workspace_id (str): + The workspace ID for which content is to be exported. + export_id (str): + The export ID for the content to be exported. + get_func (Callable): + The function to call to get the export data. + timeout (float, optional): + The total time in seconds to wait for a successful response. Defaults to 60.0. + retry (float, optional): + Initial time in seconds to wait between retries. Defaults to 0.2. + max_retry (float, optional): + Maximum time in seconds to wait between retries. Defaults to 5.0. + Returns: + bytes: The exported content as bytes. + Raises: + ValueError: If the server is not able to return a response or if the input values are invalid. + """ assert ( timeout > 0 and retry > 0 and max_retry > 0 ), f"Timeout value '{timeout}' or retry value '{retry}' or max retry value '{max_retry}' is negative." @@ -58,15 +107,33 @@ def _get_exported_content( def _create_export( workspace_id: str, request: Union[PdfExportRequest, TabularExportRequest], create_func: Callable ) -> str: + """ + Creates an export of the requested type (PDF or Tabular) in the specified Workspace. + Args: + workspace_id (str): The ID of the target Workspace. + request (Union[PdfExportRequest, TabularExportRequest]): + A request object specifying the type of export (PDF or Tabular) to be created. + create_func (Callable): The function used to create the export. + Returns: + str: The export result from the response object. + """ response = create_func(workspace_id, request) return response["export_result"] def _dashboard_id_exists(self, workspace_id: str, dashboard_id: str) -> bool: """ - Check is dashboard id exists. + Check if dashboard id exists. + + Args: + workspace_id (str): + The ID of the target Workspace. + dashboard_id (str): + The ID of the target Dashboard. + Returns: + bool: Returns true, if the dashboard exists. Note: - This is needed due to the fact that exporters do not check existence of dashboard id. + This is needed due to the fact that exporters do not check existence of the dashboard id. """ try: self._entities_api.get_entity_analytical_dashboards(workspace_id=workspace_id, object_id=dashboard_id) @@ -85,6 +152,28 @@ def _export_common( retry: float = 0.2, max_retry: float = 5.0, ) -> None: + """ + Common method to export content from a workspace. + Args: + workspace_id (str): + The ID of the workspace to export from. + request (Union[PdfExportRequest, TabularExportRequest]): + The export request object (Pdf or Tabular). + file_path (Path): + The local file path to save the exported content. + create_func (Callable): + The function to create an export task. + get_func (Callable): + The function to get the exported content. + timeout (float, optional): + The maximum time to wait for the export (in seconds). Defaults to 60.0. + retry (float, optional): + The time interval to retry checking for exported content (in seconds). Defaults to 0.2. + max_retry (float, optional): + The maximum number of retries to check for exported content. Defaults to 5.0. + Returns: + None + """ export_id = self._create_export(workspace_id, request, create_func) content = self._get_exported_content(workspace_id, export_id, get_func, timeout, retry, max_retry) with open(file_path, "wb") as f: @@ -100,6 +189,24 @@ def export_pdf( retry: float = 0.2, max_retry: float = 5.0, ) -> None: + """ + Export a PDF of the specified GoodData Dashboard and save it to the specified file path. + Args: + workspace_id (str): + The ID of the GoodData Workspace. + dashboard_id (str): + The ID of the GoodData Dashboard. + file_name (str): + The name of the PDF file (excluding the file extension). + store_path (Union[str, Path], optional): + The path to save the exported PDF. Defaults to the current directory. + timeout (float, optional): + The maximum amount of time (in seconds) to wait for the server to process the export. Defaults to 60.0. + retry (float, optional): + Initial wait time (in seconds) before retrying to get the exported content. Defaults to 0.2. + max_retry (float, optional): + The maximum retry wait time (in seconds). Defaults to 5.0. + """ if not self._dashboard_id_exists(workspace_id, dashboard_id): raise ValueError(f"Dashboard id '{dashboard_id}' does not exist for workspace '{workspace_id}'.") store_path = store_path if isinstance(store_path, Path) else Path(store_path) @@ -118,6 +225,22 @@ def export_tabular( retry: float = 0.2, max_retry: float = 5.0, ) -> None: + """ + Export Tabular (CSV, XLSX) data from the specified GoodData Dashboard report, saved to the specified file path. + Args: + workspace_id (str): + The ID of the GoodData Workspace. + export_request (ExportRequest): + An instance of ExportRequest containing the required information for the tabular export. + store_path (Union[str, Path], optional): + The path to save the exported tabular data. Defaults to the current directory. + timeout (float, optional): + The maximum amount of time (in seconds) to wait for the server to process the export. Defaults to 60.0. + retry (float, optional): + Initial wait time (in seconds) before retrying to get the exported content. Defaults to 0.2. + max_retry (float, optional): + The maximum retry wait time (in seconds). Defaults to 5.0. + """ store_path = store_path if isinstance(store_path, Path) else Path(store_path) file_path = store_path / export_request.file create_func = self._actions_api.create_tabular_export @@ -165,6 +288,24 @@ def export_tabular_by_insight_id( retry: float = 0.2, max_retry: float = 5.0, ) -> None: + """ + Exports the tabular data of a particular insight id. + + Args: + workspace_id (str): The workspace id from which the insight is to be exported. + insight_id (str): The id of the insight to be exported. + file_format (str): The format of the file to be exported. + file_name (Optional[str], optional): The name which the exported file should have. Defaults to None. + settings (Optional[ExportSettings], optional): Any additional settings for the export. Defaults to None. + store_path (Union[str, Path], optional): The path to store the exported file. Defaults to Path.cwd(). + timeout (float, optional): The maximum time to wait for the export to finish. Defaults to 60.0. + retry (float, optional): + Initial wait time (in seconds) before retrying to get the exported content. Defaults to 0.2. + max_retry (float, optional): The maximum retry wait time (in seconds). Defaults to 5.0. + + Returns: + None + """ exec_table, insight_tile = self._get_insight_exec_table(workspace_id, insight_id) custom_override = self._custom_overrides_labels(exec_table) file_name = file_name if file_name is not None else insight_tile