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.
@@ -1,9 +1,8 @@
1
+ import logging
1
2
  from typing import Any, Literal
2
3
 
3
- import httpx
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(_AsyncBaseClient):
32
- def __init__(self, client: httpx.AsyncClient, retry_count: int) -> None:
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(client, retry_count)
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 list_connections(self) -> list[Connection]:
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._get_paginated(f"{self._url}/connections", "connections")
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._post(
63
+ res = await self._http.post(
63
64
  f"{self._url}/connections", json=construct_payload(ConnectionInput, con_info)
64
65
  )
65
- return res["connections"]["connectionId"]
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._put(f"{self._url}/connections/{con_id}", json=connection_body_payload(con_info))
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._patch(f"{self._url}/connections/{con_id}", json=body)
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._delete(f"{self._url}/connections/{con_id}")
98
+ await self._http.delete(f"{self._url}/connections/{con_id}")
99
+ logger.info(f"Deleted connection '{con_id}'.")
94
100
 
95
- async def list_integrations(
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._get_paginated(f"{self._url}", "integrations", params=params)
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._get(f"{self._url}/{integration_id}"))["integration"]
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
- return (await self._post(f"{self._url}", json=json))["integration"]["integrationId"]
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._put(f"{self._url}/{integration_id}", json=json)
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
- return (await self._post_empty(f"{self._url}/{integration_id}/run"))["run"]["id"]
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._delete(f"{self._url}/{integration_id}")
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._get(f"{self._url}/runs/{integration_id}"))["history_of_runs"].get(
185
- "runs", []
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._get(f"{self._url}/run/{run_id}"))["run"])
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._get(f"{self._url}/runerror/{run_id}")
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._post(
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._put(
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._post_empty(f"{self._url}/{integration_id}/schedule/status/{status}")
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._delete(f"{self._url}/{integration_id}/schedule")
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._get(f"{self._url}/notification/{notification_id}"))["notifications"]
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._post(
299
+ res = await self._http.post(
286
300
  f"{self._url}/notification", json=construct_payload(NotificationInput, config)
287
301
  )
288
- return res["notification"]["notificationId"]
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._put(
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._delete(f"{self._url}/notification/{notification_id}")
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._get_binary(f"{self._url}/run/{run_id}/dump")
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._get_binary(f"{self._url}/run/{run_id}/process/import/{action_id}/dumps")
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 httpx
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(_AsyncBaseClient):
10
- def __init__(self, client: httpx.AsyncClient, retry_count: int) -> None:
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 list_flows(self, current_user_only: bool = False) -> list[FlowSummary]:
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._get_paginated(
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((await self._get(f"{self._url}/{flow_id}"))["integrationFlow"])
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._post(url, json={"stepsToRun": only_steps})
51
+ self._http.post(url, json={"stepsToRun": only_steps})
49
52
  if only_steps
50
- else self._post_empty(url)
53
+ else self._http.post_empty(url)
51
54
  )
52
- return res["run"]["id"]
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._post(self._url, json=construct_payload(FlowInput, flow))
63
- return res["integrationFlow"]["integrationFlowId"]
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._put(f"{self._url}/{flow_id}", json=construct_payload(FlowInput, flow))
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._delete(f"{self._url}/{flow_id}")
88
+ await self._http.delete(f"{self._url}/{flow_id}")
89
+ logger.info(f"Deleted flow '{flow_id}'.")