qe-api-client 1.2.0__py3-none-any.whl → 2.1.0__py3-none-any.whl

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.
qe_api_client/engine.py CHANGED
@@ -1,12 +1,14 @@
1
- import qe_api_client.engine_app_api as engine_app_api
1
+ import qe_api_client.api_classes.engine_app_api as engine_app_api
2
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.engine_generic_variable_api as engine_generic_variable_api
7
- import qe_api_client.engine_generic_dimension_api as engine_generic_dimension_api
8
- import qe_api_client.engine_generic_measure_api as engine_generic_measure_api
3
+ import qe_api_client.api_classes.engine_field_api as engine_field_api
4
+ import qe_api_client.api_classes.engine_generic_object_api as engine_generic_object_api
5
+ import qe_api_client.api_classes.engine_global_api as engine_global_api
6
+ import qe_api_client.api_classes.engine_generic_variable_api as engine_generic_variable_api
7
+ import qe_api_client.api_classes.engine_generic_dimension_api as engine_generic_dimension_api
8
+ import qe_api_client.api_classes.engine_generic_measure_api as engine_generic_measure_api
9
9
  import qe_api_client.structs as structs
10
+ import math
11
+ import pandas as pd
10
12
 
11
13
 
12
14
  class QixEngine:
@@ -28,7 +30,7 @@ class QixEngine:
28
30
  self.egva = engine_generic_variable_api.EngineGenericVariableApi(self.conn)
29
31
  self.egda = engine_generic_dimension_api.EngineGenericDimensionApi(self.conn)
30
32
  self.egma = engine_generic_measure_api.EngineGenericMeasureApi(self.conn)
31
- self.Structs = structs.Structs()
33
+ self.structs = structs
32
34
  self.app_handle = ''
33
35
 
34
36
  def create_app(self, app_name='my_app'):
@@ -47,57 +49,9 @@ class QixEngine:
47
49
  self.app_handle = self.ega.get_handle(opened_app)
48
50
  return opened_app['qGenericId']
49
51
 
50
- def create_hypercube(self, list_of_dimensions=[],
51
- list_of_measures=[], rows_to_return=1000):
52
- no_of_columns = len(list_of_dimensions) + len(list_of_measures)
53
- hc_dim = []
54
- for d in list_of_dimensions:
55
- hc_inline_dim = self.Structs.nx_inline_dimension_def([d])
56
- hc_dim.append(self.Structs.nx_hypercube_dimensions(hc_inline_dim))
57
- hc_mes = []
58
- for m in list_of_measures:
59
- hc_mes_sort = self.Structs.nx_sort_by()
60
- hc_inline_mes = self.Structs.nx_inline_measure_def(m)
61
- hc_mes.append(self.Structs.nx_hypercube_measure(hc_mes_sort,
62
- hc_inline_mes))
63
- nx_page = self.Structs.nx_page(0, 0, rows_to_return, no_of_columns)
64
- hc_def = self.Structs.hypercube_def("$", hc_dim, hc_mes, [nx_page])
65
- hc_response = self.eaa.create_object(self.app_handle, "CH01",
66
- "Chart", "qHyperCubeDef", hc_def)
67
- hc_handle = self.ega.get_handle(hc_response["qReturn"])
68
- self.egoa.get_layout(hc_handle)
69
- hc_data = self.egoa.get_hypercube_data(hc_handle, "/qHyperCubeDef",
70
- [nx_page])
71
- no_of_columns = len(list_of_dimensions)+len(list_of_measures)
72
- return hc_data, no_of_columns
73
-
74
- @staticmethod
75
- def convert_hypercube_to_matrix(hc_data, no_of_columns):
76
- rows = hc_data["qDataPages"][0]['qMatrix']
77
- matrix = [[0 for x in range(no_of_columns)] for y in range(len(rows))]
78
- for col_idx, row in enumerate(rows):
79
- for cell_idx, cell_val in enumerate(row):
80
- matrix[col_idx][cell_idx] = cell_val['qText']
81
- return [list(i) for i in zip(*matrix)]
82
-
83
- @staticmethod
84
- def convert_hypercube_to_inline_table(hc_data, table_name):
85
- rows = hc_data["qDataPages"][0]['qMatrix']
86
- script = str.format('{0}:{1}Load * Inline [{1}', table_name, '\n')
87
- inline_rows = ''
88
- header_row = ''
89
- for col_idx in range(len(rows[0])):
90
- header_row = header_row + str.format('Column{0}{1}', col_idx, ',')
91
- header_row = header_row[:-1] + '\n'
92
- for row in rows:
93
- for cell_val in row:
94
- inline_rows = inline_rows + "'" + cell_val['qText'] + "'" + ','
95
- inline_rows = inline_rows[:-1] + '\n'
96
- return script + header_row + inline_rows + '];'
97
-
98
52
  def select_in_dimension(self, dimension_name, list_of_values):
99
53
  lb_field = self.eaa.get_field(self.app_handle, dimension_name)
100
- fld_handle = self.ega.get_handle(lb_field["qReturn"])
54
+ fld_handle = self.ega.get_handle(lb_field)
101
55
  values_to_select = []
102
56
  for val in list_of_values:
103
57
  val = {'qText': val}
@@ -106,12 +60,12 @@ class QixEngine:
106
60
 
107
61
  def select_excluded_in_dimension(self, dimension_name):
108
62
  lb_field = self.eaa.get_field(self.app_handle, dimension_name)
109
- fld_handle = self.ega.get_handle(lb_field["qReturn"])
63
+ fld_handle = self.ega.get_handle(lb_field)
110
64
  return self.efa.select_excluded(fld_handle)
111
65
 
112
66
  def select_possible_in_dimension(self, dimension_name):
113
67
  lb_field = self.eaa.get_field(self.app_handle, dimension_name)
114
- fld_handle = self.ega.get_handle(lb_field["qReturn"])
68
+ fld_handle = self.ega.get_handle(lb_field)
115
69
  return self.efa.select_possible(fld_handle)
116
70
 
117
71
  # return a list of tuples where first value in tuple is the actual
@@ -119,18 +73,12 @@ class QixEngine:
119
73
  # values selection state
120
74
  def get_list_object_data(self, dimension_name):
121
75
  lb_field = self.eaa.get_field(self.app_handle, dimension_name)
122
- fld_handle = self.ega.get_handle(lb_field["qReturn"])
123
- nx_page = self.Structs.nx_page(0, 0,
124
- self.efa.get_cardinal(
125
- fld_handle)["qReturn"]
126
- )
127
- lb_def = self.Structs.list_object_def("$", "",
128
- [dimension_name],
129
- None, None, [nx_page]
130
- )
131
- lb_param = {"qInfo": {"qId": "SLB01", "qType": "ListObject"},
132
- "qListObjectDef": lb_def}
133
- listobj_handle = self.eaa.create_session_object(self.app_handle, lb_param)["qReturn"]["qHandle"] # NOQA
76
+ fld_handle = self.ega.get_handle(lb_field)
77
+ nx_page = self.structs.nx_page(0, 0, self.efa.get_cardinal(fld_handle)["qReturn"])
78
+ lb_def = self.structs.list_object_def("$", "",[dimension_name], None,
79
+ None, [nx_page])
80
+ lb_param = {"qInfo": {"qId": "SLB01", "qType": "ListObject"}, "qListObjectDef": lb_def}
81
+ listobj_handle = self.eaa.create_session_object(self.app_handle, lb_param)["qHandle"] # NOQA
134
82
  val_list = self.egoa.get_layout(listobj_handle)["qListObject"]["qDataPages"][0]["qMatrix"] # NOQA
135
83
  val_n_state_list = []
136
84
  for val in val_list:
@@ -139,7 +87,7 @@ class QixEngine:
139
87
 
140
88
  def clear_selection_in_dimension(self, dimension_name):
141
89
  lb_field = self.eaa.get_field(self.app_handle, dimension_name)
142
- fld_handle = self.ega.get_handle(lb_field["qReturn"])
90
+ fld_handle = self.ega.get_handle(lb_field)
143
91
  return self.efa.clear(fld_handle)['qReturn']
144
92
 
145
93
  def clear_all_selections(self):
@@ -150,3 +98,236 @@ class QixEngine:
150
98
 
151
99
  def disconnect(self):
152
100
  self.conn.close_qvengine_connection(self.conn)
101
+
102
+ @staticmethod
103
+ def get_handle(obj):
104
+ """
105
+ Retrieves the handle from a given object.
106
+
107
+ Parameters:
108
+ obj : dict
109
+ The object containing the handle.
110
+
111
+ Returns:
112
+ int: The handle value.
113
+
114
+ Raises:
115
+ ValueError: If the handle value is invalid.
116
+ """
117
+ try:
118
+ return obj["qHandle"]
119
+ except ValueError:
120
+ return "Bad handle value in " + obj
121
+
122
+ def get_chart_data(self, app_handle, obj_id):
123
+ """
124
+ Retrieves the data from a given chart object.
125
+
126
+ Parameters:
127
+ app_handle (int): The handle of the app.
128
+ obj_id (str): The ID of the chart object.
129
+
130
+ Returns:
131
+ DataFrame: A table of the chart content.
132
+ """
133
+ # Get object ID
134
+ obj = self.eaa.get_object(app_handle, obj_id)
135
+ if obj['qType'] is None:
136
+ return 'Chart ID does not exists!'
137
+
138
+
139
+ # Get object handle
140
+ obj_handle = self.get_handle(obj)
141
+ # Get object layout
142
+ obj_layout = self.egoa.get_layout(obj_handle)
143
+
144
+ # Determine the number of the columns and the rows the table has and splits in certain circumstances the table
145
+ # calls
146
+ no_of_columns = obj_layout['qHyperCube']['qSize']['qcx']
147
+ width = no_of_columns
148
+ no_of_rows = obj_layout['qHyperCube']['qSize']['qcy']
149
+ height = int(math.floor(10000 / no_of_columns))
150
+
151
+ # Extract the dimension and measure titles and concat them to column names.
152
+ dimension_titles = [dim['qFallbackTitle'] for dim in obj_layout['qHyperCube']['qDimensionInfo']]
153
+ measure_titles = [measure['qFallbackTitle'] for measure in obj_layout['qHyperCube']['qMeasureInfo']]
154
+ column_names = dimension_titles + measure_titles
155
+
156
+ # if the type of the charts has a straight data structure
157
+ if (obj_layout['qInfo']['qType'] in ['table', 'sn-table', 'piechart', 'scatterplot', 'combochart', 'barchart']
158
+ and obj_layout['qHyperCube']['qDataPages'] != []):
159
+
160
+ # Paging variables
161
+ page = 0
162
+ data_values = []
163
+
164
+ # Retrieves the hypercube data in a loop (because of limitation from 10.000 cells per call)
165
+ while no_of_rows > page * height:
166
+ nx_page = self.structs.nx_page(0, page * height, width, height)
167
+ hc_data = self.egoa.get_hypercube_data(obj_handle, '/qHyperCubeDef', nx_page)[
168
+ 'qDataPages'][0]['qMatrix']
169
+ data_values.extend(hc_data)
170
+ page += 1
171
+
172
+ # Creates Dataframe from the content of the attribute 'qText'.
173
+ df = pd.DataFrame([[d['qText'] for d in sublist] for sublist in data_values])
174
+
175
+ # Assign titles zu Dataframe columns
176
+ df.columns = column_names
177
+
178
+ # if the type of the charts has a pivot data structure
179
+ elif (obj_layout['qInfo']['qType'] in ['pivot-table', 'sn-pivot-table']
180
+ and obj_layout['qHyperCube']['qPivotDataPages'] != []):
181
+
182
+ # Supporting function to traverse all subnodes to get all dimensions
183
+ def get_all_dimensions(node):
184
+ dimensions = [node['qText']]
185
+ # if 'qSubNodes' in node and node['qSubNodes']:
186
+ if node['qSubNodes']:
187
+ sub_dimensions = []
188
+ for sub_node in node['qSubNodes']:
189
+ sub_dimensions.extend([dimensions + d for d in get_all_dimensions(sub_node)])
190
+ return sub_dimensions
191
+ else:
192
+ return [dimensions]
193
+
194
+ # Gets the column headers for the pivot table
195
+ col_headers = []
196
+ nx_page_top = self.structs.nx_page(0, 0, width, 1)
197
+ hc_top = self.egoa.get_hypercube_pivot_data(obj_handle, '/qHyperCubeDef', nx_page_top)[
198
+ 'qDataPages'][0]['qTop']
199
+ for top_node in hc_top:
200
+ col_headers.extend(get_all_dimensions(top_node))
201
+
202
+ # Paging variables
203
+ page = 0
204
+ row_headers = []
205
+ data_values = []
206
+
207
+ # Retrieves the hypercube data in a loop (bacause of limitation from 10.000 cells per call)
208
+ while no_of_rows > page * height:
209
+ nx_page = self.structs.nx_page(0, page * height, width, height)
210
+
211
+ # Retrieves the row headers for the pivot table
212
+ hc_left = self.egoa.get_hypercube_pivot_data(obj_handle, '/qHyperCubeDef', nx_page)[
213
+ 'qDataPages'][0]['qLeft']
214
+ for left_node in hc_left:
215
+ row_headers.extend(get_all_dimensions(left_node))
216
+
217
+ # Retrieves the data for the pivot table
218
+ hc_data = self.egoa.get_hypercube_pivot_data(obj_handle, '/qHyperCubeDef', nx_page)[
219
+ 'qDataPages'][0]['qData']
220
+ for row in hc_data:
221
+ data_values.append([cell['qText'] for cell in row])
222
+
223
+ page += 1
224
+
225
+ # Creates multi indes for rows and columns
226
+ row_index = pd.MultiIndex.from_tuples(row_headers)
227
+ col_index = pd.MultiIndex.from_tuples(col_headers)
228
+
229
+ # Creates the Dataframe
230
+ df = pd.DataFrame(data_values, index=row_index, columns=col_index)
231
+
232
+ # if the type of the charts has a stacked data structure
233
+ elif obj_layout['qInfo']['qType'] in ['barchart'] and obj_layout['qHyperCube']['qStackedDataPages'] != []:
234
+ max_no_cells = no_of_columns * no_of_rows
235
+ nx_page = self.structs.nx_page(0, 0, no_of_columns, no_of_rows)
236
+ hc_data = self.egoa.get_hypercube_stack_data(obj_handle, '/qHyperCubeDef', nx_page, max_no_cells)[
237
+ 'qDataPages'][0]['qData'][0]['qSubNodes']
238
+
239
+ # Transform the nested structure into a flat DataFrame
240
+ data_values = []
241
+ for node in hc_data:
242
+ for sub_node in node['qSubNodes']:
243
+ value = sub_node['qSubNodes'][0]['qValue'] if sub_node['qSubNodes'] else None
244
+ data_values.append([node['qText'], sub_node['qText'], value])
245
+
246
+ # Creates the Dataframe
247
+ df = pd.DataFrame(data_values, columns=column_names)
248
+
249
+ else:
250
+ return 'Chart type not supported.'
251
+
252
+ # Returns the Dataframe
253
+ return df
254
+
255
+ def get_constructed_table_data(self, app_handle, list_of_dimensions = [], list_of_measures = [],
256
+ list_of_master_dimensions = [], list_of_master_measures = []):
257
+ """
258
+ Creates a table from given fields, expressions, dimensions or measures and retrieves the data from it.
259
+
260
+ Parameters:
261
+ app_handle (int): The handle of the app.
262
+ list_of_dimensions (list): A list of dimensions.
263
+ list_of_measures (list): A list of measures.
264
+ list_of_master_dimensions (list): A list of master dimensions.
265
+ list_of_master_measures (list): A list of master measures.
266
+
267
+ Returns:
268
+ DataFrame: A table of the chart content.
269
+ """
270
+ # Create dimension property
271
+ hc_dim = []
272
+ for dimension in list_of_dimensions:
273
+ hc_inline_dim_def = self.structs.nx_inline_dimension_def([dimension])
274
+ hc_dim.append(self.structs.nx_dimension("", hc_inline_dim_def))
275
+ for dimension in list_of_master_dimensions:
276
+ hc_dim.append(self.structs.nx_dimension(dimension))
277
+
278
+ # Create measure property
279
+ hc_mes = []
280
+ for measure in list_of_measures:
281
+ hc_inline_mes = self.structs.nx_inline_measure_def(measure)
282
+ hc_mes.append(self.structs.nx_measure("", hc_inline_mes))
283
+ for measure in list_of_master_measures:
284
+ hc_mes.append(self.structs.nx_measure(measure))
285
+
286
+ # Create hypercube structure
287
+ hc_def = self.structs.hypercube_def("$", hc_dim, hc_mes)
288
+
289
+ # Create info structure
290
+ nx_info = self.structs.nx_info("table")
291
+
292
+ # Create generic object properties structure
293
+ gen_obj_props = self.structs.generic_object_properties(nx_info, "qHyperCubeDef", hc_def)
294
+
295
+ # Create session object
296
+ hc_obj = self.eaa.create_session_object(app_handle, gen_obj_props)
297
+
298
+ # Get object handle
299
+ hc_obj_handle = self.get_handle(hc_obj)
300
+
301
+ # Get object layout
302
+ hc_obj_layout = self.egoa.get_layout(hc_obj_handle)
303
+
304
+ # Determine the number of the columns and the rows the table has and splits in certain circumstances the table calls
305
+ no_of_columns = hc_obj_layout['qHyperCube']['qSize']['qcx']
306
+ width = no_of_columns
307
+ no_of_rows = hc_obj_layout['qHyperCube']['qSize']['qcy']
308
+ height = int(math.floor(10000 / no_of_columns))
309
+
310
+ # Extract the dimension and measure titles and concat them to column names.
311
+ dimension_titles = [dim['qFallbackTitle'] for dim in hc_obj_layout['qHyperCube']['qDimensionInfo']]
312
+ measure_titles = [measure['qFallbackTitle'] for measure in hc_obj_layout['qHyperCube']['qMeasureInfo']]
313
+ column_names = dimension_titles + measure_titles
314
+
315
+ # Paging variables
316
+ page = 0
317
+ data_values = []
318
+
319
+ # Retrieves the hypercube data in a loop (because of limitation from 10.000 cells per call)
320
+ while no_of_rows > page * height:
321
+ nx_page = self.structs.nx_page(0, page * height, width, height)
322
+ hc_data = self.egoa.get_hypercube_data(hc_obj_handle, '/qHyperCubeDef', nx_page)['qDataPages'][0]['qMatrix']
323
+ data_values.extend(hc_data)
324
+ page += 1
325
+
326
+ # Creates Dataframe from the content of the attribute 'qText'.
327
+ df = pd.DataFrame([[d['qText'] for d in sublist] for sublist in data_values])
328
+
329
+ # Assign titles zu Dataframe columns
330
+ df.columns = column_names
331
+
332
+ # Returns the Dataframe
333
+ return df
@@ -1,10 +1,10 @@
1
1
  import math
2
2
 
3
- from qe_api_client.engine_app_api import EngineAppApi
4
- from qe_api_client.engine_field_api import EngineFieldApi
5
- from qe_api_client.engine_generic_object_api import EngineGenericObjectApi
6
- from qe_api_client.engine_global_api import EngineGlobalApi
7
- from qe_api_client.structs import Structs
3
+ from qe_api_client.api_classes.engine_app_api import EngineAppApi
4
+ from qe_api_client.api_classes.engine_field_api import EngineFieldApi
5
+ from qe_api_client.api_classes.engine_generic_object_api import EngineGenericObjectApi
6
+ from qe_api_client.api_classes.engine_global_api import EngineGlobalApi
7
+ import qe_api_client.structs as structs
8
8
 
9
9
  import pandas as pd
10
10
 
@@ -12,26 +12,26 @@ import pandas as pd
12
12
  def getDataFrame(connection, appHandle, measures, dimensions, selections={}):
13
13
  engineGlobalApi = EngineGlobalApi(connection)
14
14
  # Define Dimensions of hypercube
15
- hc_inline_dim = Structs.nx_inline_dimension_def(dimensions)
15
+ hc_inline_dim = structs.nx_inline_dimension_def(dimensions)
16
16
 
17
17
  # Set sorting of Dimension by Measure
18
- hc_mes_sort = Structs.nx_sort_by()
18
+ hc_mes_sort = structs.sort_criteria()
19
19
 
20
20
  # Define Measure of hypercube
21
- hc_inline_mes = Structs.nx_inline_measure_def(measures)
21
+ hc_inline_mes = structs.nx_inline_measure_def(measures)
22
22
 
23
23
  # Build hypercube from above definition
24
- hc_dim = Structs.nx_hypercube_dimensions(hc_inline_dim)
25
- hc_mes = Structs.nx_hypercube_measure(hc_mes_sort, hc_inline_mes)
24
+ hc_dim = structs.nx_dimension(hc_inline_dim)
25
+ hc_mes = structs.nx_measure("", hc_inline_mes, hc_mes_sort)
26
26
 
27
27
  width = len(measures) + len(dimensions)
28
28
  height = int(math.floor(10000 / width))
29
- nx_page = Structs.nx_page(0, 0, height, width)
30
- hc_def = Structs.hypercube_def("$", hc_dim, hc_mes, [nx_page])
29
+ nx_page = structs.nx_page(0, 0, width, height)
30
+ hc_def = structs.hypercube_def("$", [hc_dim], [hc_mes], [nx_page])
31
31
 
32
32
  engineAppApi = EngineAppApi(connection)
33
33
  hc_response = engineAppApi.create_object(appHandle, "CH01", "Chart", "qHyperCubeDef", hc_def) # NOQA
34
- hc_handle = engineGlobalApi.get_handle(hc_response)
34
+ hc_handle = engineGlobalApi.get_handle(hc_response['qReturn'])
35
35
 
36
36
  engineGenericObjectApi = EngineGenericObjectApi(connection)
37
37
 
@@ -47,8 +47,8 @@ def getDataFrame(connection, appHandle, measures, dimensions, selections={}):
47
47
 
48
48
  i = 0
49
49
  while i % height == 0:
50
- nx_page = Structs.nx_page(i, 0, height, width)
51
- hc_data = engineGenericObjectApi.get_hypercube_data(hc_handle, "/qHyperCubeDef", [nx_page]) # NOQA
50
+ nx_page = structs.nx_page(0, i, width, height)
51
+ hc_data = engineGenericObjectApi.get_hypercube_data(hc_handle, "/qHyperCubeDef", nx_page) # NOQA
52
52
  elems = hc_data["qDataPages"][0]['qMatrix']
53
53
 
54
54
  df = pd.DataFrame()
qe_api_client/structs.py CHANGED
@@ -1,107 +1,58 @@
1
- class Structs:
2
- def __init__(self):
3
- pass
4
-
5
- @staticmethod
6
- def list_object_def(state_name="$", library_id="",
7
- field_defs=None, field_labels=None,
8
- sort_criterias=None, initial_data_fetch=None
9
- ):
10
- if initial_data_fetch is None:
11
- initial_data_fetch = []
12
- if sort_criterias is None:
13
- sort_criterias = []
14
- if field_labels is None:
15
- field_labels = []
16
- if field_defs is None:
17
- field_defs = []
18
- return {"qStateName": state_name,
19
- "qLibraryId": library_id,
20
- "qDef": {
21
- "qFieldDefs": field_defs,
22
- "qFieldLabels": field_labels,
23
- "qSortCriterias": sort_criterias
24
- },
25
- "qInitialDataFetch": initial_data_fetch
26
- }
27
-
28
- @staticmethod
29
- def hypercube_def(state_name="$", nx_dims=[],
30
- nx_meas=[], nx_page=[],
31
- inter_column_sort=[0, 1, 2], suppress_zero=False,
32
- suppress_missing=False
33
- ):
34
- return {"qStateName": state_name,
35
- "qDimensions": nx_dims, # NxDimensions
36
- "qMeasures": nx_meas, # NxMeasure
37
- "qInterColumnSortOrder": inter_column_sort,
38
- "qSuppressZero": suppress_zero,
39
- "qSuppressMissing": suppress_missing,
40
- "qInitialDataFetch": nx_page, # NxPage
41
- "qMode": 'S',
42
- "qNoOfLeftDims": -1,
43
- "qAlwaysFullyExpanded": False,
44
- "qMaxStackedCells": 5000,
45
- "qPopulateMissing": False,
46
- "qShowTotalsAbove": False,
47
- "qIndentMode": False,
48
- "qCalcCond": "",
49
- "qSortbyYValue": 0
50
- }
51
-
52
- @staticmethod
53
- def nx_hypercube_dimensions(dim_def):
54
- return {"qLibraryId": "",
55
- "qNullSuppression": False,
56
- "qDef": dim_def
57
- }
58
-
59
- @staticmethod
60
- def nx_inline_dimension_def(field_definitions=[],
61
- grouping='N',
62
- field_labels=[]
63
- ):
64
- return {"qGrouping": grouping,
65
- "qFieldDefs": field_definitions,
66
- "qFieldLabels": field_labels
67
- }
68
-
69
- @staticmethod
70
- def nx_hypercube_measure(sort_by={}, nx_inline_measures_def=""):
71
- return {"qSortBy": sort_by,
72
- "qDef": nx_inline_measures_def
73
- }
74
-
75
- @staticmethod
76
- def nx_sort_by(state=0, freq=0, numeric=0, ascii=0, load_order=1):
77
- return {"qSortByState": state,
78
- "qSortByFrequency": freq,
79
- "qSortByNumeric": numeric,
80
- "qSortByAscii": ascii,
81
- "qSortByLoadOrder": load_order,
82
- "qSortByExpression": 0,
83
- "qExpression": {
84
- "qv": ""
85
- }
86
- }
87
-
88
- @staticmethod
89
- def nx_inline_measure_def(definition, label="",
90
- description="",
91
- tags=[],
92
- grouping="N"
93
- ):
94
- return {"qLabel": label,
95
- "qDescription": description,
96
- "qTags": tags,
97
- "qGrouping": grouping,
98
- "qDef": definition
99
- }
100
-
101
- @staticmethod
102
- def nx_page(top=0, left=0, height=2, width=2):
103
- return {"qTop": top,
104
- "qLeft": left,
105
- "qHeight": height,
106
- "qWidth": width
107
- }
1
+ def list_object_def(state_name="$", library_id="", field_defs=None, field_labels=None, sort_criterias=None,
2
+ initial_data_fetch=None):
3
+ if initial_data_fetch is None:
4
+ initial_data_fetch = []
5
+ if sort_criterias is None:
6
+ sort_criterias = []
7
+ if field_labels is None:
8
+ field_labels = []
9
+ if field_defs is None:
10
+ field_defs = []
11
+ return {"qStateName": state_name, "qLibraryId": library_id,
12
+ "qDef": {"qFieldDefs": field_defs, "qFieldLabels": field_labels, "qSortCriterias": sort_criterias},
13
+ "qInitialDataFetch": initial_data_fetch}
14
+
15
+ def hypercube_def(state_name="$", nx_dims=[], nx_meas=[], nx_page=[], inter_column_sort=[0, 1, 2], suppress_zero=False,
16
+ suppress_missing=False):
17
+ return {"qStateName": state_name, "qDimensions": nx_dims, "qMeasures": nx_meas,
18
+ "qInterColumnSortOrder": inter_column_sort, "qSuppressZero": suppress_zero,
19
+ "qSuppressMissing": suppress_missing, "qInitialDataFetch": nx_page, "qMode": 'S', "qNoOfLeftDims": -1,
20
+ "qAlwaysFullyExpanded": False, "qMaxStackedCells": 5000, "qPopulateMissing": False,
21
+ "qShowTotalsAbove": False, "qIndentMode": False, "qCalcCond": "", "qSortbyYValue": 0}
22
+
23
+ def nx_inline_dimension_def(field_definitions=[], field_labels=[], sort_criterias=[], grouping='N'):
24
+ return {"qGrouping": grouping, "qFieldDefs": field_definitions, "qFieldLabels": field_labels,
25
+ "qSortCriterias": sort_criterias, "qReverseSort": False}
26
+
27
+ def nx_inline_measure_def(definition, label="", description="", tags=[], grouping="N"):
28
+ return {"qLabel": label, "qDescription": description, "qTags": tags, "qGrouping": grouping, "qDef": definition}
29
+
30
+ def nx_page(left=0, top=0, width=2, height=2):
31
+ return {"qLeft": left, "qTop": top, "qWidth": width, "qHeight": height}
32
+
33
+ def nx_info(obj_type, obj_id=""):
34
+ """
35
+ Retrieves the data from a specific list object in a generic object.
36
+
37
+ Parameters:
38
+ obj_type (str): Type of the object. This parameter is mandatory.
39
+ obj_id (str): Identifier of the object. If the chosen identifier is already in use, the engine automatically
40
+ sets another one. If an identifier is not set, the engine automatically sets one. This parameter is optional.
41
+
42
+ Returns:
43
+ dict: Struct "nxInfo"
44
+ """
45
+ return {"qId": obj_id, "qType": obj_type}
46
+
47
+ def nx_dimension(library_id="", dim_def={}, null_suppression=False):
48
+ return {"qLibraryId": library_id, "qDef": dim_def, "qNullSuppression": null_suppression}
49
+
50
+ def nx_measure(library_id="", mes_def={}, sort_by={}):
51
+ return {"qLibraryId": library_id, "qDef": mes_def, "qSortBy": sort_by}
52
+
53
+ def generic_object_properties(info, prop_name, prop_def, extends_id="", state_name="$"):
54
+ return {"qInfo": info, "qExtendsId": extends_id, prop_name: prop_def, "qStateName": state_name}
55
+
56
+ def sort_criteria(state=0, freq=0, numeric=0, ascii=0, load_order=1):
57
+ return {"qSortByState": state, "qSortByFrequency": freq, "qSortByNumeric": numeric, "qSortByAscii": ascii,
58
+ "qSortByLoadOrder": load_order, "qSortByExpression": 0, "qExpression": {"qv": ""}}
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: qe-api-client
3
- Version: 1.2.0
3
+ Version: 2.1.0
4
4
  Summary: Python wrapper around Qlik Engine JSON API
5
5
  Home-page: https://github.com/lr-bicc/qe-api-client
6
6
  Author: Rumen Vasilev
@@ -13,7 +13,7 @@ Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
14
  Requires-Dist: websocket-client >=0.47.0
15
15
 
16
- # pyqlikengine
16
+ # Qlik Engine API Client
17
17
 
18
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
19
 
@@ -23,10 +23,15 @@ Forked from [jhettler/pyqlikengine](https://github.com/jhettler/pyqlikengine)
23
23
  * Python 3.6+
24
24
  * websocket-client>=0.47.0
25
25
 
26
- ## Example of usage
26
+ ## Installation
27
27
  ```bash
28
28
  pip install qe-api-client
29
29
  ```
30
+
31
+ ## Example of usage on Qlik Sense Enterprise Server
32
+ You need to export the Qlik Sense certificates in PEM format from the Qlik Sense Enterprise server to a local folder in
33
+ order to authenticate on the server.
34
+
30
35
  ```python
31
36
  from qe_api_client.engine import QixEngine
32
37
 
@@ -36,10 +41,25 @@ user_id = 'sense'
36
41
  ca_certs = 'qlik_certs/qlik-1_root.pem'
37
42
  certfile = 'qlik_certs/qlik-1_client.pem'
38
43
  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)
44
+ qixe = QixEngine(url=url, user_directory=user_directory, user_id=user_id, ca_certs=ca_certs, certfile=certfile,
45
+ keyfile=keyfile)
46
+
47
+ # print all apps in Qlik Server
48
+ print(qixe.ega.get_doc_list())
49
+ ```
50
+
51
+ ## Example of usage on Qlik Sense Desktop
52
+ You need to start your Qlik Sense Desktop client on your local PC.
53
+
54
+ ```python
55
+ from qe_api_client.engine import QixEngine
56
+
57
+ url = 'ws://localhost:4848/app'
58
+ qixe = QixEngine(url=url)
42
59
 
43
60
  # print all apps in Qlik Server
44
61
  print(qixe.ega.get_doc_list())
45
62
  ```
63
+
64
+ ## API reference
65
+ Please click on this [link](https://lr-bicc.github.io/qe-api-client) for full API reference documentation .