anaplan-sdk 0.4.5__py3-none-any.whl → 0.5.0a2__py3-none-any.whl
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.
- anaplan_sdk/_async_clients/_alm.py +248 -44
- anaplan_sdk/_async_clients/_audit.py +13 -13
- anaplan_sdk/_async_clients/_bulk.py +181 -135
- anaplan_sdk/_async_clients/_cloud_works.py +57 -38
- anaplan_sdk/_async_clients/_cw_flow.py +25 -16
- anaplan_sdk/_async_clients/_transactional.py +251 -53
- anaplan_sdk/_clients/_alm.py +246 -45
- anaplan_sdk/_clients/_audit.py +13 -14
- anaplan_sdk/_clients/_bulk.py +180 -123
- anaplan_sdk/_clients/_cloud_works.py +54 -36
- anaplan_sdk/_clients/_cw_flow.py +25 -16
- anaplan_sdk/_clients/_transactional.py +246 -50
- anaplan_sdk/_services.py +392 -0
- anaplan_sdk/models/__init__.py +49 -2
- anaplan_sdk/models/_alm.py +64 -6
- anaplan_sdk/models/_bulk.py +16 -9
- anaplan_sdk/models/_transactional.py +221 -4
- {anaplan_sdk-0.4.5.dist-info → anaplan_sdk-0.5.0a2.dist-info}/METADATA +1 -1
- anaplan_sdk-0.5.0a2.dist-info/RECORD +30 -0
- anaplan_sdk/_base.py +0 -297
- anaplan_sdk-0.4.5.dist-info/RECORD +0 -30
- {anaplan_sdk-0.4.5.dist-info → anaplan_sdk-0.5.0a2.dist-info}/WHEEL +0 -0
- {anaplan_sdk-0.4.5.dist-info → anaplan_sdk-0.5.0a2.dist-info}/licenses/LICENSE +0 -0
@@ -1,9 +1,8 @@
|
|
1
|
+
import logging
|
1
2
|
from typing import Any, Literal
|
2
3
|
|
3
|
-
import
|
4
|
-
|
5
|
-
from anaplan_sdk._base import (
|
6
|
-
_AsyncBaseClient,
|
4
|
+
from anaplan_sdk._services import (
|
5
|
+
_AsyncHttpService,
|
7
6
|
connection_body_payload,
|
8
7
|
construct_payload,
|
9
8
|
integration_payload,
|
@@ -27,12 +26,14 @@ from anaplan_sdk.models.cloud_works import (
|
|
27
26
|
|
28
27
|
from ._cw_flow import _AsyncFlowClient
|
29
28
|
|
29
|
+
logger = logging.getLogger("anaplan_sdk")
|
30
|
+
|
30
31
|
|
31
|
-
class _AsyncCloudWorksClient
|
32
|
-
def __init__(self,
|
32
|
+
class _AsyncCloudWorksClient:
|
33
|
+
def __init__(self, http: _AsyncHttpService) -> None:
|
34
|
+
self._http = http
|
33
35
|
self._url = "https://api.cloudworks.anaplan.com/2/0/integrations"
|
34
|
-
self._flow = _AsyncFlowClient(
|
35
|
-
super().__init__(retry_count, client)
|
36
|
+
self._flow = _AsyncFlowClient(http)
|
36
37
|
|
37
38
|
@property
|
38
39
|
def flows(self) -> _AsyncFlowClient:
|
@@ -41,14 +42,14 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
41
42
|
"""
|
42
43
|
return self._flow
|
43
44
|
|
44
|
-
async def
|
45
|
+
async def get_connections(self) -> list[Connection]:
|
45
46
|
"""
|
46
47
|
List all Connections available in CloudWorks.
|
47
48
|
:return: A list of connections.
|
48
49
|
"""
|
49
50
|
return [
|
50
51
|
Connection.model_validate(e)
|
51
|
-
for e in await self.
|
52
|
+
for e in await self._http.get_paginated(f"{self._url}/connections", "connections")
|
52
53
|
]
|
53
54
|
|
54
55
|
async def create_connection(self, con_info: ConnectionInput | dict[str, Any]) -> str:
|
@@ -59,10 +60,12 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
59
60
|
against the ConnectionInput model before sending the request.
|
60
61
|
:return: The ID of the new connection.
|
61
62
|
"""
|
62
|
-
res = await self.
|
63
|
+
res = await self._http.post(
|
63
64
|
f"{self._url}/connections", json=construct_payload(ConnectionInput, con_info)
|
64
65
|
)
|
65
|
-
|
66
|
+
connection_id = res["connections"]["connectionId"]
|
67
|
+
logger.info(f"Created connection '{connection_id}'.")
|
68
|
+
return connection_id
|
66
69
|
|
67
70
|
async def update_connection(
|
68
71
|
self, con_id: str, con_info: ConnectionBody | dict[str, Any]
|
@@ -74,7 +77,9 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
74
77
|
as when initially creating the connection again. If you want to update only some of
|
75
78
|
the details, use the `patch_connection` method instead.
|
76
79
|
"""
|
77
|
-
await self.
|
80
|
+
await self._http.put(
|
81
|
+
f"{self._url}/connections/{con_id}", json=connection_body_payload(con_info)
|
82
|
+
)
|
78
83
|
|
79
84
|
async def patch_connection(self, con_id: str, body: dict[str, Any]) -> None:
|
80
85
|
"""
|
@@ -83,16 +88,17 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
83
88
|
:param body: The name and details of the connection. You can pass all the same details as
|
84
89
|
when initially creating the connection again, or just any one of them.
|
85
90
|
"""
|
86
|
-
await self.
|
91
|
+
await self._http.patch(f"{self._url}/connections/{con_id}", json=body)
|
87
92
|
|
88
93
|
async def delete_connection(self, con_id: str) -> None:
|
89
94
|
"""
|
90
95
|
Delete an existing connection in CloudWorks.
|
91
96
|
:param con_id: The ID of the connection to delete.
|
92
97
|
"""
|
93
|
-
await self.
|
98
|
+
await self._http.delete(f"{self._url}/connections/{con_id}")
|
99
|
+
logger.info(f"Deleted connection '{con_id}'.")
|
94
100
|
|
95
|
-
async def
|
101
|
+
async def get_integrations(
|
96
102
|
self, sort_by_name: Literal["ascending", "descending"] = "ascending"
|
97
103
|
) -> list[Integration]:
|
98
104
|
"""
|
@@ -103,7 +109,7 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
103
109
|
params = {"sortBy": "name" if sort_by_name == "ascending" else "-name"}
|
104
110
|
return [
|
105
111
|
Integration.model_validate(e)
|
106
|
-
for e in await self.
|
112
|
+
for e in await self._http.get_paginated(f"{self._url}", "integrations", params=params)
|
107
113
|
]
|
108
114
|
|
109
115
|
async def get_integration(self, integration_id: str) -> SingleIntegration:
|
@@ -116,7 +122,7 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
116
122
|
:return: The details of the integration, without the integration type.
|
117
123
|
"""
|
118
124
|
return SingleIntegration.model_validate(
|
119
|
-
(await self.
|
125
|
+
(await self._http.get(f"{self._url}/{integration_id}"))["integration"]
|
120
126
|
)
|
121
127
|
|
122
128
|
async def create_integration(
|
@@ -143,7 +149,10 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
143
149
|
:return: The ID of the new integration.
|
144
150
|
"""
|
145
151
|
json = integration_payload(body)
|
146
|
-
|
152
|
+
res = await self._http.post(f"{self._url}", json=json)
|
153
|
+
integration_id = res["integration"]["integrationId"]
|
154
|
+
logger.info(f"Created integration '{integration_id}'.")
|
155
|
+
return integration_id
|
147
156
|
|
148
157
|
async def update_integration(
|
149
158
|
self, integration_id: str, body: IntegrationInput | IntegrationProcessInput | dict[str, Any]
|
@@ -156,7 +165,7 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
156
165
|
of the details, use the `patch_integration` method instead.
|
157
166
|
"""
|
158
167
|
json = integration_payload(body)
|
159
|
-
await self.
|
168
|
+
await self._http.put(f"{self._url}/{integration_id}", json=json)
|
160
169
|
|
161
170
|
async def run_integration(self, integration_id: str) -> str:
|
162
171
|
"""
|
@@ -164,14 +173,17 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
164
173
|
:param integration_id: The ID of the integration to run.
|
165
174
|
:return: The ID of the run instance.
|
166
175
|
"""
|
167
|
-
|
176
|
+
run_id = (await self._http.post_empty(f"{self._url}/{integration_id}/run"))["run"]["id"]
|
177
|
+
logger.info(f"Started integration run '{run_id}' for integration '{integration_id}'.")
|
178
|
+
return run_id
|
168
179
|
|
169
180
|
async def delete_integration(self, integration_id: str) -> None:
|
170
181
|
"""
|
171
182
|
Delete an existing integration in CloudWorks.
|
172
183
|
:param integration_id: The ID of the integration to delete.
|
173
184
|
"""
|
174
|
-
await self.
|
185
|
+
await self._http.delete(f"{self._url}/{integration_id}")
|
186
|
+
logger.info(f"Deleted integration '{integration_id}'.")
|
175
187
|
|
176
188
|
async def get_run_history(self, integration_id: str) -> list[RunSummary]:
|
177
189
|
"""
|
@@ -181,9 +193,9 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
181
193
|
"""
|
182
194
|
return [
|
183
195
|
RunSummary.model_validate(e)
|
184
|
-
for e in (await self.
|
185
|
-
"
|
186
|
-
)
|
196
|
+
for e in (await self._http.get(f"{self._url}/runs/{integration_id}"))[
|
197
|
+
"history_of_runs"
|
198
|
+
].get("runs", [])
|
187
199
|
]
|
188
200
|
|
189
201
|
async def get_run_status(self, run_id: str) -> RunStatus:
|
@@ -192,7 +204,7 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
192
204
|
:param run_id: The ID of the run to retrieve.
|
193
205
|
:return: The details of the run.
|
194
206
|
"""
|
195
|
-
return RunStatus.model_validate((await self.
|
207
|
+
return RunStatus.model_validate((await self._http.get(f"{self._url}/run/{run_id}"))["run"])
|
196
208
|
|
197
209
|
async def get_run_error(self, run_id: str) -> RunError | None:
|
198
210
|
"""
|
@@ -201,7 +213,7 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
201
213
|
:param run_id: The ID of the run to retrieve.
|
202
214
|
:return: The details of the run error.
|
203
215
|
"""
|
204
|
-
run = await self.
|
216
|
+
run = await self._http.get(f"{self._url}/runerror/{run_id}")
|
205
217
|
return RunError.model_validate(run["runs"]) if run.get("runs") else None
|
206
218
|
|
207
219
|
async def create_schedule(
|
@@ -214,10 +226,11 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
214
226
|
dictionary as per the documentation. If a dictionary is passed, it will be validated
|
215
227
|
against the ScheduleInput model before sending the request.
|
216
228
|
"""
|
217
|
-
await self.
|
229
|
+
await self._http.post(
|
218
230
|
f"{self._url}/{integration_id}/schedule",
|
219
231
|
json=schedule_payload(integration_id, schedule),
|
220
232
|
)
|
233
|
+
logger.info(f"Created schedule for integration '{integration_id}'.")
|
221
234
|
|
222
235
|
async def update_schedule(
|
223
236
|
self, integration_id: str, schedule: ScheduleInput | dict[str, Any]
|
@@ -229,7 +242,7 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
229
242
|
dictionary as per the documentation. If a dictionary is passed, it will be validated
|
230
243
|
against the ScheduleInput model before sending the request.
|
231
244
|
"""
|
232
|
-
await self.
|
245
|
+
await self._http.put(
|
233
246
|
f"{self._url}/{integration_id}/schedule",
|
234
247
|
json=schedule_payload(integration_id, schedule),
|
235
248
|
)
|
@@ -242,14 +255,15 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
242
255
|
:param integration_id: The ID of the integration to schedule.
|
243
256
|
:param status: The status of the schedule. This can be either "enabled" or "disabled".
|
244
257
|
"""
|
245
|
-
await self.
|
258
|
+
await self._http.post_empty(f"{self._url}/{integration_id}/schedule/status/{status}")
|
246
259
|
|
247
260
|
async def delete_schedule(self, integration_id: str) -> None:
|
248
261
|
"""
|
249
262
|
Delete an integration schedule in CloudWorks. A schedule must already exist.
|
250
263
|
:param integration_id: The ID of the integration to schedule.
|
251
264
|
"""
|
252
|
-
await self.
|
265
|
+
await self._http.delete(f"{self._url}/{integration_id}/schedule")
|
266
|
+
logger.info(f"Deleted schedule for integration '{integration_id}'.")
|
253
267
|
|
254
268
|
async def get_notification_config(
|
255
269
|
self, notification_id: str | None = None, integration_id: str | None = None
|
@@ -268,7 +282,7 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
268
282
|
if integration_id:
|
269
283
|
notification_id = (await self.get_integration(integration_id)).notification_id
|
270
284
|
return NotificationConfig.model_validate(
|
271
|
-
(await self.
|
285
|
+
(await self._http.get(f"{self._url}/notification/{notification_id}"))["notifications"]
|
272
286
|
)
|
273
287
|
|
274
288
|
async def create_notification_config(self, config: NotificationInput | dict[str, Any]) -> str:
|
@@ -282,10 +296,12 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
282
296
|
validated against the NotificationConfig model before sending the request.
|
283
297
|
:return: The ID of the new notification configuration.
|
284
298
|
"""
|
285
|
-
res = await self.
|
299
|
+
res = await self._http.post(
|
286
300
|
f"{self._url}/notification", json=construct_payload(NotificationInput, config)
|
287
301
|
)
|
288
|
-
|
302
|
+
notification_id = res["notification"]["notificationId"]
|
303
|
+
logger.info(f"Created notification configuration '{notification_id}'.")
|
304
|
+
return notification_id
|
289
305
|
|
290
306
|
async def update_notification_config(
|
291
307
|
self, notification_id: str, config: NotificationInput | dict[str, Any]
|
@@ -300,7 +316,7 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
300
316
|
a dictionary as per the documentation. If a dictionary is passed, it will be
|
301
317
|
validated against the NotificationConfig model before sending the request.
|
302
318
|
"""
|
303
|
-
await self.
|
319
|
+
await self._http.put(
|
304
320
|
f"{self._url}/notification/{notification_id}",
|
305
321
|
json=construct_payload(NotificationInput, config),
|
306
322
|
)
|
@@ -319,7 +335,8 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
319
335
|
raise ValueError("Either notification_id or integration_id must be specified.")
|
320
336
|
if integration_id:
|
321
337
|
notification_id = (await self.get_integration(integration_id)).notification_id
|
322
|
-
await self.
|
338
|
+
await self._http.delete(f"{self._url}/notification/{notification_id}")
|
339
|
+
logger.info(f"Deleted notification configuration '{notification_id}'.")
|
323
340
|
|
324
341
|
async def get_import_error_dump(self, run_id: str) -> bytes:
|
325
342
|
"""
|
@@ -331,7 +348,7 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
331
348
|
:param run_id: The ID of the run to retrieve.
|
332
349
|
:return: The error dump.
|
333
350
|
"""
|
334
|
-
return await self.
|
351
|
+
return await self._http.get_binary(f"{self._url}/run/{run_id}/dump")
|
335
352
|
|
336
353
|
async def get_process_error_dump(self, run_id: str, action_id: int | str) -> bytes:
|
337
354
|
"""
|
@@ -341,4 +358,6 @@ class _AsyncCloudWorksClient(_AsyncBaseClient):
|
|
341
358
|
:param action_id: The ID of the action to retrieve. This can be found in the RunError.
|
342
359
|
:return: The error dump.
|
343
360
|
"""
|
344
|
-
return await self.
|
361
|
+
return await self._http.get_binary(
|
362
|
+
f"{self._url}/run/{run_id}/process/import/{action_id}/dumps"
|
363
|
+
)
|
@@ -1,17 +1,18 @@
|
|
1
|
+
import logging
|
1
2
|
from typing import Any
|
2
3
|
|
3
|
-
import
|
4
|
-
|
5
|
-
from anaplan_sdk._base import _AsyncBaseClient, construct_payload
|
4
|
+
from anaplan_sdk._services import _AsyncHttpService, construct_payload
|
6
5
|
from anaplan_sdk.models.flows import Flow, FlowInput, FlowSummary
|
7
6
|
|
7
|
+
logger = logging.getLogger("anaplan_sdk")
|
8
|
+
|
8
9
|
|
9
|
-
class _AsyncFlowClient
|
10
|
-
def __init__(self,
|
10
|
+
class _AsyncFlowClient:
|
11
|
+
def __init__(self, http: _AsyncHttpService) -> None:
|
12
|
+
self._http = http
|
11
13
|
self._url = "https://api.cloudworks.anaplan.com/2/0/integrationflows"
|
12
|
-
super().__init__(retry_count, client)
|
13
14
|
|
14
|
-
async def
|
15
|
+
async def get_flows(self, current_user_only: bool = False) -> list[FlowSummary]:
|
15
16
|
"""
|
16
17
|
List all flows in CloudWorks.
|
17
18
|
:param current_user_only: Filters the flows to only those created by the current user.
|
@@ -20,7 +21,7 @@ class _AsyncFlowClient(_AsyncBaseClient):
|
|
20
21
|
params = {"myIntegrations": 1 if current_user_only else 0}
|
21
22
|
return [
|
22
23
|
FlowSummary.model_validate(e)
|
23
|
-
for e in await self.
|
24
|
+
for e in await self._http.get_paginated(
|
24
25
|
self._url, "integrationFlows", page_size=25, params=params
|
25
26
|
)
|
26
27
|
]
|
@@ -32,7 +33,9 @@ class _AsyncFlowClient(_AsyncBaseClient):
|
|
32
33
|
:param flow_id: The ID of the flow to get.
|
33
34
|
:return: The Flow object.
|
34
35
|
"""
|
35
|
-
return Flow.model_validate(
|
36
|
+
return Flow.model_validate(
|
37
|
+
(await self._http.get(f"{self._url}/{flow_id}"))["integrationFlow"]
|
38
|
+
)
|
36
39
|
|
37
40
|
async def run_flow(self, flow_id: str, only_steps: list[str] = None) -> str:
|
38
41
|
"""
|
@@ -45,11 +48,13 @@ class _AsyncFlowClient(_AsyncBaseClient):
|
|
45
48
|
"""
|
46
49
|
url = f"{self._url}/{flow_id}/run"
|
47
50
|
res = await (
|
48
|
-
self.
|
51
|
+
self._http.post(url, json={"stepsToRun": only_steps})
|
49
52
|
if only_steps
|
50
|
-
else self.
|
53
|
+
else self._http.post_empty(url)
|
51
54
|
)
|
52
|
-
|
55
|
+
run_id = res["run"]["id"]
|
56
|
+
logger.info(f"Started flow run '{run_id}' for flow '{flow_id}'.")
|
57
|
+
return run_id
|
53
58
|
|
54
59
|
async def create_flow(self, flow: FlowInput | dict[str, Any]) -> str:
|
55
60
|
"""
|
@@ -59,8 +64,10 @@ class _AsyncFlowClient(_AsyncBaseClient):
|
|
59
64
|
:param flow: The flow to create. This can be a FlowInput object or a dictionary.
|
60
65
|
:return: The ID of the created flow.
|
61
66
|
"""
|
62
|
-
res = await self.
|
63
|
-
|
67
|
+
res = await self._http.post(self._url, json=construct_payload(FlowInput, flow))
|
68
|
+
flow_id = res["integrationFlow"]["integrationFlowId"]
|
69
|
+
logger.info(f"Created flow '{flow_id}'.")
|
70
|
+
return flow_id
|
64
71
|
|
65
72
|
async def update_flow(self, flow_id: str, flow: FlowInput | dict[str, Any]) -> None:
|
66
73
|
"""
|
@@ -69,7 +76,8 @@ class _AsyncFlowClient(_AsyncBaseClient):
|
|
69
76
|
:param flow_id: The ID of the flow to update.
|
70
77
|
:param flow: The flow to update. This can be a FlowInput object or a dictionary.
|
71
78
|
"""
|
72
|
-
await self.
|
79
|
+
await self._http.put(f"{self._url}/{flow_id}", json=construct_payload(FlowInput, flow))
|
80
|
+
logger.info(f"Updated flow '{flow_id}'.")
|
73
81
|
|
74
82
|
async def delete_flow(self, flow_id: str) -> None:
|
75
83
|
"""
|
@@ -77,4 +85,5 @@ class _AsyncFlowClient(_AsyncBaseClient):
|
|
77
85
|
the flow is running or if it has any running steps.
|
78
86
|
:param flow_id: The ID of the flow to delete.
|
79
87
|
"""
|
80
|
-
await self.
|
88
|
+
await self._http.delete(f"{self._url}/{flow_id}")
|
89
|
+
logger.info(f"Deleted flow '{flow_id}'.")
|