qe-api-client 2.5.0__py3-none-any.whl → 2.7.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 +3 -3
- qe_api_client/api_classes/engine_generic_dimension_api.py +19 -0
- qe_api_client/api_classes/engine_generic_object_api.py +35 -5
- qe_api_client/engine.py +504 -18
- qe_api_client/structs.py +453 -34
- {qe_api_client-2.5.0.dist-info → qe_api_client-2.7.0.dist-info}/METADATA +4 -3
- qe_api_client-2.7.0.dist-info/RECORD +17 -0
- {qe_api_client-2.5.0.dist-info → qe_api_client-2.7.0.dist-info}/WHEEL +1 -1
- qe_api_client-2.5.0.dist-info/RECORD +0 -17
- {qe_api_client-2.5.0.dist-info → qe_api_client-2.7.0.dist-info/licenses}/LICENSE +0 -0
- {qe_api_client-2.5.0.dist-info → qe_api_client-2.7.0.dist-info}/top_level.txt +0 -0
qe_api_client/engine.py
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
import json
|
2
|
+
|
1
3
|
import qe_api_client.api_classes.engine_app_api as engine_app_api
|
2
4
|
import qe_api_client.engine_communicator as engine_communicator
|
3
5
|
import qe_api_client.api_classes.engine_field_api as engine_field_api
|
@@ -93,8 +95,14 @@ class QixEngine:
|
|
93
95
|
fld_handle = self.get_handle(lb_field)
|
94
96
|
return self.efa.clear(fld_handle)
|
95
97
|
|
98
|
+
|
96
99
|
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
|
100
|
+
dim_desc: str = "", dim_tags: list = None, dim_color: str = None,
|
101
|
+
dim_color_index: int = -1, value_colors: list = None,
|
102
|
+
null_value_color: str = None, null_value_color_index: int = -1,
|
103
|
+
other_value_color: str = None, other_value_color_index: int = -1,
|
104
|
+
single_color: str = None, single_color_index: int = -1, palette: str = None
|
105
|
+
):
|
98
106
|
"""
|
99
107
|
Creates a single master dimension.
|
100
108
|
|
@@ -105,22 +113,105 @@ class QixEngine:
|
|
105
113
|
dim_label (str, optional): The label of the dimension.
|
106
114
|
dim_desc (str, optional): The description of the dimension.
|
107
115
|
dim_tags (list, optional): The tags of the dimension.
|
116
|
+
dim_color (str, optional): The master dimension color.
|
117
|
+
dim_color_index (int, optional): The index of the master dimension color in the theme color picker.
|
118
|
+
value_colors (list, optional): The value colors of the master dimension.
|
119
|
+
null_value_color (str, optional): The NULL value color of the master dimension.
|
120
|
+
null_value_color_index (int, optional): The index of the NULL value color of the master dimension in the theme color picker.
|
121
|
+
other_value_color (str, optional): The OTHER value color of the master dimension.
|
122
|
+
other_value_color_index (int, optional): The index of the OTHER value color of the master dimension in the theme color picker.
|
123
|
+
single_color (str, optional): Single color of the values of the master dimension.
|
124
|
+
single_color_index (int, optional): The index of single color of the values of the master dimension in the theme color picker.
|
125
|
+
palette (str, optional): Choose a color palette, if there are more than one.
|
108
126
|
|
109
127
|
Returns:
|
110
128
|
dict: The handle and Id of the dimension.
|
111
129
|
"""
|
130
|
+
if value_colors is None:
|
131
|
+
value_colors = []
|
112
132
|
if dim_tags is None:
|
113
133
|
dim_tags = []
|
134
|
+
|
135
|
+
# Define of the single dimension properties
|
114
136
|
nx_info = self.structs.nx_info(obj_type="dimension")
|
137
|
+
if dim_color is None:
|
138
|
+
coloring = self.structs.coloring()
|
139
|
+
else:
|
140
|
+
coloring = self.structs.coloring(base_color={"color": dim_color, "index": dim_color_index})
|
141
|
+
|
115
142
|
nx_library_dimension_def = self.structs.nx_library_dimension_def(grouping="N", field_definitions=[dim_def],
|
116
143
|
field_labels=[dim_title],
|
117
|
-
label_expression=dim_label
|
144
|
+
label_expression=dim_label, alias=dim_title,
|
145
|
+
title=dim_title, coloring=coloring)
|
118
146
|
gen_dim_props = self.structs.generic_dimension_properties(nx_info=nx_info,
|
119
147
|
nx_library_dimension_def=nx_library_dimension_def,
|
120
148
|
title=dim_title, description=dim_desc, tags=dim_tags)
|
149
|
+
|
150
|
+
# Create the single dimension
|
121
151
|
master_dim = self.eaa.create_dimension(app_handle, gen_dim_props)
|
152
|
+
|
153
|
+
# Get id and handle of the master dimension
|
154
|
+
master_dim_id = self.get_id(master_dim)
|
155
|
+
master_dim_handle = self.get_handle(master_dim)
|
156
|
+
|
157
|
+
# Update "colorMapRef" property with the master dimension id.
|
158
|
+
patch_value = json.dumps(master_dim_id)
|
159
|
+
patch_color_map_ref = self.structs.nx_patch(op="replace", path="/qDim/coloring/colorMapRef", value=patch_value)
|
160
|
+
self.egda.apply_patches(handle=master_dim_handle, patches=[patch_color_map_ref])
|
161
|
+
|
162
|
+
# Define the color properties
|
163
|
+
if null_value_color is None:
|
164
|
+
null_value = None
|
165
|
+
else:
|
166
|
+
null_value = {"color": null_value_color, "index": null_value_color_index}
|
167
|
+
|
168
|
+
if other_value_color is None:
|
169
|
+
other_value = None
|
170
|
+
else:
|
171
|
+
other_value = {"color": other_value_color, "index": other_value_color_index}
|
172
|
+
|
173
|
+
if single_color is None:
|
174
|
+
single = None
|
175
|
+
else:
|
176
|
+
single = {"color": single_color, "index": single_color_index}
|
177
|
+
|
178
|
+
colors = value_colors
|
179
|
+
color_map = self.structs.color_map(colors=colors, nul=null_value, oth=other_value, single=single, pal=palette)
|
180
|
+
color_map_props = self.structs.color_map_properties(dim_id=master_dim_id, _color_map=color_map)
|
181
|
+
|
182
|
+
# Create color map object, if colors are passed.
|
183
|
+
if value_colors or null_value_color is not None or other_value_color is not None or single_color is not None or palette is not None:
|
184
|
+
color_map_model = self.eaa.create_object(app_handle, color_map_props)
|
185
|
+
color_map_model_handle = self.get_handle(color_map_model)
|
186
|
+
|
187
|
+
# Set "autoFill" and "usePal" to "False", if a single color is passed.
|
188
|
+
if bool(single):
|
189
|
+
patch_value_use_pal_auto_fill = json.dumps(False)
|
190
|
+
patch_use_pal = self.structs.nx_patch(op="replace", path="/colorMap/usePal",
|
191
|
+
value=patch_value_use_pal_auto_fill)
|
192
|
+
self.egda.apply_patches(handle=color_map_model_handle, patches=[patch_use_pal])
|
193
|
+
|
194
|
+
patch_auto_fill = self.structs.nx_patch(op="replace", path="/colorMap/autoFill",
|
195
|
+
value=patch_value_use_pal_auto_fill)
|
196
|
+
self.egda.apply_patches(handle=color_map_model_handle, patches=[patch_auto_fill])
|
197
|
+
|
198
|
+
# Set "autoFill" to "False", if a color palette is passed.
|
199
|
+
if palette is not None:
|
200
|
+
patch_value_auto_fill = json.dumps(False)
|
201
|
+
patch_auto_fill = self.structs.nx_patch(op="replace", path="/colorMap/autoFill",
|
202
|
+
value=patch_value_auto_fill)
|
203
|
+
self.egda.apply_patches(handle=color_map_model_handle, patches=[patch_auto_fill])
|
204
|
+
|
205
|
+
# Update "hasValueColors" property, if value colors are passed.
|
206
|
+
if value_colors:
|
207
|
+
patch_value_has_value_colors = json.dumps(True)
|
208
|
+
patch_has_value_colors = self.structs.nx_patch(op="replace", path="/qDim/coloring/hasValueColors",
|
209
|
+
value=patch_value_has_value_colors)
|
210
|
+
self.egda.apply_patches(handle=master_dim_handle, patches=[patch_has_value_colors])
|
211
|
+
|
122
212
|
return master_dim
|
123
213
|
|
214
|
+
|
124
215
|
def create_master_measure(self, app_handle: int, mes_title: str, mes_def: str, mes_label: str = "",
|
125
216
|
mes_desc: str = "", mes_tags: list = None):
|
126
217
|
"""
|
@@ -139,15 +230,215 @@ class QixEngine:
|
|
139
230
|
"""
|
140
231
|
if mes_tags is None:
|
141
232
|
mes_tags = []
|
233
|
+
|
234
|
+
# Define of the measure properties
|
142
235
|
nx_info = self.structs.nx_info(obj_type="measure")
|
143
236
|
nx_library_measure_def = self.structs.nx_library_measure_def(label=mes_title, mes_def=mes_def,
|
144
237
|
label_expression=mes_label)
|
145
238
|
gen_mes_props = self.structs.generic_measure_properties(nx_info=nx_info,
|
146
239
|
nx_library_measure_def=nx_library_measure_def,
|
147
240
|
title=mes_title, description=mes_desc, tags=mes_tags)
|
241
|
+
|
242
|
+
# Create the measure
|
148
243
|
master_mes = self.eaa.create_measure(app_handle, gen_mes_props)
|
244
|
+
|
149
245
|
return master_mes
|
150
246
|
|
247
|
+
def create_sheet(self, app_handle: int, sheet_title: str, sheet_desc: str = "", no_of_rows: int = 18):
|
248
|
+
"""
|
249
|
+
Creates a sheet.
|
250
|
+
|
251
|
+
Parameters:
|
252
|
+
app_handle (int): The handle of the app.
|
253
|
+
sheet_title (str): The title of the sheet.
|
254
|
+
sheet_desc (str, optional): The description of the sheet.
|
255
|
+
no_of_rows (int, optional): TThe number of the sheet rows. Min. 8 rows and max. 42 rows.
|
256
|
+
|
257
|
+
Returns:
|
258
|
+
dict: The handle and Id of the sheet.
|
259
|
+
"""
|
260
|
+
# Define of the sheet properties
|
261
|
+
nx_info = self.structs.nx_info(obj_type="sheet")
|
262
|
+
sheet_def = {"title": sheet_title, "description": sheet_desc}
|
263
|
+
sheet_props = self.structs.generic_object_properties(info=nx_info, prop_name="qMetaDef", prop_def=sheet_def)
|
264
|
+
|
265
|
+
# Add row and column attributes. The number of the row should be between 8 and 42.
|
266
|
+
if no_of_rows not in range(8, 43):
|
267
|
+
no_of_rows = 18
|
268
|
+
no_of_columns = no_of_rows * 2
|
269
|
+
|
270
|
+
# Derive the grid_resolution property
|
271
|
+
if no_of_rows == 12:
|
272
|
+
grid_resolution = "small"
|
273
|
+
elif no_of_rows == 15:
|
274
|
+
grid_resolution = "medium"
|
275
|
+
elif no_of_rows == 18:
|
276
|
+
grid_resolution = "large"
|
277
|
+
else:
|
278
|
+
grid_resolution = "customrows"
|
279
|
+
|
280
|
+
# Add new properties
|
281
|
+
sheet_props.update(
|
282
|
+
{
|
283
|
+
"thumbnail": {"qStaticContentUrlDef": {"qUrl": ""}}, "columns": no_of_columns, "rows": no_of_rows,
|
284
|
+
"customRowBase": no_of_rows, "gridResolution": grid_resolution, "layoutOptions": {"mobileLayout": "LIST"},
|
285
|
+
"qChildListDef": {"qData": {"title": "/title"}}
|
286
|
+
}
|
287
|
+
)
|
288
|
+
|
289
|
+
# Create the sheet
|
290
|
+
sheet = self.eaa.create_object(app_handle, sheet_props)
|
291
|
+
|
292
|
+
return sheet
|
293
|
+
|
294
|
+
def create_list_object(self, handle: int, dim_id: str = "", field_def: str = "", field_title: str = ""):
|
295
|
+
"""
|
296
|
+
Creates a list object.
|
297
|
+
|
298
|
+
Parameters:
|
299
|
+
handle (int): The handle of the parent object.
|
300
|
+
dim_id (str, optional): The ID of the master dimension. Let this parameter empty, if you passed the "field_def".
|
301
|
+
field_def (str, optional): The definition of the field. Let this parameter empty, if you passed the "dim_id".
|
302
|
+
field_title (int, optional): The title of the field. Let this parameter empty, if you passed the "dim_id".
|
303
|
+
|
304
|
+
Returns:
|
305
|
+
dict: The handle and Id of the list object.
|
306
|
+
"""
|
307
|
+
if field_def is None:
|
308
|
+
field_def = []
|
309
|
+
|
310
|
+
nx_info = self.structs.nx_info(obj_type="listbox")
|
311
|
+
sort_criterias = self.structs.sort_criteria()
|
312
|
+
|
313
|
+
nx_library_dimension_def = self.structs.nx_inline_dimension_def(grouping="N", field_definitions=[field_def],
|
314
|
+
field_labels=[field_def],
|
315
|
+
sort_criterias=[sort_criterias])
|
316
|
+
list_object_def = self.structs.list_object_def(library_id=dim_id, definition=nx_library_dimension_def)
|
317
|
+
list_object_props = self.structs.generic_object_properties(info=nx_info, prop_name="qListObjectDef",
|
318
|
+
prop_def=list_object_def)
|
319
|
+
list_object_props.update(
|
320
|
+
{"showTitles": True, "title": field_title, "subtitle": "", "footnote": "", "disableNavMenu": False,
|
321
|
+
"showDetails": True, "showDetailsExpression": False, "visualization": "listbox"})
|
322
|
+
list_object = self.egoa.create_child(handle=handle, prop=list_object_props)
|
323
|
+
|
324
|
+
return list_object
|
325
|
+
|
326
|
+
def create_filterpane_frame(self, handle: int, no_of_rows_sheet: int, col: int, row: int, colspan: int, rowspan: int):
|
327
|
+
"""
|
328
|
+
Creates a filterpane frame.
|
329
|
+
|
330
|
+
Parameters:
|
331
|
+
handle (int): The handle of the parent object.
|
332
|
+
no_of_rows_sheet (int): The number of the sheet rows.
|
333
|
+
col (int): First column the filterpane visualisation starts.
|
334
|
+
row (int): First row the filterpane visualisation starts.
|
335
|
+
colspan (int): The width of the filterpane in columns.
|
336
|
+
rowspan (int): The height of the filterpane in rows.
|
337
|
+
|
338
|
+
Returns:
|
339
|
+
dict: The handle and Id of the filterpane frame.
|
340
|
+
"""
|
341
|
+
nx_info = self.structs.nx_info(obj_type="filterpane")
|
342
|
+
filterpane_props = self.structs.generic_object_properties(info=nx_info, prop_name="qMetaDef")
|
343
|
+
filterpane_props.update({"qChildListDef": {"qData": {}}})
|
344
|
+
filterpane = self.egoa.create_child(handle=handle, prop=filterpane_props)
|
345
|
+
|
346
|
+
filterpane_id = self.get_id(filterpane)
|
347
|
+
|
348
|
+
no_of_cols_sheet = no_of_rows_sheet * 2
|
349
|
+
width = colspan / no_of_cols_sheet * 100
|
350
|
+
height = rowspan / no_of_rows_sheet * 100
|
351
|
+
y = row / no_of_rows_sheet * 100
|
352
|
+
x = col / no_of_cols_sheet * 100
|
353
|
+
|
354
|
+
if col >= 0 and colspan > 0 and no_of_cols_sheet >= col + colspan and row >= 0 and rowspan > 0 and no_of_rows_sheet >= row + rowspan:
|
355
|
+
filterpane_layout = self.structs.object_position_size(obj_id=filterpane_id, obj_type="filterpane",
|
356
|
+
col=col, row=row, colspan=colspan,
|
357
|
+
rowspan=rowspan, y=y, x=x, width=width,
|
358
|
+
height=height)
|
359
|
+
|
360
|
+
sheet_layout = self.egoa.get_layout(handle=handle)
|
361
|
+
|
362
|
+
if "cells" not in sheet_layout:
|
363
|
+
patch_value = str([filterpane_layout]).replace("'", "\"")
|
364
|
+
patch_cell = self.structs.nx_patch(op="add", path="/cells", value=patch_value)
|
365
|
+
else:
|
366
|
+
cells = sheet_layout["cells"]
|
367
|
+
cells.append(filterpane_layout)
|
368
|
+
patch_value = str(cells).replace("'", "\"")
|
369
|
+
patch_cell = self.structs.nx_patch(op="replace", path="/cells", value=patch_value)
|
370
|
+
|
371
|
+
self.egoa.apply_patches(handle=handle, patches=[patch_cell])
|
372
|
+
else:
|
373
|
+
print("The position of filterpane \"" + filterpane_id + "\" is out of range. This one will not be created.")
|
374
|
+
|
375
|
+
return filterpane
|
376
|
+
|
377
|
+
|
378
|
+
def create_chart(self, handle: int, obj_type: str, hypercube_def: dict, no_of_rows_sheet: int, col: int, row: int,
|
379
|
+
colspan: int, rowspan: int):
|
380
|
+
"""
|
381
|
+
Creates a chart object.
|
382
|
+
|
383
|
+
Parameters:
|
384
|
+
handle (int): The handle of the parent object.
|
385
|
+
obj_type (str): The type of the chart.
|
386
|
+
hypercube_def (dict): Chart hypercube definition.
|
387
|
+
no_of_rows_sheet (int): The number of the sheet rows.
|
388
|
+
col (int): First column the chart visualisation starts.
|
389
|
+
row (int): First row the chart visualisation starts.
|
390
|
+
colspan (int): The width of the chart in columns.
|
391
|
+
rowspan (int): The height of the chart in rows.
|
392
|
+
|
393
|
+
Returns:
|
394
|
+
dict: The handle and Id of the filterpane frame.
|
395
|
+
"""
|
396
|
+
|
397
|
+
nx_info = self.structs.nx_info(obj_type=obj_type)
|
398
|
+
if obj_type == "table":
|
399
|
+
chart_props = self.structs.table_properties(info=nx_info, hypercube_def=hypercube_def)
|
400
|
+
elif obj_type == "sn-table":
|
401
|
+
chart_props = self.structs.sn_table_properties(info=nx_info, hypercube_def=hypercube_def)
|
402
|
+
elif obj_type == "pivot-table":
|
403
|
+
chart_props = self.structs.pivot_table_properties(info=nx_info, hypercube_def=hypercube_def)
|
404
|
+
elif obj_type == "sn-pivot-table":
|
405
|
+
chart_props = self.structs.pivot_table_properties(info=nx_info, hypercube_def=hypercube_def)
|
406
|
+
else:
|
407
|
+
print("Not valid object type.")
|
408
|
+
|
409
|
+
chart = self.egoa.create_child(handle=handle, prop=chart_props)
|
410
|
+
|
411
|
+
chart_id = self.get_id(chart)
|
412
|
+
|
413
|
+
no_of_cols_sheet = no_of_rows_sheet * 2
|
414
|
+
width = colspan / no_of_cols_sheet * 100
|
415
|
+
height = rowspan / no_of_rows_sheet * 100
|
416
|
+
y = row / no_of_rows_sheet * 100
|
417
|
+
x = col / no_of_cols_sheet * 100
|
418
|
+
|
419
|
+
if col >= 0 and colspan > 0 and no_of_cols_sheet >= col + colspan and row >= 0 and rowspan > 0 and no_of_rows_sheet >= row + rowspan:
|
420
|
+
chart_layout = self.structs.object_position_size(obj_id=chart_id, obj_type=obj_type, col=col, row=row,
|
421
|
+
colspan=colspan, rowspan=rowspan, y=y, x=x, width=width,
|
422
|
+
height=height)
|
423
|
+
|
424
|
+
sheet_layout = self.egoa.get_layout(handle=handle)
|
425
|
+
|
426
|
+
if "cells" not in sheet_layout:
|
427
|
+
patch_value = str([chart_layout]).replace("'", "\"")
|
428
|
+
patch_cell = self.structs.nx_patch(op="add", path="/cells", value=patch_value)
|
429
|
+
else:
|
430
|
+
cells = sheet_layout["cells"]
|
431
|
+
cells.append(chart_layout)
|
432
|
+
patch_value = str(cells).replace("'", "\"")
|
433
|
+
patch_cell = self.structs.nx_patch(op="replace", path="/cells", value=patch_value)
|
434
|
+
|
435
|
+
self.egoa.apply_patches(handle=handle, patches=[patch_cell])
|
436
|
+
else:
|
437
|
+
print("The position of chart \"" + chart_id + "\" is out of range. This one will not be created.")
|
438
|
+
|
439
|
+
return chart
|
440
|
+
|
441
|
+
|
151
442
|
def get_app_lineage_info(self, app_handle):
|
152
443
|
"""
|
153
444
|
Gets the lineage information of the app. The lineage information includes the LOAD and STORE statements from
|
@@ -190,6 +481,26 @@ class QixEngine:
|
|
190
481
|
except ValueError:
|
191
482
|
return "Bad handle value in " + obj
|
192
483
|
|
484
|
+
@staticmethod
|
485
|
+
def get_id(obj):
|
486
|
+
"""
|
487
|
+
Retrieves the id from a given object.
|
488
|
+
|
489
|
+
Parameters:
|
490
|
+
obj : dict
|
491
|
+
The object containing the handle.
|
492
|
+
|
493
|
+
Returns:
|
494
|
+
int: The handle value.
|
495
|
+
|
496
|
+
Raises:
|
497
|
+
ValueError: If the handle value is invalid.
|
498
|
+
"""
|
499
|
+
try:
|
500
|
+
return obj["qGenericId"]
|
501
|
+
except ValueError:
|
502
|
+
return "Bad id value in " + obj
|
503
|
+
|
193
504
|
def get_chart_data(self, app_handle, obj_id):
|
194
505
|
"""
|
195
506
|
Retrieves the data from a given chart object.
|
@@ -355,7 +666,7 @@ class QixEngine:
|
|
355
666
|
hc_mes.append(self.structs.nx_measure(library_id=measure))
|
356
667
|
|
357
668
|
# Create hypercube structure
|
358
|
-
hc_def = self.structs.hypercube_def(state_name="$",
|
669
|
+
hc_def = self.structs.hypercube_def(state_name="$", dimensions=hc_dim, measures=hc_mes)
|
359
670
|
|
360
671
|
# Create info structure
|
361
672
|
nx_info = self.structs.nx_info(obj_type="table")
|
@@ -542,39 +853,39 @@ class QixEngine:
|
|
542
853
|
df_dimension_list.loc[len(df_dimension_list)] = dim_layout
|
543
854
|
|
544
855
|
# Resolve the dictionary structure of attribute "qInfo"
|
545
|
-
df_dimension_list_expanded = (df_dimension_list["qInfo"].apply(pd.Series).add_prefix("qInfo_"))
|
856
|
+
df_dimension_list_expanded = (df_dimension_list["qInfo"].dropna().apply(pd.Series).add_prefix("qInfo_"))
|
546
857
|
df_dimension_list = df_dimension_list.drop(columns=["qInfo"]).join(df_dimension_list_expanded)
|
547
858
|
|
548
859
|
# Resolve the dictionary structure of attribute "qMeta"
|
549
|
-
df_dimension_list_expanded = (df_dimension_list["qMeta"].apply(pd.Series).add_prefix("qMeta_"))
|
860
|
+
df_dimension_list_expanded = (df_dimension_list["qMeta"].dropna().apply(pd.Series).add_prefix("qMeta_"))
|
550
861
|
df_dimension_list = df_dimension_list.drop(columns=["qMeta"]).join(df_dimension_list_expanded)
|
551
862
|
|
552
863
|
# Resolve the dictionary structure of attribute "qDim"
|
553
|
-
df_dimension_list_expanded = (df_dimension_list["qDim"].apply(pd.Series).add_prefix("qDim_"))
|
864
|
+
df_dimension_list_expanded = (df_dimension_list["qDim"].dropna().apply(pd.Series).add_prefix("qDim_"))
|
554
865
|
df_dimension_list = df_dimension_list.drop(columns=["qDim"]).join(df_dimension_list_expanded)
|
555
866
|
|
556
867
|
# Resolve the dictionary structure of attribute "qDim_coloring"
|
557
868
|
try:
|
558
869
|
df_dimension_list_expanded = (
|
559
|
-
df_dimension_list["qDim_coloring"].apply(pd.Series).add_prefix("qDim_coloring_"))
|
870
|
+
df_dimension_list["qDim_coloring"].dropna().apply(pd.Series).add_prefix("qDim_coloring_"))
|
560
871
|
df_dimension_list = df_dimension_list.drop(columns=["qDim_coloring"]).join(df_dimension_list_expanded)
|
561
872
|
except KeyError:
|
562
|
-
df_dimension_list["qDim_coloring"] =
|
873
|
+
df_dimension_list["qDim_coloring"] = None
|
563
874
|
|
564
875
|
# Resolve the dictionary structure of attribute "qDim_coloring_baseColor"
|
565
876
|
try:
|
566
877
|
df_dimension_list_expanded = (
|
567
|
-
df_dimension_list["qDim_coloring_baseColor"].apply(pd.Series).add_prefix("qDim_coloring_baseColor_"))
|
878
|
+
df_dimension_list["qDim_coloring_baseColor"].dropna().apply(pd.Series).add_prefix("qDim_coloring_baseColor_"))
|
568
879
|
df_dimension_list = df_dimension_list.drop(columns=["qDim_coloring_baseColor"]).join(
|
569
880
|
df_dimension_list_expanded)
|
570
881
|
except KeyError:
|
571
|
-
df_dimension_list["qDim_coloring_baseColor"] =
|
882
|
+
df_dimension_list["qDim_coloring_baseColor"] = None
|
572
883
|
|
573
884
|
# Resolve the list structure of attribute
|
574
885
|
df_dimension_list = df_dimension_list.explode(['qDimInfos', 'qDim_qFieldDefs', 'qDim_qFieldLabels'])
|
575
886
|
|
576
887
|
# Resolve the dictionary structure of attribute "qDimInfos"
|
577
|
-
df_dimension_list_expanded = (df_dimension_list["qDimInfos"].apply(pd.Series).add_prefix("qDimInfos_"))
|
888
|
+
df_dimension_list_expanded = (df_dimension_list["qDimInfos"].dropna().apply(pd.Series).add_prefix("qDimInfos_"))
|
578
889
|
index = df_dimension_list_expanded.index
|
579
890
|
df_dimension_list_expanded = df_dimension_list_expanded[~index.duplicated(keep="first")]
|
580
891
|
df_dimension_list = df_dimension_list.drop(columns=["qDimInfos"]).join(df_dimension_list_expanded)
|
@@ -627,11 +938,11 @@ class QixEngine:
|
|
627
938
|
df_measure_list.loc[len(df_measure_list)] = measure_layout
|
628
939
|
|
629
940
|
# Resolve the dictionary structure of attribute "qInfo"
|
630
|
-
df_measure_list_expanded = (df_measure_list["qInfo"].apply(pd.Series).add_prefix("qInfo_"))
|
941
|
+
df_measure_list_expanded = (df_measure_list["qInfo"].dropna().apply(pd.Series).add_prefix("qInfo_"))
|
631
942
|
df_measure_list = df_measure_list.drop(columns=["qInfo"]).join(df_measure_list_expanded)
|
632
943
|
|
633
944
|
# Resolve the dictionary structure of attribute "qMeasure"
|
634
|
-
df_measure_list_expanded = (df_measure_list["qMeasure"].apply(pd.Series).add_prefix("qMeasure_"))
|
945
|
+
df_measure_list_expanded = (df_measure_list["qMeasure"].dropna().apply(pd.Series).add_prefix("qMeasure_"))
|
635
946
|
df_measure_list = df_measure_list.drop(columns=["qMeasure"]).join(df_measure_list_expanded)
|
636
947
|
|
637
948
|
# Resolve the dictionary structure of attribute "qMeta"
|
@@ -640,29 +951,204 @@ class QixEngine:
|
|
640
951
|
|
641
952
|
# Resolve the dictionary structure of attribute "qMeasure_qNumFormat"
|
642
953
|
df_measure_list_expanded = (
|
643
|
-
df_measure_list["qMeasure_qNumFormat"].apply(pd.Series).add_prefix("qMeasure_qNumFormat_"))
|
954
|
+
df_measure_list["qMeasure_qNumFormat"].dropna().apply(pd.Series).add_prefix("qMeasure_qNumFormat_"))
|
644
955
|
df_measure_list = df_measure_list.drop(columns=["qMeasure_qNumFormat"]).join(df_measure_list_expanded)
|
645
956
|
|
646
957
|
# Resolve the dictionary structure of attribute "qMeasure_coloring"
|
647
958
|
try:
|
648
959
|
df_measure_list_expanded = (
|
649
|
-
df_measure_list["qMeasure_coloring"].apply(pd.Series).add_prefix("qMeasure_coloring_"))
|
960
|
+
df_measure_list["qMeasure_coloring"].dropna().apply(pd.Series).add_prefix("qMeasure_coloring_"))
|
650
961
|
df_measure_list = df_measure_list.drop(columns=["qMeasure_coloring"]).join(df_measure_list_expanded)
|
651
962
|
except KeyError:
|
652
|
-
df_measure_list["qMeasure_coloring"] =
|
963
|
+
df_measure_list["qMeasure_coloring"] = None
|
653
964
|
|
654
965
|
# Resolve the dictionary structure of attribute "qMeasure_coloring_baseColor"
|
655
966
|
try:
|
656
|
-
df_measure_list_expanded = (df_measure_list["qMeasure_coloring_baseColor"].apply(pd.Series).add_prefix(
|
967
|
+
df_measure_list_expanded = (df_measure_list["qMeasure_coloring_baseColor"].dropna().apply(pd.Series).add_prefix(
|
657
968
|
"qMeasure_coloring_baseColor_"))
|
658
969
|
df_measure_list = df_measure_list.drop(columns=["qMeasure_coloring_baseColor"]).join(
|
659
970
|
df_measure_list_expanded)
|
660
971
|
except KeyError:
|
661
|
-
df_measure_list["qMeasure_coloring_baseColor"] =
|
972
|
+
df_measure_list["qMeasure_coloring_baseColor"] = None
|
662
973
|
|
663
974
|
return df_measure_list
|
664
975
|
|
665
976
|
|
977
|
+
def get_app_sheets(self, app_handle):
|
978
|
+
"""
|
979
|
+
Retrieves a list with all app sheets and their content containing metadata.
|
980
|
+
|
981
|
+
Parameters:
|
982
|
+
app_handle (int): The handle of the app.
|
983
|
+
|
984
|
+
Returns:
|
985
|
+
DataFrame: A table with all sheets and their content from an app.
|
986
|
+
"""
|
987
|
+
# Define the parameters of the session object
|
988
|
+
nx_info = self.structs.nx_info(obj_type="SheetList")
|
989
|
+
sheet_list_def = self.structs.sheet_list_def()
|
990
|
+
gen_obj_props = self.structs.generic_object_properties(info=nx_info, prop_name="qAppObjectListDef",
|
991
|
+
prop_def=sheet_list_def)
|
992
|
+
|
993
|
+
# Create session object
|
994
|
+
session = self.eaa.create_session_object(app_handle, gen_obj_props)
|
995
|
+
|
996
|
+
# Get session handle
|
997
|
+
session_handle = self.get_handle(session)
|
998
|
+
|
999
|
+
# Get session object data
|
1000
|
+
session_layout = self.egoa.get_layout(session_handle)
|
1001
|
+
|
1002
|
+
# Get the sheet list as Dictionary structure
|
1003
|
+
sheet_list = session_layout["qAppObjectList"]["qItems"]
|
1004
|
+
|
1005
|
+
# Define the DataFrame structure
|
1006
|
+
df_sheet_list = pd.DataFrame(columns=['qInfo', 'qMeta', 'qSelectionInfo', 'rank', 'thumbnail', 'columns', 'rows', 'cells', 'qChildList', 'gridResolution', 'layoutOptions', 'gridMode', 'customRowBase'])
|
1007
|
+
|
1008
|
+
for sheet in sheet_list:
|
1009
|
+
# Get sheet ID
|
1010
|
+
sheet_id = sheet["qInfo"]["qId"]
|
1011
|
+
# Get sheet
|
1012
|
+
sheet_result = self.eaa.get_object(app_handle=app_handle, object_id=sheet_id)
|
1013
|
+
# Get sheet handle
|
1014
|
+
sheet_handle = self.get_handle(sheet_result)
|
1015
|
+
# Get session object data
|
1016
|
+
sheet_layout = self.egoa.get_layout(sheet_handle)
|
1017
|
+
|
1018
|
+
# Concatenate the measure metadata to the DataFrame structure
|
1019
|
+
df_sheet_list.loc[len(df_sheet_list)] = sheet_layout
|
1020
|
+
|
1021
|
+
# Resolve the dictionary structure of attribute "qInfo"
|
1022
|
+
df_sheet_list_expanded = (df_sheet_list["qInfo"].dropna().apply(pd.Series).add_prefix("qInfo_"))
|
1023
|
+
df_sheet_list = df_sheet_list.drop(columns=["qInfo"]).join(df_sheet_list_expanded)
|
1024
|
+
|
1025
|
+
# Resolve the dictionary structure of attribute "qMeta"
|
1026
|
+
df_sheet_list_expanded = (df_sheet_list["qMeta"].dropna().apply(pd.Series).add_prefix("qMeta_"))
|
1027
|
+
df_sheet_list = df_sheet_list.drop(columns=["qMeta"]).join(df_sheet_list_expanded)
|
1028
|
+
|
1029
|
+
# Resolve the dictionary structure of attribute "qSelectionInfo"
|
1030
|
+
df_sheet_list["qSelectionInfo"] = df_sheet_list["qSelectionInfo"].apply(
|
1031
|
+
lambda x: None if isinstance(x, dict) and len(x) == 0 else x
|
1032
|
+
)
|
1033
|
+
df_sheet_list_expanded = (df_sheet_list["qSelectionInfo"].dropna().apply(pd.Series).add_prefix("qSelectionInfo_"))
|
1034
|
+
df_sheet_list = df_sheet_list.drop(columns=["qSelectionInfo"]).join(df_sheet_list_expanded)
|
1035
|
+
|
1036
|
+
# Resolve the dictionary structure of attribute "thumbnail"
|
1037
|
+
df_sheet_list_expanded = (df_sheet_list["thumbnail"].dropna().apply(pd.Series).add_prefix("thumbnail_"))
|
1038
|
+
df_sheet_list = df_sheet_list.drop(columns=["thumbnail"]).join(df_sheet_list_expanded)
|
1039
|
+
|
1040
|
+
# Resolve the dictionary structure of attribute "thumbnail_qStaticContentUrl"
|
1041
|
+
df_sheet_list["thumbnail_qStaticContentUrl"] = df_sheet_list["thumbnail_qStaticContentUrl"].apply(
|
1042
|
+
lambda x: None if isinstance(x, dict) and len(x) == 0 else x
|
1043
|
+
)
|
1044
|
+
df_sheet_list_expanded = (df_sheet_list["thumbnail_qStaticContentUrl"].dropna().apply(pd.Series).add_prefix("thumbnail_qStaticContentUrl_"))
|
1045
|
+
df_sheet_list = df_sheet_list.drop(columns=["thumbnail_qStaticContentUrl"]).join(df_sheet_list_expanded)
|
1046
|
+
|
1047
|
+
# Resolve the dictionary structure of attribute "qChildList"
|
1048
|
+
df_sheet_list_expanded = (df_sheet_list["qChildList"].dropna().apply(pd.Series).add_prefix("qChildList_"))
|
1049
|
+
df_sheet_list = df_sheet_list.drop(columns=["qChildList"]).join(df_sheet_list_expanded)
|
1050
|
+
|
1051
|
+
# Resolve the dictionary structure of attribute "layoutOptions"
|
1052
|
+
df_sheet_list_expanded = (df_sheet_list["layoutOptions"].dropna().apply(pd.Series).add_prefix("layoutOptions_"))
|
1053
|
+
df_sheet_list = df_sheet_list.drop(columns=["layoutOptions"]).join(df_sheet_list_expanded)
|
1054
|
+
|
1055
|
+
# Resolve the list structure of attribute
|
1056
|
+
df_sheet_list = df_sheet_list.explode(['cells', 'qChildList_qItems'])
|
1057
|
+
|
1058
|
+
# Resolve the dictionary structure of attribute "cells"
|
1059
|
+
df_sheet_list_expanded = (df_sheet_list["cells"].dropna().apply(pd.Series).add_prefix("cells_"))
|
1060
|
+
index = df_sheet_list_expanded.index
|
1061
|
+
df_sheet_list_expanded = df_sheet_list_expanded[~index.duplicated(keep="first")]
|
1062
|
+
df_sheet_list = df_sheet_list.drop(columns=["cells"]).join(df_sheet_list_expanded)
|
1063
|
+
|
1064
|
+
# Resolve the dictionary structure of attribute "cells_bounds"
|
1065
|
+
df_sheet_list_expanded = (
|
1066
|
+
df_sheet_list["cells_bounds"].dropna().apply(pd.Series).add_prefix("cells_bounds_"))
|
1067
|
+
index = df_sheet_list_expanded.index
|
1068
|
+
df_sheet_list_expanded = df_sheet_list_expanded[~index.duplicated(keep="first")]
|
1069
|
+
df_sheet_list = df_sheet_list.drop(columns=["cells_bounds"]).join(df_sheet_list_expanded)
|
1070
|
+
|
1071
|
+
# Resolve the dictionary structure of attribute "qChildList_qItems"
|
1072
|
+
df_sheet_list_expanded = (
|
1073
|
+
df_sheet_list["qChildList_qItems"].dropna().apply(pd.Series).add_prefix("qChildList_qItems_"))
|
1074
|
+
index = df_sheet_list_expanded.index
|
1075
|
+
df_sheet_list_expanded = df_sheet_list_expanded[~index.duplicated(keep="first")]
|
1076
|
+
df_sheet_list = df_sheet_list.drop(columns=["qChildList_qItems"]).join(df_sheet_list_expanded)
|
1077
|
+
|
1078
|
+
# Resolve the dictionary structure of attribute "qChildList_qItems_qInfo"
|
1079
|
+
df_sheet_list_expanded = (
|
1080
|
+
df_sheet_list["qChildList_qItems_qInfo"].dropna().apply(pd.Series).add_prefix("qChildList_qItems_qInfo_"))
|
1081
|
+
index = df_sheet_list_expanded.index
|
1082
|
+
df_sheet_list_expanded = df_sheet_list_expanded[~index.duplicated(keep="first")]
|
1083
|
+
df_sheet_list = df_sheet_list.drop(columns=["qChildList_qItems_qInfo"]).join(df_sheet_list_expanded)
|
1084
|
+
|
1085
|
+
# Resolve the dictionary structure of attribute "qChildList_qItems_qMeta"
|
1086
|
+
df_sheet_list_expanded = (
|
1087
|
+
df_sheet_list["qChildList_qItems_qMeta"].dropna().apply(pd.Series).add_prefix("qChildList_qItems_qMeta_"))
|
1088
|
+
index = df_sheet_list_expanded.index
|
1089
|
+
df_sheet_list_expanded = df_sheet_list_expanded[~index.duplicated(keep="first")]
|
1090
|
+
df_sheet_list = df_sheet_list.drop(columns=["qChildList_qItems_qMeta"]).join(df_sheet_list_expanded)
|
1091
|
+
|
1092
|
+
# Resolve the dictionary structure of attribute "qChildList_qItems_qData"
|
1093
|
+
df_sheet_list_expanded = (
|
1094
|
+
df_sheet_list["qChildList_qItems_qData"].dropna().apply(pd.Series).add_prefix("qChildList_qItems_qData_"))
|
1095
|
+
index = df_sheet_list_expanded.index
|
1096
|
+
df_sheet_list_expanded = df_sheet_list_expanded[~index.duplicated(keep="first")]
|
1097
|
+
df_sheet_list = df_sheet_list.drop(columns=["qChildList_qItems_qData"]).join(df_sheet_list_expanded)
|
1098
|
+
|
1099
|
+
return df_sheet_list
|
1100
|
+
|
1101
|
+
|
1102
|
+
def get_app_variables(self, app_handle):
|
1103
|
+
"""
|
1104
|
+
Retrieves a list with all app variables containing metadata.
|
1105
|
+
|
1106
|
+
Parameters:
|
1107
|
+
app_handle (int): The handle of the app.
|
1108
|
+
|
1109
|
+
Returns:
|
1110
|
+
DataFrame: A table with all variables from an app.
|
1111
|
+
"""
|
1112
|
+
# Define the parameters of the session object
|
1113
|
+
nx_info = self.structs.nx_info(obj_type="VariableList")
|
1114
|
+
variable_list_def = self.structs.variable_list_def()
|
1115
|
+
gen_obj_props = self.structs.generic_object_properties(info=nx_info, prop_name="qVariableListDef",
|
1116
|
+
prop_def=variable_list_def)
|
1117
|
+
|
1118
|
+
# Create session object
|
1119
|
+
session = self.eaa.create_session_object(app_handle, gen_obj_props)
|
1120
|
+
|
1121
|
+
# Get session handle
|
1122
|
+
session_handle = self.get_handle(session)
|
1123
|
+
|
1124
|
+
# Get session object data
|
1125
|
+
session_layout = self.egoa.get_layout(session_handle)
|
1126
|
+
|
1127
|
+
# Get the variable list as Dictionary structure
|
1128
|
+
variable_list = session_layout["qVariableList"]["qItems"]
|
1129
|
+
|
1130
|
+
# Define the DataFrame structure
|
1131
|
+
df_variable_list = pd.DataFrame(columns=["qName", "qDefinition", "qMeta", "qInfo", "qData", "qIsScriptCreated", "qIsReserved"])
|
1132
|
+
|
1133
|
+
for variable in variable_list:
|
1134
|
+
# Concatenate the measure metadata to the DataFrame structure
|
1135
|
+
df_variable_list.loc[len(df_variable_list)] = variable
|
1136
|
+
|
1137
|
+
# Resolve the dictionary structure of attribute "qInfo"
|
1138
|
+
df_variable_list_expanded = (df_variable_list["qInfo"].dropna().apply(pd.Series).add_prefix("qInfo_"))
|
1139
|
+
df_variable_list = df_variable_list.drop(columns=["qInfo"]).join(df_variable_list_expanded)
|
1140
|
+
|
1141
|
+
# Resolve the dictionary structure of attribute "qMeta"
|
1142
|
+
df_variable_list_expanded = (df_variable_list["qMeta"].dropna().apply(pd.Series).add_prefix("qMeta_"))
|
1143
|
+
df_variable_list = df_variable_list.drop(columns=["qMeta"]).join(df_variable_list_expanded)
|
1144
|
+
|
1145
|
+
# Resolve the dictionary structure of attribute "qData"
|
1146
|
+
df_variable_list_expanded = (df_variable_list["qData"].dropna().apply(pd.Series).add_prefix("qData_"))
|
1147
|
+
df_variable_list = df_variable_list.drop(columns=["qData"]).join(df_variable_list_expanded)
|
1148
|
+
|
1149
|
+
return df_variable_list
|
1150
|
+
|
1151
|
+
|
666
1152
|
def get_app_lineage(self, app_handle):
|
667
1153
|
"""
|
668
1154
|
Retrieves a list with an app lineage data.
|