anaplan-sdk 0.3.0__tar.gz → 0.3.1b1__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.3.0 → anaplan_sdk-0.3.1b1}/PKG-INFO +1 -1
- anaplan_sdk-0.3.1b1/anaplan_sdk/_async_clients/_audit.py +42 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/anaplan_sdk/_async_clients/_bulk.py +15 -13
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/anaplan_sdk/_async_clients/_transactional.py +2 -2
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/anaplan_sdk/_base.py +60 -9
- anaplan_sdk-0.3.1b1/anaplan_sdk/_clients/_audit.py +43 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/anaplan_sdk/_clients/_bulk.py +12 -10
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/anaplan_sdk/_clients/_transactional.py +5 -3
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/pyproject.toml +88 -88
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/uv.lock +1152 -1152
- anaplan_sdk-0.3.0/anaplan_sdk/_async_clients/_audit.py +0 -87
- anaplan_sdk-0.3.0/anaplan_sdk/_clients/_audit.py +0 -86
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/.github/dependabot.yml +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/.github/workflows/docs.yml +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/.github/workflows/lint.yml +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/.github/workflows/tests.yml +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/.gitignore +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/.pre-commit-config.yaml +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/LICENSE +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/README.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/anaplan_sdk/__init__.py +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/anaplan_sdk/_async_clients/__init__.py +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/anaplan_sdk/_async_clients/_alm.py +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/anaplan_sdk/_auth.py +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/anaplan_sdk/_clients/__init__.py +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/anaplan_sdk/_clients/_alm.py +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/anaplan_sdk/exceptions.py +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/anaplan_sdk/models.py +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/anaplan_explained.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/api/alm_client.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/api/async_alm_client.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/api/async_audit_client.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/api/async_client.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/api/async_transactional_client.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/api/audit_client.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/api/client.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/api/exceptions.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/api/models.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/api/transactional_client.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/css/styles.css +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/guides/alm.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/guides/audit.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/guides/bulk.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/guides/bulk_vs_transactional.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/guides/logging.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/guides/multiple_models.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/guides/transactional.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/img/anaplan-overview.webp +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/img/anaplan-sdk.webp +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/index.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/installation.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/js/assets/hljs.js +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/js/assets/python.js +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/js/highlight.js +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/docs/quickstart.md +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/mkdocs.yml +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/tests/async/conftest.py +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/tests/async/test_async_alm_client.py +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/tests/async/test_async_audit_client.py +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/tests/async/test_async_client.py +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/tests/async/test_async_transactional_client.py +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/tests/conftest.py +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/tests/sync/conftest.py +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/tests/sync/test_alm_client.py +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/tests/sync/test_audit_client.py +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/tests/sync/test_client.py +0 -0
- {anaplan_sdk-0.3.0 → anaplan_sdk-0.3.1b1}/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.
|
3
|
+
Version: 0.3.1b1
|
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
|
@@ -0,0 +1,42 @@
|
|
1
|
+
from typing import Literal
|
2
|
+
|
3
|
+
import httpx
|
4
|
+
|
5
|
+
from anaplan_sdk._base import _AsyncBaseClient
|
6
|
+
from anaplan_sdk.models import User
|
7
|
+
|
8
|
+
Event = Literal["all", "byok", "user_activity"]
|
9
|
+
|
10
|
+
|
11
|
+
class _AsyncAuditClient(_AsyncBaseClient):
|
12
|
+
def __init__(self, client: httpx.AsyncClient, retry_count: int) -> None:
|
13
|
+
self._client = client
|
14
|
+
self._limit = 10_000
|
15
|
+
self._url = "https://audit.anaplan.com/audit/api/1/events"
|
16
|
+
super().__init__(retry_count, client)
|
17
|
+
|
18
|
+
async def list_users(self) -> list[User]:
|
19
|
+
"""
|
20
|
+
Lists all the Users in the authenticated users default tenant.
|
21
|
+
:return: The List of Users.
|
22
|
+
"""
|
23
|
+
return [
|
24
|
+
User.model_validate(e)
|
25
|
+
for e in await self._get_paginated("https://api.anaplan.com/2/0/users", "users")
|
26
|
+
]
|
27
|
+
|
28
|
+
async def get_events(self, days_into_past: int = 30, event_type: Event = "all") -> list:
|
29
|
+
"""
|
30
|
+
Get audit events from Anaplan Audit API.
|
31
|
+
:param days_into_past: The nuber of days into the past to get events for. The API provides
|
32
|
+
data for up to 30 days.
|
33
|
+
:param event_type: The type of events to get.
|
34
|
+
:return: A list of audit events.
|
35
|
+
"""
|
36
|
+
return list(
|
37
|
+
await self._get_paginated(
|
38
|
+
self._url,
|
39
|
+
"response",
|
40
|
+
params={"type": event_type, "intervalInHours": days_into_past * 24},
|
41
|
+
)
|
42
|
+
)
|
@@ -191,9 +191,11 @@ class AsyncClient(_AsyncBaseClient):
|
|
191
191
|
"""
|
192
192
|
return [
|
193
193
|
Workspace.model_validate(e)
|
194
|
-
for e in (
|
195
|
-
|
196
|
-
|
194
|
+
for e in await self._get_paginated(
|
195
|
+
"https://api.anaplan.com/2/0/workspaces",
|
196
|
+
"workspaces",
|
197
|
+
params={"tenantDetails": "true"},
|
198
|
+
)
|
197
199
|
]
|
198
200
|
|
199
201
|
async def list_models(self) -> list[Model]:
|
@@ -203,8 +205,8 @@ class AsyncClient(_AsyncBaseClient):
|
|
203
205
|
"""
|
204
206
|
return [
|
205
207
|
Model.model_validate(e)
|
206
|
-
for e in
|
207
|
-
"models",
|
208
|
+
for e in await self._get_paginated(
|
209
|
+
"https://api.anaplan.com/2/0/models", "models", params={"modelDetails": "true"}
|
208
210
|
)
|
209
211
|
]
|
210
212
|
|
@@ -214,7 +216,7 @@ class AsyncClient(_AsyncBaseClient):
|
|
214
216
|
:return: The List of Files.
|
215
217
|
"""
|
216
218
|
return [
|
217
|
-
File.model_validate(e) for e in
|
219
|
+
File.model_validate(e) for e in await self._get_paginated(f"{self._url}/files", "files")
|
218
220
|
]
|
219
221
|
|
220
222
|
async def list_actions(self) -> list[Action]:
|
@@ -226,7 +228,7 @@ class AsyncClient(_AsyncBaseClient):
|
|
226
228
|
"""
|
227
229
|
return [
|
228
230
|
Action.model_validate(e)
|
229
|
-
for e in
|
231
|
+
for e in await self._get_paginated(f"{self._url}/actions", "actions")
|
230
232
|
]
|
231
233
|
|
232
234
|
async def list_processes(self) -> list[Process]:
|
@@ -236,7 +238,7 @@ class AsyncClient(_AsyncBaseClient):
|
|
236
238
|
"""
|
237
239
|
return [
|
238
240
|
Process.model_validate(e)
|
239
|
-
for e in
|
241
|
+
for e in await self._get_paginated(f"{self._url}/processes", "processes")
|
240
242
|
]
|
241
243
|
|
242
244
|
async def list_imports(self) -> list[Import]:
|
@@ -246,7 +248,7 @@ class AsyncClient(_AsyncBaseClient):
|
|
246
248
|
"""
|
247
249
|
return [
|
248
250
|
Import.model_validate(e)
|
249
|
-
for e in
|
251
|
+
for e in await self._get_paginated(f"{self._url}/imports", "imports")
|
250
252
|
]
|
251
253
|
|
252
254
|
async def list_exports(self) -> list[Export]:
|
@@ -256,7 +258,7 @@ class AsyncClient(_AsyncBaseClient):
|
|
256
258
|
"""
|
257
259
|
return [
|
258
260
|
Export.model_validate(e)
|
259
|
-
for e in
|
261
|
+
for e in await self._get_paginated(f"{self._url}/exports", "exports")
|
260
262
|
]
|
261
263
|
|
262
264
|
async def run_action(self, action_id: int) -> TaskStatus:
|
@@ -406,9 +408,9 @@ class AsyncClient(_AsyncBaseClient):
|
|
406
408
|
"""
|
407
409
|
return [
|
408
410
|
TaskSummary.model_validate(e)
|
409
|
-
for e in (
|
410
|
-
|
411
|
-
)
|
411
|
+
for e in await self._get_paginated(
|
412
|
+
f"{self._url}/{action_url(action_id)}/{action_id}/tasks", "tasks"
|
413
|
+
)
|
412
414
|
]
|
413
415
|
|
414
416
|
async def get_task_status(self, action_id: int, task_id: str) -> TaskStatus:
|
@@ -32,7 +32,7 @@ class _AsyncTransactionalClient(_AsyncBaseClient):
|
|
32
32
|
"""
|
33
33
|
return [
|
34
34
|
Module.model_validate(e)
|
35
|
-
for e in
|
35
|
+
for e in await self._get_paginated(f"{self._url}/modules", "modules")
|
36
36
|
]
|
37
37
|
|
38
38
|
async def get_model_status(self) -> ModelStatus:
|
@@ -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
|
66
|
+
List.model_validate(e) for e in await self._get_paginated(f"{self._url}/lists", "lists")
|
67
67
|
]
|
68
68
|
|
69
69
|
async def get_list_metadata(self, list_id: int) -> ListMetadata:
|
@@ -6,8 +6,12 @@ import asyncio
|
|
6
6
|
import logging
|
7
7
|
import random
|
8
8
|
import time
|
9
|
+
from asyncio import gather
|
10
|
+
from concurrent.futures import ThreadPoolExecutor
|
9
11
|
from gzip import compress
|
10
|
-
from
|
12
|
+
from itertools import chain
|
13
|
+
from math import ceil
|
14
|
+
from typing import Any, Callable, Coroutine, Iterator, Literal
|
11
15
|
|
12
16
|
import httpx
|
13
17
|
from httpx import HTTPError, Response
|
@@ -26,15 +30,13 @@ class _BaseClient:
|
|
26
30
|
self._retry_count = retry_count
|
27
31
|
self._client = client
|
28
32
|
|
29
|
-
def _get(self, url: str, **kwargs) -> dict[str,
|
33
|
+
def _get(self, url: str, **kwargs) -> dict[str, Any]:
|
30
34
|
return self._run_with_retry(self._client.get, url, **kwargs).json()
|
31
35
|
|
32
36
|
def _get_binary(self, url: str) -> bytes:
|
33
37
|
return self._run_with_retry(self._client.get, url).content
|
34
38
|
|
35
|
-
def _post(
|
36
|
-
self, url: str, json: dict | list
|
37
|
-
) -> dict[str, float | int | str | list | dict | bool]:
|
39
|
+
def _post(self, url: str, json: dict | list) -> dict[str, Any]:
|
38
40
|
return self._run_with_retry(
|
39
41
|
self._client.post, url, headers={"Content-Type": "application/json"}, json=json
|
40
42
|
).json()
|
@@ -50,6 +52,30 @@ class _BaseClient:
|
|
50
52
|
content=compress(content),
|
51
53
|
)
|
52
54
|
|
55
|
+
def __get_page(self, url: str, limit: int, offset: int, result_key: str, **kwargs) -> list:
|
56
|
+
kwargs["params"] = kwargs.get("params", {}) | {"limit": limit, "offset": offset}
|
57
|
+
return self._get(url, **kwargs).get(result_key, [])
|
58
|
+
|
59
|
+
def __get_first_page(self, url: str, limit: int, result_key: str, **kwargs) -> tuple[list, int]:
|
60
|
+
kwargs["params"] = kwargs.get("params", {}) | {"limit": limit}
|
61
|
+
res = self._get(url, **kwargs)
|
62
|
+
return res.get(result_key, []), res["meta"]["paging"]["totalSize"]
|
63
|
+
|
64
|
+
def _get_paginated(
|
65
|
+
self, url: str, result_key: str, page_size: int = 5_000, **kwargs
|
66
|
+
) -> Iterator[dict[str, Any]]:
|
67
|
+
first_page, total_items = self.__get_first_page(url, page_size, result_key, **kwargs)
|
68
|
+
if total_items <= page_size:
|
69
|
+
return iter(first_page)
|
70
|
+
|
71
|
+
with ThreadPoolExecutor() as executor:
|
72
|
+
pages = executor.map(
|
73
|
+
lambda n: self.__get_page(url, page_size, n * page_size, result_key, **kwargs),
|
74
|
+
range(1, ceil(total_items / page_size)),
|
75
|
+
)
|
76
|
+
|
77
|
+
return chain(first_page, *pages)
|
78
|
+
|
53
79
|
def _run_with_retry(self, func: Callable[..., Response], *args, **kwargs) -> Response:
|
54
80
|
for i in range(max(self._retry_count, 1)):
|
55
81
|
try:
|
@@ -77,15 +103,13 @@ class _AsyncBaseClient:
|
|
77
103
|
self._retry_count = retry_count
|
78
104
|
self._client = client
|
79
105
|
|
80
|
-
async def _get(self, url: str, **kwargs) -> dict[str,
|
106
|
+
async def _get(self, url: str, **kwargs) -> dict[str, Any]:
|
81
107
|
return (await self._run_with_retry(self._client.get, url, **kwargs)).json()
|
82
108
|
|
83
109
|
async def _get_binary(self, url: str) -> bytes:
|
84
110
|
return (await self._run_with_retry(self._client.get, url)).content
|
85
111
|
|
86
|
-
async def _post(
|
87
|
-
self, url: str, json: dict | list
|
88
|
-
) -> dict[str, float | int | str | list | dict | bool]:
|
112
|
+
async def _post(self, url: str, json: dict | list) -> dict[str, Any]:
|
89
113
|
return (
|
90
114
|
await self._run_with_retry(
|
91
115
|
self._client.post, url, headers={"Content-Type": "application/json"}, json=json
|
@@ -103,6 +127,33 @@ class _AsyncBaseClient:
|
|
103
127
|
content=compress(content),
|
104
128
|
)
|
105
129
|
|
130
|
+
async def __get_page(
|
131
|
+
self, url: str, limit: int, offset: int, result_key: str, **kwargs
|
132
|
+
) -> list:
|
133
|
+
kwargs["params"] = kwargs.get("params", {}) | {"limit": limit, "offset": offset}
|
134
|
+
return (await self._get(url, **kwargs)).get(result_key, [])
|
135
|
+
|
136
|
+
async def __get_first_page(
|
137
|
+
self, url: str, limit: int, result_key: str, **kwargs
|
138
|
+
) -> tuple[list, int]:
|
139
|
+
kwargs["params"] = kwargs.get("params", {}) | {"limit": limit}
|
140
|
+
res = await self._get(url, **kwargs)
|
141
|
+
return res.get(result_key, []), res["meta"]["paging"]["totalSize"]
|
142
|
+
|
143
|
+
async def _get_paginated(
|
144
|
+
self, url: str, result_key: str, page_size: int = 5_000, **kwargs
|
145
|
+
) -> Iterator[dict[str, Any]]:
|
146
|
+
first_page, total_items = await self.__get_first_page(url, page_size, result_key, **kwargs)
|
147
|
+
if total_items <= page_size:
|
148
|
+
return iter(first_page)
|
149
|
+
pages = await gather(
|
150
|
+
*(
|
151
|
+
self.__get_page(url, page_size, n * page_size, result_key, **kwargs)
|
152
|
+
for n in range(1, ceil(total_items / page_size))
|
153
|
+
)
|
154
|
+
)
|
155
|
+
return chain(first_page, *pages)
|
156
|
+
|
106
157
|
async def _run_with_retry(
|
107
158
|
self, func: Callable[..., Coroutine[Any, Any, Response]], *args, **kwargs
|
108
159
|
) -> Response:
|
@@ -0,0 +1,43 @@
|
|
1
|
+
from typing import Literal
|
2
|
+
|
3
|
+
import httpx
|
4
|
+
|
5
|
+
from anaplan_sdk._base import _BaseClient
|
6
|
+
from anaplan_sdk.models import User
|
7
|
+
|
8
|
+
Event = Literal["all", "byok", "user_activity"]
|
9
|
+
|
10
|
+
|
11
|
+
class _AuditClient(_BaseClient):
|
12
|
+
def __init__(self, client: httpx.Client, retry_count: int, thread_count: int) -> None:
|
13
|
+
self._client = client
|
14
|
+
self._limit = 10_000
|
15
|
+
self._thread_count = thread_count
|
16
|
+
self._url = "https://audit.anaplan.com/audit/api/1/events"
|
17
|
+
super().__init__(retry_count, client)
|
18
|
+
|
19
|
+
def list_users(self) -> list[User]:
|
20
|
+
"""
|
21
|
+
Lists all the Users in the authenticated users default tenant.
|
22
|
+
:return: The List of Users.
|
23
|
+
"""
|
24
|
+
return [
|
25
|
+
User.model_validate(e)
|
26
|
+
for e in self._get_paginated("https://api.anaplan.com/2/0/users", "users")
|
27
|
+
]
|
28
|
+
|
29
|
+
def get_events(self, days_into_past: int = 30, event_type: Event = "all") -> list:
|
30
|
+
"""
|
31
|
+
Get audit events from Anaplan Audit API.
|
32
|
+
:param days_into_past: The nuber of days into the past to get events for. The API provides
|
33
|
+
data for up to 30 days.
|
34
|
+
:param event_type: The type of events to get.
|
35
|
+
:return: A list of audit events.
|
36
|
+
"""
|
37
|
+
return list(
|
38
|
+
self._get_paginated(
|
39
|
+
self._url,
|
40
|
+
"response",
|
41
|
+
params={"type": event_type, "intervalInHours": days_into_past * 24},
|
42
|
+
)
|
43
|
+
)
|
@@ -199,8 +199,10 @@ class Client(_BaseClient):
|
|
199
199
|
"""
|
200
200
|
return [
|
201
201
|
Workspace.model_validate(e)
|
202
|
-
for e in self.
|
203
|
-
"workspaces",
|
202
|
+
for e in self._get_paginated(
|
203
|
+
"https://api.anaplan.com/2/0/workspaces",
|
204
|
+
"workspaces",
|
205
|
+
params={"tenantDetails": "true"},
|
204
206
|
)
|
205
207
|
]
|
206
208
|
|
@@ -211,8 +213,8 @@ class Client(_BaseClient):
|
|
211
213
|
"""
|
212
214
|
return [
|
213
215
|
Model.model_validate(e)
|
214
|
-
for e in self.
|
215
|
-
"models",
|
216
|
+
for e in self._get_paginated(
|
217
|
+
"https://api.anaplan.com/2/0/models", "models", params={"modelDetails": "true"}
|
216
218
|
)
|
217
219
|
]
|
218
220
|
|
@@ -221,7 +223,7 @@ class Client(_BaseClient):
|
|
221
223
|
Lists all the Files in the Model.
|
222
224
|
:return: The List of Files.
|
223
225
|
"""
|
224
|
-
return [File.model_validate(e) for e in self.
|
226
|
+
return [File.model_validate(e) for e in self._get_paginated(f"{self._url}/files", "files")]
|
225
227
|
|
226
228
|
def list_actions(self) -> list[Action]:
|
227
229
|
"""
|
@@ -231,7 +233,7 @@ class Client(_BaseClient):
|
|
231
233
|
:return: The List of Actions.
|
232
234
|
"""
|
233
235
|
return [
|
234
|
-
Action.model_validate(e) for e in
|
236
|
+
Action.model_validate(e) for e in self._get_paginated(f"{self._url}/actions", "actions")
|
235
237
|
]
|
236
238
|
|
237
239
|
def list_processes(self) -> list[Process]:
|
@@ -241,7 +243,7 @@ class Client(_BaseClient):
|
|
241
243
|
"""
|
242
244
|
return [
|
243
245
|
Process.model_validate(e)
|
244
|
-
for e in
|
246
|
+
for e in self._get_paginated(f"{self._url}/processes", "processes")
|
245
247
|
]
|
246
248
|
|
247
249
|
def list_imports(self) -> list[Import]:
|
@@ -250,7 +252,7 @@ class Client(_BaseClient):
|
|
250
252
|
:return: The List of Imports.
|
251
253
|
"""
|
252
254
|
return [
|
253
|
-
Import.model_validate(e) for e in
|
255
|
+
Import.model_validate(e) for e in self._get_paginated(f"{self._url}/imports", "imports")
|
254
256
|
]
|
255
257
|
|
256
258
|
def list_exports(self) -> list[Export]:
|
@@ -400,8 +402,8 @@ class Client(_BaseClient):
|
|
400
402
|
"""
|
401
403
|
return [
|
402
404
|
TaskSummary.model_validate(e)
|
403
|
-
for e in self.
|
404
|
-
"tasks",
|
405
|
+
for e in self._get_paginated(
|
406
|
+
f"{self._url}/{action_url(action_id)}/{action_id}/tasks", "tasks"
|
405
407
|
)
|
406
408
|
]
|
407
409
|
|
@@ -28,7 +28,9 @@ class _TransactionalClient(_BaseClient):
|
|
28
28
|
Lists all the Modules in the Model.
|
29
29
|
:return: The List of Modules.
|
30
30
|
"""
|
31
|
-
return [
|
31
|
+
return [
|
32
|
+
Module.model_validate(e) for e in self._get_paginated(f"{self._url}/modules", "modules")
|
33
|
+
]
|
32
34
|
|
33
35
|
def get_model_status(self) -> ModelStatus:
|
34
36
|
"""
|
@@ -53,9 +55,9 @@ class _TransactionalClient(_BaseClient):
|
|
53
55
|
def list_lists(self) -> list[List]:
|
54
56
|
"""
|
55
57
|
Lists all the Lists in the Model.
|
56
|
-
:return: All Lists on this
|
58
|
+
:return: All Lists on this model.
|
57
59
|
"""
|
58
|
-
return [List.model_validate(e) for e in self.
|
60
|
+
return [List.model_validate(e) for e in self._get_paginated(f"{self._url}/lists", "lists")]
|
59
61
|
|
60
62
|
def get_list_metadata(self, list_id: int) -> ListMetadata:
|
61
63
|
"""
|
@@ -1,88 +1,88 @@
|
|
1
|
-
[project]
|
2
|
-
name = "anaplan-sdk"
|
3
|
-
version = "0.3.
|
4
|
-
description = "Provides pythonic access to the Anaplan API"
|
5
|
-
license = "Apache-2.0"
|
6
|
-
authors = [{ name = "Vinzenz Klass", email = "vinzenz.klass@valantic.com" }]
|
7
|
-
readme = "README.md"
|
8
|
-
keywords = ["anaplan", "anaplan api", "anaplan bulk api", "anaplan integration", "anaplan alm api", "anaplan audit api"]
|
9
|
-
requires-python = ">=3.10.4"
|
10
|
-
dependencies = [
|
11
|
-
"pydantic>=2.7.2,<3.0.0",
|
12
|
-
"httpx>=0.27.0,<1.0.0",
|
13
|
-
"cryptography>=42.0.7,<45.0.0"
|
14
|
-
]
|
15
|
-
|
16
|
-
[dependency-groups]
|
17
|
-
dev = [
|
18
|
-
"ruff>=0.9.2",
|
19
|
-
"pre-commit>=4.0.1",
|
20
|
-
"pytest>=8.3.3",
|
21
|
-
"pytest-asyncio>=0.26.0",
|
22
|
-
"pytest-xdist>=3.6.1",
|
23
|
-
"mkdocs>=1.6.1",
|
24
|
-
"mkdocs-material>=9.5.41",
|
25
|
-
"mkdocstrings[python]>=0.26.2",
|
26
|
-
"polars>=1.25.2",
|
27
|
-
"griffe-fieldz>=0.2.1",
|
28
|
-
]
|
29
|
-
|
30
|
-
[project.urls]
|
31
|
-
Homepage = "https://vinzenzklass.github.io/anaplan-sdk/"
|
32
|
-
Repository = "https://github.com/VinzenzKlass/anaplan-sdk"
|
33
|
-
Documentation = "https://vinzenzklass.github.io/anaplan-sdk/"
|
34
|
-
|
35
|
-
[build-system]
|
36
|
-
requires = ["hatchling"]
|
37
|
-
build-backend = "hatchling.build"
|
38
|
-
|
39
|
-
[tool.ruff]
|
40
|
-
exclude = [
|
41
|
-
".bzr",
|
42
|
-
".direnv",
|
43
|
-
".eggs",
|
44
|
-
".git",
|
45
|
-
".git-rewrite",
|
46
|
-
".hg",
|
47
|
-
".ipynb_checkpoints",
|
48
|
-
".mypy_cache",
|
49
|
-
".nox",
|
50
|
-
".pants.d",
|
51
|
-
".pyenv",
|
52
|
-
".pytest_cache",
|
53
|
-
".pytype",
|
54
|
-
".ruff_cache",
|
55
|
-
".svn",
|
56
|
-
".tox",
|
57
|
-
".venv",
|
58
|
-
".vscode",
|
59
|
-
"__pypackages__",
|
60
|
-
"_build",
|
61
|
-
"buck-out",
|
62
|
-
"build",
|
63
|
-
"dist",
|
64
|
-
"node_modules",
|
65
|
-
"site-packages",
|
66
|
-
"venv",
|
67
|
-
]
|
68
|
-
|
69
|
-
line-length = 100
|
70
|
-
fix = true
|
71
|
-
target-version = "py312"
|
72
|
-
|
73
|
-
[tool.ruff.format]
|
74
|
-
skip-magic-trailing-comma = false
|
75
|
-
|
76
|
-
[tool.ruff.lint]
|
77
|
-
select = ["E", "F", "B", "I"]
|
78
|
-
|
79
|
-
[tool.pytest.ini_options]
|
80
|
-
asyncio_mode = "auto"
|
81
|
-
asyncio_default_fixture_loop_scope = "session"
|
82
|
-
asyncio_default_test_loop_scope = "session"
|
83
|
-
minversion = "8.0"
|
84
|
-
addopts = "-ra -q"
|
85
|
-
pythonpath = "anaplan_sdk/"
|
86
|
-
testpaths = [
|
87
|
-
"tests",
|
88
|
-
]
|
1
|
+
[project]
|
2
|
+
name = "anaplan-sdk"
|
3
|
+
version = "0.3.1b1"
|
4
|
+
description = "Provides pythonic access to the Anaplan API"
|
5
|
+
license = "Apache-2.0"
|
6
|
+
authors = [{ name = "Vinzenz Klass", email = "vinzenz.klass@valantic.com" }]
|
7
|
+
readme = "README.md"
|
8
|
+
keywords = ["anaplan", "anaplan api", "anaplan bulk api", "anaplan integration", "anaplan alm api", "anaplan audit api"]
|
9
|
+
requires-python = ">=3.10.4"
|
10
|
+
dependencies = [
|
11
|
+
"pydantic>=2.7.2,<3.0.0",
|
12
|
+
"httpx>=0.27.0,<1.0.0",
|
13
|
+
"cryptography>=42.0.7,<45.0.0"
|
14
|
+
]
|
15
|
+
|
16
|
+
[dependency-groups]
|
17
|
+
dev = [
|
18
|
+
"ruff>=0.9.2",
|
19
|
+
"pre-commit>=4.0.1",
|
20
|
+
"pytest>=8.3.3",
|
21
|
+
"pytest-asyncio>=0.26.0",
|
22
|
+
"pytest-xdist>=3.6.1",
|
23
|
+
"mkdocs>=1.6.1",
|
24
|
+
"mkdocs-material>=9.5.41",
|
25
|
+
"mkdocstrings[python]>=0.26.2",
|
26
|
+
"polars>=1.25.2",
|
27
|
+
"griffe-fieldz>=0.2.1",
|
28
|
+
]
|
29
|
+
|
30
|
+
[project.urls]
|
31
|
+
Homepage = "https://vinzenzklass.github.io/anaplan-sdk/"
|
32
|
+
Repository = "https://github.com/VinzenzKlass/anaplan-sdk"
|
33
|
+
Documentation = "https://vinzenzklass.github.io/anaplan-sdk/"
|
34
|
+
|
35
|
+
[build-system]
|
36
|
+
requires = ["hatchling"]
|
37
|
+
build-backend = "hatchling.build"
|
38
|
+
|
39
|
+
[tool.ruff]
|
40
|
+
exclude = [
|
41
|
+
".bzr",
|
42
|
+
".direnv",
|
43
|
+
".eggs",
|
44
|
+
".git",
|
45
|
+
".git-rewrite",
|
46
|
+
".hg",
|
47
|
+
".ipynb_checkpoints",
|
48
|
+
".mypy_cache",
|
49
|
+
".nox",
|
50
|
+
".pants.d",
|
51
|
+
".pyenv",
|
52
|
+
".pytest_cache",
|
53
|
+
".pytype",
|
54
|
+
".ruff_cache",
|
55
|
+
".svn",
|
56
|
+
".tox",
|
57
|
+
".venv",
|
58
|
+
".vscode",
|
59
|
+
"__pypackages__",
|
60
|
+
"_build",
|
61
|
+
"buck-out",
|
62
|
+
"build",
|
63
|
+
"dist",
|
64
|
+
"node_modules",
|
65
|
+
"site-packages",
|
66
|
+
"venv",
|
67
|
+
]
|
68
|
+
|
69
|
+
line-length = 100
|
70
|
+
fix = true
|
71
|
+
target-version = "py312"
|
72
|
+
|
73
|
+
[tool.ruff.format]
|
74
|
+
skip-magic-trailing-comma = false
|
75
|
+
|
76
|
+
[tool.ruff.lint]
|
77
|
+
select = ["E", "F", "B", "I"]
|
78
|
+
|
79
|
+
[tool.pytest.ini_options]
|
80
|
+
asyncio_mode = "auto"
|
81
|
+
asyncio_default_fixture_loop_scope = "session"
|
82
|
+
asyncio_default_test_loop_scope = "session"
|
83
|
+
minversion = "8.0"
|
84
|
+
addopts = "-ra -q"
|
85
|
+
pythonpath = "anaplan_sdk/"
|
86
|
+
testpaths = [
|
87
|
+
"tests",
|
88
|
+
]
|