diff --git a/cirro/sdk/dataset.py b/cirro/sdk/dataset.py index cdb95ae..8bcb753 100644 --- a/cirro/sdk/dataset.py +++ b/cirro/sdk/dataset.py @@ -7,7 +7,8 @@ from cirro_api_client.v1.api.processes import validate_file_requirements from cirro_api_client.v1.errors import CirroException, UnexpectedStatus from cirro_api_client.v1.models import Dataset, DatasetDetail, RunAnalysisRequest, ProcessDetail, \ - Status, RunAnalysisRequestParams, Tag, ArtifactType, NamedItem, ValidateFileRequirementsRequest + Status, RunAnalysisRequestParams, Tag, ArtifactType, NamedItem, ValidateFileRequirementsRequest, \ + CostResponse from cirro.cirro_client import CirroApi from cirro.config import Constants @@ -265,6 +266,26 @@ def created_at(self) -> datetime.datetime: """Timestamp of dataset creation""" return self._data.created_at + @property + def cost(self) -> Optional[CostResponse]: + """ + Compute cost of the analysis which produced this dataset, as a + `cirro_api_client.v1.models.CostResponse` -- `total_cost` alongside a + breakdown by task (`tasks`) and by task status group (`groups`), plus an + `is_estimate` flag for whether the figure is estimated or measured. + + Not cached: the cost of a running analysis grows as tasks complete, so + each access re-fetches. + + Returns: + `cirro_api_client.v1.models.CostResponse`, or ``None`` for datasets + which were uploaded rather than produced by an analysis. + """ + return self._client.execution.get_cost( + project_id=self.project_id, + dataset_id=self.id + ) + @cached_property def logs(self) -> str: """ diff --git a/cirro/services/execution.py b/cirro/services/execution.py index 6862ee3..6c4da41 100644 --- a/cirro/services/execution.py +++ b/cirro/services/execution.py @@ -1,9 +1,10 @@ from typing import List, Optional, Dict from cirro_api_client.v1.api.execution import run_analysis, stop_analysis, get_project_summary, \ - get_tasks_for_execution, get_task_logs, get_execution_logs, get_task, get_task_files + get_tasks_for_execution, get_task_logs, get_execution_logs, get_task, get_task_files, calculate_cost from cirro_api_client.v1.api.processes import get_process_parameters -from cirro_api_client.v1.models import RunAnalysisRequest, CreateResponse, Task, GetTaskFilesResponse +from cirro_api_client.v1.models import RunAnalysisRequest, CreateResponse, Task, GetTaskFilesResponse, \ + CostResponse from cirro.models.form_specification import ParameterSpecification from cirro.services.base import BaseService @@ -194,3 +195,21 @@ def get_task_files(self, project_id: str, dataset_id: str, task_id: str) -> Opti task_id=task_id, client=self._api_client ) + + def get_cost(self, project_id: str, dataset_id: str) -> Optional[CostResponse]: + """ + Gets the compute cost of the analysis which produced a dataset, + broken down by task and by task status group. + + The returned `cirro_api_client.v1.models.CostResponse` carries an + `is_estimate` flag for whether the figure is estimated or measured. + + Args: + project_id (str): ID of the Project + dataset_id (str): ID of the Dataset + """ + return calculate_cost.sync( + project_id=project_id, + dataset_id=dataset_id, + client=self._api_client + ) diff --git a/pyproject.toml b/pyproject.toml index 658a114..845d74d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "cirro" -version = "1.13.0" +version = "1.13.1" description = "CLI tool and SDK for interacting with the Cirro platform" authors = ["Cirro Bio "] license = "MIT"