1
2 from io import StringIO
3 import urllib
4 import json
5 import requests
6 import math
7 import time
8
10 """
11 AnalyticsClient provides the python based language binding to the https based API of Zoho Analytics.
12 """
13
14 CLIENT_VERSION = "2.5.0"
15 COMMON_ENCODE_CHAR = "UTF-8"
16
17 - def __init__(self, client_id, client_secret, refresh_token):
18 """
19 Creates a new C{AnalyticsClient} instance.
20 @param client_id: User client id for OAUth
21 @type client_id:string
22 @param client_secret: User client secret for OAuth
23 @type client_secret:string
24 @param refresh_token: User's refresh token for OAUth).
25 @type refresh_token:string
26 """
27
28 self.proxy = False
29 self.proxy_host = None
30 self.proxy_port = None
31 self.proxy_user_name = None
32 self.proxy_password = None
33
34 self.accounts_server_url = "https://@@ACCOUNTS_URL"
35 self.analytics_server_url = "https://@@ANALYTICS_URL"
36
37 self.client_id = client_id
38 self.client_secret = client_secret
39 self.refresh_token = refresh_token
40 self.access_token = None
41
43 """
44 Returns a new C{OrgAPI} instance.
45 @param org_id: The id of the organization.
46 @type org_id:string
47 """
48 org_instance = AnalyticsClient.OrgAPI(self, org_id)
49 return org_instance
50
52 """
53 Returns a new C{WorkspaceAPI} instance.
54 @param org_id: The id of the organization.
55 @type org_id:string
56 @param workspace_id: The id of the workspace.
57 @type workspace_id:string
58 """
59 workspace_instance = AnalyticsClient.WorkspaceAPI(self, org_id, workspace_id)
60 return workspace_instance
61
63 """
64 Returns a new C{ViewAPI} instance.
65 @param org_id: The id of the organization.
66 @type org_id:string
67 @param workspace_id: The id of the workspace.
68 @type workspace_id:string
69 @param view_id: The id of the view.
70 @type view_id:string
71 """
72 view_instance = AnalyticsClient.ViewAPI(self, org_id, workspace_id, view_id)
73 return view_instance
74
76 """
77 Returns a new C{BulkAPI} instance.
78 @param org_id: The id of the organization.
79 @type org_id:string
80 @param workspace_id: The id of the workspace.
81 @type workspace_id:string
82 """
83 data_instance = AnalyticsClient.BulkAPI(self, org_id, workspace_id)
84 return data_instance
85
86
88 """
89 Returns list of all accessible organizations.
90 @return: Organization list.
91 @rtype:list
92 @raise ServerError: If the server has received the request but did not process the request
93 due to some error.
94 @raise ParseError: If the server has responded but client was not able to parse the response.
95 """
96 endpoint = "/restapi/v2/orgs"
97 response = self.send_api_request("GET", endpoint, None, None)
98 return response["data"]["orgs"]
99
101 """
102 Returns list of all accessible workspaces.
103 @return: Workspace list.
104 @rtype:list
105 @raise ServerError: If the server has received the request but did not process the request
106 due to some error.
107 @raise ParseError: If the server has responded but client was not able to parse the response.
108 """
109 endpoint = "/restapi/v2/workspaces"
110 response = self.send_api_request("GET", endpoint, None, None)
111 return response["data"]
112
114 """
115 Returns list of owned workspaces.
116 @return: Workspace list.
117 @rtype:list
118 @raise ServerError: If the server has received the request but did not process the request
119 due to some error.
120 @raise ParseError: If the server has responded but client was not able to parse the response.
121 """
122 endpoint = "/restapi/v2/workspaces/owned"
123 response = self.send_api_request("GET", endpoint, None, None)
124 return response["data"]["workspaces"]
125
127 """
128 Returns list of shared workspaces.
129 @return: Workspace list.
130 @rtype:list
131 @raise ServerError: If the server has received the request but did not process the request
132 due to some error.
133 @raise ParseError: If the server has responded but client was not able to parse the response.
134 """
135 endpoint = "/restapi/v2/workspaces/shared"
136 response = self.send_api_request("GET", endpoint, None, None)
137 return response["data"]["workspaces"]
138
140 """
141 Returns list of recently accessed views.
142 @return: View list.
143 @rtype:list
144 @raise ServerError: If the server has received the request but did not process the request
145 due to some error.
146 @raise ParseError: If the server has responded but client was not able to parse the response.
147 """
148 endpoint = "/restapi/v2/recentviews"
149 response = self.send_api_request("GET", endpoint, None, None)
150 return response["data"]["views"]
151
153 """
154 Returns list of all accessible dashboards.
155 @return: Dashboard list.
156 @rtype:list
157 @raise ServerError: If the server has received the request but did not process the request
158 due to some error.
159 @raise ParseError: If the server has responded but client was not able to parse the response.
160 """
161 endpoint = "/restapi/v2/dashboards"
162 response = self.send_api_request("GET", endpoint, None, None)
163 return response["data"]
164
166 """
167 Returns list of owned dashboards.
168 @return: Dashboard list.
169 @rtype:list
170 @raise ServerError: If the server has received the request but did not process the request
171 due to some error.
172 @raise ParseError: If the server has responded but client was not able to parse the response.
173 """
174 endpoint = "/restapi/v2/dashboards/owned"
175 response = self.send_api_request("GET", endpoint, None, None)
176 return response["data"]["views"]
177
179 """
180 Returns list of shared dashboards.
181 @return: Dashboard list.
182 @rtype:list
183 @raise ServerError: If the server has received the request but did not process the request
184 due to some error.
185 @raise ParseError: If the server has responded but client was not able to parse the response.
186 """
187 endpoint = "/restapi/v2/dashboards/shared"
188 response = self.send_api_request("GET", endpoint, None, None)
189 return response["data"]["views"]
190
192 """
193 Returns details of the specified workspace.
194 @param workspace_id: Id of the workspace.
195 @type workspace_id: string
196 @raise ServerError: If the server has received the request but did not process the request due to some error.
197 @raise ParseError: If the server has responded but client was not able to parse the response.
198 @return: Workspace details.
199 @rtype:dictionary
200 """
201 endpoint = "/restapi/v2/workspaces/" + workspace_id
202 response = self.send_api_request("GET", endpoint, None, None)
203 return response["data"]["workspaces"]
204
206 """
207 Returns details of the specified view.
208 @param view_id: Id of the view.
209 @type view_id: string
210 @param config: Contains any additional control parameters. Can be C{None}.
211 @type config:dictionary
212 @raise ServerError: If the server has received the request but did not process the request due to some error.
213 @raise ParseError: If the server has responded but client was not able to parse the response.
214 @return: View details.
215 @rtype:dictionary
216 """
217 endpoint = "/restapi/v2/views/" + view_id
218 response = self.send_api_request("GET", endpoint, config, None)
219 return response["data"]["views"]
220
221
223 """
224 OrgAPI contains organization level operations.
225 """
227 self.ac = ac
228 self.request_headers = {}
229 self.request_headers["ZANALYTICS-ORGID"] = org_id
230
232 """
233 Create a blank workspace in the specified organization.
234 @param workspace_name: The name of the workspace.
235 @type workspace_name:string
236 @param config: Contains any additional control parameters. Can be C{None}.
237 @type config:dictionary
238 @raise ServerError: If the server has received the request but did not process the request due to some error.
239 @raise ParseError: If the server has responded but client was not able to parse the response.
240 @return: Created workspace id.
241 @rtype:string
242 """
243 config["workspaceName"] = workspace_name
244 endpoint = "/restapi/v2/workspaces/"
245 response = self.ac.send_api_request("POST", endpoint, config, self.request_headers)
246 return int(response["data"]["workspaceId"])
247
249 """
250 Returns list of admins for a specified organization.
251 @raise ServerError: If the server has received the request but did not process the request due to some error.
252 @raise ParseError: If the server has responded but client was not able to parse the response.
253 @return: Organization admin list.
254 @rtype:list
255 """
256 endpoint = "/restapi/v2/orgadmins"
257 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
258 return response["data"]["orgAdmins"]
259
261 """
262 Returns list of users for the specified organization.
263 @raise ServerError: If the server has received the request but did not process the request due to some error.
264 @raise ParseError: If the server has responded but client was not able to parse the response.
265 @return: User list.
266 @rtype:list
267 """
268 endpoint = "/restapi/v2/users"
269 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
270 return response["data"]["users"]
271
272 - def add_users(self, email_ids, config = {}):
273 """
274 Add users to the specified organization.
275 @param email_ids: The email address of the users to be added.
276 @type email_ids:list
277 @param config: Contains any additional control parameters. Can be C{None}.
278 @type config:dictionary
279 @raise ServerError: If the server has received the request but did not process the request due to some error.
280 @raise ParseError: If the server has responded but client was not able to parse the response.
281 """
282 config["emailIds"] = email_ids
283 endpoint = "/restapi/v2/users"
284 self.ac.send_api_request("POST", endpoint, config, self.request_headers)
285
287 """
288 Remove users from the specified organization.
289 @param email_ids: The email address of the users to be removed.
290 @type email_ids:list
291 @param config: Contains any additional control parameters. Can be C{None}.
292 @type config:dictionary
293 @raise ServerError: If the server has received the request but did not process the request due to some error.
294 @raise ParseError: If the server has responded but client was not able to parse the response.
295 """
296 config["emailIds"] = email_ids
297 endpoint = "/restapi/v2/users"
298 self.ac.send_api_request("DELETE", endpoint, config, self.request_headers)
299
301 """
302 Activate users in the specified organization.
303 @param email_ids: The email address of the users to be activated.
304 @type email_ids:list
305 @param config: Contains any additional control parameters. Can be C{None}.
306 @type config:dictionary
307 @raise ServerError: If the server has received the request but did not process the request due to some error.
308 @raise ParseError: If the server has responded but client was not able to parse the response.
309 """
310 config["emailIds"] = email_ids
311 endpoint = "/restapi/v2/users/active"
312 self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
313
315 """
316 Deactivate users in the specified organization.
317 @param email_ids: The email address of the users to be deactivated.
318 @type email_ids:list
319 @param config: Contains any additional control parameters. Can be C{None}.
320 @type config:dictionary
321 @raise ServerError: If the server has received the request but did not process the request due to some error.
322 @raise ParseError: If the server has responded but client was not able to parse the response.
323 """
324 config["emailIds"] = email_ids
325 endpoint = "/restapi/v2/users/inactive"
326 self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
327
329 """
330 Change role for the specified users.
331 @param email_ids: The email address of the users to be deactivated.
332 @type email_ids:list
333 @param role: New role for the users.
334 @type role:string
335 @param config: Contains any additional control parameters. Can be C{None}.
336 @type config:dictionary
337 @raise ServerError: If the server has received the request but did not process the request due to some error.
338 @raise ParseError: If the server has responded but client was not able to parse the response.
339 """
340 config["emailIds"] = email_ids
341 config["role"] = role
342 endpoint = "/restapi/v2/users/role"
343 self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
344
346 """
347 Returns subscription details of the specified organization.
348 @raise ServerError: If the server has received the request but did not process the request due to some error.
349 @raise ParseError: If the server has responded but client was not able to parse the response.
350 @return: Subscription details.
351 @rtype:dictionary
352 """
353 endpoint = "/restapi/v2/subscription"
354 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
355 return response["data"]["subscription"]
356
357
359 """
360 Returns resource usage details of the specified organization.
361 @raise ServerError: If the server has received the request but did not process the request due to some error.
362 @raise ParseError: If the server has responded but client was not able to parse the response.
363 @return: Resource details.
364 @rtype:dictionary
365 """
366 endpoint = "/restapi/v2/resources"
367 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
368 return response["data"]["resourceDetails"]
369
389
390
392 """
393 WorkspaceAPI contains workspace level operations.
394 """
395 - def __init__(self, ac, org_id, workspace_id):
396 self.ac = ac
397 self.endpoint = "/restapi/v2/workspaces/" + workspace_id
398 self.request_headers = {}
399 self.request_headers["ZANALYTICS-ORGID"] = org_id
400
401 - def copy(self, new_workspace_name, config = {}, dest_org_id = None):
402 """
403 Copy the specified workspace from one organization to another or within the organization.
404 @param new_workspace_name: Name of the new workspace.
405 @type new_workspace_name: string
406 @param config: Contains any additional control parameters. Can be C{None}.
407 @type config:dictionary
408 @param dest_org_id: Id of the organization where the destination workspace is present. Can be C{None}.
409 @type dest_org_id: string
410 @raise ServerError: If the server has received the request but did not process the request due to some error.
411 @raise ParseError: If the server has responded but client was not able to parse the response.
412 @return: Copied workspace id.
413 @rtype:string
414 """
415 config["newWorkspaceName"] = new_workspace_name
416 headers = self.request_headers.copy()
417 if bool(dest_org_id):
418 headers["ZANALYTICS-DEST-ORGID"] = dest_org_id
419 response = self.ac.send_api_request("POST", self.endpoint, config, headers)
420 return int(response["data"]["workspaceId"])
421
422 - def rename(self, workspace_name, config = {}):
423 """
424 Rename a specified workspace in the organization.
425 @param workspace_name: New name for the workspace.
426 @type workspace_name: string
427 @param config: Contains any additional control parameters. Can be C{None}.
428 @type config:dictionary
429 @raise ServerError: If the server has received the request but did not process the request due to some error.
430 @raise ParseError: If the server has responded but client was not able to parse the response.
431 """
432 config["workspaceName"] = workspace_name
433 response = self.ac.send_api_request("PUT", self.endpoint, config, self.request_headers)
434
436 """
437 Delete a specified workspace in the organization.
438 @raise ServerError: If the server has received the request but did not process the request due to some error.
439 @raise ParseError: If the server has responded but client was not able to parse the response.
440 """
441 response = self.ac.send_api_request("DELETE", self.endpoint, None, self.request_headers)
442
444 """
445 Returns the secret key of the specified workspace.
446 @param config: Contains any additional control parameters. Can be C{None}.
447 @type config:dictionary
448 @raise ServerError: If the server has received the request but did not process the request due to some error.
449 @raise ParseError: If the server has responded but client was not able to parse the response.
450 @return: Workspace secret key.
451 @rtype:string
452 """
453 endpoint = self.endpoint + "/secretkey"
454 response = self.ac.send_api_request("GET", endpoint, config, self.request_headers)
455 return response["data"]["workspaceKey"]
456
458 """
459 Adds a specified workspace as favorite.
460 @raise ServerError: If the server has received the request but did not process the request due to some error.
461 @raise ParseError: If the server has responded but client was not able to parse the response.
462 """
463 endpoint = self.endpoint + "/favorite"
464 response = self.ac.send_api_request("POST", endpoint, None, self.request_headers)
465
467 """
468 Remove a specified workspace from favorite.
469 @raise ServerError: If the server has received the request but did not process the request due to some error.
470 @raise ParseError: If the server has responded but client was not able to parse the response.
471 """
472 endpoint = self.endpoint + "/favorite"
473 response = self.ac.send_api_request("DELETE", endpoint, None, self.request_headers)
474
476 """
477 Adds a specified workspace as default.
478 @raise ServerError: If the server has received the request but did not process the request due to some error.
479 @raise ParseError: If the server has responded but client was not able to parse the response.
480 """
481 endpoint = self.endpoint + "/default"
482 response = self.ac.send_api_request("POST", endpoint, None, self.request_headers)
483
485 """
486 Remove a specified workspace from default.
487 @raise ServerError: If the server has received the request but did not process the request due to some error.
488 @raise ParseError: If the server has responded but client was not able to parse the response.
489 """
490 endpoint = self.endpoint + "/default"
491 response = self.ac.send_api_request("DELETE", endpoint, None, self.request_headers)
492
494 """
495 Returns list of admins for the specified workspace.
496 @raise ServerError: If the server has received the request but did not process the request due to some error.
497 @raise ParseError: If the server has responded but client was not able to parse the response.
498 @return: Workspace admin list.
499 @rtype:list
500 """
501 endpoint = self.endpoint + "/admins"
502 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
503 return response["data"]["workspaceAdmins"]
504
506 """
507 Add admins for the specified workspace.
508 @param email_ids: The email address of the admin users to be added.
509 @type email_ids: list
510 @param config: Contains any additional control parameters. Can be C{None}.
511 @type config:dictionary
512 @raise ServerError: If the server has received the request but did not process the request due to some error.
513 @raise ParseError: If the server has responded but client was not able to parse the response.
514 """
515 config["emailIds"] = email_ids
516 endpoint = self.endpoint + "/admins"
517 self.ac.send_api_request("POST", endpoint, config, self.request_headers)
518
520 """
521 Remove admins from the specified workspace.
522 @param email_ids: The email address of the admin users to be removed.
523 @type email_ids: list
524 @param config: Contains any additional control parameters. Can be C{None}.
525 @type config:dictionary
526 @raise ServerError: If the server has received the request but did not process the request due to some error.
527 @raise ParseError: If the server has responded but client was not able to parse the response.
528 """
529 config["emailIds"] = email_ids
530 endpoint = self.endpoint + "/admins"
531 self.ac.send_api_request("DELETE", endpoint, config, self.request_headers)
532
534 """
535 Returns shared details of the specified workspace.
536 @raise ServerError: If the server has received the request but did not process the request due to some error.
537 @raise ParseError: If the server has responded but client was not able to parse the response.
538 @return: Workspace share info.
539 @rtype:dictionary
540 """
541 endpoint = self.endpoint + "/share"
542 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
543 return response["data"]
544
545 - def share_views(self, view_ids, email_ids, permissions, config = {}):
546 """
547 Share views to the specified users.
548 @param view_ids: View ids which to be shared.
549 @type view_ids: list
550 @param email_ids: The email address of the users to whom the views need to be shared.
551 @type email_ids: list
552 @param permissions: Contains permission details.
553 @type permissions: dictionary
554 @param config: Contains any additional control parameters. Can be C{None}.
555 @type config:dictionary
556 @raise ServerError: If the server has received the request but did not process the request due to some error.
557 @raise ParseError: If the server has responded but client was not able to parse the response.
558 """
559 config["viewIds"] = view_ids
560 config["emailIds"] = email_ids
561 config["permissions"] = permissions
562 endpoint = self.endpoint + "/share"
563 self.ac.send_api_request("POST", endpoint, config, self.request_headers)
564
566 """
567 Remove shared views for the specified users.
568 @param view_ids: View ids whose sharing needs to be removed.
569 @type view_ids: list
570 @param email_ids: The email address of the users to whom the sharing need to be removed.
571 @type email_ids: list
572 @param config: Contains any additional control parameters. Can be C{None}.
573 @type config:dictionary
574 @raise ServerError: If the server has received the request but did not process the request due to some error.
575 @raise ParseError: If the server has responded but client was not able to parse the response.
576 """
577 config["emailIds"] = email_ids
578 if view_ids != None:
579 config["viewIds"] = view_ids
580 endpoint = self.endpoint + "/share"
581 self.ac.send_api_request("DELETE", endpoint, config, self.request_headers)
582
584 """
585 Returns shared details of the specified views.
586 @param view_ids: View ids for which sharing details are required.
587 @type view_ids: list
588 @raise ServerError: If the server has received the request but did not process the request due to some error.
589 @raise ParseError: If the server has responded but client was not able to parse the response.
590 @return: Shared information.
591 @rtype:list
592 """
593 config = {}
594 config["viewIds"] = view_ids
595 endpoint = self.endpoint + "/share/shareddetails"
596 response = self.ac.send_api_request("GET", endpoint, config, self.request_headers)
597 return response["data"]["sharedDetails"]
598
600 """
601 Returns list of all accessible folders for the specified workspace.
602 @raise ServerError: If the server has received the request but did not process the request due to some error.
603 @raise ParseError: If the server has responded but client was not able to parse the response.
604 @return: Folder list.
605 @rtype:list
606 """
607 endpoint = self.endpoint + "/folders"
608 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
609 return response["data"]["folders"]
610
612 """
613 Create a folder in the specified workspace.
614 @param folder_name: Name of the folder to be created.
615 @type folder_name: string
616 @param config: Contains any additional control parameters. Can be C{None}.
617 @type config:dictionary
618 @raise ServerError: If the server has received the request but did not process the request due to some error.
619 @raise ParseError: If the server has responded but client was not able to parse the response.
620 @return: Created folder id.
621 @rtype:string
622 """
623 config["folderName"] = folder_name
624 endpoint = self.endpoint + "/folders"
625 response = self.ac.send_api_request("POST", endpoint, config, self.request_headers)
626 return int(response["data"]["folderId"])
627
629 """
630 Returns list of all accessible views for the specified workspace.
631 @param config: Contains any additional control parameters. Can be C{None}.
632 @type config:dictionary
633 @raise ServerError: If the server has received the request but did not process the request due to some error.
634 @raise ParseError: If the server has responded but client was not able to parse the response.
635 @return: View list.
636 @rtype:list
637 """
638 endpoint = self.endpoint + "/views"
639 response = self.ac.send_api_request("GET", endpoint, config, self.request_headers)
640 return response["data"]["views"]
641
643 """
644 Create a table in the specified workspace.
645 @param table_design: Table structure.
646 @type table_design: dictionary
647 @raise ServerError: If the server has received the request but did not process the request due to some error.
648 @raise ParseError: If the server has responded but client was not able to parse the response.
649 @return: created table id.
650 @rtype:string
651 """
652 config = {}
653 config["tableDesign"] = table_design
654 endpoint = self.endpoint + "/tables"
655 response = self.ac.send_api_request("POST", endpoint, config, self.request_headers)
656 return int(response["data"]["viewId"])
657
659 """
660 Create a new query table in the workspace.
661 @param sql_query: SQL query to construct the query table.
662 @type sql_query: string
663 @param query_table_name: Name of the query table to be created.
664 @type query_table_name: string
665 @param config: Contains any additional control parameters. Can be C{None}.
666 @type config:dictionary
667 @raise ServerError: If the server has received the request but did not process the request due to some error.
668 @raise ParseError: If the server has responded but client was not able to parse the response.
669 @return: created table id.
670 @rtype:string
671 """
672 config["sqlQuery"] = sql_query
673 config["queryTableName"] = query_table_name
674 endpoint = self.endpoint + "/querytables"
675 response = self.ac.send_api_request("POST", endpoint, config, self.request_headers)
676 return int(response["data"]["viewId"])
677
679 """
680 Update the mentioned query table in the workspace.
681 @param view_id: Id of the query table to be updated.
682 @type view_id: string
683 @param sql_query: New SQL query to be updated.
684 @type sql_query: string
685 @param config: Contains any additional control parameters. Can be C{None}.
686 @type config:dictionary
687 @raise ServerError: If the server has received the request but did not process the request due to some error.
688 @raise ParseError: If the server has responded but client was not able to parse the response.
689 """
690 config["sqlQuery"] = sql_query
691 endpoint = self.endpoint + "/querytables/" + view_id
692 self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
693
694 - def copy_views(self, view_ids, dest_workspace_id, config = {}, dest_org_id = None):
695 """
696 Copy the specified views from one workspace to another workspace.
697 @param view_ids: The id of the views to be copied.
698 @type view_ids: list
699 @param dest_workspace_id: The destination workspace id.
700 @type dest_workspace_id: string
701 @param dest_org_id: Id of the organization where the destination workspace is present. Can be C{None}.
702 @type dest_org_id: string
703 @param config: Contains any additional control parameters. Can be C{None}.
704 @type config:dictionary
705 @raise ServerError: If the server has received the request but did not process the request due to some error.
706 @raise ParseError: If the server has responded but client was not able to parse the response.
707 @return: View list.
708 @rtype:list
709 """
710 config["viewIds"] = view_ids
711 config["destWorkspaceId"] = dest_workspace_id
712 endpoint = self.endpoint + "/views/copy"
713 headers = self.request_headers.copy()
714 if bool(dest_org_id):
715 headers["ZANALYTICS-DEST-ORGID"] = dest_org_id
716 response = self.ac.send_api_request("POST", endpoint, config, headers)
717 return response["data"]["views"]
718
720 """
721 Enable workspace to the specified white label domain.
722 @raise ServerError: If the server has received the request but did not process the request due to some error.
723 @raise ParseError: If the server has responded but client was not able to parse the response.
724 """
725 endpoint = self.endpoint + "/wlaccess"
726 response = self.ac.send_api_request("POST", endpoint, None, self.request_headers)
727
729 """
730 Disable workspace from the specified white label domain.
731 @raise ServerError: If the server has received the request but did not process the request due to some error.
732 @raise ParseError: If the server has responded but client was not able to parse the response.
733 """
734 endpoint = self.endpoint + "/wlaccess"
735 response = self.ac.send_api_request("DELETE", endpoint, None, self.request_headers)
736
738 """
739 Rename a specified folder in the workspace.
740 @param folder_id: Id of the folder.
741 @type folder_id: string
742 @param folder_name: New name for the folder.
743 @type folder_name: string
744 @param config: Contains any additional control parameters. Can be C{None}.
745 @type config:dictionary
746 @raise ServerError: If the server has received the request but did not process the request due to some error.
747 @raise ParseError: If the server has responded but client was not able to parse the response.
748 """
749 config["folderName"] = folder_name
750 endpoint = self.endpoint + "/folders/" + folder_id
751 self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
752
754 """
755 Delete a specified folder in the workspace.
756 @param folder_id: Id of the folder to be deleted.
757 @type folder_id: string
758 @raise ServerError: If the server has received the request but did not process the request due to some error.
759 @raise ParseError: If the server has responded but client was not able to parse the response.
760 """
761 endpoint = self.endpoint + "/folders/" + folder_id
762 self.ac.send_api_request("DELETE", endpoint, None, self.request_headers)
763
765 """
766 Returns list of groups for the specified workspace.
767 @raise ServerError: If the server has received the request but did not process the request due to some error.
768 @raise ParseError: If the server has responded but client was not able to parse the response.
769 @return: Group list.
770 @rtype:list
771 """
772 endpoint = self.endpoint + "/groups"
773 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
774 return response["data"]["groups"]
775
776 - def create_group(self, group_name, email_ids, config = {}):
777 """
778 Create a group in the specified workspace.
779 @param group_name: Name of the group.
780 @type group_name: string
781 @param email_ids: The email address of the users to be added to the group.
782 @type email_ids: list
783 @param config: Contains any additional control parameters. Can be C{None}.
784 @type config:dictionary
785 @raise ServerError: If the server has received the request but did not process the request due to some error.
786 @raise ParseError: If the server has responded but client was not able to parse the response.
787 @return: Created group id.
788 @rtype:string
789 """
790 config["groupName"] = group_name
791 config["emailIds"] = email_ids
792 endpoint = self.endpoint + "/groups"
793 response = self.ac.send_api_request("POST", endpoint, config, self.request_headers)
794 return int(response["data"]["groupId"])
795
797 """
798 Get the details of the specified group.
799 @param group_id: Id of the group.
800 @type group_id: string
801 @raise ServerError: If the server has received the request but did not process the request due to some error.
802 @raise ParseError: If the server has responded but client was not able to parse the response.
803 @return: Details of the specified group.
804 @rtype:dictionary
805 """
806 endpoint = self.endpoint + "/groups/" + group_id
807 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
808 return response["data"]["groups"]
809
811 """
812 Rename a specified group.
813 @param group_id: Id of the group.
814 @type group_id: string
815 @param group_name: New name for the group.
816 @type group_name: string
817 @param config: Contains any additional control parameters. Can be C{None}.
818 @type config:dictionary
819 @raise ServerError: If the server has received the request but did not process the request due to some error.
820 @raise ParseError: If the server has responded but client was not able to parse the response.
821 """
822 config["groupName"] = group_name
823 endpoint = self.endpoint + "/groups/" + group_id
824 self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
825
827 """
828 Delete a specified group.
829 @param group_id: The id of the group.
830 @type group_id: string
831 @raise ServerError: If the server has received the request but did not process the request due to some error.
832 @raise ParseError: If the server has responded but client was not able to parse the response.
833 """
834 endpoint = self.endpoint + "/groups/" + group_id
835 self.ac.send_api_request("DELETE", endpoint, None, self.request_headers)
836
838 """
839 Add users to the specified group.
840 @param group_id: Id of the group.
841 @type group_id: string
842 @param email_ids: The email address of the users to be added to the group.
843 @type email_ids: list
844 @param config: Contains any additional control parameters. Can be C{None}.
845 @type config:dictionary
846 @raise ServerError: If the server has received the request but did not process the request due to some error.
847 @raise ParseError: If the server has responded but client was not able to parse the response.
848 """
849 config["emailIds"] = email_ids
850 endpoint = self.endpoint + "/groups/" + group_id + "/members"
851 self.ac.send_api_request("POST", endpoint, config, self.request_headers)
852
854 """
855 Remove users from the specified group.
856 @param group_id: Id of the group.
857 @type group_id: string
858 @param email_ids: The email address of the users to be removed from the group.
859 @type email_ids: list
860 @param config: Contains any additional control parameters. Can be C{None}.
861 @type config:dictionary
862 @raise ServerError: If the server has received the request but did not process the request due to some error.
863 @raise ParseError: If the server has responded but client was not able to parse the response.
864 """
865 config["emailIds"] = email_ids
866 endpoint = self.endpoint + "/groups/" + group_id + "/members"
867 self.ac.send_api_request("DELETE", endpoint, config, self.request_headers)
868
870 """
871 Create a slideshow in the specified workspace.
872 @param slide_name: Name of the slideshow to be created.
873 @type slide_name: string
874 @param view_ids: Ids of the view to be included in the slideshow.
875 @type view_ids: list
876 @param config: Contains any additional control parameters. Can be C{None}.
877 @type config:dictionary
878 @raise ServerError: If the server has received the request but did not process the request due to some error.
879 @raise ParseError: If the server has responded but client was not able to parse the response.
880 @return: Id of the created slideshow.
881 @rtype:string
882 """
883 endpoint = self.endpoint + "/slides"
884 config["slideName"] = slide_name
885 config["viewIds"] = view_ids
886 response = self.ac.send_api_request("POST", endpoint, config, self.request_headers)
887 return int(response["data"]["slideId"])
888
890 """
891 Update details of the specified slideshow.
892 @param slide_id: The id of the slideshow.
893 @type slide_id: string
894 @param config - Contains the control configurations.
895 @type config:dictionary
896 @raise ServerError: If the server has received the request but did not process the request due to some error.
897 @raise ParseError: If the server has responded but client was not able to parse the response.
898 """
899 endpoint = self.endpoint + "/slides/" + slide_id
900 self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
901
903 """
904 Delete a specified slideshow in the workspace.
905 @param slide_id: Id of the slideshow.
906 @type slide_id: string
907 @raise ServerError: If the server has received the request but did not process the request due to some error.
908 @raise ParseError: If the server has responded but client was not able to parse the response.
909 """
910 endpoint = self.endpoint + "/slides/" + slide_id
911 self.ac.send_api_request("DELETE", endpoint, None, self.request_headers)
912
914 """
915 Returns list of slideshows for the specified workspace.
916 @raise ServerError: If the server has received the request but did not process the request due to some error.
917 @raise ParseError: If the server has responded but client was not able to parse the response.
918 @return: Slideshow list.
919 @rtype:list
920 """
921 endpoint = self.endpoint + "/slides"
922 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
923 return response["data"]["slideshows"]
924
926 """
927 Returns slide URL to access the specified slideshow.
928 @param slide_id: Id of the slideshow.
929 @type slide_id: string
930 @param config: Contains any additional control parameters. Can be C{None}.
931 @type config:dictionary
932 @raise ServerError: If the server has received the request but did not process the request due to some error.
933 @raise ParseError: If the server has responded but client was not able to parse the response.
934 @return: Slideshow URL.
935 @rtype:string
936 """
937 endpoint = self.endpoint + "/slides/" + slide_id + "/publish"
938 response = self.ac.send_api_request("GET", endpoint, config, self.request_headers)
939 return response["data"]["slideUrl"]
940
942 """
943 Returns details of the specified slideshow.
944 @param slide_id: Id of the slideshow.
945 @type slide_id: string
946 @raise ServerError: If the server has received the request but did not process the request due to some error.
947 @raise ParseError: If the server has responded but client was not able to parse the response.
948 @return: Slideshow details.
949 @rtype:dictionary
950 """
951 endpoint = self.endpoint + "/slides/" + slide_id
952 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
953 return response["data"]["slideInfo"]
954
955 - def create_variable(self, variable_name, variable_datatype, variable_type, config = {}):
956 """
957 Create a variable in the workspace.
958 @param variable_name: Name of the variable to be created.
959 @type variable_name: string
960 @param variable_datatype: Datatype of the variable to be created.
961 @type variable_datatype: string
962 @param variable_type: Type of the variable to be created.
963 @type variable_type: string
964 @param config: Contains the control parameters.
965 @type config:dictionary
966 @raise ServerError: If the server has received the request but did not process the request due to some error.
967 @raise ParseError: If the server has responded but client was not able to parse the response.
968 @return: Id of the created variable.
969 @rtype:string
970 """
971 endpoint = self.endpoint + "/variables"
972 config["variableName"] = variable_name
973 config["variableDataType"] = variable_datatype
974 config["variableType"] = variable_type
975 response = self.ac.send_api_request("POST", endpoint, config, self.request_headers)
976 return int(response["data"]["variableId"])
977
978 - def update_variable(self, variable_id, variable_name, variable_datatype, variable_type, config = {}):
979 """
980 Update details of the specified variable in the workspace.
981 @param variable_id: Id of the variable.
982 @type variable_id: string
983 @param variable_name: New name for the variable.
984 @type variable_name: string
985 @param variable_datatype: New datatype for the variable.
986 @type variable_datatype: string
987 @param variable_type: New type for the variable.
988 @type variable_type: string
989 @param config: Contains the control parameters.
990 @type config:dictionary
991 @raise ServerError: If the server has received the request but did not process the request due to some error.
992 @raise ParseError: If the server has responded but client was not able to parse the response.
993 """
994 endpoint = self.endpoint + "/variables/" + variable_id
995 config["variableName"] = variable_name
996 config["variableDataType"] = variable_datatype
997 config["variableType"] = variable_type
998 response = self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
999
1001 """
1002 Delete the specified variable in the workspace.
1003 @param variable_id: Id of the variable.
1004 @type variable_id: string
1005 @raise ServerError: If the server has received the request but did not process the request due to some error.
1006 @raise ParseError: If the server has responded but client was not able to parse the response.
1007 """
1008 endpoint = self.endpoint + "/variables/" + variable_id
1009 response = self.ac.send_api_request("DELETE", endpoint, None, self.request_headers)
1010
1012 """
1013 Returns list of variables for the specified workspace.
1014 @raise ServerError: If the server has received the request but did not process the request due to some error.
1015 @raise ParseError: If the server has responded but client was not able to parse the response.
1016 @return: Variable list.
1017 @rtype:list
1018 """
1019 endpoint = self.endpoint + "/variables"
1020 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
1021 return response["data"]["variables"]
1022
1024 """
1025 Returns list of variables for the specified workspace.
1026 @param variable_id: Id of the variable.
1027 @type variable_id: string
1028 @raise ServerError: If the server has received the request but did not process the request due to some error.
1029 @raise ParseError: If the server has responded but client was not able to parse the response.
1030 @return: Variable details.
1031 @rtype:dictionary
1032 """
1033 endpoint = self.endpoint + "/variables/" + variable_id
1034 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
1035 return response["data"]
1036
1038 """
1039 Make the specified folder as default.
1040 @param folder_id: Id of the folder.
1041 @type folder_id: string
1042 @raise ServerError: If the server has received the request but did not process the request due to some error.
1043 @raise ParseError: If the server has responded but client was not able to parse the response.
1044 """
1045 endpoint = self.endpoint + "/folders/" + folder_id + "/default"
1046 response = self.ac.send_api_request("PUT", endpoint, None, self.request_headers)
1047
1049 """
1050 Returns list of datasources for the specified workspace.
1051 @raise ServerError: If the server has received the request but did not process the request due to some error.
1052 @raise ParseError: If the server has responded but client was not able to parse the response.
1053 @return: Datasource list.
1054 @rtype:list
1055 """
1056 endpoint = self.endpoint + "/datasources"
1057 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
1058 return response["data"]["dataSources"]
1059
1060 - def sync_data(self, datasource_id, config = {}):
1061 """
1062 Initiate data sync for the specified datasource.
1063 @param datasource_id: Id of the datasource.
1064 @type datasource_id: string
1065 @param config: Contains any additional control parameters. Can be C{None}.
1066 @type config:dictionary
1067 @raise ServerError: If the server has received the request but did not process the request due to some error.
1068 @raise ParseError: If the server has responded but client was not able to parse the response.
1069 """
1070 endpoint = self.endpoint + "/datasources/" + datasource_id + "/sync"
1071 response = self.ac.send_api_request("POST", endpoint, config, self.request_headers)
1072
1074 """
1075 Update connection details for the specified datasource.
1076 @param datasource_id: Id of the datasource.
1077 @type datasource_id: string
1078 @param config: Contains the control parameters.
1079 @type config:dictionary
1080 @raise ServerError: If the server has received the request but did not process the request due to some error.
1081 @raise ParseError: If the server has responded but client was not able to parse the response.
1082 """
1083 endpoint = self.endpoint + "/datasources/" + datasource_id
1084 response = self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
1085
1087 """
1088 Initiate data sync for the specified datasource.
1089 @raise ServerError: If the server has received the request but did not process the request due to some error.
1090 @raise ParseError: If the server has responded but client was not able to parse the response.
1091 @return: Trash view list.
1092 @rtype:list
1093 """
1094 endpoint = self.endpoint + "/trash"
1095 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
1096 return response["data"]["views"]
1097
1099 """
1100 Restore the specified view from trash.
1101 @param view_id: Id of the view.
1102 @type view_id: string
1103 @param config: Contains any additional control parameters. Can be C{None}.
1104 @type config:dictionary
1105 @raise ServerError: If the server has received the request but did not process the request due to some error.
1106 @raise ParseError: If the server has responded but client was not able to parse the response.
1107 """
1108 endpoint = self.endpoint + "/trash/" + view_id
1109 response = self.ac.send_api_request("POST", endpoint, None, self.request_headers)
1110
1112 """
1113 Delete the specified view permanently from trash.
1114 @param view_id: Id of the view.
1115 @type view_id: string
1116 @param config: Contains any additional control parameters. Can be C{None}.
1117 @type config:dictionary
1118 @raise ServerError: If the server has received the request but did not process the request due to some error.
1119 @raise ParseError: If the server has responded but client was not able to parse the response.
1120 """
1121 endpoint = self.endpoint + "/trash/" + view_id
1122 response = self.ac.send_api_request("DELETE", endpoint, None, self.request_headers)
1123
1125 """
1126 Swaps the hierarchy of a parent folder and a subfolder.
1127 @param folder_id: Id of the folder.
1128 @type folder_id: string
1129 @param hierarchy: New hierarchy for the folder. (0 - Parent; 1 - Child).
1130 @type hierarchy: string
1131 @param config: Contains any additional control parameters. Can be C{None}.
1132 @type config:dictionary
1133 @raise ServerError: If the server has received the request but did not process the request due to some error.
1134 @raise ParseError: If the server has responded but client was not able to parse the response.
1135 """
1136 endpoint = self.endpoint + "/folders/" + folder_id + "/move";
1137 config["hierarchy"] = hierarchy
1138 self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
1139
1141 """
1142 Place the folder above the reference folder.
1143 @param folder_id: Id of the folder.
1144 @type folder_id: string
1145 @param reference_folder_id: Id of the reference folder.
1146 @type reference_folder_id: string
1147 @param config: Contains any additional control parameters. Can be C{None}.
1148 @type config:dictionary
1149 @raise ServerError: If the server has received the request but did not process the request due to some error.
1150 @raise ParseError: If the server has responded but client was not able to parse the response.
1151 """
1152 endpoint = self.endpoint + "/folders/" + folder_id + "/reorder";
1153 config["referenceFolderId"] = reference_folder_id
1154 self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
1155
1157 """
1158 Move views to the mentioned folder.
1159 @param folder_id: Id of the folder.
1160 @type folder_id: string
1161 @param view_ids: View ids to be moved.
1162 @type view_ids: list
1163 @param config: Contains any additional control parameters. Can be C{None}.
1164 @type config:dictionary
1165 @raise ServerError: If the server has received the request but did not process the request due to some error.
1166 @raise ParseError: If the server has responded but client was not able to parse the response.
1167 """
1168 endpoint = self.endpoint + "/views/movetofolder";
1169 config["folderId"] = folder_id
1170 config["viewIds"] = view_ids
1171 self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
1172
1174 """
1175 Export the mentioned views as templates.
1176 @param view_ids: Ids of the views to be exported.
1177 @type view_ids: list
1178 @param file_path: Path of the file where the data exported to be stored. ( Should be in 'atpt' format )
1179 @type file_path: string
1180 @param config: Contains any additional control parameters. Can be C{None}.
1181 @type config:dictionary
1182 @raise ServerError: If the server has received the request but did not process the request due to some error.
1183 @raise ParseError: If the server has responded but client was not able to parse the response.
1184 """
1185 endpoint = self.endpoint + "/template/data"
1186 config["viewIds"] = view_ids
1187 self.ac.send_export_api_request(endpoint, config, self.request_headers, file_path)
1188
1190 """
1191 Returns list of users for the specified workspace.
1192 @raise ServerError: If the server has received the request but did not process the request due to some error.
1193 @raise ParseError: If the server has responded but client was not able to parse the response.
1194 @return: User list.
1195 @rtype:list
1196 """
1197 endpoint = self.endpoint + "/users";
1198 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
1199 return response["data"]["users"]
1200
1202 """
1203 Add users to the specified workspace.
1204 @param email_ids: The email address of the users to be added.
1205 @type email_ids:list
1206 @param role: Role of the user to be added.
1207 @type role:string
1208 @param config: Contains any additional control parameters. Can be C{None}.
1209 @type config:dictionary
1210 @raise ServerError: If the server has received the request but did not process the request due to some error.
1211 @raise ParseError: If the server has responded but client was not able to parse the response.
1212 """
1213 config["emailIds"] = email_ids
1214 config["role"] = role
1215 endpoint = self.endpoint + "/users";
1216 self.ac.send_api_request("POST", endpoint, config, self.request_headers)
1217
1219 """
1220 Remove users from the specified workspace.
1221 @param email_ids: The email address of the users to be removed.
1222 @type email_ids:list
1223 @param config: Contains any additional control parameters. Can be C{None}.
1224 @type config:dictionary
1225 @raise ServerError: If the server has received the request but did not process the request due to some error.
1226 @raise ParseError: If the server has responded but client was not able to parse the response.
1227 """
1228 config["emailIds"] = email_ids
1229 endpoint = self.endpoint + "/users";
1230 self.ac.send_api_request("DELETE", endpoint, config, self.request_headers)
1231
1233 """
1234 Change users status in the specified workspace.
1235 @param email_ids: The email address of the users.
1236 @type email_ids:list
1237 @param operation: New status for the users ( Values - activate | deactivate ).
1238 @type operation:string
1239 @param config: Contains any additional control parameters. Can be C{None}.
1240 @type config:dictionary
1241 @raise ServerError: If the server has received the request but did not process the request due to some error.
1242 @raise ParseError: If the server has responded but client was not able to parse the response.
1243 """
1244 config["emailIds"] = email_ids
1245 config["operation"] = operation
1246 endpoint = self.endpoint + "/users/status";
1247 self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
1248
1250 """
1251 Change role for the specified users.
1252 @param email_ids: The email address of the users.
1253 @type email_ids:list
1254 @param role: New role for the users.
1255 @type role:string
1256 @param config: Contains any additional control parameters. Can be C{None}.
1257 @type config:dictionary
1258 @raise ServerError: If the server has received the request but did not process the request due to some error.
1259 @raise ParseError: If the server has responded but client was not able to parse the response.
1260 """
1261 config["emailIds"] = email_ids
1262 config["role"] = role
1263 endpoint = self.endpoint + "/users/role";
1264 self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
1265
1266
1268 """
1269 Returns list of email schedules available in the specified workspace.
1270 @raise ServerError: If the server has received the request but did not process the request due to some error.
1271 @raise ParseError: If the server has responded but client was not able to parse the response.
1272 @return: List of email schedules.
1273 @rtype: list
1274 """
1275 endpoint = self.endpoint + "/emailschedules"
1276 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
1277 return response["data"]["emailSchedules"]
1278
1279 - def create_email_schedule(self, schedule_name, view_ids, format, email_ids, schedule_details, config={}):
1280 """
1281 Create an email schedule in the specified workspace.
1282 @param schedule_name: Name of the email schedule.
1283 @type schedule_name: string
1284 @param view_ids: View ids to be mailed.
1285 @type view_ids: list
1286 @param format: The format in which the data has to be mailed.
1287 @type format: string
1288 @param email_ids: The recipients' email addresses for sending views.
1289 @type email_ids: list
1290 @param schedule_details: Contains schedule frequency, date, and time info.
1291 @type schedule_details: dictionary
1292 @param config: Contains any additional control parameters. Can be None.
1293 @type config: dictionary
1294 @raise ServerError: If the server has received the request but did not process the request due to some error.
1295 @raise ParseError: If the server has responded but client was not able to parse the response.
1296 @return: Email schedule id.
1297 @rtype: string
1298 """
1299 config["scheduleName"] = schedule_name
1300 config["viewIds"] = view_ids
1301 config["exportType"] = format
1302 config["emailIds"] = email_ids
1303 config["scheduleDetails"] = schedule_details
1304 endpoint = self.endpoint + "/emailschedules"
1305 response = self.ac.send_api_request("POST", endpoint, config, self.request_headers)
1306 return str(response["data"]["scheduleId"])
1307
1309 """
1310 Update configurations of the specified email schedule in the workspace.
1311 @param schedule_id: Id for the email schedule.
1312 @type schedule_id: string
1313 @param config: Contains the control configurations.
1314 @type config: dictionary
1315 @raise ServerError: If the server has received the request but did not process the request due to some error.
1316 @raise ParseError: If the server has responded but client was not able to parse the response.
1317 @return: Updated schedule id.
1318 @rtype: string
1319 """
1320 endpoint = self.endpoint + "/emailschedules/" + schedule_id
1321 response = self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
1322 return str(response["data"]["scheduleId"])
1323
1325 """
1326 Trigger configured email schedules instantly.
1327 @param schedule_id: Id for the email schedule.
1328 @type schedule_id: string
1329 @raise ServerError: If the server has received the request but did not process the request due to some error.
1330 @raise ParseError: If the server has responded but client was not able to parse the response.
1331 """
1332 endpoint = self.endpoint + "/emailschedules/" + schedule_id
1333 self.ac.send_api_request("POST", endpoint, None, self.request_headers)
1334
1336 """
1337 Update email schedule status.
1338 @param schedule_id: Id for the email schedule.
1339 @type schedule_id: string
1340 @param operation: New status for the schedule ( Values - activate | deactivate )
1341 @type operation: string
1342 @raise ServerError: If the server has received the request but did not process the request due to some error.
1343 @raise ParseError: If the server has responded but client was not able to parse the response.
1344 """
1345 endpoint = self.endpoint + "/emailschedules/" + schedule_id + "/status"
1346 config = {"operation": operation}
1347 self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
1348
1350 """
1351 Delete the specified email schedule in the workspace.
1352 @param schedule_id: Id for the email schedule.
1353 @type schedule_id: string
1354 @raise ServerError: If the server has received the request but did not process the request due to some error.
1355 @raise ParseError: If the server has responded but client was not able to parse the response.
1356 """
1357 endpoint = self.endpoint + "/emailschedules/" + schedule_id
1358 self.ac.send_api_request("DELETE", endpoint, None, self.request_headers)
1359
1360
1362 """
1363 ViewAPI contains view level operations.
1364 """
1365 - def __init__(self, ac, org_id, workspace_id, view_id):
1366 self.ac = ac
1367 self.endpoint = "/restapi/v2/workspaces/" + workspace_id + "/views/" + view_id
1368 self.request_headers = {}
1369 self.request_headers["ZANALYTICS-ORGID"] = org_id
1370
1371 - def rename(self, view_name, config = {}):
1372 """
1373 Rename a specified view in the workspace.
1374 @param view_name: New name of the view.
1375 @type view_name: string
1376 @param config: Contains any additional control parameters. Can be C{None}.
1377 @type config:dictionary
1378 @raise ServerError: If the server has received the request but did not process the request due to some error.
1379 @raise ParseError: If the server has responded but client was not able to parse the response.
1380 """
1381 config["viewName"] = view_name
1382 response = self.ac.send_api_request("PUT", self.endpoint, config, self.request_headers)
1383
1384 - def delete(self, config = {}):
1385 """
1386 Delete a specified view in the workspace.
1387 @param config: Contains any additional control parameters. Can be C{None}.
1388 @type config:dictionary
1389 @raise ServerError: If the server has received the request but did not process the request due to some error.
1390 @raise ParseError: If the server has responded but client was not able to parse the response.
1391 """
1392 response = self.ac.send_api_request("DELETE", self.endpoint, config, self.request_headers)
1393
1394 - def save_as(self, new_view_name, config = {}):
1395 """
1396 Copy a specified view within the workspace.
1397 @param new_view_name: The name of the new view.
1398 @type new_view_name: string
1399 @param config: Contains any additional control parameters. Can be C{None}.
1400 @type config:dictionary
1401 @raise ServerError: If the server has received the request but did not process the request due to some error.
1402 @raise ParseError: If the server has responded but client was not able to parse the response.
1403 @return: Created view id.
1404 @rtype:string
1405 """
1406 config["viewName"] = new_view_name
1407 endpoint = self.endpoint + "/saveas"
1408 response = self.ac.send_api_request("POST", endpoint, config, self.request_headers)
1409 return int(response["data"]["viewId"])
1410
1432
1434 """
1435 Adds a specified view as favorite.
1436 @raise ServerError: If the server has received the request but did not process the request due to some error.
1437 @raise ParseError: If the server has responded but client was not able to parse the response.
1438 """
1439 endpoint = self.endpoint + "/favorite"
1440 response = self.ac.send_api_request("POST", endpoint, None, self.request_headers)
1441
1443 """
1444 Remove a specified view from favorite.
1445 @raise ServerError: If the server has received the request but did not process the request due to some error.
1446 @raise ParseError: If the server has responded but client was not able to parse the response.
1447 """
1448 endpoint = self.endpoint + "/favorite"
1449 response = self.ac.send_api_request("DELETE", endpoint, None, self.request_headers)
1450
1452 """
1453 Create reports for the specified table based on the reference table.
1454 @param ref_view_id: The ID of the reference view.
1455 @type ref_view_id: string
1456 @param folder_id: The folder id where the views to be saved.
1457 @type folder_id: string
1458 @param config: Contains any additional control parameters. Can be C{None}.
1459 @type config:dictionary
1460 @raise ServerError: If the server has received the request but did not process the request due to some error.
1461 @raise ParseError: If the server has responded but client was not able to parse the response.
1462 """
1463 config["referenceViewId"] = ref_view_id
1464 config["folderId"] = folder_id
1465 endpoint = self.endpoint + "/similarviews"
1466 self.ac.send_api_request("POST", endpoint, config, self.request_headers)
1467
1469 """
1470 Auto generate reports for the specified table.
1471 @param config: Contains any additional control parameters. Can be C{None}.
1472 @type config:dictionary
1473 @raise ServerError: If the server has received the request but did not process the request due to some error.
1474 @raise ParseError: If the server has responded but client was not able to parse the response.
1475 """
1476 endpoint = self.endpoint + "/autoanalyse"
1477 self.ac.send_api_request("POST", endpoint, config, self.request_headers)
1478
1480 """
1481 Returns permissions for the specified view.
1482 @raise ServerError: If the server has received the request but did not process the request due to some error.
1483 @raise ParseError: If the server has responded but client was not able to parse the response.
1484 @return: Permission details.
1485 @rtype:dictionary
1486 """
1487 endpoint = self.endpoint + "/share/userpermissions"
1488 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
1489 return response["data"]["permissions"]
1490
1492 """
1493 Returns the URL to access the specified view.
1494 @param config: Contains any additional control parameters. Can be C{None}.
1495 @type config:dictionary
1496 @raise ServerError: If the server has received the request but did not process the request due to some error.
1497 @raise ParseError: If the server has responded but client was not able to parse the response.
1498 @return: View URL.
1499 @rtype:string
1500 """
1501 endpoint = self.endpoint + "/publish"
1502 response = self.ac.send_api_request("GET", endpoint, config, self.request_headers)
1503 return response["data"]["viewUrl"]
1504
1506 """
1507 Returns embed URL to access the specified view.
1508 @param config: Contains any additional control parameters. Can be C{None}.
1509 @type config:dictionary
1510 @raise ServerError: If the server has received the request but did not process the request due to some error.
1511 @raise ParseError: If the server has responded but client was not able to parse the response.
1512 @return: Embed URL.
1513 @rtype:string
1514 """
1515 endpoint = self.endpoint + "/publish/embed"
1516 response = self.ac.send_api_request("GET", endpoint, config, self.request_headers)
1517 return response["data"]["embedUrl"]
1518
1520 """
1521 Returns private URL to access the specified view.
1522 @param config: Contains any additional control parameters. Can be C{None}.
1523 @type config:dictionary
1524 @raise ServerError: If the server has received the request but did not process the request due to some error.
1525 @raise ParseError: If the server has responded but client was not able to parse the response.
1526 @return: Private URL.
1527 @rtype:string
1528 """
1529 endpoint = self.endpoint + "/publish/privatelink"
1530 response = self.ac.send_api_request("GET", endpoint, config, self.request_headers)
1531 return response["data"]["privateUrl"]
1532
1534 """
1535 Create a private URL for the specified view.
1536 @param config: Contains any additional control parameters. Can be C{None}.
1537 @type config:dictionary
1538 @raise ServerError: If the server has received the request but did not process the request due to some error.
1539 @raise ParseError: If the server has responded but client was not able to parse the response.
1540 @return: Private URL.
1541 @rtype:string
1542 """
1543 endpoint = self.endpoint + "/publish/privatelink"
1544 response = self.ac.send_api_request("POST", endpoint, config, self.request_headers)
1545 return response["data"]["privateUrl"]
1546
1548 """
1549 Remove private link access for the specified view.
1550 @raise ServerError: If the server has received the request but did not process the request due to some error.
1551 @raise ParseError: If the server has responded but client was not able to parse the response.
1552 """
1553 endpoint = self.endpoint + "/publish/privatelink"
1554 response = self.ac.send_api_request("DELETE", endpoint, None, self.request_headers)
1555
1557 """
1558 Make the specified view publically accessible.
1559 @param config: Contains any additional control parameters. Can be C{None}.
1560 @type config:dictionary
1561 @raise ServerError: If the server has received the request but did not process the request due to some error.
1562 @raise ParseError: If the server has responded but client was not able to parse the response.
1563 @return: Public URL.
1564 @rtype:string
1565 """
1566 endpoint = self.endpoint + "/publish/public"
1567 response = self.ac.send_api_request("POST", endpoint, config, self.request_headers)
1568 return response["data"]["publicUrl"]
1569
1571 """
1572 Remove public access for the specified view.
1573 @raise ServerError: If the server has received the request but did not process the request due to some error.
1574 @raise ParseError: If the server has responded but client was not able to parse the response.
1575 """
1576 response = endpoint = self.endpoint + "/publish/public"
1577 self.ac.send_api_request("DELETE", endpoint, None, self.request_headers)
1578
1580 """
1581 Returns publish configurations for the specified view.
1582 @raise ServerError: If the server has received the request but did not process the request due to some error.
1583 @raise ParseError: If the server has responded but client was not able to parse the response.
1584 @return: Publish details.
1585 @rtype:dictionary
1586 """
1587 endpoint = self.endpoint + "/publish/config"
1588 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
1589 return response["data"]
1590
1592 """
1593 Update publish configurations for the specified view.
1594 @param config: Contains the control parameters.
1595 @type config:dictionary
1596 @raise ServerError: If the server has received the request but did not process the request due to some error.
1597 @raise ParseError: If the server has responded but client was not able to parse the response.
1598 """
1599 endpoint = self.endpoint + "/publish/config"
1600 response = self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
1601
1602 - def add_column(self, column_name, data_type, config = {}):
1603 """
1604 Add a column in the specified table.
1605 @param column_name: The name of the column.
1606 @type column_name: string
1607 @param data_type: The data-type of the column.
1608 @type data_type: string
1609 @param config: Contains any additional control parameters. Can be C{None}.
1610 @type config:dictionary
1611 @raise ServerError: If the server has received the request but did not process the request due to some error.
1612 @raise ParseError: If the server has responded but client was not able to parse the response.
1613 @return: Created column id.
1614 @rtype:string
1615 """
1616 config["columnName"] = column_name
1617 config["dataType"] = data_type
1618 endpoint = self.endpoint + "/columns"
1619 response = self.ac.send_api_request("POST", endpoint, config, self.request_headers)
1620 return int(response["data"]["columnId"])
1621
1623 """
1624 Hide the specified columns in the table.
1625 @param column_ids: Ids of the columns to be hidden.
1626 @type column_ids: list
1627 @raise ServerError: If the server has received the request but did not process the request due to some error.
1628 @raise ParseError: If the server has responded but client was not able to parse the response.
1629 """
1630 config = {}
1631 config["columnIds"] = column_ids
1632 endpoint = self.endpoint + "/columns/hide"
1633 self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
1634
1636 """
1637 Show the specified hidden columns in the table.
1638 @param column_ids: Ids of the columns to be shown.
1639 @type column_ids: list
1640 @raise ServerError: If the server has received the request but did not process the request due to some error.
1641 @raise ParseError: If the server has responded but client was not able to parse the response.
1642 """
1643 config = {}
1644 config["columnIds"] = column_ids
1645 endpoint = self.endpoint + "/columns/show"
1646 self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
1647
1648 - def add_row(self, column_values, config = {}):
1649 """
1650 Add a single row in the specified table.
1651 @param column_values: Contains the values for the row. The column names are the key.
1652 @type column_values: dictionary
1653 @param config: Contains any additional control parameters. Can be C{None}.
1654 @type config:dictionary
1655 @raise ServerError: If the server has received the request but did not process the request due to some error.
1656 @raise ParseError: If the server has responded but client was not able to parse the response.
1657 @return: Column Names and Added Row Values.
1658 @rtype:dictionary
1659 """
1660 config["columns"] = column_values
1661 endpoint = self.endpoint + "/rows"
1662 response = self.ac.send_api_request("POST", endpoint, config, self.request_headers)
1663 return response["data"]
1664
1665 - def update_row(self, column_values, criteria, config = {}):
1666 """
1667 Update rows in the specified table.
1668 @param column_values: Contains the values for the row. The column names are the key.
1669 @type column_values: dictionary
1670 @param criteria: The criteria to be applied for updating data. Only rows matching the criteria will be updated. Should be null for update all rows.
1671 @type criteria: string
1672 @param config: Contains any additional control parameters. Can be C{None}.
1673 @type config:dictionary
1674 @raise ServerError: If the server has received the request but did not process the request due to some error.
1675 @raise ParseError: If the server has responded but client was not able to parse the response.
1676 @return: Updated Columns List and Updated Rows Count.
1677 @rtype:dictionary
1678 """
1679 config["columns"] = column_values
1680 if criteria != None:
1681 config["criteria"] = criteria
1682 endpoint = self.endpoint + "/rows"
1683 response = self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
1684 return response["data"]
1685
1687 """
1688 Delete rows in the specified table.
1689 @param criteria: The criteria to be applied for deleting data. Only rows matching the criteria will be deleted. Should be null for delete all rows.
1690 @type criteria: string
1691 @param config: Contains any additional control parameters. Can be C{None}.
1692 @type config:dictionary
1693 @raise ServerError: If the server has received the request but did not process the request due to some error.
1694 @raise ParseError: If the server has responded but client was not able to parse the response.
1695 @return: Deleted rows details.
1696 @rtype:string
1697 """
1698 if criteria != None:
1699 config["criteria"] = criteria
1700 endpoint = self.endpoint + "/rows"
1701 response = self.ac.send_api_request("DELETE", endpoint, config, self.request_headers)
1702 return response["data"]["deletedRows"]
1703
1705 """
1706 Rename a specified column in the table.
1707 @param column_id: Id of the column.
1708 @type column_id: string
1709 @param column_name: New name for the column.
1710 @type column_name: string
1711 @param config: Contains any additional control parameters. Can be C{None}.
1712 @type config:dictionary
1713 @raise ServerError: If the server has received the request but did not process the request due to some error.
1714 @raise ParseError: If the server has responded but client was not able to parse the response.
1715 """
1716 config["columnName"] = column_name
1717 endpoint = self.endpoint + "/columns/" + column_id
1718 self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
1719
1721 """
1722 Delete a specified column in the table.
1723 @param column_id: Id of the column.
1724 @type column_id: string
1725 @param config: Contains any additional control parameters. Can be C{None}.
1726 @type config:dictionary
1727 @raise ServerError: If the server has received the request but did not process the request due to some error.
1728 @raise ParseError: If the server has responded but client was not able to parse the response.
1729 """
1730 endpoint = self.endpoint + "/columns/" + column_id
1731 self.ac.send_api_request("DELETE", endpoint, config, self.request_headers)
1732
1733 - def add_lookup(self, column_id, ref_view_id, ref_column_id, config = {}):
1734 """
1735 Add a lookup in the specified child table.
1736 @param column_id: Id of the column.
1737 @type column_id: string
1738 @param ref_view_id: The id of the table contains the parent column.
1739 @type ref_view_id: string
1740 @param ref_column_id: The id of the parent column.
1741 @type ref_column_id: string
1742 @param config: Contains any additional control parameters. Can be C{None}.
1743 @type config:dictionary
1744 @raise ServerError: If the server has received the request but did not process the request due to some error.
1745 @raise ParseError: If the server has responded but client was not able to parse the response.
1746 """
1747 config["referenceViewId"] = ref_view_id;
1748 config["referenceColumnId"] = ref_column_id
1749 endpoint = self.endpoint + "/columns/" + column_id + "/lookup"
1750 self.ac.send_api_request("POST", endpoint, config, self.request_headers)
1751
1753 """
1754 Remove the lookup for the specified column in the table.
1755 @param column_id: Id of the column.
1756 @type column_id: string
1757 @param config: Contains any additional control parameters. Can be C{None}.
1758 @type config:dictionary
1759 @raise ServerError: If the server has received the request but did not process the request due to some error.
1760 @raise ParseError: If the server has responded but client was not able to parse the response.
1761 """
1762 endpoint = self.endpoint + "/columns/" + column_id + "/lookup"
1763 self.ac.send_api_request("DELETE", endpoint, config, self.request_headers)
1764
1766 """
1767 Auto generate reports for the specified column.
1768 @param column_id: Id of the column.
1769 @type column_id: string
1770 @param config: Contains any additional control parameters. Can be C{None}.
1771 @type config:dictionary
1772 @raise ServerError: If the server has received the request but did not process the request due to some error.
1773 @raise ParseError: If the server has responded but client was not able to parse the response.
1774 """
1775 endpoint = self.endpoint + "/columns/" + column_id + "/autoanalyse"
1776 self.ac.send_api_request("POST", endpoint, config, self.request_headers)
1777
1779 """
1780 Sync data from available datasource for the specified view.
1781 @param config: Contains any additional control parameters. Can be C{None}.
1782 @type config:dictionary
1783 @raise ServerError: If the server has received the request but did not process the request due to some error.
1784 @raise ParseError: If the server has responded but client was not able to parse the response.
1785 """
1786 endpoint = self.endpoint + "/sync"
1787 response = self.ac.send_api_request("POST", endpoint, config, self.request_headers)
1788
1790 """
1791 Returns last import details of the specified view.
1792 @raise ServerError: If the server has received the request but did not process the request due to some error.
1793 @raise ParseError: If the server has responded but client was not able to parse the response.
1794 @return: Last import details.
1795 @rtype:dictionary
1796 """
1797 endpoint = self.endpoint + "/importdetails"
1798 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
1799 return response["data"]
1800
1812
1832
1848
1861
1873
1893
1909
1922
1924 """
1925 Returns list of dependents views for the specified view.
1926 @raise ServerError: If the server has received the request but did not process the request due to some error.
1927 @raise ParseError: If the server has responded but client was not able to parse the response.
1928 @return: Dependent view list.
1929 @rtype:list
1930 """
1931 endpoint = self.endpoint + "/dependents"
1932 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
1933 return response["data"]["views"]
1934
1936 """
1937 Returns list of dependents views and formulas for the specified column.
1938 @raise ServerError: If the server has received the request but did not process the request due to some error.
1939 @raise ParseError: If the server has responded but client was not able to parse the response.
1940 @return: Dependent details.
1941 @rtype:dictionary
1942 """
1943 endpoint = self.endpoint + "/columns/" + column_id + "/dependents"
1944 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
1945 return response["data"]
1946
1948 """
1949 Update shared details of the specified view.
1950 @param config: Contains the control parameters.
1951 @type config:dictionary
1952 @raise ServerError: If the server has received the request but did not process the request due to some error.
1953 @raise ParseError: If the server has responded but client was not able to parse the response.
1954 """
1955 endpoint = self.endpoint + "/share"
1956 self.ac.send_api_request("PUT", endpoint, config, self.request_headers)
1957
1958
1960 """
1961 BulkAPI contains data operations.
1962 """
1963 - def __init__(self, ac, org_id, workspace_id):
1964 self.ac = ac
1965 self.endpoint = "/restapi/v2/workspaces/" + workspace_id
1966 self.bulk_endpoint = "/restapi/v2/bulk/workspaces/" + workspace_id
1967 self.request_headers = {}
1968 self.request_headers["ZANALYTICS-ORGID"] = org_id
1969
1971 """
1972 Create a new table and import the data contained in the mentioned file into the created table.
1973 @param table_name: Name of the new table to be created.
1974 @type table_name: string
1975 @param file_type: Type of the file to be imported.
1976 @type file_type: string
1977 @param auto_identify: Used to specify whether to auto identify the CSV format. Allowable values - true/false.
1978 @type auto_identify: string
1979 @param file_path: Path of the file to be imported.
1980 @type file_path: string
1981 @param config: Contains any additional control parameters. Can be C{None}.
1982 @type config:dictionary
1983 @raise ServerError: If the server has received the request but did not process the request due to some error.
1984 @raise ParseError: If the server has responded but client was not able to parse the response.
1985 @return Import result
1986 @rtype:dictionary
1987 """
1988 endpoint = self.endpoint + "/data"
1989 config["tableName"] = table_name
1990 config["fileType"] = file_type
1991 config["autoIdentify"] = auto_identify
1992 response = self.ac.send_import_api_request(endpoint, config, self.request_headers, file_path)
1993 return response["data"]
1994
1997 """
1998 Create a new table and import the data contained in the mentioned file into the created table.
1999 @param table_name: Name of the new table to be created.
2000 @type table_name: string
2001 @param auto_identify: Used to specify whether to auto identify the CSV format. Allowable values - true/false.
2002 @type auto_identify: string
2003 @param file_path: Path of the file to be imported.
2004 @type file_path: string
2005 @param batch_size: Number of lines per batch.
2006 @type batch_size:int
2007 @param config: Contains any additional control parameters. Can be C{None}.
2008 @type config:dictionary
2009 @param tool_config: Contains any additional control parameters for the library. Can be C{None}.
2010 @type tool_config:dictionary
2011 @raise ServerError: If the server has received the request but did not process the request due to some error.
2012 @raise ParseError: If the server has responded but client was not able to parse the response.
2013 @return Import job id
2014 @rtype:string
2015 """
2016 endpoint = self.bulk_endpoint + "/data/batch"
2017 config["tableName"] = table_name
2018 config["autoIdentify"] = auto_identify
2019 response = self.ac.send_batch_import_api_request(endpoint, config, self.request_headers, file_path,
2020 batch_size, tool_config)
2021 return response["data"]["jobId"]
2022
2024 """
2025 Create a new table and import the raw data provided into the created table.
2026 @param table_name: Name of the new table to be created.
2027 @type table_name: string
2028 @param file_type: Type of the file to be imported.
2029 @type file_type: string
2030 @param auto_identify: Used to specify whether to auto identify the CSV format. Allowable values - true/false.
2031 @type auto_identify: string
2032 @param data: Raw data to be imported.
2033 @type data: string
2034 @param config: Contains any additional control parameters. Can be C{None}.
2035 @type config:dictionary
2036 @raise ServerError: If the server has received the request but did not process the request due to some error.
2037 @raise ParseError: If the server has responded but client was not able to parse the response.
2038 @return Import result
2039 @rtype:dictionary
2040 """
2041 endpoint = self.endpoint + "/data"
2042 config["tableName"] = table_name
2043 config["fileType"] = file_type
2044 config["autoIdentify"] = auto_identify
2045 response = self.ac.send_import_api_request(endpoint, config, self.request_headers, None, data)
2046 return response["data"]
2047
2048 - def import_data(self, view_id, import_type, file_type, auto_identify, file_path, config = {}):
2049 """
2050 Import the data contained in the mentioned file into the table.
2051 @param view_id: Id of the view where the data to be imported.
2052 @type view_id: string
2053 @param import_type: The type of import. Can be one of - append, truncateadd, updateadd.
2054 @type import_type: string
2055 @param file_type: Type of the file to be imported.
2056 @type file_type: string
2057 @param auto_identify: Used to specify whether to auto identify the CSV format. Allowable values - true/false.
2058 @type auto_identify: string
2059 @param file_path: Path of the file to be imported.
2060 @type file_path: string
2061 @param config: Contains any additional control parameters. Can be C{None}.
2062 @type config:dictionary
2063 @raise ServerError: If the server has received the request but did not process the request due to some error.
2064 @raise ParseError: If the server has responded but client was not able to parse the response.
2065 @return Import result
2066 @rtype:dictionary
2067 """
2068 endpoint = self.endpoint + "/views/" + view_id + "/data"
2069 config["fileType"] = file_type
2070 config["autoIdentify"] = auto_identify
2071 config["importType"] = import_type
2072 response = self.ac.send_import_api_request(endpoint, config, self.request_headers, file_path)
2073 return response["data"]
2074
2075 - def import_raw_data(self, view_id, import_type, file_type, auto_identify, data, config = {}):
2076 """
2077 Import the raw data provided into the table.
2078 @param view_id: Id of the view where the data to be imported.
2079 @type view_id: string
2080 @param import_type: The type of import. Can be one of - append, truncateadd, updateadd.
2081 @type import_type: string
2082 @param file_type: Type of the file to be imported.
2083 @type file_type: string
2084 @param auto_identify: Used to specify whether to auto identify the CSV format. Allowable values - true/false.
2085 @type auto_identify: string
2086 @param data: Raw data to be imported.
2087 @type data: string
2088 @param config: Contains any additional control parameters. Can be C{None}.
2089 @type config:dictionary
2090 @raise ServerError: If the server has received the request but did not process the request due to some error.
2091 @raise ParseError: If the server has responded but client was not able to parse the response.
2092 @return Import result
2093 @rtype:dictionary
2094 """
2095 endpoint = self.endpoint + "/views/" + view_id + "/data"
2096 config["fileType"] = file_type
2097 config["autoIdentify"] = auto_identify
2098 config["importType"] = import_type
2099 response = self.ac.send_import_api_request(endpoint, config, self.request_headers, None, data)
2100 return response["data"]
2101
2103 """
2104 Asynchronously create a new table and import the data contained in the mentioned file into the created table.
2105 @param table_name: Name of the new table to be created.
2106 @type table_name: string
2107 @param file_type: Type of the file to be imported.
2108 @type file_type: string
2109 @param auto_identify: Used to specify whether to auto identify the CSV format. Allowable values - true/false.
2110 @type auto_identify: string
2111 @param file_path: Path of the file to be imported.
2112 @type file_path: string
2113 @param config: Contains any additional control parameters. Can be C{None}.
2114 @type config:dictionary
2115 @raise ServerError: If the server has received the request but did not process the request due to some error.
2116 @raise ParseError: If the server has responded but client was not able to parse the response.
2117 @return Import job id
2118 @rtype:string
2119 """
2120 endpoint = self.bulk_endpoint + "/data"
2121 config["tableName"] = table_name
2122 config["fileType"] = file_type
2123 config["autoIdentify"] = auto_identify
2124 response = self.ac.send_import_api_request(endpoint, config, self.request_headers, file_path)
2125 return response["data"]["jobId"]
2126
2127 - def import_bulk_data(self, view_id, import_type, file_type, auto_identify, file_path, config = {}):
2128 """
2129 Asynchronously import the data contained in the mentioned file into the table.
2130 @param view_id: Id of the view where the data to be imported.
2131 @type view_id: string
2132 @param import_type: The type of import. Can be one of - append, truncateadd, updateadd.
2133 @type import_type: string
2134 @param file_type: Type of the file to be imported.
2135 @type file_type: string
2136 @param auto_identify: Used to specify whether to auto identify the CSV format. Allowable values - true/false.
2137 @type auto_identify: string
2138 @param file_path: Path of the file to be imported.
2139 @type file_path: string
2140 @param config: Contains any additional control parameters. Can be C{None}.
2141 @type config:dictionary
2142 @raise ServerError: If the server has received the request but did not process the request due to some error.
2143 @raise ParseError: If the server has responded but client was not able to parse the response.
2144 @return Import job id
2145 @rtype:string
2146 """
2147 endpoint = self.bulk_endpoint + "/views/" + view_id + "/data"
2148 config["fileType"] = file_type
2149 config["autoIdentify"] = auto_identify
2150 config["importType"] = import_type
2151 response = self.ac.send_import_api_request(endpoint, config, self.request_headers, file_path)
2152 return response["data"]["jobId"]
2153
2154 - def import_data_as_batches(self, view_id, import_type, auto_identify, file_path, batch_size,
2155 config={}, tool_config={}):
2156 """
2157 Asynchronously import the data contained in the mentioned file into the table.
2158 @param view_id: Id of the view where the data to be imported.
2159 @type view_id: string
2160 @param import_type: The type of import. Can be one of - append, truncateadd, updateadd.
2161 @type import_type: string
2162 @param auto_identify: Used to specify whether to auto identify the CSV format. Allowable values - true/false.
2163 @type auto_identify: string
2164 @param file_path: Path of the file to be imported.
2165 @type file_path: string
2166 @param batch_size: Number of lines per batch.
2167 @type batch_size:int
2168 @param config: Contains any additional control parameters. Can be C{None}.
2169 @type config:dictionary
2170 @param tool_config: Contains any additional control parameters for the library. Can be C{None}.
2171 @type tool_config:dictionary
2172 @raise ServerError: If the server has received the request but did not process the request due to some error.
2173 @raise ParseError: If the server has responded but client was not able to parse the response.
2174 @return Import job id
2175 @rtype:string
2176 """
2177 endpoint = self.bulk_endpoint + "/views/" + view_id + "/data/batch"
2178 config["importType"] = import_type
2179 config["autoIdentify"] = auto_identify
2180 response = self.ac.send_batch_import_api_request(endpoint, config, self.request_headers, file_path,
2181 batch_size, tool_config)
2182 return response["data"]["jobId"]
2183
2185 """
2186 Returns the details of the import job.
2187 @param job_id: Id of the job.
2188 @type job_id: string
2189 @raise ServerError: If the server has received the request but did not process the request due to some error.
2190 @raise ParseError: If the server has responded but client was not able to parse the response.
2191 @return Import job details
2192 @rtype:dictionary
2193 """
2194 endpoint = self.bulk_endpoint + "/importjobs/" + job_id
2195 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
2196 return response["data"]
2197
2198 - def export_data(self, view_id, response_format, file_path, config = {}):
2199 """
2200 Export the mentioned table (or) view data.
2201 @param view_id: Id of the view to be exported.
2202 @type view_id: string
2203 @param response_format: The format in which the data is to be exported.
2204 @type response_format: string
2205 @param file_path: Path of the file where the data exported to be stored.
2206 @type file_path: string
2207 @param config: Contains any additional control parameters. Can be C{None}.
2208 @type config:dictionary
2209 @raise ServerError: If the server has received the request but did not process the request due to some error.
2210 @raise ParseError: If the server has responded but client was not able to parse the response.
2211 """
2212 endpoint = self.endpoint + "/views/" + view_id + "/data"
2213 config["responseFormat"] = response_format
2214 self.ac.send_export_api_request(endpoint, config, self.request_headers, file_path)
2215
2217 """
2218 Initiate asynchronous export for the mentioned table (or) view data.
2219 @param view_id: Id of the view to be exported.
2220 @type view_id: string
2221 @param response_format: The format in which the data is to be exported.
2222 @type response_format: string
2223 @param config: Contains any additional control parameters. Can be C{None}.
2224 @type config:dictionary
2225 @raise ServerError: If the server has received the request but did not process the request due to some error.
2226 @raise ParseError: If the server has responded but client was not able to parse the response.
2227 @return Export job id
2228 @rtype:string
2229 """
2230 endpoint = self.bulk_endpoint + "/views/" + view_id + "/data"
2231 config["responseFormat"] = response_format
2232 response = self.ac.send_api_request("GET", endpoint, config, self.request_headers)
2233 return response["data"]["jobId"]
2234
2236 """
2237 Initiate asynchronous export with the given SQL Query.
2238 @param sql_query: SQL Query.
2239 @type sql_query: string
2240 @param response_format: The format in which the data is to be exported.
2241 @type response_format: string
2242 @param config: Contains any additional control parameters. Can be C{None}.
2243 @type config:dictionary
2244 @raise ServerError: If the server has received the request but did not process the request due to some error.
2245 @raise ParseError: If the server has responded but client was not able to parse the response.
2246 @return Export job id
2247 @rtype:string
2248 """
2249 endpoint = self.bulk_endpoint + "/data"
2250 config["responseFormat"] = response_format
2251 config["sqlQuery"] = sql_query
2252 response = self.ac.send_api_request("GET", endpoint, config, self.request_headers)
2253 return response["data"]["jobId"]
2254
2256 """
2257 Returns the details of the export job.
2258 @param job_id: Id of the export job.
2259 @type job_id: string
2260 @raise ServerError: If the server has received the request but did not process the request due to some error.
2261 @raise ParseError: If the server has responded but client was not able to parse the response.
2262 @return Export job details
2263 @rtype:dictionary
2264 """
2265 endpoint = self.bulk_endpoint + "/exportjobs/" + job_id
2266 response = self.ac.send_api_request("GET", endpoint, None, self.request_headers)
2267 return response["data"]
2268
2270 """
2271 Download the exported data for the mentioned job id.
2272 @param job_id: Id of the job to be exported.
2273 @type job_id: string
2274 @param file_path: Path of the file where the data exported to be stored.
2275 @type file_path: string
2276 @raise ServerError: If the server has received the request but did not process the request due to some error.
2277 @raise ParseError: If the server has responded but client was not able to parse the response.
2278 """
2279 endpoint = self.bulk_endpoint + "/exportjobs/" + job_id + "/data"
2280 self.ac.send_export_api_request(endpoint, None, self.request_headers, file_path)
2281
2282
2283 - def set_proxy(self, proxy_host, proxy_port, proxy_user_name, proxy_password):
2284 """
2285 Internal method to handle proxy details.
2286 """
2287 self.proxy = True
2288 self.proxy_host = proxy_host
2289 self.proxy_port = proxy_port
2290 self.proxy_user_name = proxy_user_name
2291 self.proxy_password = proxy_password
2292
2294 if self.access_token is None:
2295 self.regenerate_analytics_oauth_token()
2296
2297 file_header = open(file_path, 'r').readline()
2298 file_content = open(file_path, 'r').readlines()
2299 file_content.__delitem__(0)
2300 total_lines = len(file_content)
2301 total_batch_count = math.ceil(total_lines / batch_size)
2302 config["batchKey"] = "start"
2303 request_url = self.analytics_server_url + request_url
2304
2305 for i in range(total_batch_count):
2306 batch = ("".join(file_content[batch_size * i:batch_size + (i * batch_size)]))
2307 batch_file = StringIO( file_header + batch )
2308 files = {'FILE': batch_file}
2309
2310 config["isLastBatch"] = "true" if (i == (total_batch_count - 1)) else "false"
2311 config_data = "CONFIG=" + urllib.parse.quote_plus(json.dumps(config))
2312
2313 resp_obj = self.submit_import_request(request_url, config_data, request_headers, self.access_token, files)
2314
2315 if not (str(resp_obj.status_code).startswith("2")):
2316 if self.is_oauth_expired(resp_obj):
2317 self.regenerate_analytics_oauth_token()
2318 resp_obj = self.submit_import_request(request_url, config_data, request_headers, self.access_token,
2319 files)
2320 if not (str(resp_obj.status_code).startswith("2")):
2321 raise ServerError(resp_obj.resp_content, False)
2322 else:
2323 raise ServerError(resp_obj.resp_content, False)
2324
2325 response = resp_obj.resp_content
2326 response = json.loads(response)
2327 config["batchKey"] = response["data"]["batchKey"]
2328 time.sleep(2)
2329
2330 return response
2331
2333 """
2334 Internal method to handle HTTP request.
2335 """
2336 if self.access_token == None:
2337 self.regenerate_analytics_oauth_token()
2338
2339 request_url = self.analytics_server_url + request_url
2340 config_data = None
2341 if bool(config):
2342 config_data = "CONFIG=" + urllib.parse.quote_plus(json.dumps(config))
2343
2344 if bool(data):
2345 if(bool(config_data)):
2346 config_data += "&"
2347 else:
2348 config_data = ""
2349
2350 config_data += "DATA=" + urllib.parse.quote_plus(json.dumps(data))
2351 resp_obj = self.submit_import_request(request_url, config_data, request_headers, self.access_token)
2352 else:
2353 files = {'FILE': open(file_path,'rb')}
2354 resp_obj = self.submit_import_request(request_url, config_data, request_headers, self.access_token, files)
2355
2356
2357 if not (str(resp_obj.status_code).startswith("2")):
2358 if(self.is_oauth_expired(resp_obj)):
2359 self.regenerate_analytics_oauth_token()
2360 if bool(data):
2361 resp_obj = self.submit_import_request(request_url, config_data, request_headers, self.access_token)
2362 else:
2363 resp_obj = self.submit_import_request(request_url, config_data, request_headers, self.access_token, files)
2364 if not (str(resp_obj.status_code).startswith("2")):
2365 raise ServerError(resp_obj.resp_content, False)
2366 else:
2367 raise ServerError(resp_obj.resp_content, False)
2368
2369 response = resp_obj.resp_content
2370 response = json.loads(response)
2371 return response
2372
2373
2374 - def submit_import_request(self, request_url, parameters, request_headers = {}, access_token = None, files = None):
2375 """
2376 Internal method to send request to server.
2377 """
2378 try:
2379 if request_headers == None:
2380 request_headers = {}
2381
2382 if access_token != None:
2383 request_headers["Authorization"] = "Zoho-oauthtoken " + access_token
2384
2385 request_headers["User-Agent"] = "Analytics Python Client v" + self.CLIENT_VERSION
2386
2387 req_obj = req_obj = requests.Session()
2388 if self.proxy:
2389 proxy_details = {
2390 "http" : "http://" + self.proxy_host + ":" + self.proxy_port,
2391 "https": "http://" + self.proxy_host + ":" + self.proxy_port
2392 }
2393 req_obj.proxies = proxy_details
2394 if self.proxy_user_name != None and self.proxy_password != None:
2395 proxy_auth_details = HTTPProxyDigestAuth(self.proxy_user_name, self.proxy_password)
2396 req_obj.auth = proxy_auth_details
2397
2398 if bool(files):
2399 resp_obj = req_obj.post(request_url, params = parameters, files = files, headers = request_headers)
2400 else:
2401 resp_obj = req_obj.post(request_url, params = parameters, headers = request_headers)
2402
2403 resp_obj = response_obj(resp_obj)
2404 except Exception as ex:
2405 resp_obj = response_obj(ex)
2406
2407 return resp_obj
2408
2410 """
2411 Internal method to handle HTTP request.
2412 """
2413 file = open(file_path,"wb")
2414
2415 if self.access_token == None:
2416 self.regenerate_analytics_oauth_token()
2417
2418 request_url = self.analytics_server_url + request_url
2419 config_data = None
2420 if bool(config):
2421 config_data = "CONFIG=" + urllib.parse.quote_plus(json.dumps(config))
2422
2423 resp_obj = self.submit_export_request(request_url, config_data, request_headers, self.access_token)
2424
2425 if not (str(resp_obj.status_code).startswith("2")):
2426 resp_obj = response_obj(resp_obj)
2427 if(self.is_oauth_expired(resp_obj)):
2428 self.regenerate_analytics_oauth_token()
2429 resp_obj = self.submit_export_request(request_url, config_data, request_headers, self.access_token)
2430 if not (str(resp_obj.status_code).startswith("2")):
2431 raise ServerError(resp_obj.resp_content, False)
2432 else:
2433 raise ServerError(resp_obj.resp_content, False)
2434
2435 file.write(resp_obj.content)
2436 file.close()
2437 return
2438
2439
2441 """
2442 Internal method to send request to server.
2443 """
2444 try:
2445 if request_headers == None:
2446 request_headers = {}
2447
2448 if access_token != None:
2449 request_headers["Authorization"] = "Zoho-oauthtoken " + access_token
2450
2451 request_headers["User-Agent"] = "Analytics Python Client v" + self.CLIENT_VERSION
2452
2453 req_obj = req_obj = requests.Session()
2454 if self.proxy:
2455 proxy_details = {
2456 "http" : "http://" + self.proxy_host + ":" + self.proxy_port,
2457 "https": "http://" + self.proxy_host + ":" + self.proxy_port
2458 }
2459 req_obj.proxies = proxy_details
2460 if self.proxy_user_name != None and self.proxy_password != None:
2461 proxy_auth_details = HTTPProxyDigestAuth(self.proxy_user_name, self.proxy_password)
2462 req_obj.auth = proxy_auth_details
2463
2464 resp_obj = req_obj.get(request_url, params = parameters, headers = request_headers)
2465
2466 except Exception as ex:
2467 resp_obj = response_obj(ex)
2468
2469 return resp_obj
2470
2471 - def send_api_request(self, request_method, request_url, config, request_headers, is_json_response = True):
2472 """
2473 Internal method to handle HTTP request.
2474 """
2475 if self.access_token == None:
2476 self.regenerate_analytics_oauth_token()
2477
2478 request_url = self.analytics_server_url + request_url
2479 config_data = None
2480 if bool(config):
2481 config_data = "CONFIG=" + urllib.parse.quote_plus(json.dumps(config))
2482
2483 resp_obj = self.submit_request(request_method, request_url, config_data, request_headers, self.access_token)
2484
2485 if not (str(resp_obj.status_code).startswith("2")):
2486 if(self.is_oauth_expired(resp_obj)):
2487 self.regenerate_analytics_oauth_token()
2488 resp_obj = self.submit_request(request_method, request_url, config_data, request_headers, self.access_token)
2489 if not (str(resp_obj.status_code).startswith("2")):
2490 raise ServerError(resp_obj.resp_content, False)
2491 else:
2492 raise ServerError(resp_obj.resp_content, False)
2493
2494
2495 if (str(resp_obj.status_code) != "200"):
2496 return
2497
2498 response = resp_obj.resp_content
2499 if is_json_response:
2500 response = json.loads(response)
2501 return response
2502
2503
2504 - def submit_request(self, request_method, request_url, parameters, request_headers = {}, access_token = None):
2505 """
2506 Internal method to send request to server.
2507 """
2508 try:
2509 if request_headers == None:
2510 request_headers = {}
2511
2512 if access_token != None:
2513 request_headers["Authorization"] = "Zoho-oauthtoken " + access_token
2514
2515 request_headers["User-Agent"] = "Analytics Python Client v" + self.CLIENT_VERSION
2516
2517 req_obj = req_obj = requests.Session()
2518 if self.proxy:
2519 proxy_details = {
2520 "http" : "http://" + self.proxy_host + ":" + self.proxy_port,
2521 "https": "http://" + self.proxy_host + ":" + self.proxy_port
2522 }
2523 req_obj.proxies = proxy_details
2524 if self.proxy_user_name != None and self.proxy_password != None:
2525 proxy_auth_details = HTTPProxyDigestAuth(self.proxy_user_name, self.proxy_password)
2526 req_obj.auth = proxy_auth_details
2527
2528 resp_obj = None
2529
2530 if request_method == "GET":
2531 resp_obj = req_obj.get(request_url, params = parameters, headers = request_headers)
2532 elif request_method == "POST":
2533 resp_obj = req_obj.post(request_url, params = parameters, headers = request_headers)
2534 elif request_method == "PUT":
2535 resp_obj = req_obj.put(request_url, params = parameters, headers = request_headers)
2536 elif request_method == "DELETE":
2537 resp_obj = req_obj.delete(request_url, params = parameters, headers = request_headers)
2538
2539 resp_obj = response_obj(resp_obj)
2540 except Exception as ex:
2541 resp_obj = response_obj(ex)
2542
2543 return resp_obj
2544
2546 """
2547 Internal method for getting OAuth token.
2548 """
2549 req_obj = requests.Session()
2550
2551 if self.proxy:
2552 proxy_details = {
2553 "http" : "http://" + self.proxy_host + ":" + self.proxy_port,
2554 "https": "http://" + self.proxy_host + ":" + self.proxy_port
2555 }
2556 req_obj.proxies = proxy_details
2557 if self.proxy_user_name != None and self.proxy_password != None:
2558 proxy_auth_details = HTTPProxyDigestAuth(self.proxy_user_name, self.proxy_password)
2559 req_obj.auth = proxy_auth_details
2560 return req_obj
2561
2562
2564 """
2565 Internal method to check whether the accesstoken expired or not.
2566 """
2567 try:
2568 resp_content = json.loads(resp_obj.resp_content)
2569 err_code = resp_content["data"]["errorCode"]
2570 return err_code == 8535
2571 except Exception:
2572 return False
2573
2574
2576 """
2577 Internal method for getting OAuth token.
2578 """
2579 oauth_params = {}
2580 oauth_params["client_id"] = self.client_id
2581 oauth_params["client_secret"] = self.client_secret
2582 oauth_params["refresh_token"] = self.refresh_token
2583 oauth_params["grant_type"] = "refresh_token"
2584 oauth_params = urllib.parse.urlencode(oauth_params)
2585 req_url = self.accounts_server_url + "/oauth/v2/token"
2586 oauth_resp_obj = self.submit_request("POST", req_url, oauth_params)
2587
2588 if(oauth_resp_obj.status_code == 200):
2589 oauth_json_resp = json.loads(oauth_resp_obj.resp_content)
2590 if("access_token" in oauth_json_resp):
2591 self.access_token = oauth_json_resp["access_token"]
2592 return
2593
2594 raise ServerError(oauth_resp_obj.resp_content, True)
2595
2596
2598 """
2599 Internal class.
2600 """
2602 self.resp_content = resp_obj.text
2603 self.status_code = resp_obj.status_code
2604 self.headers = resp_obj.headers
2605
2606
2608 """
2609 ServerError is thrown if the analytics server has received the request but did not process the
2610 request due to some error. For example if authorization failure.
2611 """
2612
2613 - def __init__(self, response, is_IAM_Error):
2614 self.errorCode = 0
2615 self.message = response
2616
2617 try:
2618 error_data = json.loads(response)
2619 if is_IAM_Error :
2620 self.message = "Exception while generating oauth token. Response - " + response
2621 else:
2622 self.errorCode = error_data["data"]["errorCode"]
2623 self.message = error_data["data"]["errorMessage"]
2624 except Exception as inst :
2625 print(inst)
2626 self.parseError = inst
2627
2629 return repr(self.message)
2630
2631
2633 """
2634 ParseError is thrown if the server has responded but client was not able to parse the response.
2635 Possible reasons could be version mismatch.The client might have to be updated to a newer version.
2636 """
2637 - def __init__(self, responseContent, message, origExcep):
2638 self.responseContent= responseContent
2639 self.message=message
2640 self.origExcep= origExcep
2641
2643 return repr(self.message)
2644