anaplan-sdk 0.2.11__tar.gz → 0.3.0__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.
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/.gitignore +1 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/PKG-INFO +2 -2
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/README.md +1 -1
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/anaplan_sdk/_async_clients/_bulk.py +31 -21
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/anaplan_sdk/_async_clients/_transactional.py +15 -4
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/anaplan_sdk/_clients/_bulk.py +28 -15
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/anaplan_sdk/_clients/_transactional.py +15 -4
- anaplan_sdk-0.3.0/anaplan_sdk/models.py +329 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/api/async_transactional_client.md +2 -2
- anaplan_sdk-0.3.0/docs/css/styles.css +64 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/guides/bulk.md +62 -13
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/guides/logging.md +1 -1
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/guides/multiple_models.md +2 -2
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/guides/transactional.md +17 -17
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/index.md +1 -1
- anaplan_sdk-0.3.0/docs/js/assets/hljs.js +1242 -0
- anaplan_sdk-0.3.0/docs/js/assets/python.js +334 -0
- anaplan_sdk-0.3.0/docs/js/highlight.js +12 -0
- anaplan_sdk-0.3.0/docs/quickstart.md +162 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/mkdocs.yml +9 -2
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/pyproject.toml +2 -1
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/tests/async/conftest.py +2 -2
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/tests/async/test_async_client.py +36 -10
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/tests/sync/conftest.py +2 -2
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/tests/sync/test_client.py +36 -10
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/uv.lock +179 -127
- anaplan_sdk-0.2.11/anaplan_sdk/models.py +0 -318
- anaplan_sdk-0.2.11/docs/css/styles.css +0 -13
- anaplan_sdk-0.2.11/docs/quickstart.md +0 -102
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/.github/dependabot.yml +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/.github/workflows/docs.yml +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/.github/workflows/lint.yml +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/.github/workflows/tests.yml +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/.pre-commit-config.yaml +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/LICENSE +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/anaplan_sdk/__init__.py +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/anaplan_sdk/_async_clients/__init__.py +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/anaplan_sdk/_async_clients/_alm.py +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/anaplan_sdk/_async_clients/_audit.py +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/anaplan_sdk/_auth.py +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/anaplan_sdk/_base.py +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/anaplan_sdk/_clients/__init__.py +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/anaplan_sdk/_clients/_alm.py +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/anaplan_sdk/_clients/_audit.py +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/anaplan_sdk/exceptions.py +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/anaplan_explained.md +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/api/alm_client.md +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/api/async_alm_client.md +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/api/async_audit_client.md +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/api/async_client.md +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/api/audit_client.md +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/api/client.md +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/api/exceptions.md +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/api/models.md +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/api/transactional_client.md +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/guides/alm.md +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/guides/audit.md +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/guides/bulk_vs_transactional.md +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/img/anaplan-overview.webp +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/img/anaplan-sdk.webp +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/docs/installation.md +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/tests/async/test_async_alm_client.py +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/tests/async/test_async_audit_client.py +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/tests/async/test_async_transactional_client.py +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/tests/conftest.py +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/tests/sync/test_alm_client.py +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/tests/sync/test_audit_client.py +0 -0
- {anaplan_sdk-0.2.11 → anaplan_sdk-0.3.0}/tests/sync/test_transactional_client.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: anaplan-sdk
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.3.0
|
4
4
|
Summary: Provides pythonic access to the Anaplan API
|
5
5
|
Project-URL: Homepage, https://vinzenzklass.github.io/anaplan-sdk/
|
6
6
|
Project-URL: Repository, https://github.com/VinzenzKlass/anaplan-sdk
|
@@ -38,7 +38,7 @@ implementation details like authentication, error handling, chunking, compressio
|
|
38
38
|
This Projects supports
|
39
39
|
the [Bulk APIs](https://help.anaplan.com/use-the-bulk-apis-93218e5e-00e5-406e-8361-09ab861889a7),
|
40
40
|
the [Transactional APIs](https://help.anaplan.com/use-the-transactional-apis-cc1c1e91-39fc-4272-a4b5-16bc91e9c313) and
|
41
|
-
the [ALM
|
41
|
+
the [ALM APIs](https://help.anaplan.com/application-lifecycle-management-api-2565cfa6-e0c2-4e24-884e-d0df957184d6),
|
42
42
|
the [Audit APIs](https://auditservice.docs.apiary.io/#),
|
43
43
|
providing both synchronous and asynchronous Clients.
|
44
44
|
|
@@ -21,7 +21,7 @@ implementation details like authentication, error handling, chunking, compressio
|
|
21
21
|
This Projects supports
|
22
22
|
the [Bulk APIs](https://help.anaplan.com/use-the-bulk-apis-93218e5e-00e5-406e-8361-09ab861889a7),
|
23
23
|
the [Transactional APIs](https://help.anaplan.com/use-the-transactional-apis-cc1c1e91-39fc-4272-a4b5-16bc91e9c313) and
|
24
|
-
the [ALM
|
24
|
+
the [ALM APIs](https://help.anaplan.com/application-lifecycle-management-api-2565cfa6-e0c2-4e24-884e-d0df957184d6),
|
25
25
|
the [Audit APIs](https://auditservice.docs.apiary.io/#),
|
26
26
|
providing both synchronous and asynchronous Clients.
|
27
27
|
|
@@ -3,8 +3,7 @@ Asynchronous Client.
|
|
3
3
|
"""
|
4
4
|
|
5
5
|
import logging
|
6
|
-
import
|
7
|
-
from asyncio import gather
|
6
|
+
from asyncio import gather, sleep
|
8
7
|
from copy import copy
|
9
8
|
from typing import AsyncIterator, Iterator
|
10
9
|
|
@@ -14,7 +13,17 @@ from typing_extensions import Self
|
|
14
13
|
from anaplan_sdk._auth import AnaplanBasicAuth, AnaplanCertAuth, get_certificate, get_private_key
|
15
14
|
from anaplan_sdk._base import _AsyncBaseClient, action_url
|
16
15
|
from anaplan_sdk.exceptions import AnaplanActionError, InvalidIdentifierException
|
17
|
-
from anaplan_sdk.models import
|
16
|
+
from anaplan_sdk.models import (
|
17
|
+
Action,
|
18
|
+
Export,
|
19
|
+
File,
|
20
|
+
Import,
|
21
|
+
Model,
|
22
|
+
Process,
|
23
|
+
TaskStatus,
|
24
|
+
TaskSummary,
|
25
|
+
Workspace,
|
26
|
+
)
|
18
27
|
|
19
28
|
from ._alm import _AsyncAlmClient
|
20
29
|
from ._audit import _AsyncAuditClient
|
@@ -250,7 +259,7 @@ class AsyncClient(_AsyncBaseClient):
|
|
250
259
|
for e in (await self._get(f"{self._url}/exports")).get("exports", [])
|
251
260
|
]
|
252
261
|
|
253
|
-
async def run_action(self, action_id: int) ->
|
262
|
+
async def run_action(self, action_id: int) -> TaskStatus:
|
254
263
|
"""
|
255
264
|
Runs the specified Anaplan Action and validates the spawned task. If the Action fails or
|
256
265
|
completes with errors, will raise an :py:class:`AnaplanActionError`. Failed Tasks are
|
@@ -268,16 +277,15 @@ class AsyncClient(_AsyncBaseClient):
|
|
268
277
|
task_id = await self.invoke_action(action_id)
|
269
278
|
task_status = await self.get_task_status(action_id, task_id)
|
270
279
|
|
271
|
-
while
|
272
|
-
|
280
|
+
while task_status.task_state != "COMPLETE":
|
281
|
+
await sleep(self.status_poll_delay)
|
273
282
|
task_status = await self.get_task_status(action_id, task_id)
|
274
283
|
|
275
|
-
if task_status.
|
276
|
-
"successful"
|
277
|
-
):
|
284
|
+
if task_status.task_state == "COMPLETE" and not task_status.result.successful:
|
278
285
|
raise AnaplanActionError(f"Task '{task_id}' completed with errors.")
|
279
286
|
|
280
287
|
logger.info(f"Task '{task_id}' completed successfully.")
|
288
|
+
return task_status
|
281
289
|
|
282
290
|
async def get_file(self, file_id: int) -> bytes:
|
283
291
|
"""
|
@@ -390,29 +398,31 @@ class AsyncClient(_AsyncBaseClient):
|
|
390
398
|
await self.run_action(action_id)
|
391
399
|
return await self.get_file(action_id)
|
392
400
|
|
393
|
-
async def list_task_status(self, action_id: int) -> list:
|
401
|
+
async def list_task_status(self, action_id: int) -> list[TaskSummary]:
|
394
402
|
"""
|
395
403
|
Retrieves the status of all tasks spawned by the specified action.
|
396
404
|
:param action_id: The identifier of the action that was invoked.
|
397
405
|
:return: The list of tasks spawned by the action.
|
398
406
|
"""
|
399
|
-
return
|
400
|
-
|
401
|
-
|
407
|
+
return [
|
408
|
+
TaskSummary.model_validate(e)
|
409
|
+
for e in (
|
410
|
+
await self._get(f"{self._url}/{action_url(action_id)}/{action_id}/tasks")
|
411
|
+
).get("tasks", [])
|
412
|
+
]
|
402
413
|
|
403
|
-
async def get_task_status(
|
404
|
-
self, action_id: int, task_id: str
|
405
|
-
) -> dict[str, float | int | str | list | dict | bool]:
|
414
|
+
async def get_task_status(self, action_id: int, task_id: str) -> TaskStatus:
|
406
415
|
"""
|
407
416
|
Retrieves the status of the specified task.
|
408
417
|
:param action_id: The identifier of the action that was invoked.
|
409
418
|
:param task_id: The identifier of the spawned task.
|
410
|
-
:return: The status of the task
|
411
|
-
see: https://anaplan.docs.apiary.io.
|
419
|
+
:return: The status of the task.
|
412
420
|
"""
|
413
|
-
return (
|
414
|
-
|
415
|
-
|
421
|
+
return TaskStatus.model_validate(
|
422
|
+
(
|
423
|
+
await self._get(f"{self._url}/{action_url(action_id)}/{action_id}/tasks/{task_id}")
|
424
|
+
).get("task")
|
425
|
+
)
|
416
426
|
|
417
427
|
async def invoke_action(self, action_id: int) -> str:
|
418
428
|
"""
|
@@ -32,7 +32,7 @@ class _AsyncTransactionalClient(_AsyncBaseClient):
|
|
32
32
|
"""
|
33
33
|
return [
|
34
34
|
Module.model_validate(e)
|
35
|
-
for e in (await self._get(f"{self._url}/modules")).get("modules")
|
35
|
+
for e in (await self._get(f"{self._url}/modules")).get("modules", [])
|
36
36
|
]
|
37
37
|
|
38
38
|
async def get_model_status(self) -> ModelStatus:
|
@@ -55,7 +55,7 @@ class _AsyncTransactionalClient(_AsyncBaseClient):
|
|
55
55
|
if only_module_id
|
56
56
|
else f"{self._url}/lineItems?includeAll=true"
|
57
57
|
)
|
58
|
-
return [LineItem.model_validate(e) for e in (await self._get(url)).get("items")]
|
58
|
+
return [LineItem.model_validate(e) for e in (await self._get(url)).get("items", [])]
|
59
59
|
|
60
60
|
async def list_lists(self) -> list[List]:
|
61
61
|
"""
|
@@ -63,7 +63,7 @@ class _AsyncTransactionalClient(_AsyncBaseClient):
|
|
63
63
|
:return: All Lists on this model.
|
64
64
|
"""
|
65
65
|
return [
|
66
|
-
List.model_validate(e) for e in (await self._get(f"{self._url}/lists")).get("lists")
|
66
|
+
List.model_validate(e) for e in (await self._get(f"{self._url}/lists")).get("lists", [])
|
67
67
|
]
|
68
68
|
|
69
69
|
async def get_list_metadata(self, list_id: int) -> ListMetadata:
|
@@ -156,7 +156,7 @@ class _AsyncTransactionalClient(_AsyncBaseClient):
|
|
156
156
|
"""
|
157
157
|
await self._post_empty(f"{self._url}/lists/{list_id}/resetIndex")
|
158
158
|
|
159
|
-
async def
|
159
|
+
async def update_module_data(
|
160
160
|
self, module_id: int, data: list[dict[str, Any]]
|
161
161
|
) -> int | dict[str, Any]:
|
162
162
|
"""
|
@@ -171,6 +171,17 @@ class _AsyncTransactionalClient(_AsyncBaseClient):
|
|
171
171
|
res = await self._post(f"{self._url}/modules/{module_id}/data", json=data)
|
172
172
|
return res if "failures" in res else res["numberOfCellsChanged"]
|
173
173
|
|
174
|
+
async def write_to_module(
|
175
|
+
self, module_id: int, data: list[dict[str, Any]]
|
176
|
+
) -> int | dict[str, Any]:
|
177
|
+
warnings.warn(
|
178
|
+
"`write_to_module()` is deprecated and will be removed in a future version. "
|
179
|
+
"Use `update_module_data()` instead.",
|
180
|
+
DeprecationWarning,
|
181
|
+
stacklevel=1,
|
182
|
+
)
|
183
|
+
return await self.update_module_data(module_id, data)
|
184
|
+
|
174
185
|
async def add_items_to_list(
|
175
186
|
self, list_id: int, items: list[dict[str, str | int | dict]]
|
176
187
|
) -> InsertionResult:
|
@@ -15,7 +15,17 @@ from typing_extensions import Self
|
|
15
15
|
from anaplan_sdk._auth import AnaplanBasicAuth, AnaplanCertAuth, get_certificate, get_private_key
|
16
16
|
from anaplan_sdk._base import _BaseClient, action_url
|
17
17
|
from anaplan_sdk.exceptions import AnaplanActionError, InvalidIdentifierException
|
18
|
-
from anaplan_sdk.models import
|
18
|
+
from anaplan_sdk.models import (
|
19
|
+
Action,
|
20
|
+
Export,
|
21
|
+
File,
|
22
|
+
Import,
|
23
|
+
Model,
|
24
|
+
Process,
|
25
|
+
TaskStatus,
|
26
|
+
TaskSummary,
|
27
|
+
Workspace,
|
28
|
+
)
|
19
29
|
|
20
30
|
from ._alm import _AlmClient
|
21
31
|
from ._audit import _AuditClient
|
@@ -252,7 +262,7 @@ class Client(_BaseClient):
|
|
252
262
|
Export.model_validate(e) for e in (self._get(f"{self._url}/exports")).get("exports", [])
|
253
263
|
]
|
254
264
|
|
255
|
-
def run_action(self, action_id: int) ->
|
265
|
+
def run_action(self, action_id: int) -> TaskStatus:
|
256
266
|
"""
|
257
267
|
Runs the specified Anaplan Action and validates the spawned task. If the Action fails or
|
258
268
|
completes with errors, will raise an :py:class:`AnaplanActionError`. Failed Tasks are
|
@@ -270,16 +280,15 @@ class Client(_BaseClient):
|
|
270
280
|
task_id = self.invoke_action(action_id)
|
271
281
|
task_status = self.get_task_status(action_id, task_id)
|
272
282
|
|
273
|
-
while
|
283
|
+
while task_status.task_state != "COMPLETE":
|
274
284
|
time.sleep(self.status_poll_delay)
|
275
285
|
task_status = self.get_task_status(action_id, task_id)
|
276
286
|
|
277
|
-
if task_status.
|
278
|
-
"successful"
|
279
|
-
):
|
287
|
+
if task_status.task_state == "COMPLETE" and not task_status.result.successful:
|
280
288
|
raise AnaplanActionError(f"Task '{task_id}' completed with errors.")
|
281
289
|
|
282
290
|
logger.info(f"Task '{task_id}' completed successfully.")
|
291
|
+
return task_status
|
283
292
|
|
284
293
|
def get_file(self, file_id: int) -> bytes:
|
285
294
|
"""
|
@@ -383,26 +392,30 @@ class Client(_BaseClient):
|
|
383
392
|
self.run_action(action_id)
|
384
393
|
return self.get_file(action_id)
|
385
394
|
|
386
|
-
def list_task_status(self, action_id: int) -> list:
|
395
|
+
def list_task_status(self, action_id: int) -> list[TaskSummary]:
|
387
396
|
"""
|
388
397
|
Retrieves the status of all tasks spawned by the specified action.
|
389
398
|
:param action_id: The identifier of the action that was invoked.
|
390
399
|
:return: The list of tasks spawned by the action.
|
391
400
|
"""
|
392
|
-
return
|
401
|
+
return [
|
402
|
+
TaskSummary.model_validate(e)
|
403
|
+
for e in self._get(f"{self._url}/{action_url(action_id)}/{action_id}/tasks").get(
|
404
|
+
"tasks", []
|
405
|
+
)
|
406
|
+
]
|
393
407
|
|
394
|
-
def get_task_status(
|
395
|
-
self, action_id: int, task_id: str
|
396
|
-
) -> dict[str, float | int | str | list | dict | bool]:
|
408
|
+
def get_task_status(self, action_id: int, task_id: str) -> TaskStatus:
|
397
409
|
"""
|
398
410
|
Retrieves the status of the specified task.
|
399
411
|
:param action_id: The identifier of the action that was invoked.
|
400
412
|
:param task_id: The identifier of the spawned task.
|
401
|
-
:return: The status of the task
|
402
|
-
see: https://anaplan.docs.apiary.io.
|
413
|
+
:return: The status of the task.
|
403
414
|
"""
|
404
|
-
return
|
405
|
-
"
|
415
|
+
return TaskStatus.model_validate(
|
416
|
+
self._get(f"{self._url}/{action_url(action_id)}/{action_id}/tasks/{task_id}").get(
|
417
|
+
"task"
|
418
|
+
)
|
406
419
|
)
|
407
420
|
|
408
421
|
def invoke_action(self, action_id: int) -> str:
|
@@ -48,14 +48,14 @@ class _TransactionalClient(_BaseClient):
|
|
48
48
|
if only_module_id
|
49
49
|
else f"{self._url}/lineItems?includeAll=true"
|
50
50
|
)
|
51
|
-
return [LineItem.model_validate(e) for e in self._get(url).get("items")]
|
51
|
+
return [LineItem.model_validate(e) for e in self._get(url).get("items", [])]
|
52
52
|
|
53
53
|
def list_lists(self) -> list[List]:
|
54
54
|
"""
|
55
55
|
Lists all the Lists in the Model.
|
56
56
|
:return: All Lists on this Model.
|
57
57
|
"""
|
58
|
-
return [List.model_validate(e) for e in self._get(f"{self._url}/lists").get("lists")]
|
58
|
+
return [List.model_validate(e) for e in self._get(f"{self._url}/lists").get("lists", [])]
|
59
59
|
|
60
60
|
def get_list_metadata(self, list_id: int) -> ListMetadata:
|
61
61
|
"""
|
@@ -76,7 +76,7 @@ class _TransactionalClient(_BaseClient):
|
|
76
76
|
return [
|
77
77
|
ListItem.model_validate(e)
|
78
78
|
for e in self._get(f"{self._url}/lists/{list_id}/items?includeAll=true").get(
|
79
|
-
"listItems"
|
79
|
+
"listItems", []
|
80
80
|
)
|
81
81
|
]
|
82
82
|
|
@@ -149,7 +149,9 @@ class _TransactionalClient(_BaseClient):
|
|
149
149
|
"""
|
150
150
|
self._post_empty(f"{self._url}/lists/{list_id}/resetIndex")
|
151
151
|
|
152
|
-
def
|
152
|
+
def update_module_data(
|
153
|
+
self, module_id: int, data: list[dict[str, Any]]
|
154
|
+
) -> int | dict[str, Any]:
|
153
155
|
"""
|
154
156
|
Write the passed items to the specified module. If successful, the number of cells changed
|
155
157
|
is returned, if only partially successful or unsuccessful, the response with the according
|
@@ -162,6 +164,15 @@ class _TransactionalClient(_BaseClient):
|
|
162
164
|
res = self._post(f"{self._url}/modules/{module_id}/data", json=data)
|
163
165
|
return res if "failures" in res else res["numberOfCellsChanged"]
|
164
166
|
|
167
|
+
def write_to_module(self, module_id: int, data: list[dict[str, Any]]) -> int | dict[str, Any]:
|
168
|
+
warnings.warn(
|
169
|
+
"`write_to_module()` is deprecated and will be removed in a future version. "
|
170
|
+
"Use `update_module_data()` instead.",
|
171
|
+
DeprecationWarning,
|
172
|
+
stacklevel=1,
|
173
|
+
)
|
174
|
+
return self.update_module_data(module_id, data)
|
175
|
+
|
165
176
|
def add_items_to_list(
|
166
177
|
self, list_id: int, items: list[dict[str, str | int | dict]]
|
167
178
|
) -> InsertionResult:
|
@@ -0,0 +1,329 @@
|
|
1
|
+
from typing import Literal, TypeAlias
|
2
|
+
|
3
|
+
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
4
|
+
from pydantic.alias_generators import to_camel
|
5
|
+
|
6
|
+
ExportTypes: TypeAlias = Literal[
|
7
|
+
"TABULAR_MULTI_COLUMN",
|
8
|
+
"TABULAR_SINGLE_COLUMN",
|
9
|
+
"GRID_CURRENT_PAGE",
|
10
|
+
"AUDIT_LOG",
|
11
|
+
"TABULAR_ALL_LINE_ITEMS",
|
12
|
+
"TABULAR_CURRENT_LINE_ITEM",
|
13
|
+
]
|
14
|
+
|
15
|
+
ImportTypes: TypeAlias = Literal[
|
16
|
+
"MODULE_DATA", "HIERARCHY_DATA", "LINE_ITEM_DEFINITION", "USERS", "VERSIONS"
|
17
|
+
]
|
18
|
+
|
19
|
+
|
20
|
+
class Workspace(BaseModel):
|
21
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
22
|
+
id: str = Field(description="The unique identifier of this workspace.")
|
23
|
+
name: str = Field(description="The name of this workspace that is also displayed to the users.")
|
24
|
+
active: bool = Field(description="Whether this workspace is active or not.")
|
25
|
+
size_allowance: int = Field(description="The maximum allowed size of this workspace in bytes.")
|
26
|
+
current_size: int = Field(description="The current size of this workspace in bytes.")
|
27
|
+
|
28
|
+
|
29
|
+
class Model(BaseModel):
|
30
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
31
|
+
id: str = Field(description="The unique identifier of this model.")
|
32
|
+
name: str
|
33
|
+
active_state: Literal["ARCHIVED", "UNLOCKED", "ACTIVE", "PRODUCTION"] = Field(
|
34
|
+
description="The current state of this model."
|
35
|
+
)
|
36
|
+
last_saved_serial_number: int = Field(
|
37
|
+
description="The serial number of the last save of this model."
|
38
|
+
)
|
39
|
+
last_modified_by_user_guid: str = Field(
|
40
|
+
description="The unique identifier of the user who last modified this model."
|
41
|
+
)
|
42
|
+
memory_usage: int = Field(0, description="The memory usage of this model in bytes.")
|
43
|
+
current_workspace_id: str = Field(
|
44
|
+
description="The unique identifier of the workspace that this model is currently in."
|
45
|
+
)
|
46
|
+
current_workspace_name: str = Field(
|
47
|
+
description="The name of the workspace that this model is currently in."
|
48
|
+
)
|
49
|
+
url: str = Field(validation_alias="modelUrl", description="The current URL of this model.")
|
50
|
+
category_values: list = Field(description="The category values of this model.")
|
51
|
+
iso_creation_date: str = Field(description="The creation date of this model in ISO format.")
|
52
|
+
last_modified: str = Field(description="The last modified date of this model.")
|
53
|
+
|
54
|
+
|
55
|
+
class File(BaseModel):
|
56
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
57
|
+
id: int = Field(description="The unique identifier of this file.")
|
58
|
+
name: str = Field(description="The name of this file.")
|
59
|
+
chunk_count: int = Field(description="The number of chunks this file is split into.")
|
60
|
+
delimiter: str | None = Field(None, description="The delimiter used in this file.")
|
61
|
+
encoding: str | None = Field(None, description="The encoding of this file.")
|
62
|
+
first_data_row: int = Field(description="The row number of the first data row in this file.")
|
63
|
+
format: str | None = Field(None, description="The format of this file.")
|
64
|
+
header_row: int = Field(description="The row number of the header row in this file.")
|
65
|
+
separator: str | None = Field(None, description="The separator used in this file.")
|
66
|
+
|
67
|
+
|
68
|
+
class List(BaseModel):
|
69
|
+
id: int = Field(description="The unique identifier of this list.")
|
70
|
+
name: str = Field(description="The name of this list.")
|
71
|
+
|
72
|
+
|
73
|
+
class ListMetadata(BaseModel):
|
74
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
75
|
+
id: int = Field(description="The unique identifier of this list.")
|
76
|
+
name: str = Field(description="The name of this list.")
|
77
|
+
has_selective_access: bool = Field(description="Whether this list has selective access or not.")
|
78
|
+
properties: list = Field([], description="The properties of this list.")
|
79
|
+
production_data: bool = Field(description="Whether this list is production data or not.")
|
80
|
+
managed_by: str = Field(description="The user who manages this list.")
|
81
|
+
numbered_list: bool = Field(description="Whether this list is a numbered list or not.")
|
82
|
+
use_top_level_as_page_default: bool = Field(
|
83
|
+
description="Whether the top level is used as the page default or not."
|
84
|
+
)
|
85
|
+
item_count: int = Field(description="The number of items in this list.")
|
86
|
+
next_item_index: int | None = Field(
|
87
|
+
None, description="The index of the next item in this list."
|
88
|
+
)
|
89
|
+
workflow_enabled: bool = Field(
|
90
|
+
description="Whether the workflow is enabled for this list or not."
|
91
|
+
)
|
92
|
+
permitted_items: int = Field(description="The number of permitted items in this list.")
|
93
|
+
used_in_applies_to: str | None = Field(None, description="The applies to value of this list.")
|
94
|
+
|
95
|
+
|
96
|
+
class Action(BaseModel):
|
97
|
+
model_config = ConfigDict(populate_by_name=True)
|
98
|
+
id: int = Field(description="The unique identifier of this action.")
|
99
|
+
name: str = Field(
|
100
|
+
description="The name of this Action. This is the same as the one displayed in the Web UI."
|
101
|
+
)
|
102
|
+
type: str | None = Field(
|
103
|
+
None, validation_alias="actionType", description="The type of this action."
|
104
|
+
)
|
105
|
+
|
106
|
+
|
107
|
+
class ListItem(BaseModel):
|
108
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
109
|
+
id: int = Field(description="The unique identifier of this list item.")
|
110
|
+
name: str = Field(description="The name of this list item.")
|
111
|
+
code: str | None = Field(None, description="The code of this list item.")
|
112
|
+
properties: dict = Field({}, description="The properties of this list item.")
|
113
|
+
subsets: dict = Field({}, description="The subsets of this list item.")
|
114
|
+
parent: str | None = Field(None, description="The parent of this list item.")
|
115
|
+
parent_id: str | None = Field(
|
116
|
+
None, description="The unique identifier of the parent of this list item."
|
117
|
+
)
|
118
|
+
|
119
|
+
|
120
|
+
class Process(BaseModel):
|
121
|
+
id: int = Field(description="The unique identifier of this process.")
|
122
|
+
name: str = Field(description="The name of this process.")
|
123
|
+
|
124
|
+
|
125
|
+
class Import(BaseModel):
|
126
|
+
id: int = Field(description="The unique identifier of this import.")
|
127
|
+
name: str = Field(description="The name of this import.")
|
128
|
+
type: ImportTypes = Field(validation_alias="importType", description="The type of this import.")
|
129
|
+
file_id: int | None = Field(
|
130
|
+
None,
|
131
|
+
validation_alias="importDataSourceId",
|
132
|
+
description=(
|
133
|
+
"The unique identifier of the data source of this import. If it is absent, it means "
|
134
|
+
"that the import is not a file import."
|
135
|
+
),
|
136
|
+
)
|
137
|
+
|
138
|
+
# noinspection PyNestedDecorators
|
139
|
+
@field_validator("file_id", mode="before")
|
140
|
+
@classmethod
|
141
|
+
def _empty_source_is_none(cls, inp: str):
|
142
|
+
return inp if inp else None
|
143
|
+
|
144
|
+
|
145
|
+
class Export(BaseModel):
|
146
|
+
model_config = ConfigDict(populate_by_name=True)
|
147
|
+
id: int = Field(description="The unique identifier of this export.")
|
148
|
+
name: str = Field(description="The name of this export.")
|
149
|
+
type: ExportTypes = Field(validation_alias="exportType", description="The type of this export.")
|
150
|
+
format: str = Field(validation_alias="exportFormat", description="The format of this export.")
|
151
|
+
encoding: str | None = Field(None, description="The encoding of this export.")
|
152
|
+
layout: ExportTypes = Field(
|
153
|
+
description="The layout of this export, representing the Anaplan Export Structure."
|
154
|
+
)
|
155
|
+
|
156
|
+
|
157
|
+
class Module(BaseModel):
|
158
|
+
id: int = Field(description="The unique identifier of this module.")
|
159
|
+
name: str = Field(description="The name of this module.")
|
160
|
+
|
161
|
+
|
162
|
+
class ModelStatus(BaseModel):
|
163
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
164
|
+
peak_memory_usage_estimate: int | None = Field(
|
165
|
+
description="The peak memory usage estimate of this model."
|
166
|
+
)
|
167
|
+
peak_memory_usage_time: int | None = Field(
|
168
|
+
description="The peak memory usage time of this model."
|
169
|
+
)
|
170
|
+
progress: float = Field(description="The progress of this model.")
|
171
|
+
current_step: str = Field(description="The current step of this model.")
|
172
|
+
tooltip: str | None = Field(description="The tooltip of this model.")
|
173
|
+
task_id: str | None = Field(description="The unique identifier of the task of this model.")
|
174
|
+
creation_time: int = Field(description="The creation time of this model.")
|
175
|
+
export_task_type: str | None = Field(description="The export task type of this model.")
|
176
|
+
|
177
|
+
|
178
|
+
class LineItem(BaseModel):
|
179
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
180
|
+
id: int = Field(description="The unique identifier of this line item.")
|
181
|
+
name: str = Field(description="The name of this line item.")
|
182
|
+
module_id: int = Field(
|
183
|
+
description="The unique identifier of the module this line item belongs to."
|
184
|
+
)
|
185
|
+
module_name: str = Field(description="The name of the module this line item belongs to.")
|
186
|
+
format: str = Field(description="The format of this line item.")
|
187
|
+
format_metadata: dict = Field(description="The format metadata of this line item.")
|
188
|
+
summary: str = Field(description="The summary of this line item.")
|
189
|
+
applies_to: list[dict] = Field([], description="The applies to value of this line item.")
|
190
|
+
time_scale: str = Field(description="The time scale of this line item.")
|
191
|
+
time_range: str = Field(description="The time range of this line item.")
|
192
|
+
version: dict = Field(description="The version of this line item.")
|
193
|
+
style: str = Field(description="The style of this line item.")
|
194
|
+
cell_count: int | None = Field(None, description="The cell count of this line item.")
|
195
|
+
notes: str = Field(description="The notes of this line item.")
|
196
|
+
is_summary: bool = Field(description="Whether this line item is a summary or not.")
|
197
|
+
formula: str | None = Field(None, description="The formula of this line item.")
|
198
|
+
formula_scope: str = Field(description="The formula scope of this line item.")
|
199
|
+
use_switchover: bool = Field(description="Whether the switchover is used or not.")
|
200
|
+
breakback: bool = Field(description="Whether the breakback is enabled or not.")
|
201
|
+
brought_forward: bool = Field(description="Whether the brought forward is enabled or not.")
|
202
|
+
start_of_section: bool = Field(
|
203
|
+
description="Whether this line item is the start of a section or not."
|
204
|
+
)
|
205
|
+
|
206
|
+
|
207
|
+
class Failure(BaseModel):
|
208
|
+
model_config = ConfigDict(populate_by_name=True)
|
209
|
+
index: int = Field(
|
210
|
+
validation_alias="requestIndex", description="The index of the item that failed."
|
211
|
+
)
|
212
|
+
reason: str = Field(validation_alias="failureType", description="The reason for the failure.")
|
213
|
+
details: str = Field(
|
214
|
+
validation_alias="failureMessageDetails", description="The details of the failure."
|
215
|
+
)
|
216
|
+
|
217
|
+
|
218
|
+
class InsertionResult(BaseModel):
|
219
|
+
added: int = Field(description="The number of items successfully added.")
|
220
|
+
ignored: int = Field(description="The number of items ignored, or items that failed.")
|
221
|
+
total: int = Field(description="The total number of items.")
|
222
|
+
failures: list[Failure] = Field([], description="The list of failures.")
|
223
|
+
|
224
|
+
|
225
|
+
class Revision(BaseModel):
|
226
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
227
|
+
id: str = Field(description="The unique identifier of this revision.")
|
228
|
+
name: str = Field(description="The name of this revision.")
|
229
|
+
description: str | None = Field(
|
230
|
+
None, description="The description of this revision. Not always present."
|
231
|
+
)
|
232
|
+
created_on: str = Field(description="The creation date of this revision in ISO format.")
|
233
|
+
created_by: str = Field(
|
234
|
+
description="The unique identifier of the user who created this revision."
|
235
|
+
)
|
236
|
+
creation_method: str = Field(description="The creation method of this revision.")
|
237
|
+
applied_on: str = Field(description="The application date of this revision in ISO format.")
|
238
|
+
applied_by: str = Field(
|
239
|
+
description="The unique identifier of the user who applied this revision."
|
240
|
+
)
|
241
|
+
|
242
|
+
|
243
|
+
class ModelRevision(BaseModel):
|
244
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
245
|
+
id: str = Field(
|
246
|
+
validation_alias="modelId",
|
247
|
+
description="The unique identifier of the model this revision belongs to.",
|
248
|
+
)
|
249
|
+
name: str = Field(
|
250
|
+
validation_alias="modelName", description="The name of the model this revision belongs to."
|
251
|
+
)
|
252
|
+
workspace_id: str = Field(
|
253
|
+
description="The unique identifier of the workspace this revision belongs to."
|
254
|
+
)
|
255
|
+
applied_by: str = Field(
|
256
|
+
description="The unique identifier of the user who applied this revision."
|
257
|
+
)
|
258
|
+
applied_on: str = Field(description="The application date of this revision in ISO format.")
|
259
|
+
applied_method: str = Field(description="The application method of this revision.")
|
260
|
+
deleted: bool | None = Field(
|
261
|
+
None,
|
262
|
+
validation_alias="modelDeleted",
|
263
|
+
description="Whether the model has been deleted or not.",
|
264
|
+
)
|
265
|
+
|
266
|
+
|
267
|
+
class SyncTask(BaseModel):
|
268
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
269
|
+
id: str = Field(validation_alias="taskId", description="The unique identifier of this task.")
|
270
|
+
task_state: str = Field(description="The state of this task.")
|
271
|
+
creation_time: int = Field(description="The creation time of this task.")
|
272
|
+
|
273
|
+
|
274
|
+
class User(BaseModel):
|
275
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
276
|
+
id: str = Field(description="The unique identifier of this user.")
|
277
|
+
active: bool = Field(description="Whether this user is active or not.")
|
278
|
+
email: str = Field(description="The email address of this user.")
|
279
|
+
email_opt_in: bool = Field(
|
280
|
+
description="Whether this user has opted in to receive emails or not."
|
281
|
+
)
|
282
|
+
first_name: str = Field(description="The first name of this user.")
|
283
|
+
last_name: str = Field(description="The last name of this user.")
|
284
|
+
last_login_date: str | None = Field(
|
285
|
+
None, description="The last login date of this user in ISO format."
|
286
|
+
)
|
287
|
+
|
288
|
+
|
289
|
+
class TaskSummary(BaseModel):
|
290
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
291
|
+
id: str = Field(validation_alias="taskId", description="The unique identifier of this task.")
|
292
|
+
task_state: Literal["NOT_STARTED", "IN_PROGRESS", "COMPLETE"] = Field(
|
293
|
+
description="The state of this task."
|
294
|
+
)
|
295
|
+
creation_time: int = Field(description="Unix timestamp of when this task was created.")
|
296
|
+
|
297
|
+
|
298
|
+
class TaskResultDetail(BaseModel):
|
299
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
300
|
+
local_message_text: str = Field(description="Error message text.")
|
301
|
+
occurrences: int = Field(0, description="The number of occurrences of this error.")
|
302
|
+
type: str = Field(description="The type of this error.")
|
303
|
+
values: list[str] = Field([], description="Further error information if available.")
|
304
|
+
|
305
|
+
|
306
|
+
class TaskResult(BaseModel):
|
307
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
308
|
+
details: list[TaskResultDetail] = Field(
|
309
|
+
[], description="The details of this task result if available."
|
310
|
+
)
|
311
|
+
successful: bool = Field(description="Whether this task completed successfully or not.")
|
312
|
+
failure_dump_available: bool = Field(
|
313
|
+
description="Whether this task completed successfully or not."
|
314
|
+
)
|
315
|
+
nested_results: list["TaskResult"] = Field(
|
316
|
+
[], description="The nested results of this task, if available."
|
317
|
+
)
|
318
|
+
|
319
|
+
|
320
|
+
class TaskStatus(BaseModel):
|
321
|
+
model_config = ConfigDict(alias_generator=to_camel, populate_by_name=True)
|
322
|
+
id: str = Field(validation_alias="taskId", description="The unique identifier of this task.")
|
323
|
+
task_state: Literal["NOT_STARTED", "IN_PROGRESS", "COMPLETE"] = Field(
|
324
|
+
description="The state of this task."
|
325
|
+
)
|
326
|
+
creation_time: int = Field(description="Unix timestamp of when this task was created.")
|
327
|
+
progress: float = Field(description="The progress of this task as a float between 0 and 1.")
|
328
|
+
current_step: str | None = Field(None, description="The current step of this task.")
|
329
|
+
result: TaskResult | None = Field(None)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
!!! note
|
2
|
-
This Class is not meant to be instantiated directly, but rather accessed through the `
|
2
|
+
This Class is not meant to be instantiated directly, but rather accessed through the `transactional` Property on an
|
3
3
|
instance of [AsyncClient](async_client.md). For more details, see the [Guide](../guides/transactional.md).
|
4
4
|
|
5
|
-
::: anaplan_sdk._async_clients.
|
5
|
+
::: anaplan_sdk._async_clients._AsyncTransactionalClient
|