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 )
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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).
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.
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).
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.
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.
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.
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.
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.
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().
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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().
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.
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.