anaplan-sdk 0.3.1b1__tar.gz → 0.4.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.
Files changed (115) hide show
  1. anaplan_sdk-0.4.0/.github/workflows/lint.yml +9 -0
  2. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/.github/workflows/tests.yml +3 -1
  3. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/.pre-commit-config.yaml +2 -2
  4. anaplan_sdk-0.4.0/PKG-INFO +87 -0
  5. anaplan_sdk-0.4.0/README.md +67 -0
  6. anaplan_sdk-0.4.0/anaplan_sdk/_async_clients/__init__.py +13 -0
  7. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/anaplan_sdk/_async_clients/_alm.py +1 -22
  8. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/anaplan_sdk/_async_clients/_audit.py +18 -3
  9. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/anaplan_sdk/_async_clients/_bulk.py +75 -28
  10. anaplan_sdk-0.4.0/anaplan_sdk/_async_clients/_cloud_works.py +344 -0
  11. anaplan_sdk-0.4.0/anaplan_sdk/_async_clients/_cw_flow.py +80 -0
  12. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/anaplan_sdk/_async_clients/_transactional.py +26 -30
  13. anaplan_sdk-0.4.0/anaplan_sdk/_auth.py +248 -0
  14. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/anaplan_sdk/_base.py +115 -30
  15. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/anaplan_sdk/_clients/_alm.py +1 -22
  16. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/anaplan_sdk/_clients/_audit.py +16 -3
  17. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/anaplan_sdk/_clients/_bulk.py +73 -32
  18. anaplan_sdk-0.4.0/anaplan_sdk/_clients/_cloud_works.py +342 -0
  19. anaplan_sdk-0.4.0/anaplan_sdk/_clients/_cw_flow.py +78 -0
  20. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/anaplan_sdk/_clients/_transactional.py +26 -26
  21. anaplan_sdk-0.4.0/anaplan_sdk/models/__init__.py +49 -0
  22. anaplan_sdk-0.4.0/anaplan_sdk/models/_alm.py +55 -0
  23. anaplan_sdk-0.4.0/anaplan_sdk/models/_base.py +12 -0
  24. anaplan_sdk-0.4.0/anaplan_sdk/models/_bulk.py +176 -0
  25. anaplan_sdk-0.4.0/anaplan_sdk/models/_transactional.py +94 -0
  26. anaplan_sdk-0.4.0/anaplan_sdk/models/cloud_works.py +474 -0
  27. anaplan_sdk-0.4.0/anaplan_sdk/models/flows.py +86 -0
  28. anaplan_sdk-0.4.0/docs/anaplan_explained.md +68 -0
  29. {anaplan_sdk-0.3.1b1/docs/api → anaplan_sdk-0.4.0/docs/api/async}/async_alm_client.md +2 -2
  30. {anaplan_sdk-0.3.1b1/docs/api → anaplan_sdk-0.4.0/docs/api/async}/async_audit_client.md +2 -2
  31. anaplan_sdk-0.4.0/docs/api/async/async_cw_client.md +5 -0
  32. anaplan_sdk-0.4.0/docs/api/async/async_flows_client.md +5 -0
  33. {anaplan_sdk-0.3.1b1/docs/api → anaplan_sdk-0.4.0/docs/api/async}/async_transactional_client.md +1 -1
  34. anaplan_sdk-0.3.1b1/docs/api/alm_client.md → anaplan_sdk-0.4.0/docs/api/sync/sync_alm_client.md +1 -1
  35. anaplan_sdk-0.3.1b1/docs/api/audit_client.md → anaplan_sdk-0.4.0/docs/api/sync/sync_audit_client.md +1 -1
  36. anaplan_sdk-0.4.0/docs/api/sync/sync_cw_client.md +5 -0
  37. anaplan_sdk-0.4.0/docs/api/sync/sync_flows_client.md +5 -0
  38. anaplan_sdk-0.3.1b1/docs/api/transactional_client.md → anaplan_sdk-0.4.0/docs/api/sync/sync_transactional_client.md +1 -1
  39. anaplan_sdk-0.4.0/docs/assets/overview.html +282 -0
  40. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/docs/css/styles.css +39 -11
  41. anaplan_sdk-0.4.0/docs/guides/alm.md +58 -0
  42. anaplan_sdk-0.4.0/docs/guides/audit.md +67 -0
  43. anaplan_sdk-0.4.0/docs/guides/authentication.md +205 -0
  44. anaplan_sdk-0.4.0/docs/guides/bulk.md +250 -0
  45. anaplan_sdk-0.4.0/docs/guides/cloud_works.md +307 -0
  46. anaplan_sdk-0.4.0/docs/guides/index.md +21 -0
  47. anaplan_sdk-0.4.0/docs/guides/multiple_models.md +32 -0
  48. anaplan_sdk-0.4.0/docs/guides/transactional.md +191 -0
  49. anaplan_sdk-0.4.0/docs/img/anaplan-sdk.webp +0 -0
  50. anaplan_sdk-0.4.0/docs/index.md +59 -0
  51. anaplan_sdk-0.4.0/docs/installation.md +59 -0
  52. anaplan_sdk-0.4.0/docs/js/assets/hljs.js +2973 -0
  53. anaplan_sdk-0.4.0/docs/js/assets/hljs.min.js +1 -0
  54. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/docs/js/assets/python.js +9 -9
  55. anaplan_sdk-0.4.0/docs/js/assets/python.min.js +1 -0
  56. anaplan_sdk-0.4.0/docs/js/highlight.js +9 -0
  57. anaplan_sdk-0.4.0/docs/js/highlight.min.js +1 -0
  58. anaplan_sdk-0.4.0/docs/quickstart.md +138 -0
  59. anaplan_sdk-0.4.0/mkdocs.yml +109 -0
  60. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/pyproject.toml +102 -88
  61. anaplan_sdk-0.4.0/tests/async/conftest.py +99 -0
  62. anaplan_sdk-0.4.0/tests/async/test_async_audit_client.py +23 -0
  63. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/tests/async/test_async_client.py +13 -3
  64. anaplan_sdk-0.4.0/tests/async/test_async_cloud_works_client.py +194 -0
  65. anaplan_sdk-0.4.0/tests/async/test_async_flows_client.py +49 -0
  66. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/tests/async/test_async_transactional_client.py +1 -1
  67. anaplan_sdk-0.4.0/tests/conftest.py +280 -0
  68. anaplan_sdk-0.4.0/tests/sync/conftest.py +99 -0
  69. anaplan_sdk-0.4.0/tests/sync/test_audit_client.py +21 -0
  70. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/tests/sync/test_client.py +13 -5
  71. anaplan_sdk-0.4.0/tests/sync/test_cloud_works_client.py +186 -0
  72. anaplan_sdk-0.4.0/tests/sync/test_flows_client.py +47 -0
  73. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/tests/sync/test_transactional_client.py +1 -1
  74. anaplan_sdk-0.4.0/uv.lock +1180 -0
  75. anaplan_sdk-0.3.1b1/.github/workflows/lint.yml +0 -8
  76. anaplan_sdk-0.3.1b1/PKG-INFO +0 -109
  77. anaplan_sdk-0.3.1b1/README.md +0 -92
  78. anaplan_sdk-0.3.1b1/anaplan_sdk/_async_clients/__init__.py +0 -6
  79. anaplan_sdk-0.3.1b1/anaplan_sdk/_auth.py +0 -135
  80. anaplan_sdk-0.3.1b1/anaplan_sdk/models.py +0 -329
  81. anaplan_sdk-0.3.1b1/docs/anaplan_explained.md +0 -56
  82. anaplan_sdk-0.3.1b1/docs/guides/alm.md +0 -82
  83. anaplan_sdk-0.3.1b1/docs/guides/audit.md +0 -81
  84. anaplan_sdk-0.3.1b1/docs/guides/bulk.md +0 -340
  85. anaplan_sdk-0.3.1b1/docs/guides/multiple_models.md +0 -35
  86. anaplan_sdk-0.3.1b1/docs/guides/transactional.md +0 -242
  87. anaplan_sdk-0.3.1b1/docs/img/anaplan-overview.webp +0 -0
  88. anaplan_sdk-0.3.1b1/docs/img/anaplan-sdk.webp +0 -0
  89. anaplan_sdk-0.3.1b1/docs/index.md +0 -34
  90. anaplan_sdk-0.3.1b1/docs/installation.md +0 -28
  91. anaplan_sdk-0.3.1b1/docs/js/assets/hljs.js +0 -1242
  92. anaplan_sdk-0.3.1b1/docs/js/highlight.js +0 -12
  93. anaplan_sdk-0.3.1b1/docs/quickstart.md +0 -162
  94. anaplan_sdk-0.3.1b1/mkdocs.yml +0 -86
  95. anaplan_sdk-0.3.1b1/tests/async/conftest.py +0 -65
  96. anaplan_sdk-0.3.1b1/tests/async/test_async_audit_client.py +0 -12
  97. anaplan_sdk-0.3.1b1/tests/conftest.py +0 -17
  98. anaplan_sdk-0.3.1b1/tests/sync/conftest.py +0 -65
  99. anaplan_sdk-0.3.1b1/tests/sync/test_audit_client.py +0 -14
  100. anaplan_sdk-0.3.1b1/uv.lock +0 -1152
  101. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/.github/dependabot.yml +0 -0
  102. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/.github/workflows/docs.yml +0 -0
  103. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/.gitignore +0 -0
  104. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/LICENSE +0 -0
  105. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/anaplan_sdk/__init__.py +0 -0
  106. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/anaplan_sdk/_clients/__init__.py +0 -0
  107. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/anaplan_sdk/exceptions.py +0 -0
  108. {anaplan_sdk-0.3.1b1/docs/api → anaplan_sdk-0.4.0/docs/api/async}/async_client.md +0 -0
  109. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/docs/api/exceptions.md +0 -0
  110. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/docs/api/models.md +0 -0
  111. /anaplan_sdk-0.3.1b1/docs/api/client.md → /anaplan_sdk-0.4.0/docs/api/sync/sync_client.md +0 -0
  112. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/docs/guides/bulk_vs_transactional.md +0 -0
  113. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/docs/guides/logging.md +0 -0
  114. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/tests/async/test_async_alm_client.py +0 -0
  115. {anaplan_sdk-0.3.1b1 → anaplan_sdk-0.4.0}/tests/sync/test_alm_client.py +0 -0
@@ -0,0 +1,9 @@
1
+ name: Ruff
2
+ on: [ push, pull_request ]
3
+ jobs:
4
+ ruff:
5
+ runs-on: ubuntu-latest
6
+ steps:
7
+ - uses: actions/checkout@v4
8
+ - uses: astral-sh/ruff-action@v3
9
+ - run: ruff format --check
@@ -13,6 +13,8 @@ jobs:
13
13
  ANAPLAN_SDK_TEST_MODEL_ID: ${{secrets.ANAPLAN_SDK_TEST_MODEL_ID}}
14
14
  ANAPLAN_SDK_TEST_CERT: ${{secrets.ANAPLAN_SDK_TEST_CERT}}
15
15
  ANAPLAN_SDK_TEST_PK: ${{secrets.ANAPLAN_SDK_TEST_PK}}
16
+ AZ_STORAGE_ACCOUNT: ${{secrets.AZ_STORAGE_ACCOUNT}}
17
+ AZ_STORAGE_SAS_TOKEN: ${{secrets.AZ_STORAGE_SAS_TOKEN}}
16
18
 
17
19
  name: "Python ${{ matrix.python-version }}"
18
20
  runs-on: "ubuntu-latest"
@@ -32,4 +34,4 @@ jobs:
32
34
  pip install uv
33
35
  uv sync
34
36
  - name: "Run tests"
35
- run: "uv run python -m pytest -n 8 --dist loadfile tests/"
37
+ run: "uv run python -m pytest -n 12 --dist loadfile tests/"
@@ -1,10 +1,10 @@
1
1
  repos:
2
2
  - repo: https://github.com/astral-sh/uv-pre-commit
3
- rev: 0.5.29
3
+ rev: 0.7.3
4
4
  hooks:
5
5
  - id: uv-lock
6
6
  - repo: https://github.com/astral-sh/ruff-pre-commit
7
- rev: v0.9.6
7
+ rev: v0.11.9
8
8
  hooks:
9
9
  - id: ruff
10
10
  args: [ --fix ]
@@ -0,0 +1,87 @@
1
+ Metadata-Version: 2.4
2
+ Name: anaplan-sdk
3
+ Version: 0.4.0
4
+ Summary: Streamlined Python Interface for Anaplan
5
+ Project-URL: Homepage, https://vinzenzklass.github.io/anaplan-sdk/
6
+ Project-URL: Repository, https://github.com/VinzenzKlass/anaplan-sdk
7
+ Project-URL: Documentation, https://vinzenzklass.github.io/anaplan-sdk/
8
+ Author-email: Vinzenz Klass <vinzenz.klass@valantic.com>
9
+ License-Expression: Apache-2.0
10
+ License-File: LICENSE
11
+ Keywords: anaplan,anaplan alm api,anaplan api,anaplan audit api,anaplan bulk api,anaplan cloudworks api,anaplan integration,anaplan integration api,anaplan sdk,anaplan transactional api
12
+ Requires-Python: >=3.10.4
13
+ Requires-Dist: httpx<1.0.0,>=0.27.0
14
+ Requires-Dist: pydantic<3.0.0,>=2.7.2
15
+ Provides-Extra: cert
16
+ Requires-Dist: cryptography<46.0.0,>=42.0.7; extra == 'cert'
17
+ Provides-Extra: oauth
18
+ Requires-Dist: oauthlib<4.0.0,>=3.0.0; extra == 'oauth'
19
+ Description-Content-Type: text/markdown
20
+
21
+ <p align="center">
22
+ <img width="160" height="160" src="https://vinzenzklass.github.io/anaplan-sdk/img/anaplan-sdk.webp" alt='Python' style="border-radius: 15px">
23
+ </p>
24
+
25
+ <h3 align="center" style="font-size: 3rem; font-weight: 600;">
26
+ Anaplan SDK
27
+ </h3>
28
+
29
+ <p align="center" style="font-size: 1.2rem; font-weight: 300; margin: 15px 0">
30
+ Streamlined Python Interface for Anaplan
31
+ </p>
32
+
33
+ <div align="center">
34
+ <a href="https://pepy.tech/projects/anaplan-sdk">
35
+ <img src="https://static.pepy.tech/badge/anaplan-sdk" alt="">
36
+ </a>
37
+ <a href="https://pypi.org/project/anaplan-sdk/">
38
+ <img src="https://img.shields.io/pypi/v/anaplan-sdk.svg" alt="PyPi Latest Release"/>
39
+ </a>
40
+ <a href="https://pepy.tech/projects/anaplan-sdk">
41
+ <img src="https://static.pepy.tech/badge/anaplan-sdk/month" alt="PyPI Downloads">
42
+ </a>
43
+ </div>
44
+
45
+ ---
46
+
47
+ Anaplan SDK is an independent, unofficial project providing pythonic access to Anaplan. It delivers high-level
48
+ abstractions over all Anaplan APIs, allowing you to focus on business requirements rather than implementation details.
49
+
50
+ ## Key Features
51
+
52
+ - **Pythonic Interface**: Clean, intuitive access to Anaplan functionality
53
+ - **Simplified API Interactions**: Automatic handling of authentication, error handling, and data formatting
54
+ - **Performance Optimizations**: Built-in chunking and compression techniques
55
+ - **Multiple API Support**: Compatible with all major Anaplan API endpoints
56
+ - **Flexible Client Options**: Both synchronous and asynchronous implementations
57
+ - **Developer-Friendly**: Designed to reduce boilerplate code and accelerate development
58
+
59
+ ## Getting Started
60
+
61
+ Head over to the [Quick Start](quickstart.md) for basic usage instructions and examples.
62
+
63
+ ## Contributing
64
+
65
+ Pull Requests are welcome. For major changes,
66
+ please [open an issue](https://github.com/VinzenzKlass/anaplan-sdk/issues/new) first to discuss what you would like to
67
+ change. To submit a pull request, please follow the
68
+ standard [Fork & Pull Request workflow](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork).
69
+
70
+ Before submitting your pull request, please ensure that all the files pass linting and formatting checks. You can do
71
+ this by running the following command:
72
+
73
+ ```shell
74
+ uv sync --dev
75
+
76
+ ruff check
77
+ ruff format
78
+ ```
79
+
80
+ You can also enable [pre-commit](https://pre-commit.com/) hooks to automatically format and lint your code before
81
+ committing:
82
+
83
+ ```shell
84
+ pre-commit install
85
+ ```
86
+
87
+ If your PR goes beyond a simple bug fix or small changes, please add tests to cover your changes.
@@ -0,0 +1,67 @@
1
+ <p align="center">
2
+ <img width="160" height="160" src="https://vinzenzklass.github.io/anaplan-sdk/img/anaplan-sdk.webp" alt='Python' style="border-radius: 15px">
3
+ </p>
4
+
5
+ <h3 align="center" style="font-size: 3rem; font-weight: 600;">
6
+ Anaplan SDK
7
+ </h3>
8
+
9
+ <p align="center" style="font-size: 1.2rem; font-weight: 300; margin: 15px 0">
10
+ Streamlined Python Interface for Anaplan
11
+ </p>
12
+
13
+ <div align="center">
14
+ <a href="https://pepy.tech/projects/anaplan-sdk">
15
+ <img src="https://static.pepy.tech/badge/anaplan-sdk" alt="">
16
+ </a>
17
+ <a href="https://pypi.org/project/anaplan-sdk/">
18
+ <img src="https://img.shields.io/pypi/v/anaplan-sdk.svg" alt="PyPi Latest Release"/>
19
+ </a>
20
+ <a href="https://pepy.tech/projects/anaplan-sdk">
21
+ <img src="https://static.pepy.tech/badge/anaplan-sdk/month" alt="PyPI Downloads">
22
+ </a>
23
+ </div>
24
+
25
+ ---
26
+
27
+ Anaplan SDK is an independent, unofficial project providing pythonic access to Anaplan. It delivers high-level
28
+ abstractions over all Anaplan APIs, allowing you to focus on business requirements rather than implementation details.
29
+
30
+ ## Key Features
31
+
32
+ - **Pythonic Interface**: Clean, intuitive access to Anaplan functionality
33
+ - **Simplified API Interactions**: Automatic handling of authentication, error handling, and data formatting
34
+ - **Performance Optimizations**: Built-in chunking and compression techniques
35
+ - **Multiple API Support**: Compatible with all major Anaplan API endpoints
36
+ - **Flexible Client Options**: Both synchronous and asynchronous implementations
37
+ - **Developer-Friendly**: Designed to reduce boilerplate code and accelerate development
38
+
39
+ ## Getting Started
40
+
41
+ Head over to the [Quick Start](quickstart.md) for basic usage instructions and examples.
42
+
43
+ ## Contributing
44
+
45
+ Pull Requests are welcome. For major changes,
46
+ please [open an issue](https://github.com/VinzenzKlass/anaplan-sdk/issues/new) first to discuss what you would like to
47
+ change. To submit a pull request, please follow the
48
+ standard [Fork & Pull Request workflow](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request-from-a-fork).
49
+
50
+ Before submitting your pull request, please ensure that all the files pass linting and formatting checks. You can do
51
+ this by running the following command:
52
+
53
+ ```shell
54
+ uv sync --dev
55
+
56
+ ruff check
57
+ ruff format
58
+ ```
59
+
60
+ You can also enable [pre-commit](https://pre-commit.com/) hooks to automatically format and lint your code before
61
+ committing:
62
+
63
+ ```shell
64
+ pre-commit install
65
+ ```
66
+
67
+ If your PR goes beyond a simple bug fix or small changes, please add tests to cover your changes.
@@ -0,0 +1,13 @@
1
+ from ._alm import _AsyncAlmClient
2
+ from ._audit import _AsyncAuditClient
3
+ from ._bulk import AsyncClient
4
+ from ._cloud_works import _AsyncCloudWorksClient
5
+ from ._transactional import _AsyncTransactionalClient
6
+
7
+ __all__ = [
8
+ "AsyncClient",
9
+ "_AsyncAlmClient",
10
+ "_AsyncAuditClient",
11
+ "_AsyncCloudWorksClient",
12
+ "_AsyncTransactionalClient",
13
+ ]
@@ -1,35 +1,14 @@
1
- import warnings
2
-
3
1
  import httpx
4
2
 
5
3
  from anaplan_sdk._base import _AsyncBaseClient
6
- from anaplan_sdk.models import ModelRevision, Revision, SyncTask, User
7
-
8
- warnings.filterwarnings("always", category=DeprecationWarning)
4
+ from anaplan_sdk.models import ModelRevision, Revision, SyncTask
9
5
 
10
6
 
11
7
  class _AsyncAlmClient(_AsyncBaseClient):
12
8
  def __init__(self, client: httpx.AsyncClient, model_id: str, retry_count: int) -> None:
13
- self._client = client
14
9
  self._url = f"https://api.anaplan.com/2/0/models/{model_id}/alm"
15
10
  super().__init__(retry_count, client)
16
11
 
17
- async def list_users(self) -> list[User]:
18
- """
19
- Lists all the Users in the authenticated users default tenant.
20
- :return: The List of Users.
21
- """
22
- warnings.warn(
23
- "`list_users()` on the ALM client is deprecated and will be removed in a "
24
- "future version. Use `list_users()` on the Audit client instead.",
25
- DeprecationWarning,
26
- stacklevel=1,
27
- )
28
- return [
29
- User.model_validate(e)
30
- for e in (await self._get("https://api.anaplan.com/2/0/users")).get("users")
31
- ]
32
-
33
12
  async def get_syncable_revisions(self, source_model_id: str) -> list[Revision]:
34
13
  """
35
14
  Use this call to return the list of revisions from your source model that can be
@@ -10,21 +10,36 @@ Event = Literal["all", "byok", "user_activity"]
10
10
 
11
11
  class _AsyncAuditClient(_AsyncBaseClient):
12
12
  def __init__(self, client: httpx.AsyncClient, retry_count: int) -> None:
13
- self._client = client
14
13
  self._limit = 10_000
15
14
  self._url = "https://audit.anaplan.com/audit/api/1/events"
16
15
  super().__init__(retry_count, client)
17
16
 
18
- async def list_users(self) -> list[User]:
17
+ async def list_users(self, search_pattern: str | None = None) -> list[User]:
19
18
  """
20
19
  Lists all the Users in the authenticated users default tenant.
20
+ :param search_pattern: Optionally filter for specific users. When provided,
21
+ case-insensitive matches users with emails or names containing this string.
22
+ You can use the wildcards `%` for 0-n characters, and `_` for exactly 1 character.
23
+ When None (default), returns all users.
21
24
  :return: The List of Users.
22
25
  """
26
+ params = {"s": search_pattern} if search_pattern else None
23
27
  return [
24
28
  User.model_validate(e)
25
- for e in await self._get_paginated("https://api.anaplan.com/2/0/users", "users")
29
+ for e in await self._get_paginated(
30
+ "https://api.anaplan.com/2/0/users", "users", params=params
31
+ )
26
32
  ]
27
33
 
34
+ async def get_user(self, user_id: str = "me") -> User:
35
+ """
36
+ Retrieves information about the specified user, or the authenticated user if none specified.
37
+ :return: The requested or currently authenticated User.
38
+ """
39
+ return User.model_validate(
40
+ (await self._get(f"https://api.anaplan.com/2/0/users/{user_id}")).get("user")
41
+ )
42
+
28
43
  async def get_events(self, days_into_past: int = 30, event_type: Event = "all") -> list:
29
44
  """
30
45
  Get audit events from Anaplan Audit API.
@@ -1,16 +1,12 @@
1
- """
2
- Asynchronous Client.
3
- """
4
-
5
1
  import logging
6
2
  from asyncio import gather, sleep
7
3
  from copy import copy
8
- from typing import AsyncIterator, Iterator
4
+ from typing import AsyncIterator, Callable, Iterator
9
5
 
10
6
  import httpx
11
7
  from typing_extensions import Self
12
8
 
13
- from anaplan_sdk._auth import AnaplanBasicAuth, AnaplanCertAuth, get_certificate, get_private_key
9
+ from anaplan_sdk._auth import create_auth
14
10
  from anaplan_sdk._base import _AsyncBaseClient, action_url
15
11
  from anaplan_sdk.exceptions import AnaplanActionError, InvalidIdentifierException
16
12
  from anaplan_sdk.models import (
@@ -27,6 +23,7 @@ from anaplan_sdk.models import (
27
23
 
28
24
  from ._alm import _AsyncAlmClient
29
25
  from ._audit import _AsyncAuditClient
26
+ from ._cloud_works import _AsyncCloudWorksClient
30
27
  from ._transactional import _AsyncTransactionalClient
31
28
 
32
29
  logging.getLogger("httpx").setLevel(logging.CRITICAL)
@@ -54,7 +51,13 @@ class AsyncClient(_AsyncBaseClient):
54
51
  certificate: str | bytes | None = None,
55
52
  private_key: str | bytes | None = None,
56
53
  private_key_password: str | bytes | None = None,
57
- timeout: float = 30,
54
+ client_id: str | None = None,
55
+ client_secret: str | None = None,
56
+ redirect_uri: str | None = None,
57
+ refresh_token: str | None = None,
58
+ oauth2_scope: str = "openid profile email offline_access",
59
+ on_token_refresh: Callable[[dict[str, str]], None] | None = None,
60
+ timeout: float | httpx.Timeout = 30,
58
61
  retry_count: int = 2,
59
62
  status_poll_delay: int = 1,
60
63
  upload_chunk_size: int = 25_000_000,
@@ -82,7 +85,19 @@ class AsyncClient(_AsyncBaseClient):
82
85
  itself.
83
86
  :param private_key: The absolute path to the private key file or the private key itself.
84
87
  :param private_key_password: The password to access the private key if there is one.
85
- :param timeout: The timeout in seconds for the HTTP requests.
88
+ :param client_id: The client Id of the Oauth2 Anaplan Client.
89
+ :param client_secret: The client secret for your Oauth2 Anaplan Client.
90
+ :param redirect_uri: The redirect URI for your Oauth2 Anaplan Client.
91
+ :param refresh_token: If you have a valid refresh token, you can pass it to skip the
92
+ interactive authentication code step.
93
+ :param oauth2_scope: The scope of the Oauth2 token, if you want to narrow it.
94
+ :param on_token_refresh: A callback function that is called whenever the token is refreshed.
95
+ With this you can for example securely store the token in your
96
+ application or on your server for later reuse. The function
97
+ must accept a single argument, which is the token dictionary
98
+ returned by the Oauth2 token endpoint and does not return anything.
99
+ :param timeout: The timeout in seconds for the HTTP requests. Alternatively, you can pass
100
+ an instance of `httpx.Timeout` to set the timeout for the HTTP requests.
86
101
  :param retry_count: The number of times to retry an HTTP request if it fails. Set this to 0
87
102
  to never retry. Defaults to 2, meaning each HTTP Operation will be
88
103
  tried a total number of 2 times.
@@ -96,34 +111,38 @@ class AsyncClient(_AsyncBaseClient):
96
111
  manually assigned so there is typically no value in dynamically
97
112
  creating new files and uploading content to them.
98
113
  """
99
- if not ((user_email and password) or (certificate and private_key)):
100
- raise ValueError(
101
- "Must provide `certificate` and `private_key` or `user_email` and `password`."
102
- "If you Private Key is Password protected, must also pass `private_key_password`."
103
- )
104
- self._client = httpx.AsyncClient(
114
+ _client = httpx.AsyncClient(
105
115
  auth=(
106
- AnaplanCertAuth(
107
- get_certificate(certificate), get_private_key(private_key, private_key_password)
116
+ create_auth(
117
+ user_email=user_email,
118
+ password=password,
119
+ certificate=certificate,
120
+ private_key=private_key,
121
+ private_key_password=private_key_password,
122
+ client_id=client_id,
123
+ client_secret=client_secret,
124
+ redirect_uri=redirect_uri,
125
+ refresh_token=refresh_token,
126
+ oauth2_scope=oauth2_scope,
127
+ on_token_refresh=on_token_refresh,
108
128
  )
109
- if certificate
110
- else AnaplanBasicAuth(user_email=user_email, password=password)
111
129
  ),
112
130
  timeout=timeout,
113
131
  )
114
132
  self._retry_count = retry_count
115
133
  self._url = f"https://api.anaplan.com/2/0/workspaces/{workspace_id}/models/{model_id}"
116
134
  self._transactional_client = (
117
- _AsyncTransactionalClient(self._client, model_id, retry_count) if model_id else None
135
+ _AsyncTransactionalClient(_client, model_id, retry_count) if model_id else None
118
136
  )
119
137
  self._alm_client = (
120
- _AsyncAlmClient(self._client, model_id, self._retry_count) if model_id else None
138
+ _AsyncAlmClient(_client, model_id, self._retry_count) if model_id else None
121
139
  )
122
- self.audit = _AsyncAuditClient(self._client, self._retry_count)
140
+ self._audit = _AsyncAuditClient(_client, self._retry_count)
141
+ self._cloud_works = _AsyncCloudWorksClient(_client, self._retry_count)
123
142
  self.status_poll_delay = status_poll_delay
124
143
  self.upload_chunk_size = upload_chunk_size
125
144
  self.allow_file_creation = allow_file_creation
126
- super().__init__(retry_count, self._client)
145
+ super().__init__(retry_count, _client)
127
146
 
128
147
  @classmethod
129
148
  def from_existing(cls, existing: Self, workspace_id: str, model_id: str) -> Self:
@@ -145,6 +164,22 @@ class AsyncClient(_AsyncBaseClient):
145
164
  client._alm_client = _AsyncAlmClient(existing._client, model_id, existing._retry_count)
146
165
  return client
147
166
 
167
+ @property
168
+ def audit(self) -> _AsyncAuditClient:
169
+ """
170
+ The Audit Client provides access to the Anaplan Audit API.
171
+ For details, see https://vinzenzklass.github.io/anaplan-sdk/guides/audit/.
172
+ """
173
+ return self._audit
174
+
175
+ @property
176
+ def cw(self) -> _AsyncCloudWorksClient:
177
+ """
178
+ The Cloud Works Client provides access to the Anaplan Cloud Works API.
179
+ For details, see https://vinzenzklass.github.io/anaplan-sdk/guides/cloud_works/.
180
+ """
181
+ return self._cloud_works
182
+
148
183
  @property
149
184
  def transactional(self) -> _AsyncTransactionalClient:
150
185
  """
@@ -184,29 +219,41 @@ class AsyncClient(_AsyncBaseClient):
184
219
  )
185
220
  return self._alm_client
186
221
 
187
- async def list_workspaces(self) -> list[Workspace]:
222
+ async def list_workspaces(self, search_pattern: str | None = None) -> list[Workspace]:
188
223
  """
189
224
  Lists all the Workspaces the authenticated user has access to.
225
+ :param search_pattern: Optionally filter for specific workspaces. When provided,
226
+ case-insensitive matches workspaces with names containing this string.
227
+ You can use the wildcards `%` for 0-n characters, and `_` for exactly 1 character.
228
+ When None (default), returns all users.
190
229
  :return: The List of Workspaces.
191
230
  """
231
+ params = {"tenantDetails": "true"}
232
+ if search_pattern:
233
+ params["s"] = search_pattern
192
234
  return [
193
235
  Workspace.model_validate(e)
194
236
  for e in await self._get_paginated(
195
- "https://api.anaplan.com/2/0/workspaces",
196
- "workspaces",
197
- params={"tenantDetails": "true"},
237
+ "https://api.anaplan.com/2/0/workspaces", "workspaces", params=params
198
238
  )
199
239
  ]
200
240
 
201
- async def list_models(self) -> list[Model]:
241
+ async def list_models(self, search_pattern: str | None = None) -> list[Model]:
202
242
  """
203
243
  Lists all the Models the authenticated user has access to.
244
+ :param search_pattern: Optionally filter for specific models. When provided,
245
+ case-insensitive matches models names containing this string.
246
+ You can use the wildcards `%` for 0-n characters, and `_` for exactly 1 character.
247
+ When None (default), returns all users.
204
248
  :return: The List of Models.
205
249
  """
250
+ params = {"modelDetails": "true"}
251
+ if search_pattern:
252
+ params["s"] = search_pattern
206
253
  return [
207
254
  Model.model_validate(e)
208
255
  for e in await self._get_paginated(
209
- "https://api.anaplan.com/2/0/models", "models", params={"modelDetails": "true"}
256
+ "https://api.anaplan.com/2/0/models", "models", params=params
210
257
  )
211
258
  ]
212
259