qe-api-client 2.4.0__py3-none-any.whl → 2.5.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/api_classes/engine_app_api.py +0 -10
- qe_api_client/api_classes/engine_generic_dimension_api.py +3 -3
- qe_api_client/api_classes/engine_generic_measure_api.py +3 -3
- qe_api_client/engine.py +347 -44
- qe_api_client/structs.py +56 -12
- {qe_api_client-2.4.0.dist-info → qe_api_client-2.5.0.dist-info}/METADATA +2 -2
- {qe_api_client-2.4.0.dist-info → qe_api_client-2.5.0.dist-info}/RECORD +10 -10
- {qe_api_client-2.4.0.dist-info → qe_api_client-2.5.0.dist-info}/WHEEL +1 -1
- {qe_api_client-2.4.0.dist-info → qe_api_client-2.5.0.dist-info}/LICENSE +0 -0
- {qe_api_client-2.4.0.dist-info → qe_api_client-2.5.0.dist-info}/top_level.txt +0 -0
@@ -556,16 +556,6 @@ class EngineAppApi:
|
|
556
556
|
except KeyError:
|
557
557
|
return response['error']
|
558
558
|
|
559
|
-
# GetDimension: Get the handle of a dimension by using the GetDimension method. # NOQA
|
560
|
-
# Parameter: dimension id
|
561
|
-
def get_dimension(self, doc_handle, dim_id):
|
562
|
-
msg = json.dumps({"jsonrpc": "2.0", "id": 0, "handle": doc_handle, "method": "GetDimension",
|
563
|
-
"params": [dim_id]})
|
564
|
-
response = json.loads(self.engine_socket.send_call(self.engine_socket, msg))
|
565
|
-
try:
|
566
|
-
return response['result']['qReturn']
|
567
|
-
except KeyError:
|
568
|
-
return response['error']
|
569
559
|
|
570
560
|
# GetEmptyScript: Creates a script that contains one section. This section contains Set statements that give # NOQA
|
571
561
|
# localized information from the regional settings of the computer.
|
@@ -18,18 +18,18 @@ class EngineGenericDimensionApi:
|
|
18
18
|
"""
|
19
19
|
self.engine_socket = socket
|
20
20
|
|
21
|
-
def get_dimension(self,
|
21
|
+
def get_dimension(self, app_handle: int, dimension_id: str):
|
22
22
|
"""
|
23
23
|
Retrieves the definition of a specific dimension from the Qlik Sense engine.
|
24
24
|
|
25
25
|
Parameters:
|
26
|
-
|
26
|
+
app_handle (int): The handle identifying the application.
|
27
27
|
dimension_id (str): The unique identifier (qId) of the dimension to retrieve.
|
28
28
|
|
29
29
|
Returns:
|
30
30
|
dict: The definition of the requested dimension (qReturn). In case of an error, returns the error information.
|
31
31
|
"""
|
32
|
-
msg = json.dumps({"jsonrpc": "2.0", "id": 0, "handle":
|
32
|
+
msg = json.dumps({"jsonrpc": "2.0", "id": 0, "handle": app_handle, "method": "GetDimension",
|
33
33
|
"params": {"qId": dimension_id}})
|
34
34
|
response = json.loads(self.engine_socket.send_call(self.engine_socket, msg))
|
35
35
|
try:
|
@@ -18,18 +18,18 @@ class EngineGenericMeasureApi:
|
|
18
18
|
"""
|
19
19
|
self.engine_socket = socket
|
20
20
|
|
21
|
-
def get_measure(self,
|
21
|
+
def get_measure(self, app_handle: int, measure_id: str):
|
22
22
|
"""
|
23
23
|
Retrieves the definition of a specific measure from the Qlik Sense engine.
|
24
24
|
|
25
25
|
Parameters:
|
26
|
-
|
26
|
+
app_handle (int): The handle identifying the application.
|
27
27
|
measure_id (str): The unique identifier (qId) of the measure to retrieve.
|
28
28
|
|
29
29
|
Returns:
|
30
30
|
dict: The definition of the requested measure (qReturn). In case of an error, returns the error information.
|
31
31
|
"""
|
32
|
-
msg = json.dumps({"jsonrpc": "2.0", "id": 0, "handle":
|
32
|
+
msg = json.dumps({"jsonrpc": "2.0", "id": 0, "handle": app_handle, "method": "GetMeasure", "params": {"qId": measure_id}})
|
33
33
|
response = json.loads(self.engine_socket.send_call(self.engine_socket, msg))
|
34
34
|
try:
|
35
35
|
return response["result"]["qReturn"]
|
qe_api_client/engine.py
CHANGED
@@ -9,6 +9,7 @@ import qe_api_client.api_classes.engine_generic_measure_api as engine_generic_me
|
|
9
9
|
import qe_api_client.structs as structs
|
10
10
|
import math
|
11
11
|
import pandas as pd
|
12
|
+
import numpy as np
|
12
13
|
|
13
14
|
|
14
15
|
class QixEngine:
|
@@ -39,42 +40,45 @@ class QixEngine:
|
|
39
40
|
self.structs = structs
|
40
41
|
self.app_handle = ''
|
41
42
|
|
42
|
-
def
|
43
|
-
lb_field = self.eaa.get_field(app_handle,
|
43
|
+
def select_in_field(self, app_handle, field_name, list_of_values):
|
44
|
+
lb_field = self.eaa.get_field(app_handle, field_name)
|
44
45
|
fld_handle = self.get_handle(lb_field)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
values_to_select
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
46
|
+
if fld_handle is None:
|
47
|
+
return "The field name " + field_name + " doesn't exist!"
|
48
|
+
else:
|
49
|
+
values_to_select = []
|
50
|
+
for val in list_of_values:
|
51
|
+
fld_value = self.structs.field_value(text=val)
|
52
|
+
values_to_select.append(fld_value)
|
53
|
+
return self.efa.select_values(fld_handle, values_to_select)
|
54
|
+
|
55
|
+
def select_excluded_in_field(self, app_handle, field_name):
|
56
|
+
lb_field = self.eaa.get_field(app_handle, field_name)
|
53
57
|
fld_handle = self.get_handle(lb_field)
|
54
58
|
return self.efa.select_excluded(fld_handle)
|
55
59
|
|
56
|
-
def
|
57
|
-
lb_field = self.eaa.get_field(app_handle,
|
60
|
+
def select_possible_in_field(self, app_handle, field_name):
|
61
|
+
lb_field = self.eaa.get_field(app_handle, field_name)
|
58
62
|
fld_handle = self.get_handle(lb_field)
|
59
63
|
return self.efa.select_possible(fld_handle)
|
60
64
|
|
61
65
|
# return a list of tuples where first value in tuple is the actual
|
62
66
|
# data value and the second tuple value is that
|
63
67
|
# values selection state
|
64
|
-
def get_list_object_data(self, app_handle,
|
65
|
-
lb_field = self.eaa.get_field(app_handle,
|
68
|
+
def get_list_object_data(self, app_handle, field_name):
|
69
|
+
lb_field = self.eaa.get_field(app_handle, field_name)
|
66
70
|
fld_handle = self.get_handle(lb_field)
|
67
71
|
|
68
|
-
nx_inline_dimension_def = self.structs.nx_inline_dimension_def([
|
69
|
-
nx_page = self.structs.nx_page(0, 0, self.efa.get_cardinal(fld_handle))
|
72
|
+
nx_inline_dimension_def = self.structs.nx_inline_dimension_def([field_name])
|
73
|
+
nx_page = self.structs.nx_page(left=0, top=0, width=self.efa.get_cardinal(fld_handle))
|
70
74
|
lb_def = self.structs.list_object_def("$", "", nx_inline_dimension_def,
|
71
75
|
[nx_page])
|
72
76
|
|
73
77
|
# Create info structure
|
74
|
-
nx_info = self.structs.nx_info("ListObject", "SLB01")
|
78
|
+
nx_info = self.structs.nx_info(obj_type="ListObject", obj_id="SLB01")
|
75
79
|
|
76
80
|
# Create generic object properties structure
|
77
|
-
gen_obj_props = self.structs.generic_object_properties(nx_info, "qListObjectDef", lb_def)
|
81
|
+
gen_obj_props = self.structs.generic_object_properties(info=nx_info, prop_name="qListObjectDef", prop_def=lb_def)
|
78
82
|
listobj = self.eaa.create_session_object(app_handle, gen_obj_props) # NOQA
|
79
83
|
listobj_handle = self.get_handle(listobj)
|
80
84
|
val_list = self.egoa.get_layout(listobj_handle)["qListObject"]["qDataPages"][0]["qMatrix"] # NOQA
|
@@ -89,7 +93,8 @@ class QixEngine:
|
|
89
93
|
fld_handle = self.get_handle(lb_field)
|
90
94
|
return self.efa.clear(fld_handle)
|
91
95
|
|
92
|
-
def create_single_master_dimension(self, app_handle, dim_title, dim_def, dim_label
|
96
|
+
def create_single_master_dimension(self, app_handle: int, dim_title: str, dim_def: str, dim_label: str = "",
|
97
|
+
dim_desc: str = "", dim_tags: list = None):
|
93
98
|
"""
|
94
99
|
Creates a single master dimension.
|
95
100
|
|
@@ -97,18 +102,27 @@ class QixEngine:
|
|
97
102
|
app_handle (int): The handle of the app.
|
98
103
|
dim_title (str): The title of the dimension.
|
99
104
|
dim_def (str): The definition of the dimension.
|
100
|
-
dim_label (str): The label of the dimension.
|
105
|
+
dim_label (str, optional): The label of the dimension.
|
106
|
+
dim_desc (str, optional): The description of the dimension.
|
107
|
+
dim_tags (list, optional): The tags of the dimension.
|
101
108
|
|
102
109
|
Returns:
|
103
110
|
dict: The handle and Id of the dimension.
|
104
111
|
"""
|
105
|
-
|
106
|
-
|
107
|
-
|
112
|
+
if dim_tags is None:
|
113
|
+
dim_tags = []
|
114
|
+
nx_info = self.structs.nx_info(obj_type="dimension")
|
115
|
+
nx_library_dimension_def = self.structs.nx_library_dimension_def(grouping="N", field_definitions=[dim_def],
|
116
|
+
field_labels=[dim_title],
|
117
|
+
label_expression=dim_label)
|
118
|
+
gen_dim_props = self.structs.generic_dimension_properties(nx_info=nx_info,
|
119
|
+
nx_library_dimension_def=nx_library_dimension_def,
|
120
|
+
title=dim_title, description=dim_desc, tags=dim_tags)
|
108
121
|
master_dim = self.eaa.create_dimension(app_handle, gen_dim_props)
|
109
122
|
return master_dim
|
110
123
|
|
111
|
-
def create_master_measure(self, app_handle, mes_title, mes_def, mes_label
|
124
|
+
def create_master_measure(self, app_handle: int, mes_title: str, mes_def: str, mes_label: str = "",
|
125
|
+
mes_desc: str = "", mes_tags: list = None):
|
112
126
|
"""
|
113
127
|
Creates a master measure.
|
114
128
|
|
@@ -116,14 +130,21 @@ class QixEngine:
|
|
116
130
|
app_handle (int): The handle of the app.
|
117
131
|
mes_title (str): The title of the measure.
|
118
132
|
mes_def (str): The definition of the measure.
|
119
|
-
mes_label (str): The label of the measure.
|
133
|
+
mes_label (str, optional): The label of the measure.
|
134
|
+
mes_desc (str, optional): The description of the measure.
|
135
|
+
mes_tags (list, optional): The tags of the measure.
|
120
136
|
|
121
137
|
Returns:
|
122
138
|
dict: The handle and Id of the measure.
|
123
139
|
"""
|
124
|
-
|
125
|
-
|
126
|
-
|
140
|
+
if mes_tags is None:
|
141
|
+
mes_tags = []
|
142
|
+
nx_info = self.structs.nx_info(obj_type="measure")
|
143
|
+
nx_library_measure_def = self.structs.nx_library_measure_def(label=mes_title, mes_def=mes_def,
|
144
|
+
label_expression=mes_label)
|
145
|
+
gen_mes_props = self.structs.generic_measure_properties(nx_info=nx_info,
|
146
|
+
nx_library_measure_def=nx_library_measure_def,
|
147
|
+
title=mes_title, description=mes_desc, tags=mes_tags)
|
127
148
|
master_mes = self.eaa.create_measure(app_handle, gen_mes_props)
|
128
149
|
return master_mes
|
129
150
|
|
@@ -213,7 +234,7 @@ class QixEngine:
|
|
213
234
|
|
214
235
|
# Retrieves the hypercube data in a loop (because of limitation from 10.000 cells per call)
|
215
236
|
while no_of_rows > page * height:
|
216
|
-
nx_page = self.structs.nx_page(0, page * height, width, height)
|
237
|
+
nx_page = self.structs.nx_page(left=0, top=page * height, width=width, height=height)
|
217
238
|
hc_data = self.egoa.get_hypercube_data(obj_handle, '/qHyperCubeDef', nx_page)[
|
218
239
|
'qDataPages'][0]['qMatrix']
|
219
240
|
data_values.extend(hc_data)
|
@@ -243,7 +264,7 @@ class QixEngine:
|
|
243
264
|
|
244
265
|
# Gets the column headers for the pivot table
|
245
266
|
col_headers = []
|
246
|
-
nx_page_top = self.structs.nx_page(0, 0, width, 1)
|
267
|
+
nx_page_top = self.structs.nx_page(left=0, top=0, width=width, height=1)
|
247
268
|
hc_top = self.egoa.get_hypercube_pivot_data(obj_handle, '/qHyperCubeDef', nx_page_top)[
|
248
269
|
'qDataPages'][0]['qTop']
|
249
270
|
for top_node in hc_top:
|
@@ -256,7 +277,7 @@ class QixEngine:
|
|
256
277
|
|
257
278
|
# Retrieves the hypercube data in a loop (bacause of limitation from 10.000 cells per call)
|
258
279
|
while no_of_rows > page * height:
|
259
|
-
nx_page = self.structs.nx_page(0, page * height, width, height)
|
280
|
+
nx_page = self.structs.nx_page(left=0, top=page * height, width=width, height=height)
|
260
281
|
|
261
282
|
# Retrieves the row headers for the pivot table
|
262
283
|
hc_left = self.egoa.get_hypercube_pivot_data(obj_handle, '/qHyperCubeDef', nx_page)[
|
@@ -282,7 +303,7 @@ class QixEngine:
|
|
282
303
|
# if the type of the charts has a stacked data structure
|
283
304
|
elif obj_layout['qInfo']['qType'] in ['barchart'] and obj_layout['qHyperCube']['qStackedDataPages'] != []:
|
284
305
|
max_no_cells = no_of_columns * no_of_rows
|
285
|
-
nx_page = self.structs.nx_page(0, 0, no_of_columns, no_of_rows)
|
306
|
+
nx_page = self.structs.nx_page(left=0, top=0, width=no_of_columns, height=no_of_rows)
|
286
307
|
hc_data = self.egoa.get_hypercube_stack_data(obj_handle, '/qHyperCubeDef', nx_page, max_no_cells)[
|
287
308
|
'qDataPages'][0]['qData'][0]['qSubNodes']
|
288
309
|
|
@@ -315,32 +336,32 @@ class QixEngine:
|
|
315
336
|
list_of_master_measures (list): A list of master measures.
|
316
337
|
|
317
338
|
Returns:
|
318
|
-
|
339
|
+
DataFrame: A table of the chart content.
|
319
340
|
"""
|
320
341
|
# Create dimension property
|
321
342
|
hc_dim = []
|
322
343
|
for dimension in list_of_dimensions:
|
323
|
-
hc_inline_dim_def = self.structs.nx_inline_dimension_def([dimension])
|
324
|
-
hc_dim.append(self.structs.nx_dimension("", hc_inline_dim_def))
|
344
|
+
hc_inline_dim_def = self.structs.nx_inline_dimension_def(field_definitions=[dimension])
|
345
|
+
hc_dim.append(self.structs.nx_dimension(library_id="", dim_def=hc_inline_dim_def))
|
325
346
|
for dimension in list_of_master_dimensions:
|
326
|
-
hc_dim.append(self.structs.nx_dimension(dimension))
|
347
|
+
hc_dim.append(self.structs.nx_dimension(library_id=dimension))
|
327
348
|
|
328
349
|
# Create measure property
|
329
350
|
hc_mes = []
|
330
351
|
for measure in list_of_measures:
|
331
|
-
hc_inline_mes = self.structs.nx_inline_measure_def(measure)
|
332
|
-
hc_mes.append(self.structs.nx_measure("", hc_inline_mes))
|
352
|
+
hc_inline_mes = self.structs.nx_inline_measure_def(definition=measure)
|
353
|
+
hc_mes.append(self.structs.nx_measure(library_id="", mes_def=hc_inline_mes))
|
333
354
|
for measure in list_of_master_measures:
|
334
|
-
hc_mes.append(self.structs.nx_measure(measure))
|
355
|
+
hc_mes.append(self.structs.nx_measure(library_id=measure))
|
335
356
|
|
336
357
|
# Create hypercube structure
|
337
|
-
hc_def = self.structs.hypercube_def("$", hc_dim, hc_mes)
|
358
|
+
hc_def = self.structs.hypercube_def(state_name="$", nx_dims=hc_dim, nx_meas=hc_mes)
|
338
359
|
|
339
360
|
# Create info structure
|
340
|
-
nx_info = self.structs.nx_info("table")
|
361
|
+
nx_info = self.structs.nx_info(obj_type="table")
|
341
362
|
|
342
363
|
# Create generic object properties structure
|
343
|
-
gen_obj_props = self.structs.generic_object_properties(nx_info, "qHyperCubeDef", hc_def)
|
364
|
+
gen_obj_props = self.structs.generic_object_properties(info=nx_info, prop_name="qHyperCubeDef", prop_def=hc_def)
|
344
365
|
|
345
366
|
# Create session object
|
346
367
|
hc_obj = self.eaa.create_session_object(app_handle, gen_obj_props)
|
@@ -368,7 +389,7 @@ class QixEngine:
|
|
368
389
|
|
369
390
|
# Retrieves the hypercube data in a loop (because of limitation from 10.000 cells per call)
|
370
391
|
while no_of_rows > page * height:
|
371
|
-
nx_page = self.structs.nx_page(0, page * height, width, height)
|
392
|
+
nx_page = self.structs.nx_page(left=0, top=page * height, width=width, height=height)
|
372
393
|
hc_data = self.egoa.get_hypercube_data(hc_obj_handle, '/qHyperCubeDef', nx_page)['qDataPages'][0]['qMatrix']
|
373
394
|
data_values.extend(hc_data)
|
374
395
|
page += 1
|
@@ -380,4 +401,286 @@ class QixEngine:
|
|
380
401
|
df.columns = column_names
|
381
402
|
|
382
403
|
# Returns the Dataframe
|
383
|
-
return df
|
404
|
+
return df
|
405
|
+
|
406
|
+
def get_apps(self):
|
407
|
+
"""
|
408
|
+
Retrieves a list with all apps on the server containing metadata.
|
409
|
+
|
410
|
+
Parameters:
|
411
|
+
|
412
|
+
Returns:
|
413
|
+
DataFrame: A table with all server apps.
|
414
|
+
"""
|
415
|
+
|
416
|
+
# Get all apps from Qlik Server
|
417
|
+
doc_list = self.ega.get_doc_list()
|
418
|
+
|
419
|
+
# Convert into DataFrame structure
|
420
|
+
df_doc_list = pd.DataFrame(doc_list)
|
421
|
+
|
422
|
+
# Resolve the attribute "qMeta"
|
423
|
+
field_meta = df_doc_list['qMeta'].apply(pd.Series).reindex(columns=["createdDate", "modifiedDate", "published",
|
424
|
+
"publishTime", "privileges", "description",
|
425
|
+
"qStaticByteSize", "dynamicColor", "create",
|
426
|
+
"stream", "canCreateDataConnections"])
|
427
|
+
|
428
|
+
# Concat the resolved attribute and rename the new columns
|
429
|
+
df_doc_list_meta = pd.concat([df_doc_list.drop(['qMeta'], axis=1), field_meta], axis=1)
|
430
|
+
df_doc_list_meta = df_doc_list_meta.rename(columns={"createdDate": "qMeta_createdDate",
|
431
|
+
"modifiedDate": "qMeta_modifiedDate",
|
432
|
+
"published": "qMeta_published",
|
433
|
+
"publishTime": "qMeta_publishTime",
|
434
|
+
"privileges": "qMeta_privileges",
|
435
|
+
"description": "qMeta_description",
|
436
|
+
"qStaticByteSize": "qMeta_qStaticByteSize",
|
437
|
+
"dynamicColor": "qMeta_dynamicColor",
|
438
|
+
"create": "qMeta_create",
|
439
|
+
"stream": "qMeta_stream",
|
440
|
+
"canCreateDataConnections": "qMeta_canCreateDataConnections"})
|
441
|
+
|
442
|
+
# Resolve the attribute "stream"
|
443
|
+
field_meta_stream = df_doc_list_meta['qMeta_stream'].apply(pd.Series).reindex(columns=["id", "name"])
|
444
|
+
|
445
|
+
# Concat the resolved attribute and rename the new columns
|
446
|
+
df_doc_list_meta_stream = pd.concat([df_doc_list_meta.drop(['qMeta_stream'], axis=1), field_meta_stream],
|
447
|
+
axis=1)
|
448
|
+
df_doc_list_meta_stream = df_doc_list_meta_stream.rename(
|
449
|
+
columns={"id": "qMeta_stream_id", "name": "qMeta_stream_name"})
|
450
|
+
|
451
|
+
# Resolve the attribute "qThumbnail"
|
452
|
+
field_thumbnail = df_doc_list_meta_stream['qThumbnail'].apply(pd.Series).reindex(columns=["qUrl"])
|
453
|
+
|
454
|
+
## Concat the resolved attribute and rename the new columns
|
455
|
+
df_doc_list_resolved = pd.concat([df_doc_list_meta_stream.drop(['qThumbnail'], axis=1), field_thumbnail],
|
456
|
+
axis=1)
|
457
|
+
df_doc_list_resolved = df_doc_list_resolved.rename(columns={"qUrl": "qThumbnail_qUrl"}).replace(np.nan,'')
|
458
|
+
|
459
|
+
return df_doc_list_resolved
|
460
|
+
|
461
|
+
|
462
|
+
def get_app_fields(self, app_handle):
|
463
|
+
"""
|
464
|
+
Retrieves a list with all app fields containing meta data.
|
465
|
+
|
466
|
+
Parameters:
|
467
|
+
app_handle (int): The handle of the app.
|
468
|
+
|
469
|
+
Returns:
|
470
|
+
DataFrame: A table with all fields from an app.
|
471
|
+
"""
|
472
|
+
# Define the parameters of the session object
|
473
|
+
nx_info = self.structs.nx_info(obj_type="FieldList")
|
474
|
+
field_list_def = self.structs.field_list_def()
|
475
|
+
gen_obj_props = self.structs.generic_object_properties(info=nx_info, prop_name="qFieldListDef",
|
476
|
+
prop_def=field_list_def)
|
477
|
+
|
478
|
+
# Create session object
|
479
|
+
session = self.eaa.create_session_object(app_handle, gen_obj_props)
|
480
|
+
|
481
|
+
# Get session handle
|
482
|
+
session_handle = self.get_handle(session)
|
483
|
+
|
484
|
+
# Get session object data
|
485
|
+
layout = self.egoa.get_layout(session_handle)
|
486
|
+
|
487
|
+
# Get the field list as Dictionary structure
|
488
|
+
fields_list = layout["qFieldList"]["qItems"]
|
489
|
+
|
490
|
+
# Define the DataFrame structure
|
491
|
+
df_fields_list = pd.DataFrame(columns=['qIsHidden', 'qIsSystem', 'qName', 'qCardinal', 'qTags', 'qSrcTables'])
|
492
|
+
|
493
|
+
for fields in fields_list:
|
494
|
+
# Concatenate the field list on the DataFrame structure
|
495
|
+
df_fields_list.loc[len(df_fields_list)] = fields
|
496
|
+
|
497
|
+
return df_fields_list
|
498
|
+
|
499
|
+
|
500
|
+
def get_app_dimensions(self, app_handle):
|
501
|
+
"""
|
502
|
+
Retrieves a list with all app dimensions containing metadata.
|
503
|
+
|
504
|
+
Parameters:
|
505
|
+
app_handle (int): The handle of the app.
|
506
|
+
|
507
|
+
Returns:
|
508
|
+
DataFrame: A table with all dimensions from an app.
|
509
|
+
"""
|
510
|
+
# Define the parameters of the session object
|
511
|
+
nx_info = self.structs.nx_info(obj_type="DimensionList")
|
512
|
+
dimension_list_def = self.structs.dimension_list_def()
|
513
|
+
gen_obj_props = self.structs.generic_object_properties(info=nx_info, prop_name="qDimensionListDef",
|
514
|
+
prop_def=dimension_list_def)
|
515
|
+
|
516
|
+
# Create session object
|
517
|
+
session = self.eaa.create_session_object(app_handle, gen_obj_props)
|
518
|
+
|
519
|
+
# Get session handle
|
520
|
+
session_handle = self.get_handle(session)
|
521
|
+
|
522
|
+
# Get session object data
|
523
|
+
session_layout = self.egoa.get_layout(session_handle)
|
524
|
+
|
525
|
+
# Get the dimension list as Dictionary structure
|
526
|
+
dimension_list = session_layout["qDimensionList"]["qItems"]
|
527
|
+
|
528
|
+
# Define the DataFrame structure
|
529
|
+
df_dimension_list = pd.DataFrame(columns=["qInfo", "qMeta", "qDim", "qDimInfos"])
|
530
|
+
|
531
|
+
for dimension in dimension_list:
|
532
|
+
# Get dimension ID
|
533
|
+
dim_id = dimension["qInfo"]["qId"]
|
534
|
+
# Get dimension
|
535
|
+
dim_result = self.egda.get_dimension(app_handle=app_handle, dimension_id=dim_id)
|
536
|
+
# Get dimension handle
|
537
|
+
dim_handle = self.get_handle(dim_result)
|
538
|
+
# Get dimension metadata
|
539
|
+
dim_layout = self.egoa.get_layout(dim_handle)
|
540
|
+
|
541
|
+
# Concatenate the dimension to the DataFrame structure
|
542
|
+
df_dimension_list.loc[len(df_dimension_list)] = dim_layout
|
543
|
+
|
544
|
+
# Resolve the dictionary structure of attribute "qInfo"
|
545
|
+
df_dimension_list_expanded = (df_dimension_list["qInfo"].apply(pd.Series).add_prefix("qInfo_"))
|
546
|
+
df_dimension_list = df_dimension_list.drop(columns=["qInfo"]).join(df_dimension_list_expanded)
|
547
|
+
|
548
|
+
# Resolve the dictionary structure of attribute "qMeta"
|
549
|
+
df_dimension_list_expanded = (df_dimension_list["qMeta"].apply(pd.Series).add_prefix("qMeta_"))
|
550
|
+
df_dimension_list = df_dimension_list.drop(columns=["qMeta"]).join(df_dimension_list_expanded)
|
551
|
+
|
552
|
+
# Resolve the dictionary structure of attribute "qDim"
|
553
|
+
df_dimension_list_expanded = (df_dimension_list["qDim"].apply(pd.Series).add_prefix("qDim_"))
|
554
|
+
df_dimension_list = df_dimension_list.drop(columns=["qDim"]).join(df_dimension_list_expanded)
|
555
|
+
|
556
|
+
# Resolve the dictionary structure of attribute "qDim_coloring"
|
557
|
+
try:
|
558
|
+
df_dimension_list_expanded = (
|
559
|
+
df_dimension_list["qDim_coloring"].apply(pd.Series).add_prefix("qDim_coloring_"))
|
560
|
+
df_dimension_list = df_dimension_list.drop(columns=["qDim_coloring"]).join(df_dimension_list_expanded)
|
561
|
+
except KeyError:
|
562
|
+
df_dimension_list["qDim_coloring"] = ""
|
563
|
+
|
564
|
+
# Resolve the dictionary structure of attribute "qDim_coloring_baseColor"
|
565
|
+
try:
|
566
|
+
df_dimension_list_expanded = (
|
567
|
+
df_dimension_list["qDim_coloring_baseColor"].apply(pd.Series).add_prefix("qDim_coloring_baseColor_"))
|
568
|
+
df_dimension_list = df_dimension_list.drop(columns=["qDim_coloring_baseColor"]).join(
|
569
|
+
df_dimension_list_expanded)
|
570
|
+
except KeyError:
|
571
|
+
df_dimension_list["qDim_coloring_baseColor"] = ""
|
572
|
+
|
573
|
+
# Resolve the list structure of attribute
|
574
|
+
df_dimension_list = df_dimension_list.explode(['qDimInfos', 'qDim_qFieldDefs', 'qDim_qFieldLabels'])
|
575
|
+
|
576
|
+
# Resolve the dictionary structure of attribute "qDimInfos"
|
577
|
+
df_dimension_list_expanded = (df_dimension_list["qDimInfos"].apply(pd.Series).add_prefix("qDimInfos_"))
|
578
|
+
index = df_dimension_list_expanded.index
|
579
|
+
df_dimension_list_expanded = df_dimension_list_expanded[~index.duplicated(keep="first")]
|
580
|
+
df_dimension_list = df_dimension_list.drop(columns=["qDimInfos"]).join(df_dimension_list_expanded)
|
581
|
+
|
582
|
+
return df_dimension_list
|
583
|
+
|
584
|
+
|
585
|
+
def get_app_measures(self, app_handle):
|
586
|
+
"""
|
587
|
+
Retrieves a list with all app measures containing metadata.
|
588
|
+
|
589
|
+
Parameters:
|
590
|
+
app_handle (int): The handle of the app.
|
591
|
+
|
592
|
+
Returns:
|
593
|
+
DataFrame: A table with all measures from an app.
|
594
|
+
"""
|
595
|
+
# Define the parameters of the session object
|
596
|
+
nx_info = self.structs.nx_info(obj_type="MeasureList")
|
597
|
+
measure_list_def = self.structs.measure_list_def()
|
598
|
+
gen_obj_props = self.structs.generic_object_properties(info=nx_info, prop_name="qMeasureListDef",
|
599
|
+
prop_def=measure_list_def)
|
600
|
+
|
601
|
+
# Create session object
|
602
|
+
session = self.eaa.create_session_object(app_handle, gen_obj_props)
|
603
|
+
|
604
|
+
# Get session handle
|
605
|
+
session_handle = self.get_handle(session)
|
606
|
+
|
607
|
+
# Get session object data
|
608
|
+
session_layout = self.egoa.get_layout(session_handle)
|
609
|
+
|
610
|
+
# Get the measure list as Dictionary structure
|
611
|
+
measure_list = session_layout["qMeasureList"]["qItems"]
|
612
|
+
|
613
|
+
# Define the DataFrame structure
|
614
|
+
df_measure_list = pd.DataFrame(columns=["qInfo", "qMeasure", "qMeta"])
|
615
|
+
|
616
|
+
for measure in measure_list:
|
617
|
+
# Get measure ID
|
618
|
+
measure_id = measure["qInfo"]["qId"]
|
619
|
+
# Get measure
|
620
|
+
measure_result = self.egma.get_measure(app_handle=app_handle, measure_id=measure_id)
|
621
|
+
# Get measure handle
|
622
|
+
measure_handle = self.get_handle(measure_result)
|
623
|
+
# Get session object data
|
624
|
+
measure_layout = self.egoa.get_layout(measure_handle)
|
625
|
+
|
626
|
+
# Concatenate the measure metadata to the DataFrame structure
|
627
|
+
df_measure_list.loc[len(df_measure_list)] = measure_layout
|
628
|
+
|
629
|
+
# Resolve the dictionary structure of attribute "qInfo"
|
630
|
+
df_measure_list_expanded = (df_measure_list["qInfo"].apply(pd.Series).add_prefix("qInfo_"))
|
631
|
+
df_measure_list = df_measure_list.drop(columns=["qInfo"]).join(df_measure_list_expanded)
|
632
|
+
|
633
|
+
# Resolve the dictionary structure of attribute "qMeasure"
|
634
|
+
df_measure_list_expanded = (df_measure_list["qMeasure"].apply(pd.Series).add_prefix("qMeasure_"))
|
635
|
+
df_measure_list = df_measure_list.drop(columns=["qMeasure"]).join(df_measure_list_expanded)
|
636
|
+
|
637
|
+
# Resolve the dictionary structure of attribute "qMeta"
|
638
|
+
df_measure_list_expanded = (df_measure_list["qMeta"].apply(pd.Series).add_prefix("qMeta_"))
|
639
|
+
df_measure_list = df_measure_list.drop(columns=["qMeta"]).join(df_measure_list_expanded)
|
640
|
+
|
641
|
+
# Resolve the dictionary structure of attribute "qMeasure_qNumFormat"
|
642
|
+
df_measure_list_expanded = (
|
643
|
+
df_measure_list["qMeasure_qNumFormat"].apply(pd.Series).add_prefix("qMeasure_qNumFormat_"))
|
644
|
+
df_measure_list = df_measure_list.drop(columns=["qMeasure_qNumFormat"]).join(df_measure_list_expanded)
|
645
|
+
|
646
|
+
# Resolve the dictionary structure of attribute "qMeasure_coloring"
|
647
|
+
try:
|
648
|
+
df_measure_list_expanded = (
|
649
|
+
df_measure_list["qMeasure_coloring"].apply(pd.Series).add_prefix("qMeasure_coloring_"))
|
650
|
+
df_measure_list = df_measure_list.drop(columns=["qMeasure_coloring"]).join(df_measure_list_expanded)
|
651
|
+
except KeyError:
|
652
|
+
df_measure_list["qMeasure_coloring"] = ""
|
653
|
+
|
654
|
+
# Resolve the dictionary structure of attribute "qMeasure_coloring_baseColor"
|
655
|
+
try:
|
656
|
+
df_measure_list_expanded = (df_measure_list["qMeasure_coloring_baseColor"].apply(pd.Series).add_prefix(
|
657
|
+
"qMeasure_coloring_baseColor_"))
|
658
|
+
df_measure_list = df_measure_list.drop(columns=["qMeasure_coloring_baseColor"]).join(
|
659
|
+
df_measure_list_expanded)
|
660
|
+
except KeyError:
|
661
|
+
df_measure_list["qMeasure_coloring_baseColor"] = ""
|
662
|
+
|
663
|
+
return df_measure_list
|
664
|
+
|
665
|
+
|
666
|
+
def get_app_lineage(self, app_handle):
|
667
|
+
"""
|
668
|
+
Retrieves a list with an app lineage data.
|
669
|
+
|
670
|
+
Parameters:
|
671
|
+
app_handle (int): The handle of the app.
|
672
|
+
|
673
|
+
Returns:
|
674
|
+
DataFrame: A table with lineage data from an app.
|
675
|
+
"""
|
676
|
+
# Get lineage data from an app
|
677
|
+
lineage_list = self.eaa.get_lineage(app_handle)
|
678
|
+
|
679
|
+
# Define the DataFrame structure
|
680
|
+
df_lineage_list = pd.DataFrame(columns=['qDiscriminator', 'qStatement'])
|
681
|
+
|
682
|
+
for lineage in lineage_list:
|
683
|
+
# Concatenate the lineage row on the DataFrame structure
|
684
|
+
df_lineage_list.loc[len(df_lineage_list)] = lineage
|
685
|
+
|
686
|
+
return df_lineage_list
|
qe_api_client/structs.py
CHANGED
@@ -2,6 +2,7 @@ def list_object_def(state_name="$", library_id="", field_defs=[], initial_data_f
|
|
2
2
|
return {"qStateName": state_name, "qLibraryId": library_id, "qDef": field_defs,
|
3
3
|
"qInitialDataFetch": initial_data_fetch}
|
4
4
|
|
5
|
+
|
5
6
|
def hypercube_def(state_name="$", nx_dims=[], nx_meas=[], nx_page=[], inter_column_sort=[0, 1, 2], suppress_zero=False,
|
6
7
|
suppress_missing=False):
|
7
8
|
return {"qStateName": state_name, "qDimensions": nx_dims, "qMeasures": nx_meas,
|
@@ -10,23 +11,27 @@ def hypercube_def(state_name="$", nx_dims=[], nx_meas=[], nx_page=[], inter_colu
|
|
10
11
|
"qAlwaysFullyExpanded": False, "qMaxStackedCells": 5000, "qPopulateMissing": False,
|
11
12
|
"qShowTotalsAbove": False, "qIndentMode": False, "qCalcCond": "", "qSortbyYValue": 0}
|
12
13
|
|
14
|
+
|
13
15
|
def nx_inline_dimension_def(field_definitions=[], field_labels=[], sort_criterias=[], grouping='N'):
|
14
16
|
return {"qGrouping": grouping, "qFieldDefs": field_definitions, "qFieldLabels": field_labels,
|
15
17
|
"qSortCriterias": sort_criterias, "qReverseSort": False}
|
16
18
|
|
19
|
+
|
17
20
|
def nx_inline_measure_def(definition, label="", description="", tags=[], grouping="N"):
|
18
21
|
return {"qLabel": label, "qDescription": description, "qTags": tags, "qGrouping": grouping, "qDef": definition}
|
19
22
|
|
23
|
+
|
20
24
|
def nx_page(left=0, top=0, width=2, height=2):
|
21
25
|
return {"qLeft": left, "qTop": top, "qWidth": width, "qHeight": height}
|
22
26
|
|
27
|
+
|
23
28
|
def nx_info(obj_type, obj_id=""):
|
24
29
|
"""
|
25
30
|
Retrieves the data from a specific list object in a generic object.
|
26
31
|
|
27
32
|
Parameters:
|
28
33
|
obj_type (str): Type of the object. This parameter is mandatory.
|
29
|
-
obj_id (str): Identifier of the object. If the chosen identifier is already in use, the engine automatically
|
34
|
+
obj_id (str, optional): Identifier of the object. If the chosen identifier is already in use, the engine automatically
|
30
35
|
sets another one. If an identifier is not set, the engine automatically sets one. This parameter is optional.
|
31
36
|
|
32
37
|
Returns:
|
@@ -34,45 +39,84 @@ def nx_info(obj_type, obj_id=""):
|
|
34
39
|
"""
|
35
40
|
return {"qId": obj_id, "qType": obj_type}
|
36
41
|
|
42
|
+
|
37
43
|
def nx_dimension(library_id="", dim_def={}, null_suppression=False):
|
38
44
|
return {"qLibraryId": library_id, "qDef": dim_def, "qNullSuppression": null_suppression}
|
39
45
|
|
46
|
+
|
40
47
|
def nx_measure(library_id="", mes_def={}, sort_by={}):
|
41
48
|
return {"qLibraryId": library_id, "qDef": mes_def, "qSortBy": sort_by}
|
42
49
|
|
50
|
+
|
43
51
|
def generic_object_properties(info, prop_name, prop_def, extends_id="", state_name="$"):
|
44
52
|
return {"qInfo": info, "qExtendsId": extends_id, prop_name: prop_def, "qStateName": state_name}
|
45
53
|
|
54
|
+
|
46
55
|
def sort_criteria(state=0, freq=0, numeric=0, ascii=0, load_order=1):
|
47
56
|
return {"qSortByState": state, "qSortByFrequency": freq, "qSortByNumeric": numeric, "qSortByAscii": ascii,
|
48
57
|
"qSortByLoadOrder": load_order, "qSortByExpression": 0, "qExpression": {"qv": ""}}
|
49
58
|
|
59
|
+
|
50
60
|
def field_value(text, is_numeric = False, number = 0):
|
51
61
|
return {"qText": text, "qIsNumeric": is_numeric, "qNumber": number}
|
52
62
|
|
53
|
-
def generic_dimension_properties(info, lb_dim_def, dim_title):
|
54
|
-
return {"qInfo": info, "qDim": lb_dim_def, "qMetaDef": {"title": dim_title}}
|
55
63
|
|
56
|
-
def
|
64
|
+
def generic_dimension_properties(nx_info: dict, nx_library_dimension_def: dict, title: str, description: str = "",
|
65
|
+
tags: list = None):
|
66
|
+
if tags is None:
|
67
|
+
tags = []
|
68
|
+
return {"qInfo": nx_info, "qDim": nx_library_dimension_def, "qMetaDef": {"title": title, "description": description,
|
69
|
+
"tags": tags}}
|
70
|
+
|
71
|
+
|
72
|
+
def nx_library_dimension_def(grouping: str = "N", field_definitions: list = None, field_labels: list = None,
|
73
|
+
label_expression: str = ""):
|
74
|
+
if field_labels is None:
|
75
|
+
field_labels = []
|
76
|
+
if field_definitions is None:
|
77
|
+
field_definitions = []
|
57
78
|
return {"qGrouping": grouping, "qFieldDefs": field_definitions, "qFieldLabels": field_labels,
|
58
79
|
"qLabelExpression": label_expression}
|
59
80
|
|
60
|
-
|
61
|
-
|
81
|
+
|
82
|
+
def nx_library_measure_def(label: str, mes_def: str, grouping: str = "N", expressions: list = None,
|
83
|
+
active_expression: int = 0, label_expression:str = "", num_format: dict = None):
|
84
|
+
if num_format is None:
|
85
|
+
num_format = {}
|
86
|
+
if expressions is None:
|
87
|
+
expressions = []
|
62
88
|
return {"qLabel": label, "qDef": mes_def,"qGrouping": grouping, "qExpressions": expressions,
|
63
89
|
"qActiveExpression": active_expression, "qLabelExpression": label_expression, "qNumFormat": num_format}
|
64
90
|
|
65
|
-
|
91
|
+
|
92
|
+
def num_format(type: str = "U", n_dec: int = 10, use_thou:int = 0, fmt: str = "", dec: str = "", thou: str = ""):
|
66
93
|
return {"qType": type, "qnDec": n_dec, "qUseThou": use_thou, "qFmt": fmt, "qDec": dec, "qThou": thou}
|
67
94
|
|
68
|
-
|
69
|
-
|
95
|
+
|
96
|
+
def generic_measure_properties(nx_info: dict, nx_library_measure_def: dict, title: str, description: str = "",
|
97
|
+
tags: list = None):
|
98
|
+
if tags is None:
|
99
|
+
tags = []
|
100
|
+
return {"qInfo": nx_info, "qMeasure": nx_library_measure_def, "qMetaDef": {"title": title,
|
101
|
+
"description": description,
|
102
|
+
"tags": tags}}
|
103
|
+
|
70
104
|
|
71
105
|
def do_reload_ex_params(mode=0, partial=False, debug=False, reload_id="", skip_store=False, row_limit=0):
|
72
106
|
return {"qMode": mode, "qPartial": partial, "qDebug": debug, "qReloadId": reload_id, "qSkipStore": skip_store,
|
73
107
|
"qRowLimit": row_limit}
|
74
108
|
|
109
|
+
|
75
110
|
def dimension_list_def():
|
76
|
-
return {"
|
77
|
-
"
|
78
|
-
|
111
|
+
return {"qType": "dimension",
|
112
|
+
"qData": {"title": "/title", "tags": "/tags", "grouping": "/qDim/qGrouping", "info": "/qDimInfos"}}
|
113
|
+
|
114
|
+
|
115
|
+
def measure_list_def():
|
116
|
+
return {"qType": "measure", "qData": {"title": "/title", "tags": "/tags"}}
|
117
|
+
|
118
|
+
|
119
|
+
def field_list_def(show_system: bool = True, show_hidden: bool = True, show_derived_fields: bool = True,
|
120
|
+
show_semantic: bool = True, show_src_tables: bool = True, show_implicit: bool = True):
|
121
|
+
return {"qShowSystem": show_system, "qShowHidden": show_hidden, "qShowDerivedFields": show_derived_fields,
|
122
|
+
"qShowSemantic": show_semantic, "qShowSrcTables": show_src_tables, "qShowImplicit": show_implicit}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: qe-api-client
|
3
|
-
Version: 2.
|
4
|
-
Summary: Python
|
3
|
+
Version: 2.5.0
|
4
|
+
Summary: Python client for the Qlik Engine JSON API
|
5
5
|
Home-page: https://github.com/lr-bicc/qe-api-client
|
6
6
|
Author: Rumen Vasilev
|
7
7
|
Author-email: R.Vasilev@LRWorld.com
|
@@ -1,17 +1,17 @@
|
|
1
1
|
qe_api_client/__init__.py,sha256=bypB4CIjpHtf5Pu_NwtJajC69zqQD7qB9jo8cCX0B54,23
|
2
|
-
qe_api_client/engine.py,sha256=
|
2
|
+
qe_api_client/engine.py,sha256=AGv3Ab5YE5-PpNdkQF6aCLYECKkgbiU96jqEcpb6VUE,32019
|
3
3
|
qe_api_client/engine_communicator.py,sha256=q6x7ix2Ev8yGmTTm7cf1vHcidOihKM0HjDXeJ-dZYjk,1133
|
4
|
-
qe_api_client/structs.py,sha256=
|
4
|
+
qe_api_client/structs.py,sha256=9_2LzC8Er_cFNmGPLRB_xuQ0v3AHY24XirGFVSBxkMo,5996
|
5
5
|
qe_api_client/api_classes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
6
|
-
qe_api_client/api_classes/engine_app_api.py,sha256=
|
6
|
+
qe_api_client/api_classes/engine_app_api.py,sha256=_wNFr3scbw0THoM_mMpSapKyiNEhjB4qYBDNgZLLoHg,37493
|
7
7
|
qe_api_client/api_classes/engine_field_api.py,sha256=zCLIR7rmxqwIrJYK_-uHVEhMvBcEP2qofuX8ZPygqCA,5479
|
8
|
-
qe_api_client/api_classes/engine_generic_dimension_api.py,sha256=
|
9
|
-
qe_api_client/api_classes/engine_generic_measure_api.py,sha256=
|
8
|
+
qe_api_client/api_classes/engine_generic_dimension_api.py,sha256=OdYnL54jTaNgfICDj5czJcFB1QZ4Y0s_YslqomQY26I,1394
|
9
|
+
qe_api_client/api_classes/engine_generic_measure_api.py,sha256=uj4i_ykX9F9Dtk78fOidMBhzSP8vEucEfrB6MrLwgPI,1340
|
10
10
|
qe_api_client/api_classes/engine_generic_object_api.py,sha256=nqsEtvKkt5XkUEIVUoBtNVXtmUvuifxrgTcw2fDuaOE,8218
|
11
11
|
qe_api_client/api_classes/engine_generic_variable_api.py,sha256=sWXZpE-GLfcMijmfORnDNrJ6lmXX3x5TRHlkEu_i0BQ,2027
|
12
12
|
qe_api_client/api_classes/engine_global_api.py,sha256=G6QQHI36WOo7W25zg4Uz__gMSLC2ptNTvbBdElPzgZI,27535
|
13
|
-
qe_api_client-2.
|
14
|
-
qe_api_client-2.
|
15
|
-
qe_api_client-2.
|
16
|
-
qe_api_client-2.
|
17
|
-
qe_api_client-2.
|
13
|
+
qe_api_client-2.5.0.dist-info/LICENSE,sha256=2bm9uFabQZ3Ykb_SaSU_uUbAj2-htc6WJQmS_65qD00,1073
|
14
|
+
qe_api_client-2.5.0.dist-info/METADATA,sha256=TcvlAA9v6e69nWGG-dCXD9E0lxx_jrxrjBi7cVLKgmw,2363
|
15
|
+
qe_api_client-2.5.0.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
16
|
+
qe_api_client-2.5.0.dist-info/top_level.txt,sha256=m_43YagP8UtZgJHmZEfu0vlBNwt36M01-Qby2jByMnk,14
|
17
|
+
qe_api_client-2.5.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|