apapi.transactional

apapi.transactional

Child of Basic Connection class, responsible for Transactional API capabilities.

  1"""
  2apapi.transactional
  3
  4Child of Basic Connection class, responsible for Transactional API capabilities.
  5"""
  6from __future__ import annotations
  7
  8import json
  9from typing import Iterable
 10
 11from requests import Response
 12
 13from .basic_connection import BasicConnection
 14from .utils import ENCODING_GZIP, PAGING_LIMIT, ExportType, MIMEType
 15
 16
 17class TransactionalConnection(BasicConnection):
 18    """Anaplan connection with Transactional API functions."""
 19
 20    # Users
 21    def get_users(self) -> Response:
 22        """Get info about all users in the tenant."""
 23        return self.request("GET", f"{self._api_main_url}/users")
 24
 25    def get_me(self) -> Response:
 26        """Get info about me."""
 27        return self.request("GET", f"{self._api_main_url}/users/me")
 28
 29    def get_user(self, user_id: str) -> Response:
 30        """Get info about a specified user."""
 31        return self.request("GET", f"{self._api_main_url}/users/{user_id}")
 32
 33    def get_workspace_users(self, workspace_id: str) -> Response:
 34        """Get info about users with access to a specified workspace."""
 35        return self.request(
 36            "GET",
 37            f"{self._api_main_url}/workspaces/{workspace_id}/users",
 38        )
 39
 40    def get_workspace_admins(self, workspace_id: str) -> Response:
 41        """Get info about all administrators of a specified workspace."""
 42        return self.request(
 43            "GET",
 44            f"{self._api_main_url}/workspaces/{workspace_id}/admins",
 45            {"limit": PAGING_LIMIT},  # needed for this endpoint, as default is 20
 46        )
 47
 48    def get_model_users(self, model_id: str) -> Response:
 49        """Get info about users with access to a specified model."""
 50        return self.request("GET", f"{self._api_main_url}/models/{model_id}/users")
 51
 52    # Workspaces
 53    def get_workspaces(self, details: bool = None) -> Response:
 54        """Get info about all workspaces in the tenant."""
 55        return self.request(
 56            "GET",
 57            f"{self._api_main_url}/workspaces",
 58            {"tenantDetails": self.details if details is None else details},
 59        )
 60
 61    def get_workspace(self, workspace_id: str, details: bool = None) -> Response:
 62        """Get info about all a specified workspace."""
 63        return self.request(
 64            "GET",
 65            f"{self._api_main_url}/workspaces/{workspace_id}",
 66            {"tenantDetails": self.details if details is None else details},
 67        )
 68
 69    def get_user_workspaces(self, user_id: str) -> Response:
 70        """Get info about all workspaces to which a specified user has access."""
 71        return self.request("GET", f"{self._api_main_url}/users/{user_id}/workspaces")
 72
 73    # Models
 74    def get_models(self, details: bool = None) -> Response:
 75        """Get info about all models in the tenant."""
 76        return self.request(
 77            "GET",
 78            f"{self._api_main_url}/models",
 79            {"modelDetails": self.details if details is None else details},
 80        )
 81
 82    def get_workspace_models(self, workspace_id: str, details: bool = None) -> Response:
 83        """Get info about all models within a specified workspace."""
 84        return self.request(
 85            "GET",
 86            f"{self._api_main_url}/workspaces/{workspace_id}/models",
 87            {"modelDetails": self.details if details is None else details},
 88        )
 89
 90    def get_model(self, model_id: str, details: bool = None) -> Response:
 91        """Get info about a specified model."""
 92        return self.request(
 93            "GET",
 94            f"{self._api_main_url}/models/{model_id}",
 95            {"modelDetails": self.details if details is None else details},
 96        )
 97
 98    def get_user_models(self, user_id: str) -> Response:
 99        """Get info about all models to which a specified user has access."""
100        return self.request("GET", f"{self._api_main_url}/users/{user_id}/models")
101
102    def delete_models(self, workspace_id: str, models_ids: [str]) -> Response:
103        """Delete models from a workspace.
104
105        **WARNING**: This query is destructive - use with caution! It will only work on
106        closed models - you can close a model in Anaplan web interface via Manage Tasks.
107        """
108        return self.request(
109            "POST",
110            f"{self._api_main_url}/workspaces/{workspace_id}/bulkDeleteModels",
111            data=json.dumps({"modelIdsToDelete": models_ids}),
112        )
113
114    # Calendar
115    def get_fiscal_year(self, model_id: str):
116        """Get current fiscal year setting for a specified model."""
117        return self.request(
118            "GET", f"{self._api_main_url}/models/{model_id}/modelCalendar"
119        )
120
121    def set_fiscal_year(self, model_id: str, data: str):
122        """Set current fiscal year setting."""
123        return self.request(
124            "PUT",
125            f"{self._api_main_url}/models/{model_id}/modelCalendar/fiscalYear",
126            data=json.dumps({"year": data}),
127        )
128
129    def get_current_period(self, model_id: str):
130        """Get current period setting a specified model."""
131        return self.request(
132            "GET", f"{self._api_main_url}/models/{model_id}/currentPeriod"
133        )
134
135    def set_current_period(self, model_id: str, data: str):
136        """Set current period setting (data should have YYYY-MM-DD format)."""
137        return self.request(
138            "PUT",
139            f"{self._api_main_url}/models/{model_id}/currentPeriod",
140            data=json.dumps({"date": data}),
141        )
142
143    # Versions
144    def get_versions(self, model_id: str):
145        """Get versions information and settings."""
146        return self.request("GET", f"{self._api_main_url}/models/{model_id}/versions")
147
148    def set_version_switchover(self, model_id: str, version_id: str, data: str):
149        """Set version's switchover (data should have YYYY-MM-DD format)."""
150        return self.request(
151            "PUT",
152            f"{self._api_main_url}/models/{model_id}/versions/{version_id}/switchover",
153            data=json.dumps({"date": data}),
154        )
155
156    # Lists
157    def get_lists(self, model_id: str) -> Response:
158        """Get lists information for a specified model."""
159        return self.request("GET", f"{self._api_main_url}/models/{model_id}/lists")
160
161    def get_list(self, model_id: str, list_id: str) -> Response:
162        """Get information about a specified list."""
163        return self.request(
164            "GET", f"{self._api_main_url}/models/{model_id}/lists/{list_id}"
165        )
166
167    def get_list_items(
168        self, model_id: str, list_id: str, details: bool = None, accept: MIMEType = None
169    ) -> Response:
170        """Get list's items, up to a million lines.
171
172        **WARNING**: This query can be used to retrieve information for smaller lists.
173        For larger lists use large_list_read functions.
174
175        Extra details (selective access, subsets and properties) are available.
176        Returned data can be either in JSON (default) or CSV format.
177        """
178        return self.request(
179            "GET",
180            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/items",
181            {"includeAll": self.details if details is None else details},
182            headers={"Accept": accept.value} if accept else None,
183        )
184
185    def start_large_list_read(self, model_id: str, list_id: str) -> Response:
186        """Start large list read, which allows getting unlimited list's items."""
187        return self.request(
188            "POST",
189            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/readRequests",
190        )
191
192    def get_large_list_read_status(
193        self, model_id: str, list_id: str, request_id: str
194    ) -> Response:
195        """Get status of a specified large list read request.
196
197        Tip: some pages might be available even if process is still in progress.
198        """
199        return self.request(
200            "GET",
201            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/readRequests/{request_id}",
202        )
203
204    def get_large_list_read_data(
205        self,
206        model_id: str,
207        list_id: str,
208        request_id: str,
209        page: str,
210        compress: bool = None,
211    ) -> Response:
212        """Get a page of data of a specified large list read request.
213
214        You can get information about haw many pages are already available using
215        TransactionalConnection.get_large_list_read_status().
216        If there are i.e. 10 available pages, it means that pages from 0 to 9 are ready.
217        You can clean after read using TransactionalConnection.delete_large_list_read().
218        """
219        headers = {"Accept": MIMEType.TEXT_CSV.value}
220        if compress or (compress is None and self.compress):
221            headers["Accept-Encoding"] = ENCODING_GZIP
222        return self.request(
223            "GET",
224            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/readRequests/{request_id}/pages/{page}",
225            headers=headers,
226        )
227
228    def delete_large_list_read(
229        self, model_id: str, list_id: str, request_id: str
230    ) -> Response:
231        """Delete specified large list read request.
232
233        You can call this endpoint to free up space if you don't need the data anymore.
234        If not accessed, data will be cleared after 30 minutes automatically.
235        """
236        return self.request(
237            "DELETE",
238            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/readRequests/{request_id}",
239        )
240
241    def add_list_items(self, model_id: str, list_id: str, data: list[dict]) -> Response:
242        """Add specified items to a list.
243
244        Array of items definitions is expected as documented in the official Anaplan
245        [API documentation](https://anaplanbulkapi20.docs.apiary.io/#AddListItems).
246        """
247        return self.request(
248            "POST",
249            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/items",
250            {"action": "add"},
251            json.dumps({"items": data}),
252        )
253
254    def update_list_items(
255        self, model_id: str, list_id: str, data: list[dict]
256    ) -> Response:
257        """Update a specified items of a list.
258
259        Array of items definitions is expected as documented in the official Anaplan
260        [API documentation](https://anaplanbulkapi20.docs.apiary.io/#UpdateListItems).
261        """
262        return self.request(
263            "PUT",
264            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/items",
265            data=json.dumps({"items": data}),
266        )
267
268    def delete_list_items(
269        self, model_id: str, list_id: str, data: list[dict]
270    ) -> Response:
271        """Delete specified items from a list.
272
273        Data parameter should consist of dictionaries identifying items by id or code.
274        """
275        return self.request(
276            "POST",
277            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/items",
278            {"action": "delete"},
279            json.dumps({"items": data}),
280        )
281
282    def reset_list_index(self, model_id: str, list_id: str) -> Response:
283        """Reset index of a specified numbered list.
284
285        **WARNING**: This action works only for numbered lists that are empty.
286        """
287        return self.request(
288            "POST", f"{self._api_main_url}/models/{model_id}/lists/{list_id}/resetIndex"
289        )
290
291    # Modules
292    def get_modules(self, model_id: str) -> Response:
293        """Get modules information for a specified model."""
294        return self.request("GET", f"{self._api_main_url}/models/{model_id}/modules")
295
296    # Lineitems
297    def get_lineitems(self, model_id: str, details: bool = None) -> Response:
298        """Get all lineitems information for a specified model."""
299        return self.request(
300            "GET",
301            f"{self._api_main_url}/models/{model_id}/lineItems",
302            {"includeAll": self.details if details is None else details},
303        )
304
305    def get_module_lineitems(
306        self, model_id: str, module_id: str, details: bool = None
307    ) -> Response:
308        """Get lineitems information for a specified module."""
309        return self.request(
310            "GET",
311            f"{self._api_main_url}/models/{model_id}/modules/{module_id}/lineItems",
312            {"includeAll": self.details if details is None else details},
313        )
314
315    # Views
316    def get_views(self, model_id: str, details: bool = None) -> Response:
317        """Get all views information for a specified model."""
318        return self.request(
319            "GET",
320            f"{self._api_main_url}/models/{model_id}/views",
321            {"includesubsidiaryviews": self.details if details is None else details},
322        )
323
324    def get_module_views(
325        self, model_id: str, module_id: str, details: bool = None
326    ) -> Response:
327        """Get views information for a specified module."""
328        return self.request(
329            "GET",
330            f"{self._api_main_url}/models/{model_id}/modules/{module_id}/views",
331            {"includesubsidiaryviews": self.details if details is None else details},
332        )
333
334    def get_view_dimensions(self, model_id: str, view_id: str) -> Response:
335        """Get dimensions information for a specified view."""
336        return self.request(
337            "GET", f"{self._api_main_url}/models/{model_id}/views/{view_id}"
338        )
339
340    # Dimensions
341    def get_dimension_items(self, model_id: str, dimension_id: str) -> Response:
342        """Get list of all items within a specified dimension."""
343        return self.request(
344            "GET",
345            f"{self._api_main_url}/models/{model_id}/dimensions/{dimension_id}/items",
346        )
347
348    def get_lineitem_dimensions(self, model_id: str, lineitem_id: str) -> Response:
349        """Get dimensions information for a specified lineitem."""
350        return self.request(
351            "GET",
352            f"{self._api_main_url}/models/{model_id}/lineItems/{lineitem_id}/dimensions",
353        )
354
355    def get_lineitem_dimension_items(
356        self, model_id: str, lineitem_id: str, dimension_id: str
357    ) -> Response:
358        """Get list of items for a specified dimension in the context of a lineitem."""
359        return self.request(
360            "GET",
361            f"{self._api_main_url}/models/{model_id}/lineItems/{lineitem_id}/dimensions/{dimension_id}/items",
362        )
363
364    def get_view_dimension_items(
365        self, model_id: str, view_id: str, dimension_id: str
366    ) -> Response:
367        """Get list of items for a specified dimension in the context of a view."""
368        return self.request(
369            "GET",
370            f"{self._api_main_url}/models/{model_id}/views/{view_id}/dimensions/{dimension_id}/items",
371        )
372
373    def check_dimension_items_id(
374        self, model_id: str, dimension_id: str, data: dict
375    ) -> Response:
376        """Get ids of dimension's items specified by names or codes."""
377        return self.request(
378            "POST",
379            f"{self._api_main_url}/models/{model_id}/dimensions/{dimension_id}/items",
380            data=json.dumps(data),
381        )
382
383    # Cells
384    def get_cell_data(
385        self,
386        model_id: str,
387        view_id: str,
388        accept: MIMEType = None,
389        pages: Iterable[str] = None,
390    ) -> Response:
391        """Get cells values for a specified view, up to a million cells.
392
393        **WARNING**: This query can be used to retrieve information for smaller views.
394        For larger views use large_cell_read functions.
395
396        Pages argument should be iterable collection of dimensionId & itemId strings
397        in a form of key-value pairs joined by ":" (colon),
398        i.e. ["101000000026:330000000028","20000000012:587000000000"]
399        Returned data can be either in JSON (default), CSV or CSV-escaped format.
400        More information about this endpoint can be found in the official Anaplan
401        [API documentation](https://anaplanbulkapi20.docs.apiary.io/#RetrieveCellDataView).
402        """
403        headers = self._session.headers.copy()
404        if accept:
405            headers["Accept"] = accept.value
406        params = {}
407        if pages:
408            params["pages"] = ",".join(pages)
409        if headers["Accept"] == MIMEType.APP_JSON.value:
410            params["format"] = "v1"
411        return self.request(
412            "GET",
413            f"{self._api_main_url}/models/{model_id}/views/{view_id}/data",
414            params=params,
415            headers=headers,
416        )
417
418    def start_large_cell_read(
419        self, model_id: str, view_id: str, mode: ExportType
420    ) -> Response:
421        """Start large cell read, which allows getting unlimited cells for a view.
422
423        Returned data grid mode should be set using apapi.utils.ExportType.
424        """
425        return self.request(
426            "POST",
427            f"{self._api_main_url}/models/{model_id}/views/{view_id}/readRequests",
428            data=json.dumps({"exportType": mode.value}),
429        )
430
431    def get_large_cell_read_status(
432        self, model_id: str, view_id: str, request_id: str
433    ) -> Response:
434        """Get status of a specified large cell read request.
435
436        Tip: some pages might be available even if process is still in progress.
437        """
438        return self.request(
439            "GET",
440            f"{self._api_main_url}/models/{model_id}/views/{view_id}/readRequests/{request_id}",
441        )
442
443    def get_large_cell_read_data(
444        self,
445        model_id: str,
446        view_id: str,
447        request_id: str,
448        page: str,
449        compress: bool = None,
450    ) -> Response:
451        """Get a page of data of a specified large cell read request.
452
453        You can get information about haw many pages are already available using
454        TransactionalConnection.get_large_cell_read_status().
455        If there are i.e. 10 available pages, it means that pages from 0 to 9 are ready.
456        You can clean after read using TransactionalConnection.delete_large_cell_read().
457        """
458        headers = {"Accept": MIMEType.TEXT_CSV.value}
459        if compress or (compress is None and self.compress):
460            headers["Accept-Encoding"] = ENCODING_GZIP
461        return self.request(
462            "GET",
463            f"{self._api_main_url}/models/{model_id}/views/{view_id}/readRequests/{request_id}/pages/{page}",
464            headers=headers,
465        )
466
467    def delete_large_cell_read(
468        self, model_id: str, view_id: str, request_id: str
469    ) -> Response:
470        """Delete specified large cell read request.
471
472        You can call this endpoint to free up space if you don't need the data anymore.
473        If not accessed, data will be cleared after 30 minutes automatically.
474        """
475        return self.request(
476            "DELETE",
477            f"{self._api_main_url}/models/{model_id}/views/{view_id}/readRequests/{request_id}",
478        )
479
480    def post_cell_data(
481        self, model_id: str, module_id: str, data: list[dict]
482    ) -> Response:
483        """Update value of specific cells in a module.
484
485        Data argument should be a list of dictionaries containing lineItemId,
486        dimensions definition (ids of dimensions and items), and new value.
487        More information about this endpoint can be found in the official Anaplan
488        [API documentation](https://anaplanbulkapi20.docs.apiary.io/#WriteCellDataByCoordinateModule).
489        """
490        return self.request(
491            "POST",
492            f"{self._api_main_url}/models/{model_id}/modules/{module_id}/data",
493            data=json.dumps(data),
494        )
class TransactionalConnection(apapi.basic_connection.BasicConnection):
 18class TransactionalConnection(BasicConnection):
 19    """Anaplan connection with Transactional API functions."""
 20
 21    # Users
 22    def get_users(self) -> Response:
 23        """Get info about all users in the tenant."""
 24        return self.request("GET", f"{self._api_main_url}/users")
 25
 26    def get_me(self) -> Response:
 27        """Get info about me."""
 28        return self.request("GET", f"{self._api_main_url}/users/me")
 29
 30    def get_user(self, user_id: str) -> Response:
 31        """Get info about a specified user."""
 32        return self.request("GET", f"{self._api_main_url}/users/{user_id}")
 33
 34    def get_workspace_users(self, workspace_id: str) -> Response:
 35        """Get info about users with access to a specified workspace."""
 36        return self.request(
 37            "GET",
 38            f"{self._api_main_url}/workspaces/{workspace_id}/users",
 39        )
 40
 41    def get_workspace_admins(self, workspace_id: str) -> Response:
 42        """Get info about all administrators of a specified workspace."""
 43        return self.request(
 44            "GET",
 45            f"{self._api_main_url}/workspaces/{workspace_id}/admins",
 46            {"limit": PAGING_LIMIT},  # needed for this endpoint, as default is 20
 47        )
 48
 49    def get_model_users(self, model_id: str) -> Response:
 50        """Get info about users with access to a specified model."""
 51        return self.request("GET", f"{self._api_main_url}/models/{model_id}/users")
 52
 53    # Workspaces
 54    def get_workspaces(self, details: bool = None) -> Response:
 55        """Get info about all workspaces in the tenant."""
 56        return self.request(
 57            "GET",
 58            f"{self._api_main_url}/workspaces",
 59            {"tenantDetails": self.details if details is None else details},
 60        )
 61
 62    def get_workspace(self, workspace_id: str, details: bool = None) -> Response:
 63        """Get info about all a specified workspace."""
 64        return self.request(
 65            "GET",
 66            f"{self._api_main_url}/workspaces/{workspace_id}",
 67            {"tenantDetails": self.details if details is None else details},
 68        )
 69
 70    def get_user_workspaces(self, user_id: str) -> Response:
 71        """Get info about all workspaces to which a specified user has access."""
 72        return self.request("GET", f"{self._api_main_url}/users/{user_id}/workspaces")
 73
 74    # Models
 75    def get_models(self, details: bool = None) -> Response:
 76        """Get info about all models in the tenant."""
 77        return self.request(
 78            "GET",
 79            f"{self._api_main_url}/models",
 80            {"modelDetails": self.details if details is None else details},
 81        )
 82
 83    def get_workspace_models(self, workspace_id: str, details: bool = None) -> Response:
 84        """Get info about all models within a specified workspace."""
 85        return self.request(
 86            "GET",
 87            f"{self._api_main_url}/workspaces/{workspace_id}/models",
 88            {"modelDetails": self.details if details is None else details},
 89        )
 90
 91    def get_model(self, model_id: str, details: bool = None) -> Response:
 92        """Get info about a specified model."""
 93        return self.request(
 94            "GET",
 95            f"{self._api_main_url}/models/{model_id}",
 96            {"modelDetails": self.details if details is None else details},
 97        )
 98
 99    def get_user_models(self, user_id: str) -> Response:
100        """Get info about all models to which a specified user has access."""
101        return self.request("GET", f"{self._api_main_url}/users/{user_id}/models")
102
103    def delete_models(self, workspace_id: str, models_ids: [str]) -> Response:
104        """Delete models from a workspace.
105
106        **WARNING**: This query is destructive - use with caution! It will only work on
107        closed models - you can close a model in Anaplan web interface via Manage Tasks.
108        """
109        return self.request(
110            "POST",
111            f"{self._api_main_url}/workspaces/{workspace_id}/bulkDeleteModels",
112            data=json.dumps({"modelIdsToDelete": models_ids}),
113        )
114
115    # Calendar
116    def get_fiscal_year(self, model_id: str):
117        """Get current fiscal year setting for a specified model."""
118        return self.request(
119            "GET", f"{self._api_main_url}/models/{model_id}/modelCalendar"
120        )
121
122    def set_fiscal_year(self, model_id: str, data: str):
123        """Set current fiscal year setting."""
124        return self.request(
125            "PUT",
126            f"{self._api_main_url}/models/{model_id}/modelCalendar/fiscalYear",
127            data=json.dumps({"year": data}),
128        )
129
130    def get_current_period(self, model_id: str):
131        """Get current period setting a specified model."""
132        return self.request(
133            "GET", f"{self._api_main_url}/models/{model_id}/currentPeriod"
134        )
135
136    def set_current_period(self, model_id: str, data: str):
137        """Set current period setting (data should have YYYY-MM-DD format)."""
138        return self.request(
139            "PUT",
140            f"{self._api_main_url}/models/{model_id}/currentPeriod",
141            data=json.dumps({"date": data}),
142        )
143
144    # Versions
145    def get_versions(self, model_id: str):
146        """Get versions information and settings."""
147        return self.request("GET", f"{self._api_main_url}/models/{model_id}/versions")
148
149    def set_version_switchover(self, model_id: str, version_id: str, data: str):
150        """Set version's switchover (data should have YYYY-MM-DD format)."""
151        return self.request(
152            "PUT",
153            f"{self._api_main_url}/models/{model_id}/versions/{version_id}/switchover",
154            data=json.dumps({"date": data}),
155        )
156
157    # Lists
158    def get_lists(self, model_id: str) -> Response:
159        """Get lists information for a specified model."""
160        return self.request("GET", f"{self._api_main_url}/models/{model_id}/lists")
161
162    def get_list(self, model_id: str, list_id: str) -> Response:
163        """Get information about a specified list."""
164        return self.request(
165            "GET", f"{self._api_main_url}/models/{model_id}/lists/{list_id}"
166        )
167
168    def get_list_items(
169        self, model_id: str, list_id: str, details: bool = None, accept: MIMEType = None
170    ) -> Response:
171        """Get list's items, up to a million lines.
172
173        **WARNING**: This query can be used to retrieve information for smaller lists.
174        For larger lists use large_list_read functions.
175
176        Extra details (selective access, subsets and properties) are available.
177        Returned data can be either in JSON (default) or CSV format.
178        """
179        return self.request(
180            "GET",
181            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/items",
182            {"includeAll": self.details if details is None else details},
183            headers={"Accept": accept.value} if accept else None,
184        )
185
186    def start_large_list_read(self, model_id: str, list_id: str) -> Response:
187        """Start large list read, which allows getting unlimited list's items."""
188        return self.request(
189            "POST",
190            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/readRequests",
191        )
192
193    def get_large_list_read_status(
194        self, model_id: str, list_id: str, request_id: str
195    ) -> Response:
196        """Get status of a specified large list read request.
197
198        Tip: some pages might be available even if process is still in progress.
199        """
200        return self.request(
201            "GET",
202            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/readRequests/{request_id}",
203        )
204
205    def get_large_list_read_data(
206        self,
207        model_id: str,
208        list_id: str,
209        request_id: str,
210        page: str,
211        compress: bool = None,
212    ) -> Response:
213        """Get a page of data of a specified large list read request.
214
215        You can get information about haw many pages are already available using
216        TransactionalConnection.get_large_list_read_status().
217        If there are i.e. 10 available pages, it means that pages from 0 to 9 are ready.
218        You can clean after read using TransactionalConnection.delete_large_list_read().
219        """
220        headers = {"Accept": MIMEType.TEXT_CSV.value}
221        if compress or (compress is None and self.compress):
222            headers["Accept-Encoding"] = ENCODING_GZIP
223        return self.request(
224            "GET",
225            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/readRequests/{request_id}/pages/{page}",
226            headers=headers,
227        )
228
229    def delete_large_list_read(
230        self, model_id: str, list_id: str, request_id: str
231    ) -> Response:
232        """Delete specified large list read request.
233
234        You can call this endpoint to free up space if you don't need the data anymore.
235        If not accessed, data will be cleared after 30 minutes automatically.
236        """
237        return self.request(
238            "DELETE",
239            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/readRequests/{request_id}",
240        )
241
242    def add_list_items(self, model_id: str, list_id: str, data: list[dict]) -> Response:
243        """Add specified items to a list.
244
245        Array of items definitions is expected as documented in the official Anaplan
246        [API documentation](https://anaplanbulkapi20.docs.apiary.io/#AddListItems).
247        """
248        return self.request(
249            "POST",
250            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/items",
251            {"action": "add"},
252            json.dumps({"items": data}),
253        )
254
255    def update_list_items(
256        self, model_id: str, list_id: str, data: list[dict]
257    ) -> Response:
258        """Update a specified items of a list.
259
260        Array of items definitions is expected as documented in the official Anaplan
261        [API documentation](https://anaplanbulkapi20.docs.apiary.io/#UpdateListItems).
262        """
263        return self.request(
264            "PUT",
265            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/items",
266            data=json.dumps({"items": data}),
267        )
268
269    def delete_list_items(
270        self, model_id: str, list_id: str, data: list[dict]
271    ) -> Response:
272        """Delete specified items from a list.
273
274        Data parameter should consist of dictionaries identifying items by id or code.
275        """
276        return self.request(
277            "POST",
278            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/items",
279            {"action": "delete"},
280            json.dumps({"items": data}),
281        )
282
283    def reset_list_index(self, model_id: str, list_id: str) -> Response:
284        """Reset index of a specified numbered list.
285
286        **WARNING**: This action works only for numbered lists that are empty.
287        """
288        return self.request(
289            "POST", f"{self._api_main_url}/models/{model_id}/lists/{list_id}/resetIndex"
290        )
291
292    # Modules
293    def get_modules(self, model_id: str) -> Response:
294        """Get modules information for a specified model."""
295        return self.request("GET", f"{self._api_main_url}/models/{model_id}/modules")
296
297    # Lineitems
298    def get_lineitems(self, model_id: str, details: bool = None) -> Response:
299        """Get all lineitems information for a specified model."""
300        return self.request(
301            "GET",
302            f"{self._api_main_url}/models/{model_id}/lineItems",
303            {"includeAll": self.details if details is None else details},
304        )
305
306    def get_module_lineitems(
307        self, model_id: str, module_id: str, details: bool = None
308    ) -> Response:
309        """Get lineitems information for a specified module."""
310        return self.request(
311            "GET",
312            f"{self._api_main_url}/models/{model_id}/modules/{module_id}/lineItems",
313            {"includeAll": self.details if details is None else details},
314        )
315
316    # Views
317    def get_views(self, model_id: str, details: bool = None) -> Response:
318        """Get all views information for a specified model."""
319        return self.request(
320            "GET",
321            f"{self._api_main_url}/models/{model_id}/views",
322            {"includesubsidiaryviews": self.details if details is None else details},
323        )
324
325    def get_module_views(
326        self, model_id: str, module_id: str, details: bool = None
327    ) -> Response:
328        """Get views information for a specified module."""
329        return self.request(
330            "GET",
331            f"{self._api_main_url}/models/{model_id}/modules/{module_id}/views",
332            {"includesubsidiaryviews": self.details if details is None else details},
333        )
334
335    def get_view_dimensions(self, model_id: str, view_id: str) -> Response:
336        """Get dimensions information for a specified view."""
337        return self.request(
338            "GET", f"{self._api_main_url}/models/{model_id}/views/{view_id}"
339        )
340
341    # Dimensions
342    def get_dimension_items(self, model_id: str, dimension_id: str) -> Response:
343        """Get list of all items within a specified dimension."""
344        return self.request(
345            "GET",
346            f"{self._api_main_url}/models/{model_id}/dimensions/{dimension_id}/items",
347        )
348
349    def get_lineitem_dimensions(self, model_id: str, lineitem_id: str) -> Response:
350        """Get dimensions information for a specified lineitem."""
351        return self.request(
352            "GET",
353            f"{self._api_main_url}/models/{model_id}/lineItems/{lineitem_id}/dimensions",
354        )
355
356    def get_lineitem_dimension_items(
357        self, model_id: str, lineitem_id: str, dimension_id: str
358    ) -> Response:
359        """Get list of items for a specified dimension in the context of a lineitem."""
360        return self.request(
361            "GET",
362            f"{self._api_main_url}/models/{model_id}/lineItems/{lineitem_id}/dimensions/{dimension_id}/items",
363        )
364
365    def get_view_dimension_items(
366        self, model_id: str, view_id: str, dimension_id: str
367    ) -> Response:
368        """Get list of items for a specified dimension in the context of a view."""
369        return self.request(
370            "GET",
371            f"{self._api_main_url}/models/{model_id}/views/{view_id}/dimensions/{dimension_id}/items",
372        )
373
374    def check_dimension_items_id(
375        self, model_id: str, dimension_id: str, data: dict
376    ) -> Response:
377        """Get ids of dimension's items specified by names or codes."""
378        return self.request(
379            "POST",
380            f"{self._api_main_url}/models/{model_id}/dimensions/{dimension_id}/items",
381            data=json.dumps(data),
382        )
383
384    # Cells
385    def get_cell_data(
386        self,
387        model_id: str,
388        view_id: str,
389        accept: MIMEType = None,
390        pages: Iterable[str] = None,
391    ) -> Response:
392        """Get cells values for a specified view, up to a million cells.
393
394        **WARNING**: This query can be used to retrieve information for smaller views.
395        For larger views use large_cell_read functions.
396
397        Pages argument should be iterable collection of dimensionId & itemId strings
398        in a form of key-value pairs joined by ":" (colon),
399        i.e. ["101000000026:330000000028","20000000012:587000000000"]
400        Returned data can be either in JSON (default), CSV or CSV-escaped format.
401        More information about this endpoint can be found in the official Anaplan
402        [API documentation](https://anaplanbulkapi20.docs.apiary.io/#RetrieveCellDataView).
403        """
404        headers = self._session.headers.copy()
405        if accept:
406            headers["Accept"] = accept.value
407        params = {}
408        if pages:
409            params["pages"] = ",".join(pages)
410        if headers["Accept"] == MIMEType.APP_JSON.value:
411            params["format"] = "v1"
412        return self.request(
413            "GET",
414            f"{self._api_main_url}/models/{model_id}/views/{view_id}/data",
415            params=params,
416            headers=headers,
417        )
418
419    def start_large_cell_read(
420        self, model_id: str, view_id: str, mode: ExportType
421    ) -> Response:
422        """Start large cell read, which allows getting unlimited cells for a view.
423
424        Returned data grid mode should be set using apapi.utils.ExportType.
425        """
426        return self.request(
427            "POST",
428            f"{self._api_main_url}/models/{model_id}/views/{view_id}/readRequests",
429            data=json.dumps({"exportType": mode.value}),
430        )
431
432    def get_large_cell_read_status(
433        self, model_id: str, view_id: str, request_id: str
434    ) -> Response:
435        """Get status of a specified large cell read request.
436
437        Tip: some pages might be available even if process is still in progress.
438        """
439        return self.request(
440            "GET",
441            f"{self._api_main_url}/models/{model_id}/views/{view_id}/readRequests/{request_id}",
442        )
443
444    def get_large_cell_read_data(
445        self,
446        model_id: str,
447        view_id: str,
448        request_id: str,
449        page: str,
450        compress: bool = None,
451    ) -> Response:
452        """Get a page of data of a specified large cell read request.
453
454        You can get information about haw many pages are already available using
455        TransactionalConnection.get_large_cell_read_status().
456        If there are i.e. 10 available pages, it means that pages from 0 to 9 are ready.
457        You can clean after read using TransactionalConnection.delete_large_cell_read().
458        """
459        headers = {"Accept": MIMEType.TEXT_CSV.value}
460        if compress or (compress is None and self.compress):
461            headers["Accept-Encoding"] = ENCODING_GZIP
462        return self.request(
463            "GET",
464            f"{self._api_main_url}/models/{model_id}/views/{view_id}/readRequests/{request_id}/pages/{page}",
465            headers=headers,
466        )
467
468    def delete_large_cell_read(
469        self, model_id: str, view_id: str, request_id: str
470    ) -> Response:
471        """Delete specified large cell read request.
472
473        You can call this endpoint to free up space if you don't need the data anymore.
474        If not accessed, data will be cleared after 30 minutes automatically.
475        """
476        return self.request(
477            "DELETE",
478            f"{self._api_main_url}/models/{model_id}/views/{view_id}/readRequests/{request_id}",
479        )
480
481    def post_cell_data(
482        self, model_id: str, module_id: str, data: list[dict]
483    ) -> Response:
484        """Update value of specific cells in a module.
485
486        Data argument should be a list of dictionaries containing lineItemId,
487        dimensions definition (ids of dimensions and items), and new value.
488        More information about this endpoint can be found in the official Anaplan
489        [API documentation](https://anaplanbulkapi20.docs.apiary.io/#WriteCellDataByCoordinateModule).
490        """
491        return self.request(
492            "POST",
493            f"{self._api_main_url}/models/{model_id}/modules/{module_id}/data",
494            data=json.dumps(data),
495        )

Anaplan connection with Transactional API functions.

def get_users(self) -> requests.models.Response:
22    def get_users(self) -> Response:
23        """Get info about all users in the tenant."""
24        return self.request("GET", f"{self._api_main_url}/users")

Get info about all users in the tenant.

def get_me(self) -> requests.models.Response:
26    def get_me(self) -> Response:
27        """Get info about me."""
28        return self.request("GET", f"{self._api_main_url}/users/me")

Get info about me.

def get_user(self, user_id: str) -> requests.models.Response:
30    def get_user(self, user_id: str) -> Response:
31        """Get info about a specified user."""
32        return self.request("GET", f"{self._api_main_url}/users/{user_id}")

Get info about a specified user.

def get_workspace_users(self, workspace_id: str) -> requests.models.Response:
34    def get_workspace_users(self, workspace_id: str) -> Response:
35        """Get info about users with access to a specified workspace."""
36        return self.request(
37            "GET",
38            f"{self._api_main_url}/workspaces/{workspace_id}/users",
39        )

Get info about users with access to a specified workspace.

def get_workspace_admins(self, workspace_id: str) -> requests.models.Response:
41    def get_workspace_admins(self, workspace_id: str) -> Response:
42        """Get info about all administrators of a specified workspace."""
43        return self.request(
44            "GET",
45            f"{self._api_main_url}/workspaces/{workspace_id}/admins",
46            {"limit": PAGING_LIMIT},  # needed for this endpoint, as default is 20
47        )

Get info about all administrators of a specified workspace.

def get_model_users(self, model_id: str) -> requests.models.Response:
49    def get_model_users(self, model_id: str) -> Response:
50        """Get info about users with access to a specified model."""
51        return self.request("GET", f"{self._api_main_url}/models/{model_id}/users")

Get info about users with access to a specified model.

def get_workspaces(self, details: bool = None) -> requests.models.Response:
54    def get_workspaces(self, details: bool = None) -> Response:
55        """Get info about all workspaces in the tenant."""
56        return self.request(
57            "GET",
58            f"{self._api_main_url}/workspaces",
59            {"tenantDetails": self.details if details is None else details},
60        )

Get info about all workspaces in the tenant.

def get_workspace( self, workspace_id: str, details: bool = None) -> requests.models.Response:
62    def get_workspace(self, workspace_id: str, details: bool = None) -> Response:
63        """Get info about all a specified workspace."""
64        return self.request(
65            "GET",
66            f"{self._api_main_url}/workspaces/{workspace_id}",
67            {"tenantDetails": self.details if details is None else details},
68        )

Get info about all a specified workspace.

def get_user_workspaces(self, user_id: str) -> requests.models.Response:
70    def get_user_workspaces(self, user_id: str) -> Response:
71        """Get info about all workspaces to which a specified user has access."""
72        return self.request("GET", f"{self._api_main_url}/users/{user_id}/workspaces")

Get info about all workspaces to which a specified user has access.

def get_models(self, details: bool = None) -> requests.models.Response:
75    def get_models(self, details: bool = None) -> Response:
76        """Get info about all models in the tenant."""
77        return self.request(
78            "GET",
79            f"{self._api_main_url}/models",
80            {"modelDetails": self.details if details is None else details},
81        )

Get info about all models in the tenant.

def get_workspace_models( self, workspace_id: str, details: bool = None) -> requests.models.Response:
83    def get_workspace_models(self, workspace_id: str, details: bool = None) -> Response:
84        """Get info about all models within a specified workspace."""
85        return self.request(
86            "GET",
87            f"{self._api_main_url}/workspaces/{workspace_id}/models",
88            {"modelDetails": self.details if details is None else details},
89        )

Get info about all models within a specified workspace.

def get_model(self, model_id: str, details: bool = None) -> requests.models.Response:
91    def get_model(self, model_id: str, details: bool = None) -> Response:
92        """Get info about a specified model."""
93        return self.request(
94            "GET",
95            f"{self._api_main_url}/models/{model_id}",
96            {"modelDetails": self.details if details is None else details},
97        )

Get info about a specified model.

def get_user_models(self, user_id: str) -> requests.models.Response:
 99    def get_user_models(self, user_id: str) -> Response:
100        """Get info about all models to which a specified user has access."""
101        return self.request("GET", f"{self._api_main_url}/users/{user_id}/models")

Get info about all models to which a specified user has access.

def delete_models( self, workspace_id: str, models_ids: [<class 'str'>]) -> requests.models.Response:
103    def delete_models(self, workspace_id: str, models_ids: [str]) -> Response:
104        """Delete models from a workspace.
105
106        **WARNING**: This query is destructive - use with caution! It will only work on
107        closed models - you can close a model in Anaplan web interface via Manage Tasks.
108        """
109        return self.request(
110            "POST",
111            f"{self._api_main_url}/workspaces/{workspace_id}/bulkDeleteModels",
112            data=json.dumps({"modelIdsToDelete": models_ids}),
113        )

Delete models from a workspace.

WARNING: This query is destructive - use with caution! It will only work on closed models - you can close a model in Anaplan web interface via Manage Tasks.

def get_fiscal_year(self, model_id: str):
116    def get_fiscal_year(self, model_id: str):
117        """Get current fiscal year setting for a specified model."""
118        return self.request(
119            "GET", f"{self._api_main_url}/models/{model_id}/modelCalendar"
120        )

Get current fiscal year setting for a specified model.

def set_fiscal_year(self, model_id: str, data: str):
122    def set_fiscal_year(self, model_id: str, data: str):
123        """Set current fiscal year setting."""
124        return self.request(
125            "PUT",
126            f"{self._api_main_url}/models/{model_id}/modelCalendar/fiscalYear",
127            data=json.dumps({"year": data}),
128        )

Set current fiscal year setting.

def get_current_period(self, model_id: str):
130    def get_current_period(self, model_id: str):
131        """Get current period setting a specified model."""
132        return self.request(
133            "GET", f"{self._api_main_url}/models/{model_id}/currentPeriod"
134        )

Get current period setting a specified model.

def set_current_period(self, model_id: str, data: str):
136    def set_current_period(self, model_id: str, data: str):
137        """Set current period setting (data should have YYYY-MM-DD format)."""
138        return self.request(
139            "PUT",
140            f"{self._api_main_url}/models/{model_id}/currentPeriod",
141            data=json.dumps({"date": data}),
142        )

Set current period setting (data should have YYYY-MM-DD format).

def get_versions(self, model_id: str):
145    def get_versions(self, model_id: str):
146        """Get versions information and settings."""
147        return self.request("GET", f"{self._api_main_url}/models/{model_id}/versions")

Get versions information and settings.

def set_version_switchover(self, model_id: str, version_id: str, data: str):
149    def set_version_switchover(self, model_id: str, version_id: str, data: str):
150        """Set version's switchover (data should have YYYY-MM-DD format)."""
151        return self.request(
152            "PUT",
153            f"{self._api_main_url}/models/{model_id}/versions/{version_id}/switchover",
154            data=json.dumps({"date": data}),
155        )

Set version's switchover (data should have YYYY-MM-DD format).

def get_lists(self, model_id: str) -> requests.models.Response:
158    def get_lists(self, model_id: str) -> Response:
159        """Get lists information for a specified model."""
160        return self.request("GET", f"{self._api_main_url}/models/{model_id}/lists")

Get lists information for a specified model.

def get_list(self, model_id: str, list_id: str) -> requests.models.Response:
162    def get_list(self, model_id: str, list_id: str) -> Response:
163        """Get information about a specified list."""
164        return self.request(
165            "GET", f"{self._api_main_url}/models/{model_id}/lists/{list_id}"
166        )

Get information about a specified list.

def get_list_items( self, model_id: str, list_id: str, details: bool = None, accept: apapi.utils.MIMEType = None) -> requests.models.Response:
168    def get_list_items(
169        self, model_id: str, list_id: str, details: bool = None, accept: MIMEType = None
170    ) -> Response:
171        """Get list's items, up to a million lines.
172
173        **WARNING**: This query can be used to retrieve information for smaller lists.
174        For larger lists use large_list_read functions.
175
176        Extra details (selective access, subsets and properties) are available.
177        Returned data can be either in JSON (default) or CSV format.
178        """
179        return self.request(
180            "GET",
181            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/items",
182            {"includeAll": self.details if details is None else details},
183            headers={"Accept": accept.value} if accept else None,
184        )

Get list's items, up to a million lines.

WARNING: This query can be used to retrieve information for smaller lists. For larger lists use large_list_read functions.

Extra details (selective access, subsets and properties) are available. Returned data can be either in JSON (default) or CSV format.

def start_large_list_read(self, model_id: str, list_id: str) -> requests.models.Response:
186    def start_large_list_read(self, model_id: str, list_id: str) -> Response:
187        """Start large list read, which allows getting unlimited list's items."""
188        return self.request(
189            "POST",
190            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/readRequests",
191        )

Start large list read, which allows getting unlimited list's items.

def get_large_list_read_status( self, model_id: str, list_id: str, request_id: str) -> requests.models.Response:
193    def get_large_list_read_status(
194        self, model_id: str, list_id: str, request_id: str
195    ) -> Response:
196        """Get status of a specified large list read request.
197
198        Tip: some pages might be available even if process is still in progress.
199        """
200        return self.request(
201            "GET",
202            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/readRequests/{request_id}",
203        )

Get status of a specified large list read request.

Tip: some pages might be available even if process is still in progress.

def get_large_list_read_data( self, model_id: str, list_id: str, request_id: str, page: str, compress: bool = None) -> requests.models.Response:
205    def get_large_list_read_data(
206        self,
207        model_id: str,
208        list_id: str,
209        request_id: str,
210        page: str,
211        compress: bool = None,
212    ) -> Response:
213        """Get a page of data of a specified large list read request.
214
215        You can get information about haw many pages are already available using
216        TransactionalConnection.get_large_list_read_status().
217        If there are i.e. 10 available pages, it means that pages from 0 to 9 are ready.
218        You can clean after read using TransactionalConnection.delete_large_list_read().
219        """
220        headers = {"Accept": MIMEType.TEXT_CSV.value}
221        if compress or (compress is None and self.compress):
222            headers["Accept-Encoding"] = ENCODING_GZIP
223        return self.request(
224            "GET",
225            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/readRequests/{request_id}/pages/{page}",
226            headers=headers,
227        )

Get a page of data of a specified large list read request.

You can get information about haw many pages are already available using TransactionalConnection.get_large_list_read_status(). If there are i.e. 10 available pages, it means that pages from 0 to 9 are ready. You can clean after read using TransactionalConnection.delete_large_list_read().

def delete_large_list_read( self, model_id: str, list_id: str, request_id: str) -> requests.models.Response:
229    def delete_large_list_read(
230        self, model_id: str, list_id: str, request_id: str
231    ) -> Response:
232        """Delete specified large list read request.
233
234        You can call this endpoint to free up space if you don't need the data anymore.
235        If not accessed, data will be cleared after 30 minutes automatically.
236        """
237        return self.request(
238            "DELETE",
239            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/readRequests/{request_id}",
240        )

Delete specified large list read request.

You can call this endpoint to free up space if you don't need the data anymore. If not accessed, data will be cleared after 30 minutes automatically.

def add_list_items( self, model_id: str, list_id: str, data: list[dict]) -> requests.models.Response:
242    def add_list_items(self, model_id: str, list_id: str, data: list[dict]) -> Response:
243        """Add specified items to a list.
244
245        Array of items definitions is expected as documented in the official Anaplan
246        [API documentation](https://anaplanbulkapi20.docs.apiary.io/#AddListItems).
247        """
248        return self.request(
249            "POST",
250            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/items",
251            {"action": "add"},
252            json.dumps({"items": data}),
253        )

Add specified items to a list.

Array of items definitions is expected as documented in the official Anaplan API documentation.

def update_list_items( self, model_id: str, list_id: str, data: list[dict]) -> requests.models.Response:
255    def update_list_items(
256        self, model_id: str, list_id: str, data: list[dict]
257    ) -> Response:
258        """Update a specified items of a list.
259
260        Array of items definitions is expected as documented in the official Anaplan
261        [API documentation](https://anaplanbulkapi20.docs.apiary.io/#UpdateListItems).
262        """
263        return self.request(
264            "PUT",
265            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/items",
266            data=json.dumps({"items": data}),
267        )

Update a specified items of a list.

Array of items definitions is expected as documented in the official Anaplan API documentation.

def delete_list_items( self, model_id: str, list_id: str, data: list[dict]) -> requests.models.Response:
269    def delete_list_items(
270        self, model_id: str, list_id: str, data: list[dict]
271    ) -> Response:
272        """Delete specified items from a list.
273
274        Data parameter should consist of dictionaries identifying items by id or code.
275        """
276        return self.request(
277            "POST",
278            f"{self._api_main_url}/models/{model_id}/lists/{list_id}/items",
279            {"action": "delete"},
280            json.dumps({"items": data}),
281        )

Delete specified items from a list.

Data parameter should consist of dictionaries identifying items by id or code.

def reset_list_index(self, model_id: str, list_id: str) -> requests.models.Response:
283    def reset_list_index(self, model_id: str, list_id: str) -> Response:
284        """Reset index of a specified numbered list.
285
286        **WARNING**: This action works only for numbered lists that are empty.
287        """
288        return self.request(
289            "POST", f"{self._api_main_url}/models/{model_id}/lists/{list_id}/resetIndex"
290        )

Reset index of a specified numbered list.

WARNING: This action works only for numbered lists that are empty.

def get_modules(self, model_id: str) -> requests.models.Response:
293    def get_modules(self, model_id: str) -> Response:
294        """Get modules information for a specified model."""
295        return self.request("GET", f"{self._api_main_url}/models/{model_id}/modules")

Get modules information for a specified model.

def get_lineitems(self, model_id: str, details: bool = None) -> requests.models.Response:
298    def get_lineitems(self, model_id: str, details: bool = None) -> Response:
299        """Get all lineitems information for a specified model."""
300        return self.request(
301            "GET",
302            f"{self._api_main_url}/models/{model_id}/lineItems",
303            {"includeAll": self.details if details is None else details},
304        )

Get all lineitems information for a specified model.

def get_module_lineitems( self, model_id: str, module_id: str, details: bool = None) -> requests.models.Response:
306    def get_module_lineitems(
307        self, model_id: str, module_id: str, details: bool = None
308    ) -> Response:
309        """Get lineitems information for a specified module."""
310        return self.request(
311            "GET",
312            f"{self._api_main_url}/models/{model_id}/modules/{module_id}/lineItems",
313            {"includeAll": self.details if details is None else details},
314        )

Get lineitems information for a specified module.

def get_views(self, model_id: str, details: bool = None) -> requests.models.Response:
317    def get_views(self, model_id: str, details: bool = None) -> Response:
318        """Get all views information for a specified model."""
319        return self.request(
320            "GET",
321            f"{self._api_main_url}/models/{model_id}/views",
322            {"includesubsidiaryviews": self.details if details is None else details},
323        )

Get all views information for a specified model.

def get_module_views( self, model_id: str, module_id: str, details: bool = None) -> requests.models.Response:
325    def get_module_views(
326        self, model_id: str, module_id: str, details: bool = None
327    ) -> Response:
328        """Get views information for a specified module."""
329        return self.request(
330            "GET",
331            f"{self._api_main_url}/models/{model_id}/modules/{module_id}/views",
332            {"includesubsidiaryviews": self.details if details is None else details},
333        )

Get views information for a specified module.

def get_view_dimensions(self, model_id: str, view_id: str) -> requests.models.Response:
335    def get_view_dimensions(self, model_id: str, view_id: str) -> Response:
336        """Get dimensions information for a specified view."""
337        return self.request(
338            "GET", f"{self._api_main_url}/models/{model_id}/views/{view_id}"
339        )

Get dimensions information for a specified view.

def get_dimension_items(self, model_id: str, dimension_id: str) -> requests.models.Response:
342    def get_dimension_items(self, model_id: str, dimension_id: str) -> Response:
343        """Get list of all items within a specified dimension."""
344        return self.request(
345            "GET",
346            f"{self._api_main_url}/models/{model_id}/dimensions/{dimension_id}/items",
347        )

Get list of all items within a specified dimension.

def get_lineitem_dimensions(self, model_id: str, lineitem_id: str) -> requests.models.Response:
349    def get_lineitem_dimensions(self, model_id: str, lineitem_id: str) -> Response:
350        """Get dimensions information for a specified lineitem."""
351        return self.request(
352            "GET",
353            f"{self._api_main_url}/models/{model_id}/lineItems/{lineitem_id}/dimensions",
354        )

Get dimensions information for a specified lineitem.

def get_lineitem_dimension_items( self, model_id: str, lineitem_id: str, dimension_id: str) -> requests.models.Response:
356    def get_lineitem_dimension_items(
357        self, model_id: str, lineitem_id: str, dimension_id: str
358    ) -> Response:
359        """Get list of items for a specified dimension in the context of a lineitem."""
360        return self.request(
361            "GET",
362            f"{self._api_main_url}/models/{model_id}/lineItems/{lineitem_id}/dimensions/{dimension_id}/items",
363        )

Get list of items for a specified dimension in the context of a lineitem.

def get_view_dimension_items( self, model_id: str, view_id: str, dimension_id: str) -> requests.models.Response:
365    def get_view_dimension_items(
366        self, model_id: str, view_id: str, dimension_id: str
367    ) -> Response:
368        """Get list of items for a specified dimension in the context of a view."""
369        return self.request(
370            "GET",
371            f"{self._api_main_url}/models/{model_id}/views/{view_id}/dimensions/{dimension_id}/items",
372        )

Get list of items for a specified dimension in the context of a view.

def check_dimension_items_id( self, model_id: str, dimension_id: str, data: dict) -> requests.models.Response:
374    def check_dimension_items_id(
375        self, model_id: str, dimension_id: str, data: dict
376    ) -> Response:
377        """Get ids of dimension's items specified by names or codes."""
378        return self.request(
379            "POST",
380            f"{self._api_main_url}/models/{model_id}/dimensions/{dimension_id}/items",
381            data=json.dumps(data),
382        )

Get ids of dimension's items specified by names or codes.

def get_cell_data( self, model_id: str, view_id: str, accept: apapi.utils.MIMEType = None, pages: Iterable[str] = None) -> requests.models.Response:
385    def get_cell_data(
386        self,
387        model_id: str,
388        view_id: str,
389        accept: MIMEType = None,
390        pages: Iterable[str] = None,
391    ) -> Response:
392        """Get cells values for a specified view, up to a million cells.
393
394        **WARNING**: This query can be used to retrieve information for smaller views.
395        For larger views use large_cell_read functions.
396
397        Pages argument should be iterable collection of dimensionId & itemId strings
398        in a form of key-value pairs joined by ":" (colon),
399        i.e. ["101000000026:330000000028","20000000012:587000000000"]
400        Returned data can be either in JSON (default), CSV or CSV-escaped format.
401        More information about this endpoint can be found in the official Anaplan
402        [API documentation](https://anaplanbulkapi20.docs.apiary.io/#RetrieveCellDataView).
403        """
404        headers = self._session.headers.copy()
405        if accept:
406            headers["Accept"] = accept.value
407        params = {}
408        if pages:
409            params["pages"] = ",".join(pages)
410        if headers["Accept"] == MIMEType.APP_JSON.value:
411            params["format"] = "v1"
412        return self.request(
413            "GET",
414            f"{self._api_main_url}/models/{model_id}/views/{view_id}/data",
415            params=params,
416            headers=headers,
417        )

Get cells values for a specified view, up to a million cells.

WARNING: This query can be used to retrieve information for smaller views. For larger views use large_cell_read functions.

Pages argument should be iterable collection of dimensionId & itemId strings in a form of key-value pairs joined by ":" (colon), i.e. ["101000000026:330000000028","20000000012:587000000000"] Returned data can be either in JSON (default), CSV or CSV-escaped format. More information about this endpoint can be found in the official Anaplan API documentation.

def start_large_cell_read( self, model_id: str, view_id: str, mode: apapi.utils.ExportType) -> requests.models.Response:
419    def start_large_cell_read(
420        self, model_id: str, view_id: str, mode: ExportType
421    ) -> Response:
422        """Start large cell read, which allows getting unlimited cells for a view.
423
424        Returned data grid mode should be set using apapi.utils.ExportType.
425        """
426        return self.request(
427            "POST",
428            f"{self._api_main_url}/models/{model_id}/views/{view_id}/readRequests",
429            data=json.dumps({"exportType": mode.value}),
430        )

Start large cell read, which allows getting unlimited cells for a view.

Returned data grid mode should be set using apapi.utils.ExportType.

def get_large_cell_read_status( self, model_id: str, view_id: str, request_id: str) -> requests.models.Response:
432    def get_large_cell_read_status(
433        self, model_id: str, view_id: str, request_id: str
434    ) -> Response:
435        """Get status of a specified large cell read request.
436
437        Tip: some pages might be available even if process is still in progress.
438        """
439        return self.request(
440            "GET",
441            f"{self._api_main_url}/models/{model_id}/views/{view_id}/readRequests/{request_id}",
442        )

Get status of a specified large cell read request.

Tip: some pages might be available even if process is still in progress.

def get_large_cell_read_data( self, model_id: str, view_id: str, request_id: str, page: str, compress: bool = None) -> requests.models.Response:
444    def get_large_cell_read_data(
445        self,
446        model_id: str,
447        view_id: str,
448        request_id: str,
449        page: str,
450        compress: bool = None,
451    ) -> Response:
452        """Get a page of data of a specified large cell read request.
453
454        You can get information about haw many pages are already available using
455        TransactionalConnection.get_large_cell_read_status().
456        If there are i.e. 10 available pages, it means that pages from 0 to 9 are ready.
457        You can clean after read using TransactionalConnection.delete_large_cell_read().
458        """
459        headers = {"Accept": MIMEType.TEXT_CSV.value}
460        if compress or (compress is None and self.compress):
461            headers["Accept-Encoding"] = ENCODING_GZIP
462        return self.request(
463            "GET",
464            f"{self._api_main_url}/models/{model_id}/views/{view_id}/readRequests/{request_id}/pages/{page}",
465            headers=headers,
466        )

Get a page of data of a specified large cell read request.

You can get information about haw many pages are already available using TransactionalConnection.get_large_cell_read_status(). If there are i.e. 10 available pages, it means that pages from 0 to 9 are ready. You can clean after read using TransactionalConnection.delete_large_cell_read().

def delete_large_cell_read( self, model_id: str, view_id: str, request_id: str) -> requests.models.Response:
468    def delete_large_cell_read(
469        self, model_id: str, view_id: str, request_id: str
470    ) -> Response:
471        """Delete specified large cell read request.
472
473        You can call this endpoint to free up space if you don't need the data anymore.
474        If not accessed, data will be cleared after 30 minutes automatically.
475        """
476        return self.request(
477            "DELETE",
478            f"{self._api_main_url}/models/{model_id}/views/{view_id}/readRequests/{request_id}",
479        )

Delete specified large cell read request.

You can call this endpoint to free up space if you don't need the data anymore. If not accessed, data will be cleared after 30 minutes automatically.

def post_cell_data( self, model_id: str, module_id: str, data: list[dict]) -> requests.models.Response:
481    def post_cell_data(
482        self, model_id: str, module_id: str, data: list[dict]
483    ) -> Response:
484        """Update value of specific cells in a module.
485
486        Data argument should be a list of dictionaries containing lineItemId,
487        dimensions definition (ids of dimensions and items), and new value.
488        More information about this endpoint can be found in the official Anaplan
489        [API documentation](https://anaplanbulkapi20.docs.apiary.io/#WriteCellDataByCoordinateModule).
490        """
491        return self.request(
492            "POST",
493            f"{self._api_main_url}/models/{model_id}/modules/{module_id}/data",
494            data=json.dumps(data),
495        )

Update value of specific cells in a module.

Data argument should be a list of dictionaries containing lineItemId, dimensions definition (ids of dimensions and items), and new value. More information about this endpoint can be found in the official Anaplan API documentation.