qe-api-client 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2018 The Python Packaging Authority
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,45 @@
1
+ Metadata-Version: 2.1
2
+ Name: qe-api-client
3
+ Version: 1.0.0
4
+ Summary: Python wrapper around Qlik Engine JSON API
5
+ Home-page: https://github.com/lr-bicc/qe-api-client
6
+ Author: Rumen Vasilev
7
+ Author-email: R.Vasilev@LRWorld.com
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.6
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: websocket-client>=0.47.0
15
+
16
+ # pyqlikengine
17
+
18
+ Python wrapper around [Qlik Engine JSON API](https://help.qlik.com/en-US/sense-developer/February2024/Subsystems/EngineAPI/Content/Sense_EngineAPI/introducing-engine-API.htm)
19
+
20
+ Forked from [jhettler/pyqlikengine](https://github.com/jhettler/pyqlikengine)
21
+
22
+ ## Requirements
23
+ * Python 3.6+
24
+ * websocket-client>=0.47.0
25
+
26
+ ## Example of usage
27
+ ```bash
28
+ pip install qe-api-client
29
+ ```
30
+ ```python
31
+ from qe_api_client.engine import QixEngine
32
+
33
+ url = 'qlik-1.ad.xxx.xxx'
34
+ user_directory = 'UserDomainToQlikLogin'
35
+ user_id = 'sense'
36
+ ca_certs = 'qlik_certs/qlik-1_root.pem'
37
+ certfile = 'qlik_certs/qlik-1_client.pem'
38
+ keyfile = 'qlik_certs/qlik-1_client_key.pem'
39
+ qixe = QixEngine(url=url, user_directory=user_directory,
40
+ user_id=user_id, ca_certs=ca_certs,
41
+ certfile=certfile, keyfile=keyfile)
42
+
43
+ # print all apps in Qlik Server
44
+ print(qixe.ega.get_doc_list())
45
+ ```
@@ -0,0 +1,30 @@
1
+ # pyqlikengine
2
+
3
+ Python wrapper around [Qlik Engine JSON API](https://help.qlik.com/en-US/sense-developer/February2024/Subsystems/EngineAPI/Content/Sense_EngineAPI/introducing-engine-API.htm)
4
+
5
+ Forked from [jhettler/pyqlikengine](https://github.com/jhettler/pyqlikengine)
6
+
7
+ ## Requirements
8
+ * Python 3.6+
9
+ * websocket-client>=0.47.0
10
+
11
+ ## Example of usage
12
+ ```bash
13
+ pip install qe-api-client
14
+ ```
15
+ ```python
16
+ from qe_api_client.engine import QixEngine
17
+
18
+ url = 'qlik-1.ad.xxx.xxx'
19
+ user_directory = 'UserDomainToQlikLogin'
20
+ user_id = 'sense'
21
+ ca_certs = 'qlik_certs/qlik-1_root.pem'
22
+ certfile = 'qlik_certs/qlik-1_client.pem'
23
+ keyfile = 'qlik_certs/qlik-1_client_key.pem'
24
+ qixe = QixEngine(url=url, user_directory=user_directory,
25
+ user_id=user_id, ca_certs=ca_certs,
26
+ certfile=certfile, keyfile=keyfile)
27
+
28
+ # print all apps in Qlik Server
29
+ print(qixe.ega.get_doc_list())
30
+ ```
@@ -0,0 +1 @@
1
+ name = "qe_api_client"
@@ -0,0 +1,145 @@
1
+ import qe_api_client.engine_app_api as engine_app_api
2
+ import qe_api_client.engine_communicator as engine_communicator
3
+ import qe_api_client.engine_field_api as engine_field_api
4
+ import qe_api_client.engine_generic_object_api as engine_generic_object_api
5
+ import qe_api_client.engine_global_api as engine_global_api
6
+ import qe_api_client.structs as structs
7
+
8
+
9
+ class QixEngine:
10
+
11
+ def __init__(self, url, user_directory,
12
+ user_id, ca_certs, certfile,
13
+ keyfile, app_id=None):
14
+ self.url = url
15
+ self.conn = engine_communicator.SecureEngineCommunicator(
16
+ url, user_directory,
17
+ user_id, ca_certs, certfile,
18
+ keyfile, app_id
19
+ )
20
+ self.ega = engine_global_api.EngineGlobalApi(self.conn)
21
+ self.eaa = engine_app_api.EngineAppApi(self.conn)
22
+ self.egoa = engine_generic_object_api.EngineGenericObjectApi(self.conn)
23
+ self.efa = engine_field_api.EngineFieldApi(self.conn)
24
+ self.Structs = structs.Structs()
25
+ self.app_handle = ''
26
+
27
+ def create_app(self, app_name='my_app'):
28
+ app = self.ega.create_app(app_name)
29
+ try:
30
+ return app['qAppId']
31
+ except KeyError:
32
+ return app['message']
33
+
34
+ def load_script(self, script):
35
+ self.eaa.set_script(self.app_handle, script)
36
+ return self.eaa.do_reload_ex(self.app_handle)['qResult']['qSuccess']
37
+
38
+ def open_app(self, app_obj):
39
+ opened_app = self.ega.open_doc(app_obj)['qReturn']
40
+ self.app_handle = self.ega.get_handle(opened_app)
41
+ return opened_app['qGenericId']
42
+
43
+ def create_hypercube(self, list_of_dimensions=[],
44
+ list_of_measures=[], rows_to_return=1000):
45
+ no_of_columns = len(list_of_dimensions) + len(list_of_measures)
46
+ hc_dim = []
47
+ for d in list_of_dimensions:
48
+ hc_inline_dim = self.Structs.nx_inline_dimension_def([d])
49
+ hc_dim.append(self.Structs.nx_hypercube_dimensions(hc_inline_dim))
50
+ hc_mes = []
51
+ for m in list_of_measures:
52
+ hc_mes_sort = self.Structs.nx_sort_by()
53
+ hc_inline_mes = self.Structs.nx_inline_measure_def(m)
54
+ hc_mes.append(self.Structs.nx_hypercube_measure(hc_mes_sort,
55
+ hc_inline_mes))
56
+ nx_page = self.Structs.nx_page(0, 0, rows_to_return, no_of_columns)
57
+ hc_def = self.Structs.hypercube_def("$", hc_dim, hc_mes, [nx_page])
58
+ hc_response = self.eaa.create_object(self.app_handle, "CH01",
59
+ "Chart", "qHyperCubeDef", hc_def)
60
+ hc_handle = self.ega.get_handle(hc_response["qReturn"])
61
+ self.egoa.get_layout(hc_handle)
62
+ hc_data = self.egoa.get_hypercube_data(hc_handle, "/qHyperCubeDef",
63
+ [nx_page])
64
+ no_of_columns = len(list_of_dimensions)+len(list_of_measures)
65
+ return hc_data, no_of_columns
66
+
67
+ @staticmethod
68
+ def convert_hypercube_to_matrix(hc_data, no_of_columns):
69
+ rows = hc_data["qDataPages"][0]['qMatrix']
70
+ matrix = [[0 for x in range(no_of_columns)] for y in range(len(rows))]
71
+ for col_idx, row in enumerate(rows):
72
+ for cell_idx, cell_val in enumerate(row):
73
+ matrix[col_idx][cell_idx] = cell_val['qText']
74
+ return [list(i) for i in zip(*matrix)]
75
+
76
+ @staticmethod
77
+ def convert_hypercube_to_inline_table(hc_data, table_name):
78
+ rows = hc_data["qDataPages"][0]['qMatrix']
79
+ script = str.format('{0}:{1}Load * Inline [{1}', table_name, '\n')
80
+ inline_rows = ''
81
+ header_row = ''
82
+ for col_idx in range(len(rows[0])):
83
+ header_row = header_row + str.format('Column{0}{1}', col_idx, ',')
84
+ header_row = header_row[:-1] + '\n'
85
+ for row in rows:
86
+ for cell_val in row:
87
+ inline_rows = inline_rows + "'" + cell_val['qText'] + "'" + ','
88
+ inline_rows = inline_rows[:-1] + '\n'
89
+ return script + header_row + inline_rows + '];'
90
+
91
+ def select_in_dimension(self, dimension_name, list_of_values):
92
+ lb_field = self.eaa.get_field(self.app_handle, dimension_name)
93
+ fld_handle = self.ega.get_handle(lb_field["qReturn"])
94
+ values_to_select = []
95
+ for val in list_of_values:
96
+ val = {'qText': val}
97
+ values_to_select.append(val)
98
+ return self.efa.select_values(fld_handle, values_to_select)
99
+
100
+ def select_excluded_in_dimension(self, dimension_name):
101
+ lb_field = self.eaa.get_field(self.app_handle, dimension_name)
102
+ fld_handle = self.ega.get_handle(lb_field["qReturn"])
103
+ return self.efa.select_excluded(fld_handle)
104
+
105
+ def select_possible_in_dimension(self, dimension_name):
106
+ lb_field = self.eaa.get_field(self.app_handle, dimension_name)
107
+ fld_handle = self.ega.get_handle(lb_field["qReturn"])
108
+ return self.efa.select_possible(fld_handle)
109
+
110
+ # return a list of tuples where first value in tuple is the actual
111
+ # data value and the second tuple value is that
112
+ # values selection state
113
+ def get_list_object_data(self, dimension_name):
114
+ lb_field = self.eaa.get_field(self.app_handle, dimension_name)
115
+ fld_handle = self.ega.get_handle(lb_field["qReturn"])
116
+ nx_page = self.Structs.nx_page(0, 0,
117
+ self.efa.get_cardinal(
118
+ fld_handle)["qReturn"]
119
+ )
120
+ lb_def = self.Structs.list_object_def("$", "",
121
+ [dimension_name],
122
+ None, None, [nx_page]
123
+ )
124
+ lb_param = {"qInfo": {"qId": "SLB01", "qType": "ListObject"},
125
+ "qListObjectDef": lb_def}
126
+ listobj_handle = self.eaa.create_session_object(self.app_handle, lb_param)["qReturn"]["qHandle"] # NOQA
127
+ val_list = self.egoa.get_layout(listobj_handle)["qLayout"]["qListObject"]["qDataPages"][0]["qMatrix"] # NOQA
128
+ val_n_state_list = []
129
+ for val in val_list:
130
+ val_n_state_list.append((val[0]["qText"], val[0]["qState"]))
131
+ return val_n_state_list
132
+
133
+ def clear_selection_in_dimension(self, dimension_name):
134
+ lb_field = self.eaa.get_field(self.app_handle, dimension_name)
135
+ fld_handle = self.ega.get_handle(lb_field["qReturn"])
136
+ return self.efa.clear(fld_handle)['qReturn']
137
+
138
+ def clear_all_selections(self):
139
+ return self.eaa.clear_all(self.app_handle, True)
140
+
141
+ def delete_app(self, app_name):
142
+ return self.ega.delete_app(app_name)['qSuccess']
143
+
144
+ def disconnect(self):
145
+ self.conn.close_qvengine_connection(self.conn)