Source code for qe_api_client.engine

import json

import qe_api_client.api_classes.engine_app_api as engine_app_api
import qe_api_client.engine_communicator as engine_communicator
import qe_api_client.api_classes.engine_field_api as engine_field_api
import qe_api_client.api_classes.engine_generic_object_api as engine_generic_object_api
import qe_api_client.api_classes.engine_global_api as engine_global_api
import qe_api_client.api_classes.engine_generic_variable_api as engine_generic_variable_api
import qe_api_client.api_classes.engine_generic_dimension_api as engine_generic_dimension_api
import qe_api_client.api_classes.engine_generic_measure_api as engine_generic_measure_api
import qe_api_client.structs as structs
import math
import pandas as pd
import numpy as np
from datetime import datetime, timezone
import time


[docs] class QixEngine: """ The class of the client to interact with the Qlik Sense Engine API. Methods: select_in_dimension(app_handle, dimension_name, list_of_values): Selects values in a given field. """ def __init__(self, url, user_directory=None, user_id=None, ca_certs=None, certfile=None, keyfile=None, app_id=None): self.url = url # Check, if server or local connection available if user_directory is None and user_id is None and ca_certs is None and certfile is None and keyfile is None: self.conn = engine_communicator.EngineCommunicator(url) else: self.conn = engine_communicator.SecureEngineCommunicator(url, user_directory, user_id, ca_certs, certfile, keyfile, app_id) self.ega = engine_global_api.EngineGlobalApi(self.conn) self.eaa = engine_app_api.EngineAppApi(self.conn) self.egoa = engine_generic_object_api.EngineGenericObjectApi(self.conn) self.efa = engine_field_api.EngineFieldApi(self.conn) self.egva = engine_generic_variable_api.EngineGenericVariableApi(self.conn) self.egda = engine_generic_dimension_api.EngineGenericDimensionApi(self.conn) self.egma = engine_generic_measure_api.EngineGenericMeasureApi(self.conn) self.structs = structs self.app_handle = ''
[docs] def select_in_field(self, app_handle, field_name, list_of_values): lb_field = self.eaa.get_field(app_handle, field_name) fld_handle = self.get_handle(lb_field) if fld_handle is None: return "The field name " + field_name + " doesn't exist!" else: values_to_select = [] for val in list_of_values: fld_value = self.structs.field_value(text=val) values_to_select.append(fld_value) return self.efa.select_values(fld_handle, values_to_select)
[docs] def select_excluded_in_field(self, app_handle, field_name): lb_field = self.eaa.get_field(app_handle, field_name) fld_handle = self.get_handle(lb_field) return self.efa.select_excluded(fld_handle)
[docs] def select_possible_in_field(self, app_handle, field_name): lb_field = self.eaa.get_field(app_handle, field_name) fld_handle = self.get_handle(lb_field) return self.efa.select_possible(fld_handle)
# return a list of tuples where first value in tuple is the actual # data value and the second tuple value is that # values selection state
[docs] def get_list_object_data(self, app_handle, field_name): lb_field = self.eaa.get_field(app_handle, field_name) fld_handle = self.get_handle(lb_field) nx_inline_dimension_def = self.structs.nx_inline_dimension_def([field_name]) nx_page = self.structs.nx_page(left=0, top=0, width=self.efa.get_cardinal(fld_handle)) lb_def = self.structs.list_object_def("$", "", nx_inline_dimension_def, [nx_page]) # Create info structure nx_info = self.structs.nx_info(obj_type="ListObject", obj_id="SLB01") # Create generic object properties structure gen_obj_props = self.structs.generic_object_properties(info=nx_info, prop_name="qListObjectDef", prop_def=lb_def) listobj = self.eaa.create_session_object(app_handle, gen_obj_props) # NOQA listobj_handle = self.get_handle(listobj) val_list = self.egoa.get_layout(listobj_handle)["qListObject"]["qDataPages"][0]["qMatrix"] # NOQA val_n_state_list = [] for val in val_list: val_n_state_list.append((val[0]["qText"], val[0]["qState"])) return val_n_state_list
[docs] def clear_selection_in_dimension(self, app_handle, dimension_name): lb_field = self.eaa.get_field(app_handle, dimension_name) fld_handle = self.get_handle(lb_field) return self.efa.clear(fld_handle)
[docs] def create_single_master_dimension(self, app_handle: int, dim_title: str, dim_def: str, dim_label: str = "", dim_desc: str = "", dim_tags: list = None, dim_color: str = None, dim_color_index: int = -1, value_colors: list = None, null_value_color: str = None, null_value_color_index: int = -1, other_value_color: str = None, other_value_color_index: int = -1, single_color: str = None, single_color_index: int = -1, palette: str = None ): """ Creates a single master dimension. Parameters: app_handle (int): The handle of the app. dim_title (str): The title of the dimension. dim_def (str): The definition of the dimension. dim_label (str, optional): The label of the dimension. dim_desc (str, optional): The description of the dimension. dim_tags (list, optional): The tags of the dimension. dim_color (str, optional): The master dimension color. dim_color_index (int, optional): The index of the master dimension color in the theme color picker. value_colors (list, optional): The value colors of the master dimension. null_value_color (str, optional): The NULL value color of the master dimension. null_value_color_index (int, optional): The index of the NULL value color of the master dimension in the theme color picker. other_value_color (str, optional): The OTHER value color of the master dimension. other_value_color_index (int, optional): The index of the OTHER value color of the master dimension in the theme color picker. single_color (str, optional): Single color of the values of the master dimension. single_color_index (int, optional): The index of single color of the values of the master dimension in the theme color picker. palette (str, optional): Choose a color palette, if there are more than one. Returns: dict: The handle and Id of the dimension. """ if value_colors is None: value_colors = [] if dim_tags is None: dim_tags = [] # Define of the single dimension properties nx_info = self.structs.nx_info(obj_type="dimension") if dim_color is None: coloring = self.structs.dim_coloring() else: coloring = self.structs.dim_coloring(base_color={"color": dim_color, "index": dim_color_index}) nx_library_dimension_def = self.structs.nx_library_dimension_def(grouping="N", field_definitions=[dim_def], field_labels=[dim_title], label_expression=dim_label, alias=dim_title, title=dim_title, coloring=coloring) gen_dim_props = self.structs.generic_dimension_properties(nx_info=nx_info, nx_library_dimension_def=nx_library_dimension_def, title=dim_title, description=dim_desc, tags=dim_tags) # Create the single dimension master_dim = self.eaa.create_dimension(app_handle, gen_dim_props) # Get id and handle of the master dimension master_dim_id = self.get_id(master_dim) master_dim_handle = self.get_handle(master_dim) # Update "colorMapRef" property with the master dimension id. patch_value = json.dumps(master_dim_id) patch_color_map_ref = self.structs.nx_patch(op="replace", path="/qDim/coloring/colorMapRef", value=patch_value) self.egda.apply_patches(handle=master_dim_handle, patches=[patch_color_map_ref]) # Define the color properties if null_value_color is None: null_value = None else: null_value = {"color": null_value_color, "index": null_value_color_index} if other_value_color is None: other_value = None else: other_value = {"color": other_value_color, "index": other_value_color_index} if single_color is None: single = None else: single = {"color": single_color, "index": single_color_index} colors = value_colors color_map = self.structs.color_map(colors=colors, nul=null_value, oth=other_value, single=single, pal=palette) color_map_props = self.structs.color_map_properties(dim_id=master_dim_id, _color_map=color_map) # Create color map object, if colors are passed. 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: color_map_model = self.eaa.create_object(app_handle, color_map_props) color_map_model_handle = self.get_handle(color_map_model) # Set "autoFill" and "usePal" to "False", if a single color is passed. if bool(single): patch_value_use_pal_auto_fill = json.dumps(False) patch_use_pal = self.structs.nx_patch(op="replace", path="/colorMap/usePal", value=patch_value_use_pal_auto_fill) self.egda.apply_patches(handle=color_map_model_handle, patches=[patch_use_pal]) patch_auto_fill = self.structs.nx_patch(op="replace", path="/colorMap/autoFill", value=patch_value_use_pal_auto_fill) self.egda.apply_patches(handle=color_map_model_handle, patches=[patch_auto_fill]) # Set "autoFill" to "False", if a color palette is passed. if palette is not None: patch_value_auto_fill = json.dumps(False) patch_auto_fill = self.structs.nx_patch(op="replace", path="/colorMap/autoFill", value=patch_value_auto_fill) self.egda.apply_patches(handle=color_map_model_handle, patches=[patch_auto_fill]) # Update "hasValueColors" property, if value colors are passed. if value_colors: patch_value_has_value_colors = json.dumps(True) patch_has_value_colors = self.structs.nx_patch(op="replace", path="/qDim/coloring/hasValueColors", value=patch_value_has_value_colors) self.egda.apply_patches(handle=master_dim_handle, patches=[patch_has_value_colors]) return master_dim
[docs] def create_master_measure(self, app_handle: int, mes_title: str, mes_def: str, mes_label: str = "", mes_desc: str = "", mes_tags: list = None, mes_color: str = None, mes_color_index: int = -1, gradient: dict = None): """ Creates a master measure. Parameters: app_handle (int): The handle of the app. mes_title (str): The title of the measure. mes_def (str): The definition of the measure. mes_label (str, optional): The label of the measure. mes_desc (str, optional): The description of the measure. mes_tags (list, optional): The tags of the measure. mes_color (str, optional): The color of the measure. mes_color_index (int, optional): The index of the color of the measure. Returns: dict: The handle and Id of the measure. """ if mes_tags is None: mes_tags = [] # Define of the measure properties nx_info = self.structs.nx_info(obj_type="measure") if mes_color is None: coloring = self.structs.mes_coloring() else: coloring = self.structs.mes_coloring(base_color={"color": mes_color, "index": mes_color_index}) if gradient is not None: coloring.update({"gradient": gradient}) nx_library_measure_def = self.structs.nx_library_measure_def(label=mes_title, mes_def=mes_def, label_expression=mes_label, coloring=coloring) gen_mes_props = self.structs.generic_measure_properties(nx_info=nx_info, nx_library_measure_def=nx_library_measure_def, title=mes_title, description=mes_desc, tags=mes_tags) # Create the measure master_mes = self.eaa.create_measure(app_handle, gen_mes_props) return master_mes
[docs] def create_sheet(self, app_handle: int, sheet_title: str, sheet_desc: str = "", no_of_rows: int = 18): """ Creates a sheet. Parameters: app_handle (int): The handle of the app. sheet_title (str): The title of the sheet. sheet_desc (str, optional): The description of the sheet. no_of_rows (int, optional): TThe number of the sheet rows. Min. 8 rows and max. 42 rows. Returns: dict: The handle and Id of the sheet. """ # Define of the sheet properties nx_info = self.structs.nx_info(obj_type="sheet") sheet_def = {"title": sheet_title, "description": sheet_desc} sheet_props = self.structs.generic_object_properties(info=nx_info, prop_name="qMetaDef", prop_def=sheet_def) # Add row and column attributes. The number of the row should be between 8 and 42. if no_of_rows not in range(8, 43): no_of_rows = 18 no_of_columns = no_of_rows * 2 # Derive the grid_resolution property if no_of_rows == 12: grid_resolution = "small" elif no_of_rows == 15: grid_resolution = "medium" elif no_of_rows == 18: grid_resolution = "large" else: grid_resolution = "customrows" # Add new properties sheet_props.update( { "thumbnail": {"qStaticContentUrlDef": {"qUrl": ""}}, "columns": no_of_columns, "rows": no_of_rows, "customRowBase": no_of_rows, "gridResolution": grid_resolution, "layoutOptions": {"mobileLayout": "LIST"}, "qChildListDef": {"qData": {"title": "/title"}} } ) # Create the sheet sheet = self.eaa.create_object(app_handle, sheet_props) return sheet
[docs] def create_list_object(self, handle: int, dim_id: str = "", field_def: str = "", field_title: str = ""): """ Creates a list object. Parameters: handle (int): The handle of the parent object. dim_id (str, optional): The ID of the master dimension. Let this parameter empty, if you passed the "field_def". field_def (str, optional): The definition of the field. Let this parameter empty, if you passed the "dim_id". field_title (int, optional): The title of the field. Let this parameter empty, if you passed the "dim_id". Returns: dict: The handle and Id of the list object. """ if field_def is None: field_def = [] nx_info = self.structs.nx_info(obj_type="listbox") sort_criterias = self.structs.sort_criteria() nx_library_dimension_def = self.structs.nx_inline_dimension_def(grouping="N", field_definitions=[field_def], field_labels=[field_def], sort_criterias=[sort_criterias]) list_object_def = self.structs.list_object_def(library_id=dim_id, definition=nx_library_dimension_def) list_object_props = self.structs.generic_object_properties(info=nx_info, prop_name="qListObjectDef", prop_def=list_object_def) list_object_props.update( {"showTitles": True, "title": field_title, "subtitle": "", "footnote": "", "disableNavMenu": False, "showDetails": True, "showDetailsExpression": False, "visualization": "listbox"}) list_object = self.egoa.create_child(handle=handle, prop=list_object_props) return list_object
[docs] def create_filterpane_frame(self, handle: int, no_of_rows_sheet: int, col: int, row: int, colspan: int, rowspan: int): """ Creates a filterpane frame. Parameters: handle (int): The handle of the parent object. no_of_rows_sheet (int): The number of the sheet rows. col (int): First column the filterpane visualisation starts. row (int): First row the filterpane visualisation starts. colspan (int): The width of the filterpane in columns. rowspan (int): The height of the filterpane in rows. Returns: dict: The handle and Id of the filterpane frame. """ nx_info = self.structs.nx_info(obj_type="filterpane") filterpane_props = self.structs.generic_object_properties(info=nx_info, prop_name="qMetaDef") filterpane_props.update({"qChildListDef": {"qData": {}}}) filterpane = self.egoa.create_child(handle=handle, prop=filterpane_props) filterpane_id = self.get_id(filterpane) no_of_cols_sheet = no_of_rows_sheet * 2 width = colspan / no_of_cols_sheet * 100 height = rowspan / no_of_rows_sheet * 100 y = row / no_of_rows_sheet * 100 x = col / no_of_cols_sheet * 100 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: filterpane_layout = self.structs.object_position_size(obj_id=filterpane_id, obj_type="filterpane", col=col, row=row, colspan=colspan, rowspan=rowspan, y=y, x=x, width=width, height=height) sheet_layout = self.egoa.get_layout(handle=handle) if "cells" not in sheet_layout: patch_value = str([filterpane_layout]).replace("'", "\"") patch_cell = self.structs.nx_patch(op="add", path="/cells", value=patch_value) else: cells = sheet_layout["cells"] cells.append(filterpane_layout) patch_value = str(cells).replace("'", "\"") patch_cell = self.structs.nx_patch(op="replace", path="/cells", value=patch_value) self.egoa.apply_patches(handle=handle, patches=[patch_cell]) else: print("The position of filterpane \"" + filterpane_id + "\" is out of range. This one will not be created.") return filterpane
[docs] def create_chart(self, handle: int, obj_type: str, hypercube_def: dict, no_of_rows_sheet: int, col: int, row: int, colspan: int, rowspan: int): """ Creates a chart object. Parameters: handle (int): The handle of the parent object. obj_type (str): The type of the chart. hypercube_def (dict): Chart hypercube definition. no_of_rows_sheet (int): The number of the sheet rows. col (int): First column the chart visualisation starts. row (int): First row the chart visualisation starts. colspan (int): The width of the chart in columns. rowspan (int): The height of the chart in rows. Returns: dict: The handle and Id of the filterpane frame. """ nx_info = self.structs.nx_info(obj_type=obj_type) if obj_type == "table": chart_props = self.structs.table_properties(info=nx_info, hypercube_def=hypercube_def) elif obj_type == "sn-table": chart_props = self.structs.sn_table_properties(info=nx_info, hypercube_def=hypercube_def) elif obj_type == "pivot-table": chart_props = self.structs.pivot_table_properties(info=nx_info, hypercube_def=hypercube_def) elif obj_type == "sn-pivot-table": chart_props = self.structs.pivot_table_properties(info=nx_info, hypercube_def=hypercube_def) else: print("Not valid object type.") chart = self.egoa.create_child(handle=handle, prop=chart_props) chart_id = self.get_id(chart) no_of_cols_sheet = no_of_rows_sheet * 2 width = colspan / no_of_cols_sheet * 100 height = rowspan / no_of_rows_sheet * 100 y = row / no_of_rows_sheet * 100 x = col / no_of_cols_sheet * 100 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: chart_layout = self.structs.object_position_size(obj_id=chart_id, obj_type=obj_type, col=col, row=row, colspan=colspan, rowspan=rowspan, y=y, x=x, width=width, height=height) sheet_layout = self.egoa.get_layout(handle=handle) if "cells" not in sheet_layout: patch_value = str([chart_layout]).replace("'", "\"") patch_cell = self.structs.nx_patch(op="add", path="/cells", value=patch_value) else: cells = sheet_layout["cells"] cells.append(chart_layout) patch_value = str(cells).replace("'", "\"") patch_cell = self.structs.nx_patch(op="replace", path="/cells", value=patch_value) self.egoa.apply_patches(handle=handle, patches=[patch_cell]) else: print("The position of chart \"" + chart_id + "\" is out of range. This one will not be created.") return chart
[docs] def create_snapshot(self, app_handle: int, object_id: str, snapshot_title: str = "", snapshot_description: str = "", show_titles: bool = True, object_width: float = 1280, object_height: float = 720, bounding_client_width: float = 1280, bounding_client_height: float = 720, rtl: bool = False, parent_width: float = 1280, parent_height: float = 720, content_width: float = 1280, content_height: float = 720, chart_data_scroll_offset_start: int = 0, chart_data_scroll_offset_end: int = 53, chart_data_legend_scroll_offset: int = 0, chart_data_zoom_min = 0, chart_data_zoom_max = 0): """ Creates a snapshot object. Parameters: app_handle (int): The handle of the app. object_id (str): The id of the object. snapshot_title (str): The title of the snapshot. snapshot_description (str): The description of the snapshot. show_titles (bool): Enables / disables chart title. object_width (float): The width of the snapshot object. object_height (float): The height of the snapshot object. bounding_client_width (float): The width of the bounding client. bounding_client_height (float): The height of the bounding client. rtl (bool): Controls the rendering of content with right-to-left (RTL) language support. parent_width (float): The width of the parent object. parent_height (float): The height of the parent object. content_width (float): The width of the content object. content_height (float): The height of the content object. chart_data_scroll_offset_start (int): Scroll offset start. chart_data_scroll_offset_end (int): Scroll offset end. chart_data_legend_scroll_offset (int): Legend scroll offset. chart_data_zoom_min: Minimum chart data zoom. chart_data_zoom_max: Maximum chart data zoom. Returns: dict: The handle and Id of the created snapshot. """ # Get chart object chart_obj = self.eaa.get_object(app_handle=app_handle, object_id=object_id) chart_obj_handle = self.get_handle(chart_obj) # Get sheet object sheet_obj = self.get_object_sheet(app_handle=app_handle, obj_id=object_id) sheet_id = self.get_id(sheet_obj) # Get the visualization type chart_obj_layout = self.egoa.get_layout(handle=chart_obj_handle) visualization = chart_obj_layout["visualization"] # Attribut "qInfo" changed chart_obj_layout["qInfo"] = {"qType": "snapshot"} # Attribut "showTitles" changed chart_obj_layout["showTitles"] = show_titles # Attribut "qMetaDef" added chart_obj_layout["qMetaDef"] = {"title": snapshot_title, "description": snapshot_description} # Attribut "creationDate" added chart_obj_layout["creationDate"] = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%f")[:-3] + "Z" # Attribut "permissions" added chart_obj_layout["permissions"] = {"update": True, "publish": False, "export": False, "exportData": True, "changeOwner": False, "remove": True} # Attribut "visualizationType" added chart_obj_layout["visualizationType"] = visualization # Attribut "sourceObjectId" added chart_obj_layout["sourceObjectId"] = object_id # Attribut "sheetId" added chart_obj_layout["sheetId"] = sheet_id # Attribut "timestamp" added chart_obj_layout["timestamp"] = int(time.time() * 1000) # Attribut "isClone" added chart_obj_layout["isClone"] = False # Attribut "supportExport" added chart_obj_layout["supportExport"] = True # Attribut "qIncludeVariables" added chart_obj_layout["qIncludeVariables"] = True # Build the special snapshot parameters for the different chart types. if visualization in ["pivot-table"]: # Attribut "snapshotData" added chart_obj_layout["snapshotData"] = { "object": { "size": { "w": object_width, "h": object_height, "boundingClientWidth": bounding_client_width, "boundingClientHeight": bounding_client_height } }, "rtl": rtl, "parent": { "h": parent_height, "w": parent_width } } elif visualization in ["sn-table"]: # Attribut "snapshotData" added chart_obj_layout["snapshotData"] = { "object": { "size": { "w": object_width, "h": object_height, "boundingClientWidth": bounding_client_width, "boundingClientHeight": bounding_client_height } }, "rtl": rtl, "content": { "scrollLeft": 0, "visibleLeft": 0, "visibleWidth": 6, "visibleTop": 0, "visibleHeight": 18, "rowsPerPage": 18, "page": 0, "size": { "width": object_width, "height": object_height }, "estimatedRowHeight": 25 }, "parent": { "h": parent_height, "w": parent_width } } elif visualization in ["sn-pivot-table"]: # Attribut "snapshotData" added chart_obj_layout["snapshotData"] = { "object": { "size": { "w": object_width, "h": object_height, "boundingClientWidth": bounding_client_width, "boundingClientHeight": bounding_client_height } }, "rtl": rtl, "content": { "qPivotDataPages": chart_obj_layout["qHyperCube"]["qPivotDataPages"], "scrollTop": 0, "scrollLeft": 0, "leftGridScrollLeft": 0, "topGridScrollTop": 0, "page": 0, "rowsPerPage": 15000 }, "parent": { "h": parent_height, "w": parent_width } } elif visualization in ["combochart", "barchart"]: # Attribut "snapshotData" added chart_obj_layout["snapshotData"] = { "object": { "size": { "w": object_width, "h": object_height, "boundingClientWidth": bounding_client_width, "boundingClientHeight": bounding_client_height } }, "rtl": rtl, "content": { "size": { "w": content_width, "h": content_height }, "chartData": { "scrollOffset": { "start": chart_data_scroll_offset_start, "end": chart_data_scroll_offset_end }, "legendScrollOffset": chart_data_legend_scroll_offset } }, "parent": { "h": parent_height, "w": parent_width } } elif visualization in ["linechart"]: # Attribut "snapshotData" added chart_obj_layout["snapshotData"] = { "object": { "size": { "w": object_width, "h": object_height, "boundingClientWidth": bounding_client_width, "boundingClientHeight": bounding_client_height } }, "rtl": rtl, "content": { "size": { "w": content_width, "h": content_height }, "chartData": { "zoom": { "min": chart_data_zoom_min, "max": chart_data_zoom_max } } }, "parent": { "h": parent_height, "w": parent_width } } else: print("Chart type not supported.") # Create snapshot snapshot = self.eaa.create_bookmark(doc_handle=app_handle, prop=chart_obj_layout) snapshot.update({"visualization": visualization}) return snapshot
[docs] def embed_snapshot(self, app_handle: int, snapshot_id: str, slide_id: str): """ Embeds a created snapshot object on a slide. Parameters: app_handle (int): The handle of the app. snapshot_id (str): The id of the snapshot. slide_id (str): The id of the slide to embed. """ # Get the slide, where the snapshot should be embeded. slide = self.eaa.get_object(app_handle=app_handle, object_id=slide_id) slide_handle = self.get_handle(slide) # Get the visualization type of the snapshot snapshot = self.eaa.get_bookmark(app_handle=app_handle, bookmark_id=snapshot_id) snapshot_handle = self.get_handle(snapshot) snapshot_layout = self.egoa.get_layout(handle=snapshot_handle) visualization_type = snapshot_layout["visualizationType"] # create the snapshot slideitem_snapshot_properties = self.structs.slideitem_snapshot_properties(snapshot_id=snapshot_id, visualization_type=visualization_type) slideitem_snapshot = self.egoa.create_child(handle=slide_handle, prop=slideitem_snapshot_properties) slideitem_snapshot_handle = self.get_handle(slideitem_snapshot) slideitem_snapshot_embeded = self.egoa.embed_snapshot_object(handle=slideitem_snapshot_handle, snapshot_id=snapshot_id)
[docs] def get_app_lineage_info(self, app_handle): """ Gets the lineage information of the app. The lineage information includes the LOAD and STORE statements from the data load script associated with this app. Parameters: app_handle (int): The handle of the app. Returns: DataFrame: Information about the lineage of the data in the app. """ # Lineage-Daten aus der API holen lineage_info = self.eaa.get_lineage(app_handle) # Erstelle den DataFrame und fülle fehlende Werte mit "" df_lineage_info = pd.DataFrame(lineage_info) df_lineage_info = df_lineage_info[(df_lineage_info["qDiscriminator"].notna()) | (df_lineage_info["qStatement"].notna())].fillna("") return df_lineage_info
[docs] def disconnect(self): self.conn.close_qvengine_connection(self.conn)
[docs] @staticmethod def get_handle(obj): """ Retrieves the handle from a given object. Parameters: obj : dict The object containing the handle. Returns: int: The handle value. Raises: ValueError: If the handle value is invalid. """ try: return obj["qHandle"] except ValueError: return "Bad handle value in " + obj
[docs] @staticmethod def get_id(obj): """ Retrieves the id from a given object. Parameters: obj : dict The object containing the id. Returns: int: The id value. Raises: ValueError: If the id value is invalid. """ try: return obj["qGenericId"] except ValueError: return "Bad id value in " + obj
[docs] @staticmethod def get_type(obj): """ Retrieves the type from a given object. Parameters: obj : dict The object containing the type. Returns: int: The type value. Raises: ValueError: If the type value is invalid. """ try: return obj["qGenericType"] except ValueError: return "Bad type value in " + obj
[docs] def get_object_sheet(self, app_handle: int, obj_id: str): """ Retrieves the sheet from a given chart object. Parameters: app_handle (int): The handle of the app. obj_id (str): The ID of the object. Returns: dict: The sheet object with handle and id. """ parent_obj = self.eaa.get_object(app_handle=app_handle, object_id=obj_id) while self.get_type(parent_obj) != "sheet": obj = parent_obj obj_handle = self.get_handle(obj) parent_obj = self.egoa.get_parent(handle=obj_handle) return parent_obj
[docs] def get_chart_data(self, app_handle, obj_id): """ Retrieves the data from a given chart object. Parameters: app_handle (int): The handle of the app. obj_id (str): The ID of the chart object. Returns: DataFrame: A table of the chart content. """ # Get object ID obj = self.eaa.get_object(app_handle, obj_id) if obj['qType'] is None: return 'Chart ID does not exists!' # Get object handle obj_handle = self.get_handle(obj) # Get object layout obj_layout = self.egoa.get_layout(obj_handle) # Determine the number of the columns and the rows the table has and splits in certain circumstances the table # calls no_of_columns = obj_layout['qHyperCube']['qSize']['qcx'] if no_of_columns == 0: return 'The chart either contains no columns or has a calculation condition!' width = no_of_columns no_of_rows = obj_layout['qHyperCube']['qSize']['qcy'] height = int(math.floor(10000 / no_of_columns)) # Extract the dimension and measure titles and concat them to column names. dimension_info = obj_layout['qHyperCube'].get('qDimensionInfo', []) measure_info = obj_layout['qHyperCube'].get('qMeasureInfo', []) column_info = dimension_info + measure_info # Build the column mapping using qEffectiveInterColumnSortOrder sort_order = sorted(obj_layout['qHyperCube']['qEffectiveInterColumnSortOrder']) sort_order_positive = [x for x in sort_order if x >= 0] column_names = [] for i in sort_order_positive: column_names.append(column_info[i]["qFallbackTitle"]) # if the type of the charts has a straight data structure if (obj_layout['qInfo']['qType'] in ['table', 'sn-table', 'piechart', 'scatterplot', 'combochart', 'barchart'] and obj_layout['qHyperCube']['qDataPages'] != []): # Paging variables page = 0 data_values = [] # Retrieves the hypercube data in a loop (because of limitation from 10.000 cells per call) while no_of_rows > page * height: nx_page = self.structs.nx_page(left=0, top=page * height, width=width, height=height) hc_data = self.egoa.get_hypercube_data(handle=obj_handle, path='/qHyperCubeDef', pages=[nx_page])[ 'qDataPages'][0]['qMatrix'] data_values.extend(hc_data) page += 1 # Creates Dataframe from the content of the attribute 'qText'. df = pd.DataFrame([[d['qText'] for d in sublist] for sublist in data_values]) # Assign titles zu Dataframe columns df.columns = column_names # if the type of the charts has a pivot data structure elif (obj_layout['qInfo']['qType'] in ['pivot-table', 'sn-pivot-table'] and obj_layout['qHyperCube']['qPivotDataPages'] != []): # Supporting function to traverse all subnodes to get all dimensions def get_all_dimensions(node): label = node.get('qText', '') # Leerer String, falls nicht vorhanden dimensions = [label] if 'qSubNodes' in node and node['qSubNodes']: sub_dimensions = [] for sub_node in node['qSubNodes']: sub_dimensions.extend([dimensions + d for d in get_all_dimensions(sub_node)]) return sub_dimensions else: return [dimensions] # Supporting function to get all column headers for the pivot table def get_column_paths(node): label = node.get('qText', '') current_path = [label] if 'qSubNodes' in node and node['qSubNodes']: paths = [] for sub in node['qSubNodes']: for path in get_column_paths(sub): paths.append(current_path + path) return paths else: return [current_path] col_headers = [] nx_page_top = self.structs.nx_page(left=0, top=0, width=width, height=1) hc_top = self.egoa.get_hypercube_pivot_data(handle=obj_handle, path='/qHyperCubeDef', pages=[nx_page_top])['qDataPages'][0]['qTop'] for top_node in hc_top: col_headers.extend(get_column_paths(top_node)) # Paging variables page = 0 row_headers = [] data_values = [] # Retrieves the hypercube data in a loop (bacause of limitation from 10.000 cells per call) while no_of_rows > page * height: nx_page = self.structs.nx_page(left=0, top=page * height, width=width, height=height) # Retrieves the row headers for the pivot table hc_left = self.egoa.get_hypercube_pivot_data(handle=obj_handle, path='/qHyperCubeDef', pages=[nx_page])[ 'qDataPages'][0]['qLeft'] for left_node in hc_left: row_headers.extend(get_all_dimensions(left_node)) # Retrieves the data for the pivot table hc_data = self.egoa.get_hypercube_pivot_data(handle=obj_handle, path='/qHyperCubeDef', pages=[nx_page])[ 'qDataPages'][0]['qData'] for row in hc_data: data_values.append([cell['qText'] for cell in row]) page += 1 # Creates multi indes for rows and columns row_index = pd.MultiIndex.from_tuples(row_headers) col_index = pd.MultiIndex.from_tuples(col_headers) # Creates the Dataframe df = pd.DataFrame(data_values, index=row_index, columns=col_index) index_levels = df.index.nlevels df.index.names = column_names[:index_levels] df = df.reset_index() # if the type of the charts has a stacked data structure elif obj_layout['qInfo']['qType'] in ['barchart'] and obj_layout['qHyperCube']['qStackedDataPages'] != []: max_no_cells = no_of_columns * no_of_rows nx_page = self.structs.nx_page(left=0, top=0, width=no_of_columns, height=no_of_rows) hc_data = self.egoa.get_hypercube_stack_data(handle=obj_handle, path='/qHyperCubeDef', pages=[nx_page], max_no_cells=max_no_cells)[ 'qDataPages'][0]['qData'][0]['qSubNodes'] # Transform the nested structure into a flat DataFrame data_values = [] for node in hc_data: for sub_node in node['qSubNodes']: value = sub_node['qSubNodes'][0]['qValue'] if sub_node['qSubNodes'] else None data_values.append([node['qText'], sub_node['qText'], value]) # Creates the Dataframe df = pd.DataFrame(data_values, columns=column_names) else: return 'Chart type not supported.' # Returns the Dataframe return df
[docs] def get_constructed_table_data(self, app_handle, list_of_dimensions = [], list_of_measures = [], list_of_master_dimensions = [], list_of_master_measures = []): """ Creates a table from given fields, expressions, dimensions or measures and retrieves the data from it. Parameters: app_handle (int): The handle of the app. list_of_dimensions (list): A list of dimensions. list_of_measures (list): A list of measures. list_of_master_dimensions (list): A list of master dimensions. list_of_master_measures (list): A list of master measures. Returns: DataFrame: A table of the chart content. """ # Create dimension property hc_dim = [] for dimension in list_of_dimensions: hc_inline_dim_def = self.structs.nx_inline_dimension_def(field_definitions=[dimension]) hc_dim.append(self.structs.nx_dimension(library_id="", dim_def=hc_inline_dim_def)) for dimension in list_of_master_dimensions: hc_dim.append(self.structs.nx_dimension(library_id=dimension)) # Create measure property hc_mes = [] for measure in list_of_measures: hc_inline_mes = self.structs.nx_inline_measure_def(definition=measure) hc_mes.append(self.structs.nx_measure(library_id="", mes_def=hc_inline_mes)) for measure in list_of_master_measures: hc_mes.append(self.structs.nx_measure(library_id=measure)) # Create hypercube structure hc_def = self.structs.hypercube_def(state_name="$", dimensions=hc_dim, measures=hc_mes) # Create info structure nx_info = self.structs.nx_info(obj_type="table") # Create generic object properties structure gen_obj_props = self.structs.generic_object_properties(info=nx_info, prop_name="qHyperCubeDef", prop_def=hc_def) # Create session object hc_obj = self.eaa.create_session_object(app_handle, gen_obj_props) # Get object handle hc_obj_handle = self.get_handle(hc_obj) # Get object layout hc_obj_layout = self.egoa.get_layout(hc_obj_handle) # Determine the number of the columns and the rows the table has and splits in certain circumstances the table calls no_of_columns = hc_obj_layout['qHyperCube']['qSize']['qcx'] width = no_of_columns no_of_rows = hc_obj_layout['qHyperCube']['qSize']['qcy'] height = int(math.floor(10000 / no_of_columns)) # Extract the dimension and measure titles and concat them to column names. dimension_titles = [dim['qFallbackTitle'] for dim in hc_obj_layout['qHyperCube']['qDimensionInfo']] measure_titles = [measure['qFallbackTitle'] for measure in hc_obj_layout['qHyperCube']['qMeasureInfo']] column_names = dimension_titles + measure_titles # Paging variables page = 0 data_values = [] # Retrieves the hypercube data in a loop (because of limitation from 10.000 cells per call) while no_of_rows > page * height: nx_page = self.structs.nx_page(left=0, top=page * height, width=width, height=height) hc_data = self.egoa.get_hypercube_data(handle=hc_obj_handle, path='/qHyperCubeDef', pages=[nx_page])['qDataPages'][0]['qMatrix'] data_values.extend(hc_data) page += 1 # Creates Dataframe from the content of the attribute 'qText'. df = pd.DataFrame([[d['qText'] for d in sublist] for sublist in data_values]) # Assign titles zu Dataframe columns df.columns = column_names # Returns the Dataframe return df
[docs] def get_apps(self): """ Retrieves a list with all apps on the server containing metadata. Parameters: Returns: DataFrame: A table with all server apps. """ # Get all apps from Qlik Server doc_list = self.ega.get_doc_list() # Convert into DataFrame structure df_doc_list = pd.DataFrame(doc_list) # Resolve the attribute "qMeta" field_meta = df_doc_list['qMeta'].apply(pd.Series).reindex(columns=["createdDate", "modifiedDate", "published", "publishTime", "privileges", "description", "qStaticByteSize", "dynamicColor", "create", "stream", "canCreateDataConnections"]) # Concat the resolved attribute and rename the new columns df_doc_list_meta = pd.concat([df_doc_list.drop(['qMeta'], axis=1), field_meta], axis=1) df_doc_list_meta = df_doc_list_meta.rename(columns={"createdDate": "qMeta_createdDate", "modifiedDate": "qMeta_modifiedDate", "published": "qMeta_published", "publishTime": "qMeta_publishTime", "privileges": "qMeta_privileges", "description": "qMeta_description", "qStaticByteSize": "qMeta_qStaticByteSize", "dynamicColor": "qMeta_dynamicColor", "create": "qMeta_create", "stream": "qMeta_stream", "canCreateDataConnections": "qMeta_canCreateDataConnections"}) # Resolve the attribute "stream" field_meta_stream = df_doc_list_meta['qMeta_stream'].apply(pd.Series).reindex(columns=["id", "name"]) # Concat the resolved attribute and rename the new columns df_doc_list_meta_stream = pd.concat([df_doc_list_meta.drop(['qMeta_stream'], axis=1), field_meta_stream], axis=1) df_doc_list_meta_stream = df_doc_list_meta_stream.rename( columns={"id": "qMeta_stream_id", "name": "qMeta_stream_name"}) # Resolve the attribute "qThumbnail" field_thumbnail = df_doc_list_meta_stream['qThumbnail'].apply(pd.Series).reindex(columns=["qUrl"]) ## Concat the resolved attribute and rename the new columns df_doc_list_resolved = pd.concat([df_doc_list_meta_stream.drop(['qThumbnail'], axis=1), field_thumbnail], axis=1) df_doc_list_resolved = df_doc_list_resolved.rename(columns={"qUrl": "qThumbnail_qUrl"}).replace(np.nan,'') return df_doc_list_resolved
[docs] def get_app_fields(self, app_handle): """ Retrieves a list with all app fields containing meta data. Parameters: app_handle (int): The handle of the app. Returns: DataFrame: A table with all fields from an app. """ # Define the parameters of the session object nx_info = self.structs.nx_info(obj_type="FieldList") field_list_def = self.structs.field_list_def() gen_obj_props = self.structs.generic_object_properties(info=nx_info, prop_name="qFieldListDef", prop_def=field_list_def) # Create session object session = self.eaa.create_session_object(app_handle, gen_obj_props) # Get session handle session_handle = self.get_handle(session) # Get session object data layout = self.egoa.get_layout(session_handle) # Get the field list as Dictionary structure fields_list = layout["qFieldList"]["qItems"] # Define the DataFrame structure df_fields_list = pd.DataFrame(columns=['qIsHidden', 'qIsSystem', 'qName', 'qCardinal', 'qTags', 'qSrcTables']) for fields in fields_list: # Concatenate the field list on the DataFrame structure df_fields_list.loc[len(df_fields_list)] = fields return df_fields_list
[docs] def get_app_dimensions(self, app_handle): """ Retrieves a list with all app dimensions containing metadata. Parameters: app_handle (int): The handle of the app. Returns: DataFrame: A table with all dimensions from an app. """ # Define the parameters of the session object nx_info = self.structs.nx_info(obj_type="DimensionList") dimension_list_def = self.structs.dimension_list_def() gen_obj_props = self.structs.generic_object_properties(info=nx_info, prop_name="qDimensionListDef", prop_def=dimension_list_def) # Create session object session = self.eaa.create_session_object(app_handle, gen_obj_props) # Get session handle session_handle = self.get_handle(session) # Get session object data session_layout = self.egoa.get_layout(session_handle) # Get the dimension list as Dictionary structure dimension_list = session_layout["qDimensionList"]["qItems"] # Define the DataFrame structure df_dimension_list = pd.DataFrame(columns=["qInfo", "qMeta", "qDim", "qDimInfos"]) for dimension in dimension_list: # Get dimension ID dim_id = dimension["qInfo"]["qId"] # Get dimension dim_result = self.egda.get_dimension(app_handle=app_handle, dimension_id=dim_id) # Get dimension handle dim_handle = self.get_handle(dim_result) # Get dimension metadata dim_layout = self.egoa.get_layout(dim_handle) # Concatenate the dimension to the DataFrame structure df_dimension_list.loc[len(df_dimension_list)] = dim_layout # Resolve the dictionary structure of attribute "qInfo" df_dimension_list_expanded = (df_dimension_list["qInfo"].dropna().apply(pd.Series).add_prefix("qInfo_")) df_dimension_list = df_dimension_list.drop(columns=["qInfo"]).join(df_dimension_list_expanded) # Resolve the dictionary structure of attribute "qMeta" df_dimension_list_expanded = (df_dimension_list["qMeta"].dropna().apply(pd.Series).add_prefix("qMeta_")) df_dimension_list = df_dimension_list.drop(columns=["qMeta"]).join(df_dimension_list_expanded) # Resolve the dictionary structure of attribute "qDim" df_dimension_list_expanded = (df_dimension_list["qDim"].dropna().apply(pd.Series).add_prefix("qDim_")) df_dimension_list = df_dimension_list.drop(columns=["qDim"]).join(df_dimension_list_expanded) # Resolve the dictionary structure of attribute "qDim_coloring" try: df_dimension_list_expanded = ( df_dimension_list["qDim_coloring"].dropna().apply(pd.Series).add_prefix("qDim_coloring_")) df_dimension_list = df_dimension_list.drop(columns=["qDim_coloring"]).join(df_dimension_list_expanded) except KeyError: df_dimension_list["qDim_coloring"] = None # Resolve the dictionary structure of attribute "qDim_coloring_baseColor" try: df_dimension_list_expanded = ( df_dimension_list["qDim_coloring_baseColor"].dropna().apply(pd.Series).add_prefix("qDim_coloring_baseColor_")) df_dimension_list = df_dimension_list.drop(columns=["qDim_coloring_baseColor"]).join( df_dimension_list_expanded) except KeyError: df_dimension_list["qDim_coloring_baseColor"] = None # Resolve the list structure of attribute df_dimension_list = df_dimension_list.explode(['qDimInfos', 'qDim_qFieldDefs', 'qDim_qFieldLabels']) # Resolve the dictionary structure of attribute "qDimInfos" df_dimension_list_expanded = (df_dimension_list["qDimInfos"].dropna().apply(pd.Series).add_prefix("qDimInfos_")) index = df_dimension_list_expanded.index df_dimension_list_expanded = df_dimension_list_expanded[~index.duplicated(keep="first")] df_dimension_list = df_dimension_list.drop(columns=["qDimInfos"]).join(df_dimension_list_expanded) return df_dimension_list
[docs] def get_app_measures(self, app_handle): """ Retrieves a list with all app measures containing metadata. Parameters: app_handle (int): The handle of the app. Returns: DataFrame: A table with all measures from an app. """ # Define the parameters of the session object nx_info = self.structs.nx_info(obj_type="MeasureList") measure_list_def = self.structs.measure_list_def() gen_obj_props = self.structs.generic_object_properties(info=nx_info, prop_name="qMeasureListDef", prop_def=measure_list_def) # Create session object session = self.eaa.create_session_object(app_handle, gen_obj_props) # Get session handle session_handle = self.get_handle(session) # Get session object data session_layout = self.egoa.get_layout(session_handle) # Get the measure list as Dictionary structure measure_list = session_layout["qMeasureList"]["qItems"] # Define the DataFrame structure df_measure_list = pd.DataFrame(columns=["qInfo", "qMeasure", "qMeta"]) for measure in measure_list: # Get measure ID measure_id = measure["qInfo"]["qId"] # Get measure measure_result = self.egma.get_measure(app_handle=app_handle, measure_id=measure_id) # Get measure handle measure_handle = self.get_handle(measure_result) # Get session object data measure_layout = self.egoa.get_layout(measure_handle) # Concatenate the measure metadata to the DataFrame structure df_measure_list.loc[len(df_measure_list)] = measure_layout # Resolve the dictionary structure of attribute "qInfo" df_measure_list_expanded = (df_measure_list["qInfo"].dropna().apply(pd.Series).add_prefix("qInfo_")) df_measure_list = df_measure_list.drop(columns=["qInfo"]).join(df_measure_list_expanded) # Resolve the dictionary structure of attribute "qMeasure" df_measure_list_expanded = (df_measure_list["qMeasure"].dropna().apply(pd.Series).add_prefix("qMeasure_")) df_measure_list = df_measure_list.drop(columns=["qMeasure"]).join(df_measure_list_expanded) # Resolve the dictionary structure of attribute "qMeta" df_measure_list_expanded = (df_measure_list["qMeta"].apply(pd.Series).add_prefix("qMeta_")) df_measure_list = df_measure_list.drop(columns=["qMeta"]).join(df_measure_list_expanded) # Resolve the dictionary structure of attribute "qMeasure_qNumFormat" df_measure_list_expanded = ( df_measure_list["qMeasure_qNumFormat"].dropna().apply(pd.Series).add_prefix("qMeasure_qNumFormat_")) df_measure_list = df_measure_list.drop(columns=["qMeasure_qNumFormat"]).join(df_measure_list_expanded) # Resolve the dictionary structure of attribute "qMeasure_coloring" try: df_measure_list_expanded = ( df_measure_list["qMeasure_coloring"].dropna().apply(pd.Series).add_prefix("qMeasure_coloring_")) df_measure_list = df_measure_list.drop(columns=["qMeasure_coloring"]).join(df_measure_list_expanded) except KeyError: df_measure_list["qMeasure_coloring"] = None # Resolve the dictionary structure of attribute "qMeasure_coloring_baseColor" try: df_measure_list_expanded = (df_measure_list["qMeasure_coloring_baseColor"].dropna().apply(pd.Series).add_prefix( "qMeasure_coloring_baseColor_")) df_measure_list = df_measure_list.drop(columns=["qMeasure_coloring_baseColor"]).join( df_measure_list_expanded) except KeyError: df_measure_list["qMeasure_coloring_baseColor"] = None return df_measure_list
[docs] def get_app_sheets(self, app_handle): """ Retrieves a list with all app sheets and their content containing metadata. Parameters: app_handle (int): The handle of the app. Returns: DataFrame: A table with all sheets and their content from an app. """ # Define the parameters of the session object nx_info = self.structs.nx_info(obj_type="SheetList") sheet_list_def = self.structs.sheet_list_def() gen_obj_props = self.structs.generic_object_properties(info=nx_info, prop_name="qAppObjectListDef", prop_def=sheet_list_def) # Create session object session = self.eaa.create_session_object(app_handle, gen_obj_props) # Get session handle session_handle = self.get_handle(session) # Get session object data session_layout = self.egoa.get_layout(session_handle) # Get the sheet list as Dictionary structure sheet_list = session_layout["qAppObjectList"]["qItems"] # Define the DataFrame structure df_sheet_list = pd.DataFrame(columns=['qInfo', 'qMeta', 'qSelectionInfo', 'rank', 'thumbnail', 'columns', 'rows', 'cells', 'qChildList', 'gridResolution', 'layoutOptions', 'gridMode', 'customRowBase']) for sheet in sheet_list: # Get sheet ID sheet_id = sheet["qInfo"]["qId"] # Get sheet sheet_result = self.eaa.get_object(app_handle=app_handle, object_id=sheet_id) # Get sheet handle sheet_handle = self.get_handle(sheet_result) # Get session object data sheet_layout = self.egoa.get_layout(sheet_handle) # Concatenate the measure metadata to the DataFrame structure df_sheet_list.loc[len(df_sheet_list)] = sheet_layout # Resolve the dictionary structure of attribute "qInfo" df_sheet_list_expanded = (df_sheet_list["qInfo"].dropna().apply(pd.Series).add_prefix("qInfo_")) df_sheet_list = df_sheet_list.drop(columns=["qInfo"]).join(df_sheet_list_expanded) # Resolve the dictionary structure of attribute "qMeta" df_sheet_list_expanded = (df_sheet_list["qMeta"].dropna().apply(pd.Series).add_prefix("qMeta_")) df_sheet_list = df_sheet_list.drop(columns=["qMeta"]).join(df_sheet_list_expanded) # Resolve the dictionary structure of attribute "qSelectionInfo" df_sheet_list["qSelectionInfo"] = df_sheet_list["qSelectionInfo"].apply( lambda x: None if isinstance(x, dict) and len(x) == 0 else x ) df_sheet_list_expanded = (df_sheet_list["qSelectionInfo"].dropna().apply(pd.Series).add_prefix("qSelectionInfo_")) df_sheet_list = df_sheet_list.drop(columns=["qSelectionInfo"]).join(df_sheet_list_expanded) # Resolve the dictionary structure of attribute "thumbnail" df_sheet_list_expanded = (df_sheet_list["thumbnail"].dropna().apply(pd.Series).add_prefix("thumbnail_")) df_sheet_list = df_sheet_list.drop(columns=["thumbnail"]).join(df_sheet_list_expanded) # Resolve the dictionary structure of attribute "thumbnail_qStaticContentUrl" df_sheet_list["thumbnail_qStaticContentUrl"] = df_sheet_list["thumbnail_qStaticContentUrl"].apply( lambda x: None if isinstance(x, dict) and len(x) == 0 else x ) df_sheet_list_expanded = (df_sheet_list["thumbnail_qStaticContentUrl"].dropna().apply(pd.Series).add_prefix("thumbnail_qStaticContentUrl_")) df_sheet_list = df_sheet_list.drop(columns=["thumbnail_qStaticContentUrl"]).join(df_sheet_list_expanded) # Resolve the dictionary structure of attribute "qChildList" df_sheet_list_expanded = (df_sheet_list["qChildList"].dropna().apply(pd.Series).add_prefix("qChildList_")) df_sheet_list = df_sheet_list.drop(columns=["qChildList"]).join(df_sheet_list_expanded) # Resolve the dictionary structure of attribute "layoutOptions" df_sheet_list_expanded = (df_sheet_list["layoutOptions"].dropna().apply(pd.Series).add_prefix("layoutOptions_")) df_sheet_list = df_sheet_list.drop(columns=["layoutOptions"]).join(df_sheet_list_expanded) # Resolve the list structure of attribute df_sheet_list = df_sheet_list.explode(['cells', 'qChildList_qItems']) # Resolve the dictionary structure of attribute "cells" df_sheet_list_expanded = (df_sheet_list["cells"].dropna().apply(pd.Series).add_prefix("cells_")) index = df_sheet_list_expanded.index df_sheet_list_expanded = df_sheet_list_expanded[~index.duplicated(keep="first")] df_sheet_list = df_sheet_list.drop(columns=["cells"]).join(df_sheet_list_expanded) # Resolve the dictionary structure of attribute "cells_bounds" df_sheet_list_expanded = ( df_sheet_list["cells_bounds"].dropna().apply(pd.Series).add_prefix("cells_bounds_")) index = df_sheet_list_expanded.index df_sheet_list_expanded = df_sheet_list_expanded[~index.duplicated(keep="first")] df_sheet_list = df_sheet_list.drop(columns=["cells_bounds"]).join(df_sheet_list_expanded) # Resolve the dictionary structure of attribute "qChildList_qItems" df_sheet_list_expanded = ( df_sheet_list["qChildList_qItems"].dropna().apply(pd.Series).add_prefix("qChildList_qItems_")) index = df_sheet_list_expanded.index df_sheet_list_expanded = df_sheet_list_expanded[~index.duplicated(keep="first")] df_sheet_list = df_sheet_list.drop(columns=["qChildList_qItems"]).join(df_sheet_list_expanded) # Resolve the dictionary structure of attribute "qChildList_qItems_qInfo" df_sheet_list_expanded = ( df_sheet_list["qChildList_qItems_qInfo"].dropna().apply(pd.Series).add_prefix("qChildList_qItems_qInfo_")) index = df_sheet_list_expanded.index df_sheet_list_expanded = df_sheet_list_expanded[~index.duplicated(keep="first")] df_sheet_list = df_sheet_list.drop(columns=["qChildList_qItems_qInfo"]).join(df_sheet_list_expanded) # Resolve the dictionary structure of attribute "qChildList_qItems_qMeta" df_sheet_list_expanded = ( df_sheet_list["qChildList_qItems_qMeta"].dropna().apply(pd.Series).add_prefix("qChildList_qItems_qMeta_")) index = df_sheet_list_expanded.index df_sheet_list_expanded = df_sheet_list_expanded[~index.duplicated(keep="first")] df_sheet_list = df_sheet_list.drop(columns=["qChildList_qItems_qMeta"]).join(df_sheet_list_expanded) # Resolve the dictionary structure of attribute "qChildList_qItems_qData" df_sheet_list_expanded = ( df_sheet_list["qChildList_qItems_qData"].dropna().apply(pd.Series).add_prefix("qChildList_qItems_qData_")) index = df_sheet_list_expanded.index df_sheet_list_expanded = df_sheet_list_expanded[~index.duplicated(keep="first")] df_sheet_list = df_sheet_list.drop(columns=["qChildList_qItems_qData"]).join(df_sheet_list_expanded) return df_sheet_list
[docs] def get_app_variables(self, app_handle): """ Retrieves a list with all app variables containing metadata. Parameters: app_handle (int): The handle of the app. Returns: DataFrame: A table with all variables from an app. """ # Define the parameters of the session object nx_info = self.structs.nx_info(obj_type="VariableList") variable_list_def = self.structs.variable_list_def() gen_obj_props = self.structs.generic_object_properties(info=nx_info, prop_name="qVariableListDef", prop_def=variable_list_def) # Create session object session = self.eaa.create_session_object(app_handle, gen_obj_props) # Get session handle session_handle = self.get_handle(session) # Get session object data session_layout = self.egoa.get_layout(session_handle) # Get the variable list as Dictionary structure variable_list = session_layout["qVariableList"]["qItems"] # Define the DataFrame structure df_variable_list = pd.DataFrame(columns=["qName", "qDefinition", "qMeta", "qInfo", "qData", "qIsScriptCreated", "qIsReserved"]) for variable in variable_list: # Concatenate the measure metadata to the DataFrame structure df_variable_list.loc[len(df_variable_list)] = variable # Resolve the dictionary structure of attribute "qInfo" df_variable_list_expanded = (df_variable_list["qInfo"].dropna().apply(pd.Series).add_prefix("qInfo_")) df_variable_list = df_variable_list.drop(columns=["qInfo"]).join(df_variable_list_expanded) # Resolve the dictionary structure of attribute "qMeta" df_variable_list_expanded = (df_variable_list["qMeta"].dropna().apply(pd.Series).add_prefix("qMeta_")) df_variable_list = df_variable_list.drop(columns=["qMeta"]).join(df_variable_list_expanded) # Resolve the dictionary structure of attribute "qData" df_variable_list_expanded = (df_variable_list["qData"].dropna().apply(pd.Series).add_prefix("qData_")) df_variable_list = df_variable_list.drop(columns=["qData"]).join(df_variable_list_expanded) return df_variable_list
[docs] def get_app_lineage(self, app_handle): """ Retrieves a list with an app lineage data. Parameters: app_handle (int): The handle of the app. Returns: DataFrame: A table with lineage data from an app. """ # Get lineage data from an app lineage_list = self.eaa.get_lineage(app_handle) # Define the DataFrame structure df_lineage_list = pd.DataFrame(columns=['qDiscriminator', 'qStatement']) for lineage in lineage_list: # Concatenate the lineage row on the DataFrame structure df_lineage_list.loc[len(df_lineage_list)] = lineage return df_lineage_list