convexity-sdk 0.4.3.dev152__tar.gz → 0.5.0.dev154__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/PKG-INFO +2 -2
  2. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/convexity_sdk/client.py +60 -0
  3. convexity_sdk-0.5.0.dev154/convexity_sdk/resources/connections.py +68 -0
  4. convexity_sdk-0.5.0.dev154/convexity_sdk/resources/dashboards.py +67 -0
  5. convexity_sdk-0.5.0.dev154/convexity_sdk/resources/datalake.py +23 -0
  6. convexity_sdk-0.5.0.dev154/convexity_sdk/resources/datasets.py +177 -0
  7. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/convexity_sdk/resources/organizations.py +7 -0
  8. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/convexity_sdk/resources/projects.py +10 -0
  9. convexity_sdk-0.5.0.dev154/convexity_sdk/resources/runs.py +57 -0
  10. convexity_sdk-0.5.0.dev154/convexity_sdk/resources/tasks.py +105 -0
  11. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/pyproject.toml +1 -1
  12. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/samples/README.md +1 -0
  13. convexity_sdk-0.5.0.dev154/samples/cancel_refresh_task.py +106 -0
  14. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/samples/create_dashboards.py +4 -24
  15. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/samples/create_databricks_connections.py +7 -28
  16. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/samples/create_datasets.py +23 -38
  17. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/samples/create_forecast_task.py +25 -83
  18. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/samples/query_datalake.py +3 -13
  19. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/samples/share_dashboard.py +4 -18
  20. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/.gitignore +0 -0
  21. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/README.md +0 -0
  22. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/convexity_sdk/__init__.py +0 -0
  23. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/convexity_sdk/config.py +0 -0
  24. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/convexity_sdk/exceptions.py +0 -0
  25. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/convexity_sdk/http.py +0 -0
  26. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/convexity_sdk/models/__init__.py +0 -0
  27. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/convexity_sdk/resources/__init__.py +0 -0
  28. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/samples/.env.example +0 -0
  29. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/samples/create_org_and_project.py +0 -0
  30. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/samples/getting_started.py +0 -0
  31. {convexity_sdk-0.4.3.dev152 → convexity_sdk-0.5.0.dev154}/samples/list_orgs_and_projects.py +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: convexity-sdk
3
- Version: 0.4.3.dev152
3
+ Version: 0.5.0.dev154
4
4
  Summary: Convexity Python SDK - programmatic access to the Convexity platform
5
5
  Requires-Python: >=3.12
6
- Requires-Dist: convexity-api-client<0.5.0,>=0.4.3.dev0
6
+ Requires-Dist: convexity-api-client<0.6.0,>=0.5.0.dev0
7
7
  Requires-Dist: httpx>=0.27.0
8
8
  Requires-Dist: pydantic>=2.10.0
9
9
  Description-Content-Type: text/markdown
@@ -12,8 +12,14 @@ from .config import SDKConfig, resolve_config
12
12
  from .http import AsyncTransport, SyncTransport
13
13
 
14
14
  if TYPE_CHECKING:
15
+ from .resources.connections import Connections
16
+ from .resources.dashboards import Dashboards
17
+ from .resources.datalake import Datalake
18
+ from .resources.datasets import Datasets
15
19
  from .resources.organizations import Organizations
16
20
  from .resources.projects import Projects
21
+ from .resources.runs import Runs
22
+ from .resources.tasks import Tasks
17
23
 
18
24
 
19
25
  def _build_api_client(config: SDKConfig) -> AuthenticatedClient | ApiClient:
@@ -100,6 +106,24 @@ class ConvexityClient:
100
106
  self._organizations = Organizations(self._api_client)
101
107
  return self._organizations
102
108
 
109
+ @property
110
+ def connections(self) -> Connections:
111
+ """Access connection operations."""
112
+ if not hasattr(self, "_connections"):
113
+ from .resources.connections import Connections
114
+
115
+ self._connections = Connections(self._api_client)
116
+ return self._connections
117
+
118
+ @property
119
+ def datalake(self) -> Datalake:
120
+ """Access datalake operations."""
121
+ if not hasattr(self, "_datalake"):
122
+ from .resources.datalake import Datalake
123
+
124
+ self._datalake = Datalake(self._api_client)
125
+ return self._datalake
126
+
103
127
  @property
104
128
  def projects(self) -> Projects:
105
129
  """Access project operations."""
@@ -109,6 +133,42 @@ class ConvexityClient:
109
133
  self._projects = Projects(self._api_client)
110
134
  return self._projects
111
135
 
136
+ @property
137
+ def datasets(self) -> Datasets:
138
+ """Access dataset operations."""
139
+ if not hasattr(self, "_datasets"):
140
+ from .resources.datasets import Datasets
141
+
142
+ self._datasets = Datasets(self._api_client)
143
+ return self._datasets
144
+
145
+ @property
146
+ def dashboards(self) -> Dashboards:
147
+ """Access dashboard operations."""
148
+ if not hasattr(self, "_dashboards"):
149
+ from .resources.dashboards import Dashboards
150
+
151
+ self._dashboards = Dashboards(self._api_client)
152
+ return self._dashboards
153
+
154
+ @property
155
+ def tasks(self) -> Tasks:
156
+ """Access task operations."""
157
+ if not hasattr(self, "_tasks"):
158
+ from .resources.tasks import Tasks
159
+
160
+ self._tasks = Tasks(self._api_client)
161
+ return self._tasks
162
+
163
+ @property
164
+ def runs(self) -> Runs:
165
+ """Access run operations."""
166
+ if not hasattr(self, "_runs"):
167
+ from .resources.runs import Runs
168
+
169
+ self._runs = Runs(self._api_client)
170
+ return self._runs
171
+
112
172
  # -- context manager ------------------------------------------------------
113
173
 
114
174
  def __enter__(self) -> ConvexityClient:
@@ -0,0 +1,68 @@
1
+ """Connection resource client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from convexity_api_client import AuthenticatedClient, Client
6
+ from convexity_api_client.api.v1 import (
7
+ create_databricks_connection_v1_connections_databricks_post as _create_databricks_connection,
8
+ )
9
+ from convexity_api_client.api.v1 import (
10
+ list_connections_v1_connections_get as _list_connections,
11
+ )
12
+ from convexity_api_client.api.v1 import (
13
+ verify_databricks_connection_v1_connections_databricks_connection_id_verify_post as _verify_databricks_connection,
14
+ )
15
+ from convexity_api_client.models.connection_list_response import ConnectionListResponse
16
+ from convexity_api_client.models.create_databricks_connection_request import CreateDatabricksConnectionRequest
17
+ from convexity_api_client.models.databricks_connection import DatabricksConnection
18
+ from convexity_api_client.models.verify_result import VerifyResult
19
+ from convexity_api_client.types import UNSET
20
+
21
+
22
+ class Connections:
23
+ """Synchronous sub-client for connection operations."""
24
+
25
+ def __init__(self, api_client: AuthenticatedClient | Client) -> None:
26
+ self._client = api_client
27
+
28
+ def list(self, project_id: str) -> ConnectionListResponse:
29
+ """List all connections for a project."""
30
+ result = _list_connections.sync(client=self._client, project_id=project_id)
31
+ if not isinstance(result, ConnectionListResponse):
32
+ return ConnectionListResponse(connections=[])
33
+ return result
34
+
35
+ def create_databricks(
36
+ self,
37
+ *,
38
+ name: str,
39
+ project_id: str,
40
+ server_hostname: str,
41
+ http_path: str,
42
+ access_token: str,
43
+ db_schema: str | None = None,
44
+ description: str | None = None,
45
+ catalog: str | None = None,
46
+ ) -> DatabricksConnection:
47
+ """Create a Databricks connection."""
48
+ body = CreateDatabricksConnectionRequest(
49
+ name=name,
50
+ project_id=project_id,
51
+ server_hostname=server_hostname,
52
+ http_path=http_path,
53
+ access_token=access_token,
54
+ db_schema=db_schema if db_schema is not None else UNSET,
55
+ description=description if description is not None else UNSET,
56
+ catalog=catalog if catalog is not None else UNSET,
57
+ )
58
+ result = _create_databricks_connection.sync(client=self._client, body=body, project_id=project_id)
59
+ if not isinstance(result, DatabricksConnection):
60
+ raise ValueError(f"Unexpected response when creating Databricks connection: {result}")
61
+ return result
62
+
63
+ def verify_databricks(self, connection_id: str) -> VerifyResult:
64
+ """Verify a Databricks connection."""
65
+ result = _verify_databricks_connection.sync(connection_id, client=self._client)
66
+ if not isinstance(result, VerifyResult):
67
+ raise ValueError(f"Unexpected response when verifying Databricks connection: {result}")
68
+ return result
@@ -0,0 +1,67 @@
1
+ """Dashboard resource client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from convexity_api_client import AuthenticatedClient, Client
6
+ from convexity_api_client.api.v1 import (
7
+ create_dashboard_v1_dashboards_post as _create_dashboard,
8
+ )
9
+ from convexity_api_client.api.v1 import (
10
+ create_share_v1_dashboards_dashboard_id_share_post as _create_share,
11
+ )
12
+ from convexity_api_client.api.v1 import (
13
+ get_dashboard_v1_dashboards_dashboard_id_get as _get_dashboard,
14
+ )
15
+ from convexity_api_client.api.v1 import (
16
+ list_dashboards_v1_dashboards_get as _list_dashboards,
17
+ )
18
+ from convexity_api_client.models.create_dashboard_request import CreateDashboardRequest
19
+ from convexity_api_client.models.create_share_request import CreateShareRequest
20
+ from convexity_api_client.models.dashboard_definition import DashboardDefinition
21
+ from convexity_api_client.models.dashboard_list_response import DashboardListResponse
22
+ from convexity_api_client.models.dashboard_share_response import DashboardShareResponse
23
+
24
+
25
+ class Dashboards:
26
+ """Synchronous sub-client for dashboard operations."""
27
+
28
+ def __init__(self, api_client: AuthenticatedClient | Client) -> None:
29
+ self._client = api_client
30
+
31
+ def list(self, project_id: str) -> DashboardListResponse:
32
+ """List dashboards for a project."""
33
+ result = _list_dashboards.sync(client=self._client, project_id=project_id)
34
+ if result is None or not isinstance(result, DashboardListResponse):
35
+ return DashboardListResponse(dashboards=[])
36
+ return result
37
+
38
+ def get(self, dashboard_id: str) -> DashboardDefinition | None:
39
+ """Get a single dashboard by ID."""
40
+ result = _get_dashboard.sync(dashboard_id, client=self._client)
41
+ if isinstance(result, DashboardDefinition):
42
+ return result
43
+ return None
44
+
45
+ def create(
46
+ self,
47
+ *,
48
+ project_id: str,
49
+ body: CreateDashboardRequest,
50
+ ) -> DashboardDefinition:
51
+ """Create a new dashboard."""
52
+ result = _create_dashboard.sync(client=self._client, body=body, project_id=project_id)
53
+ if not isinstance(result, DashboardDefinition):
54
+ raise ValueError(f"Unexpected response when creating dashboard: {result}")
55
+ return result
56
+
57
+ def create_share(
58
+ self,
59
+ *,
60
+ dashboard_id: str,
61
+ body: CreateShareRequest,
62
+ ) -> DashboardShareResponse:
63
+ """Create or update a share for a dashboard."""
64
+ result = _create_share.sync(dashboard_id, client=self._client, body=body)
65
+ if not isinstance(result, DashboardShareResponse):
66
+ raise ValueError(f"Unexpected response when creating dashboard share: {result}")
67
+ return result
@@ -0,0 +1,23 @@
1
+ """Datalake resource client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from convexity_api_client import AuthenticatedClient, Client
6
+ from convexity_api_client.api.v1 import (
7
+ get_or_create_datalake_connection_info_v1_datalake_connection_get as _get_datalake_info,
8
+ )
9
+ from convexity_api_client.models.datalake_connection_response import DatalakeConnectionResponse
10
+
11
+
12
+ class Datalake:
13
+ """Synchronous sub-client for datalake operations."""
14
+
15
+ def __init__(self, api_client: AuthenticatedClient | Client) -> None:
16
+ self._client = api_client
17
+
18
+ def get_info(self, project_id: str) -> DatalakeConnectionResponse:
19
+ """Get (or create) DuckLake connection info for a project."""
20
+ result = _get_datalake_info.sync(client=self._client, project_id=project_id)
21
+ if not isinstance(result, DatalakeConnectionResponse):
22
+ return DatalakeConnectionResponse()
23
+ return result
@@ -0,0 +1,177 @@
1
+ """Dataset resource client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from convexity_api_client import AuthenticatedClient, Client
6
+ from convexity_api_client.api.v1 import (
7
+ create_dataset_v1_datasets_post as _create_dataset,
8
+ )
9
+ from convexity_api_client.api.v1 import (
10
+ delete_dataset_v1_datasets_dataset_id_delete as _delete_dataset,
11
+ )
12
+ from convexity_api_client.api.v1 import (
13
+ get_dataset_v1_datasets_dataset_id_get as _get_dataset,
14
+ )
15
+ from convexity_api_client.api.v1 import (
16
+ get_refresh_task_status_v1_datasets_dataset_id_refresh_task_id_get as _get_refresh_status,
17
+ )
18
+ from convexity_api_client.api.v1 import (
19
+ list_datasets_v1_datasets_get as _list_datasets,
20
+ )
21
+ from convexity_api_client.api.v1 import (
22
+ list_refresh_tasks_v1_datasets_dataset_id_refresh_history_get as _list_refresh_tasks,
23
+ )
24
+ from convexity_api_client.api.v1 import (
25
+ refresh_dataset_async_v1_datasets_dataset_id_refresh_async_post as _refresh_dataset,
26
+ )
27
+ from convexity_api_client.api.v1 import (
28
+ update_dataset_v1_datasets_dataset_id_patch as _update_dataset,
29
+ )
30
+ from convexity_api_client.models.create_dataset_request import CreateDatasetRequest
31
+ from convexity_api_client.models.dataset_config import DatasetConfig
32
+ from convexity_api_client.models.dataset_definition import DatasetDefinition
33
+ from convexity_api_client.models.dataset_list_response import DatasetListResponse
34
+ from convexity_api_client.models.dataset_type import DatasetType
35
+ from convexity_api_client.models.refresh_mode import RefreshMode
36
+ from convexity_api_client.models.refresh_task_list_response import RefreshTaskListResponse
37
+ from convexity_api_client.models.update_dataset_request import UpdateDatasetRequest
38
+ from convexity_api_client.models.worker_task_response import WorkerTaskResponse
39
+ from convexity_api_client.types import UNSET, Unset
40
+
41
+
42
+ class Datasets:
43
+ """Synchronous sub-client for dataset operations."""
44
+
45
+ def __init__(self, api_client: AuthenticatedClient | Client) -> None:
46
+ self._client = api_client
47
+
48
+ # -- CRUD -----------------------------------------------------------------
49
+
50
+ def list(self, project_id: str) -> DatasetListResponse:
51
+ """List datasets for a project."""
52
+ result = _list_datasets.sync(client=self._client, project_id=project_id)
53
+ if result is None or not isinstance(result, DatasetListResponse):
54
+ return DatasetListResponse(datasets=[])
55
+ return result
56
+
57
+ def get(self, dataset_id: str) -> DatasetDefinition | None:
58
+ """Get a single dataset by ID."""
59
+ result = _get_dataset.sync(dataset_id, client=self._client)
60
+ if isinstance(result, DatasetDefinition):
61
+ return result
62
+ return None
63
+
64
+ def create(
65
+ self,
66
+ *,
67
+ project_id: str,
68
+ name: str,
69
+ type_: DatasetType,
70
+ config: DatasetConfig,
71
+ description: str | None = None,
72
+ connection_id: str | None = None,
73
+ refresh_mode: RefreshMode | None = None,
74
+ refresh_schedule: str | None = None,
75
+ cache_ttl_seconds: int | None = None,
76
+ tags: list[str] | None = None,
77
+ ) -> DatasetDefinition:
78
+ """Create a new dataset in a project."""
79
+ body = CreateDatasetRequest(
80
+ project_id=project_id,
81
+ name=name,
82
+ type_=type_,
83
+ config=config,
84
+ description=description if description is not None else UNSET,
85
+ connection_id=connection_id if connection_id is not None else UNSET,
86
+ refresh_mode=refresh_mode if refresh_mode is not None else UNSET,
87
+ refresh_schedule=refresh_schedule if refresh_schedule is not None else UNSET,
88
+ cache_ttl_seconds=cache_ttl_seconds if cache_ttl_seconds is not None else UNSET,
89
+ tags=tags if tags is not None else UNSET,
90
+ )
91
+ result = _create_dataset.sync(client=self._client, body=body, project_id=project_id)
92
+ if not isinstance(result, DatasetDefinition):
93
+ raise ValueError(f"Unexpected response when creating dataset: {result}")
94
+ return result
95
+
96
+ def update(
97
+ self,
98
+ dataset_id: str,
99
+ *,
100
+ name: str | None = None,
101
+ description: str | None = None,
102
+ connection_id: str | None = None,
103
+ config: DatasetConfig | None = None,
104
+ refresh_mode: RefreshMode | None = None,
105
+ refresh_schedule: str | None = None,
106
+ cache_ttl_seconds: int | None = None,
107
+ tags: list[str] | None = None,
108
+ ) -> DatasetDefinition:
109
+ """Update an existing dataset."""
110
+ body = UpdateDatasetRequest(
111
+ name=name if name is not None else UNSET,
112
+ description=description if description is not None else UNSET,
113
+ connection_id=connection_id if connection_id is not None else UNSET,
114
+ config=config if config is not None else UNSET,
115
+ refresh_mode=refresh_mode if refresh_mode is not None else UNSET,
116
+ refresh_schedule=refresh_schedule if refresh_schedule is not None else UNSET,
117
+ cache_ttl_seconds=cache_ttl_seconds if cache_ttl_seconds is not None else UNSET,
118
+ tags=tags if tags is not None else UNSET,
119
+ )
120
+ result = _update_dataset.sync(dataset_id, client=self._client, body=body)
121
+ if not isinstance(result, DatasetDefinition):
122
+ raise ValueError(f"Unexpected response when updating dataset: {result}")
123
+ return result
124
+
125
+ def delete(self, dataset_id: str) -> None:
126
+ """Delete a dataset by ID."""
127
+ _delete_dataset.sync_detailed(dataset_id, client=self._client)
128
+
129
+ # -- Refresh --------------------------------------------------------------
130
+
131
+ def refresh(self, dataset_id: str) -> WorkerTaskResponse:
132
+ """Trigger an async refresh for a dataset.
133
+
134
+ Returns a ``WorkerTaskResponse`` whose ``id`` field is the task ID.
135
+ Use :meth:`get_refresh_status` to poll for completion.
136
+ """
137
+ result = _refresh_dataset.sync(dataset_id, client=self._client)
138
+ if not isinstance(result, WorkerTaskResponse):
139
+ raise ValueError(f"Unexpected response when refreshing dataset: {result}")
140
+ return result
141
+
142
+ def get_refresh_status(self, dataset_id: str, task_id: str) -> WorkerTaskResponse:
143
+ """Get the status of a refresh task."""
144
+ result = _get_refresh_status.sync(dataset_id, task_id, client=self._client)
145
+ if not isinstance(result, WorkerTaskResponse):
146
+ raise ValueError(f"Unexpected response when fetching refresh status: {result}")
147
+ return result
148
+
149
+ def cancel_refresh(self, dataset_id: str, task_id: str) -> WorkerTaskResponse:
150
+ """Cancel a pending refresh task for a dataset."""
151
+ response = self._client.get_httpx_client().request(
152
+ "post",
153
+ f"/v1/datasets/{dataset_id}/refresh/{task_id}/cancel",
154
+ )
155
+ if response.status_code == 200:
156
+ return WorkerTaskResponse.from_dict(response.json())
157
+ raise ValueError(f"Unexpected response when cancelling refresh task: {response.status_code} {response.text}")
158
+
159
+ def list_refresh_history(
160
+ self,
161
+ dataset_id: str,
162
+ *,
163
+ limit: int | None = None,
164
+ offset: int | None = None,
165
+ ) -> RefreshTaskListResponse:
166
+ """List refresh task history for a dataset."""
167
+ limit_arg: int | Unset = UNSET if limit is None else limit
168
+ offset_arg: int | Unset = UNSET if offset is None else offset
169
+ result = _list_refresh_tasks.sync(
170
+ dataset_id,
171
+ client=self._client,
172
+ limit=limit_arg,
173
+ offset=offset_arg,
174
+ )
175
+ if not isinstance(result, RefreshTaskListResponse):
176
+ raise ValueError(f"Unexpected response when listing refresh history: {result}")
177
+ return result
@@ -9,6 +9,9 @@ from convexity_api_client.api.v1 import (
9
9
  from convexity_api_client.api.v1 import (
10
10
  create_organization_v1_organizations_post as _create_org,
11
11
  )
12
+ from convexity_api_client.api.v1 import (
13
+ get_organization_by_slug_v1_organizations_slug_slug_get as _get_org_by_slug,
14
+ )
12
15
  from convexity_api_client.api.v1 import (
13
16
  get_organization_v1_organizations_organization_id_get as _get_org,
14
17
  )
@@ -40,6 +43,10 @@ class Organizations:
40
43
  """Get a single organization by ID."""
41
44
  return _get_org.sync(organization_id, client=self._client)
42
45
 
46
+ def get_by_slug(self, slug: str) -> OrganizationResponse | None:
47
+ """Get a single organization by slug."""
48
+ return _get_org_by_slug.sync(slug, client=self._client)
49
+
43
50
  def create(
44
51
  self,
45
52
  *,
@@ -6,6 +6,9 @@ from convexity_api_client import AuthenticatedClient, Client
6
6
  from convexity_api_client.api.v1 import (
7
7
  create_project_v1_projects_post as _create_project,
8
8
  )
9
+ from convexity_api_client.api.v1 import (
10
+ get_project_by_slug_v1_organizations_organization_id_projects_slug_slug_get as _get_project_by_slug,
11
+ )
9
12
  from convexity_api_client.api.v1 import (
10
13
  get_project_v1_projects_project_id_get as _get_project,
11
14
  )
@@ -51,6 +54,13 @@ class Projects:
51
54
  return result
52
55
  return None
53
56
 
57
+ def get_by_slug(self, organization_id: str, slug: str) -> ProjectResponse | None:
58
+ """Get a single project by slug within an organization."""
59
+ result = _get_project_by_slug.sync(organization_id, slug, client=self._client)
60
+ if isinstance(result, ProjectResponse):
61
+ return result
62
+ return None
63
+
54
64
  def create(
55
65
  self,
56
66
  *,
@@ -0,0 +1,57 @@
1
+ """Run resource client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from convexity_api_client import AuthenticatedClient, Client
6
+ from convexity_api_client.api.v1 import (
7
+ cancel_run_v1_run_cancel_run_id_post as _cancel_run,
8
+ )
9
+ from convexity_api_client.api.v1 import (
10
+ create_and_start_run_v1_run_create_and_start_post as _create_and_start_run,
11
+ )
12
+ from convexity_api_client.api.v1 import (
13
+ delete_run_v1_run_delete_run_id_delete as _delete_run,
14
+ )
15
+ from convexity_api_client.api.v1 import (
16
+ get_run_status_v1_run_status_run_id_get as _get_run_status,
17
+ )
18
+ from convexity_api_client.models.cancel_run_response import CancelRunResponse
19
+ from convexity_api_client.models.create_run_request import CreateRunRequest
20
+ from convexity_api_client.models.create_run_response import CreateRunResponse
21
+ from convexity_api_client.models.delete_run_response import DeleteRunResponse
22
+ from convexity_api_client.models.run import Run
23
+
24
+
25
+ class Runs:
26
+ """Synchronous sub-client for run operations."""
27
+
28
+ def __init__(self, api_client: AuthenticatedClient | Client) -> None:
29
+ self._client = api_client
30
+
31
+ def create_and_start(self, *, body: CreateRunRequest) -> CreateRunResponse:
32
+ """Create a new run and start it immediately."""
33
+ result = _create_and_start_run.sync(client=self._client, body=body)
34
+ if not isinstance(result, CreateRunResponse):
35
+ raise ValueError(f"Unexpected response when creating run: {result}")
36
+ return result
37
+
38
+ def get_status(self, run_id: str) -> Run:
39
+ """Get the current status of a run."""
40
+ result = _get_run_status.sync(run_id, client=self._client)
41
+ if not isinstance(result, Run):
42
+ raise ValueError(f"Unexpected response when fetching run status: {result}")
43
+ return result
44
+
45
+ def cancel(self, run_id: str) -> CancelRunResponse:
46
+ """Cancel a running execution."""
47
+ result = _cancel_run.sync(run_id, client=self._client)
48
+ if not isinstance(result, CancelRunResponse):
49
+ raise ValueError(f"Unexpected response when cancelling run: {result}")
50
+ return result
51
+
52
+ def delete(self, run_id: str) -> DeleteRunResponse:
53
+ """Delete a run (only if not currently running)."""
54
+ result = _delete_run.sync(run_id, client=self._client)
55
+ if not isinstance(result, DeleteRunResponse):
56
+ raise ValueError(f"Unexpected response when deleting run: {result}")
57
+ return result
@@ -0,0 +1,105 @@
1
+ """Task resource client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from convexity_api_client import AuthenticatedClient, Client
6
+ from convexity_api_client.api.v1 import (
7
+ create_task_v1_tasks_post as _create_task,
8
+ )
9
+ from convexity_api_client.api.v1 import (
10
+ delete_task_v1_tasks_task_id_delete as _delete_task,
11
+ )
12
+ from convexity_api_client.api.v1 import (
13
+ get_task_v1_tasks_task_id_get as _get_task,
14
+ )
15
+ from convexity_api_client.api.v1 import (
16
+ list_tasks_v1_tasks_get as _list_tasks,
17
+ )
18
+ from convexity_api_client.api.v1 import (
19
+ update_task_v1_tasks_task_id_patch as _update_task,
20
+ )
21
+ from convexity_api_client.models.create_task_request import CreateTaskRequest
22
+ from convexity_api_client.models.notebook_document import NotebookDocument
23
+ from convexity_api_client.models.task_list_response import TaskListResponse
24
+ from convexity_api_client.models.task_model import TaskModel
25
+ from convexity_api_client.models.task_scenario import TaskScenario
26
+ from convexity_api_client.models.update_task_request import UpdateTaskRequest
27
+ from convexity_api_client.types import UNSET, Unset
28
+
29
+
30
+ class Tasks:
31
+ """Synchronous sub-client for task operations."""
32
+
33
+ def __init__(self, api_client: AuthenticatedClient | Client) -> None:
34
+ self._client = api_client
35
+
36
+ def list(
37
+ self,
38
+ project_id: str,
39
+ *,
40
+ scenario: TaskScenario | None = None,
41
+ ) -> TaskListResponse:
42
+ """List tasks for a project, optionally filtered by scenario."""
43
+ scenario_arg: None | TaskScenario | Unset = UNSET if scenario is None else scenario
44
+ result = _list_tasks.sync(
45
+ client=self._client,
46
+ project_id=project_id,
47
+ scenario=scenario_arg,
48
+ )
49
+ if result is None:
50
+ return TaskListResponse(tasks=[])
51
+ if not isinstance(result, TaskListResponse):
52
+ return TaskListResponse(tasks=[])
53
+ return result
54
+
55
+ def get(self, task_id: str) -> TaskModel | None:
56
+ """Get a single task by ID."""
57
+ result = _get_task.sync(task_id, client=self._client)
58
+ if isinstance(result, TaskModel):
59
+ return result
60
+ return None
61
+
62
+ def create(
63
+ self,
64
+ *,
65
+ name: str,
66
+ project_id: str,
67
+ scenario: TaskScenario,
68
+ description: str | None = None,
69
+ ) -> TaskModel:
70
+ """Create a new task in a project."""
71
+ body = CreateTaskRequest(
72
+ name=name,
73
+ project_id=project_id,
74
+ scenario=scenario,
75
+ description=description,
76
+ )
77
+ result = _create_task.sync(client=self._client, body=body, project_id=project_id)
78
+ if not isinstance(result, TaskModel):
79
+ raise ValueError(f"Unexpected response when creating task: {result}")
80
+ return result
81
+
82
+ def update(
83
+ self,
84
+ task_id: str,
85
+ *,
86
+ name: str | None = None,
87
+ description: str | None = None,
88
+ scenario: TaskScenario | None = None,
89
+ notebook: NotebookDocument | None = None,
90
+ ) -> TaskModel:
91
+ """Update an existing task."""
92
+ body = UpdateTaskRequest(
93
+ name=name if name is not None else UNSET,
94
+ description=description if description is not None else UNSET,
95
+ scenario=scenario if scenario is not None else UNSET,
96
+ notebook=notebook if notebook is not None else UNSET,
97
+ )
98
+ result = _update_task.sync(task_id, client=self._client, body=body)
99
+ if not isinstance(result, TaskModel):
100
+ raise ValueError(f"Unexpected response when updating task: {result}")
101
+ return result
102
+
103
+ def delete(self, task_id: str) -> None:
104
+ """Delete a task by ID."""
105
+ _delete_task.sync_detailed(task_id, client=self._client)
@@ -7,7 +7,7 @@ requires-python = ">=3.12"
7
7
  dependencies = [
8
8
  "httpx>=0.27.0",
9
9
  "pydantic>=2.10.0",
10
- "convexity-api-client>=0.4.3.dev0,<0.5.0",
10
+ "convexity-api-client>=0.5.0.dev0,<0.6.0",
11
11
  ]
12
12
 
13
13
  [build-system]
@@ -14,6 +14,7 @@ This directory contains sample scripts demonstrating how to use the Convexity SD
14
14
  | [share_dashboard.py](share_dashboard.py) | Share a dashboard with other users |
15
15
  | [list_orgs_and_projects.py](list_orgs_and_projects.py) | List organizations and projects |
16
16
  | [query_datalake.py](query_datalake.py) | Query the DuckLake warehouse with DuckDB |
17
+ | [cancel_refresh_task.py](cancel_refresh_task.py) | Cancel a pending dataset refresh task |
17
18
  | [create_forecast_task.py](create_forecast_task.py) | Create a demand-forecasting task and run it |
18
19
 
19
20
  ## Running Samples