def _releaseEngineForThisSession(self, session): _decoded = session # support session store and session obj try: _decoded = session.get_decoded() except Exception as ex: pass if _decoded: # remove session if "data" in _decoded: print(f"Deleting session: {session.session_key}") # parse session out of baseService for don't activate session _data = _decoded["data"] ser = ClientSessionSerializer(data=_data) ser.is_valid(raise_exception=True) cs = ser.save() if cs and cs.modelInfo and cs.modelInfo.engineUID: calcEngine = CalcEngine.factory(cs) calcEngine.releaseEngine() print('Engine released') PyplanLogger().logEndSession(None, ser.create(ser.validated_data)) else: print(f"Session: {session.session_key} without decoded")
def saveModelAs(self, modelName): """Saves Model With New Name""" if self.checkModelOpen(): currentPath = self.client_session.modelInfo.uri folderPath = currentPath[:currentPath.rfind('/') + 1] file_path = f'{folderPath}{modelName}.ppl' storage = FileSystemStorage( os.path.join(settings.MEDIA_ROOT, 'models')) if not storage.exists(file_path): calcEngine = CalcEngine.factory(self.client_session) try: fullPath = f'{storage.base_location}/{file_path}' newModel = calcEngine.saveModel(fullPath) current_session = self.getSession() res = current_session.modelInfo res.uri = file_path self.saveSession() calcEngine = None return res except Exception as ex: raise exceptions.ErrorDetail( f'Error when saving the model: {str(ex)}') raise exceptions.NotAcceptable( "The file name you provide already exists") raise exceptions.NotAcceptable("There's no currentModel")
def logout(self): """Perform logout of the current session """ if self.checkModelOpen(): calcEngine = CalcEngine.factory(self.client_session) calcEngine.releaseEngine() self.removeSession()
def getOrCreate(self, node_id): """ - If the user has a dashboard for this model and node, return it. - Otherwise, create it and return it. """ # Retrieve user dashboards for that node user_company = UserCompany(id=self.client_session.userCompanyId) dashboard = Dashboard.objects.filter( node=node_id, model=self.client_session.modelInfo.modelId, owner=user_company, ) if dashboard: return dashboard[0] else: # Create calcEngine = CalcEngine.factory(self.client_session) node_name = calcEngine.getNodeProperty(node_id, eNodeProperty.TITLE.value) return Dashboard.objects.create( model=self.client_session.modelInfo.modelId, name=node_name, node=node_id, owner=user_company, )
def exportFlatNode(self, exportData): """Export flat node to file""" file_path = join( settings.TMP_ROOT, f'{exportData.nodeId}.{exportData.fileFormat.lower()}') identifier = self.getNodeProperties(exportData.nodeId, [{ "name": "identifier", "value": "" }]) original = identifier['properties'][0]['value'] calcEngine = CalcEngine.factory(self.client_session) response = calcEngine.exportFlatNode(original, exportData.numberFormat, exportData.columnFormat, file_path) if response == 1: if exportData.compressed == "1": temp = tempfile.SpooledTemporaryFile() with zipfile.ZipFile(temp, 'w', zipfile.ZIP_DEFLATED) as zfobj: zfobj.write(file_path) for zfile in zfobj.filelist: zfile.create_system = 0 temp.seek(0) return temp, f'{file_path[file_path.rfind("/")+1:file_path.rfind(".")]}.zip' return open(file_path, 'rb'), file_path[file_path.rfind('/') + 1:] raise exceptions.NotAcceptable("Engine couldn't create file")
def importModuleFromFile(self, importModuleData): """Import module from file""" storage = FileSystemStorage(os.path.join(settings.MEDIA_ROOT, 'models')) currentPath = self.client_session.modelInfo.uri importModuleData.currentModelPath = f'{storage.base_location}/{currentPath}' fullFileName = join(settings.TMP_ROOT, importModuleData.moduleFile) if not importModuleData.fromTemp: fullFileName = f'{storage.base_location}/{importModuleData.moduleFile}' if (importModuleData.importType.name == eImportType(0).name) or (importModuleData.importType.name == eImportType(2).name): calcEngine = CalcEngine.factory(self.client_session) result = calcEngine.importModule(importModuleData.parentModelId, fullFileName, importModuleData.importType.value) if result == 1: importModuleData.importType = importModuleData.importType.value if importModuleData.fromTemp: os.remove(fullFileName) return importModuleData else: raise exceptions.NotAcceptable("Error importing module") else: # TODO: implement eImportType(1).name (APPEND) case raise exceptions.NotAcceptable( "Import Type 'APPEND' not implemented")
def setNodesPosition(self, values): """Set nodes position""" calcEngine = CalcEngine.factory(self.client_session) try: for value in values: # ToDo: return an array of engine responses calcEngine.setNodeProperties(value["id"], [ { "name": "x", "value": value["x"] }, { "name": "y", "value": value["y"] }, { "name": "w", "value": value["w"] }, { "name": "h", "value": value["h"] }, ]) return True except Exception as ex: raise ex
def _executeButtonThread(self, identifier): try: """ Dim thEngineUID As String = args(0) Dim thRestClient As RestApiClient.RestClient = args(1) Dim identifier As String = args(2) Dim token As String = args(3) Dim thCubengineManager As CubengineManager = args(4) Dim nodeJSClient As NodeJsClient = args(5) Dim modelData As Object = args(6) """ self.client_session.modelInfo.nodeIdInBackground = identifier self.saveSession() # TODO: Notify to nodejs that the thread has finished # Dim message As Object = New System.Dynamic.ExpandoObject() calcEngine = CalcEngine.factory(self.client_session) result = calcEngine.executeButton(identifier) #message.error = False #message.result = evalResult print("executeButtonThreadFinished") except Exception as ex: #message.error = True #message.result = "Error execute button " & identifier & ". " & MainLib.Helpers.getFullError(ex) raise exceptions.NotAcceptable( f"Error when performing execute button thread:{str(ex)}") finally: self.client_session.modelInfo.nodeIdInBackground = '' self.saveSession()
def createNewModel(self, modelName): """Creates a new model """ try: storage = FileSystemStorage(join(settings.MEDIA_ROOT, 'models')) folderSufix = 1 new_model_name = modelName while storage.exists(join(storage.base_location, new_model_name)): folderSufix += 1 new_model_name = f'{modelName}_{folderSufix}' folder_path = join(storage.base_location, new_model_name) model_file = join(folder_path, f'{new_model_name}.ppl') if not storage.exists(folder_path): os.mkdir(folder_path) calcEngine = CalcEngine.factory(self.client_session) if calcEngine.createNewModel(model_file, new_model_name): self.closeModel() return self.openModel( join(storage.base_location, new_model_name, f'{new_model_name}.ppl')) except Exception as ex: raise ex
def createNewModel(self, modelName): """Creates a new model """ try: storage = FileSystemStorage( os.path.join(settings.MEDIA_ROOT, 'models')) company_code = self.client_session.company_code user_full_path = f'{storage.base_location}/' folderSufix = 1 new_model_name = modelName while storage.exists(f'{user_full_path}{new_model_name}/'): folderSufix += 1 new_model_name = f'{modelName}_{folderSufix}' folder_path = f'{user_full_path}{new_model_name}/' model_file = f'{folder_path}{new_model_name}.ppl' if not storage.exists(folder_path): os.mkdir(folder_path) calcEngine = CalcEngine.factory(self.client_session) if calcEngine.createNewModel(model_file, new_model_name): self.closeModel() return self.openModel( os.path.join(user_full_path, new_model_name, new_model_name + ".ppl")) except Exception as ex: raise ex
def setNodeProperties(self, node_id, properties): """Set Node Properties""" # map same properties if node_id and len(properties) > 0: for prop in properties: if prop["name"] and prop["name"].lower() == "picture": if not prop["value"]: prop["value"] = None else: file_extension = prop["value"].rsplit(".").pop() file_path = join(settings.TMP_ROOT, prop["value"]) with open(file_path, "rb") as image_file: prop[ "value"] = f'data:image/{file_extension};base64,{str(base64.b64encode(image_file.read()), "utf-8")}' try: os.remove(file_path) except Exception as ex: raise exceptions.NotAcceptable( f'There was an error deleting the tempfile:{str(ex)}' ) calcEngine = CalcEngine.factory(self.client_session) result = calcEngine.setNodeProperties(node_id, properties) return result
def searchNodes(self, text, module_id, node_class, extra_classes, fill_detail): """Search Nodes""" calcEngine = CalcEngine.factory(self.client_session) result = calcEngine.searchNodes(text, module_id, node_class, extra_classes, fill_detail) return result
def isResultComputed(self, nodes): calcEngine = CalcEngine.factory(self.client_session) is_result = calcEngine.isResultComputed(nodes) res = [] if len(is_result) == len(nodes): for nn, node in enumerate(nodes): if not is_result[nn]: res.append(node) return res
def navigateDiagram(self, module_id, include_arrows): """Navigate Diagram""" calcEngine = CalcEngine.factory(self.client_session) res = None if module_id: res = calcEngine.getDiagram(module_id) else: res = calcEngine.getDiagram() return res
def getModelPreferences(self): """Get Model Preferences""" calcEngine = CalcEngine.factory(self.client_session) engineResponse = calcEngine.getModelPreferences() # fill default preferences engineResponse["modelId"] = engineResponse["identifier"] if not "changeIdentifier" in engineResponse: engineResponse["changeIdentifier"] = "1" return engineResponse
def evaluateNode(self, nodeQuery): calcEngine = CalcEngine.factory(self.client_session) return self._evaluateNode(nodeQuery.node, nodeQuery.dims, nodeQuery.rows, nodeQuery.columns, nodeQuery.summaryBy, nodeQuery.fromRow, nodeQuery.toRow, nodeQuery.bottomTotal, nodeQuery.rightTotal, nodeQuery.timeFormat, nodeQuery.timeFormatType, nodeQuery.calendarType, nodeQuery.resultType)
def installLibrary(self, lib): """Install python library""" calcEngine = CalcEngine.factory(self.client_session) pos = self.client_session.modelInfo.uri.find( "/", self.client_session.modelInfo.uri.find("/", 1) + 1) current_path = self.client_session.modelInfo.uri[:pos] target_path = os.path.join(settings.MEDIA_ROOT, 'models', current_path) result = calcEngine.installLibrary(lib, target_path) return result
def closeModel(self): """Close current model""" if self.checkModelOpen(): calcEngine = CalcEngine.factory(self.client_session) if calcEngine.closeModel(): current_session = self.getSession() current_session.modelInfo = ModelInfo() self.saveSession() else: return False return True
def setModelPreferences(self, modelPreferences): """Set model preferences""" calcEngine = CalcEngine.factory(self.client_session) result = calcEngine.setModelProperties(modelPreferences) if result.text == 'ok': model_pref = ModelPreference(**modelPreferences) if model_pref.identifier or model_pref.title: self.client_session.modelInfo.modelId = model_pref.identifier self.client_session.modelInfo.name = model_pref.title self.saveSession() return self.client_session return False
def getNodeIndexes(self, node, include_values=False): calcEngine = CalcEngine.factory(self.client_session) node_indexes = calcEngine.getNodeIndexes(node) result = [] for index_item in node_indexes: serializer = NodeDimensionSerializer(index_item) node_dimension = serializer.create(serializer.data) if include_values: node_dimension.values = self.getIndexValues( {'id': node_dimension.field})['results'] result.append(node_dimension) return result
def getCubeMetadata(self, query): calcEngine = CalcEngine.factory(self.client_session) result = calcEngine.getCubeMetadata(PivotQuerySerializer(query).data) original = calcEngine.getNodeProperty(query.cube, eNodeProperty.IDENTIFIER.value) # if not res is None and not res.nodeProperties is None: # Dim srvWiki As New KnowledgeBaseService(token) # res.nodeProperties.hasDescription = srvWiki.hasDescription(original) # Dim srvWorkflow As New Workflow(token) # res.nodeProperties.hasWorkflowTask = srvWorkflow.hasTask(original) return result
def getArrows(self, module_id): """Get Diagram Arrows""" calcEngine = CalcEngine.factory(self.client_session) if not module_id: current_session = self.getSession() module_id = current_session.modelInfo.modelId return { "arrows": calcEngine.getArrows(module_id), "module_id": module_id }
def getIndexValues(self, data): calcEngine = CalcEngine.factory(self.client_session) index_type = calcEngine.getIndexType(data['id']) response = calcEngine.getIndexValues(data) newResponse = {} index_values = [] if response: for index_value in response: index_values.append( NodeDimensionValue(type=index_type, value=index_value)) newResponse['results'] = index_values return newResponse
def getCubeValues(self, pivotQuery: PivotQuery): calcEngine = CalcEngine.factory(self.client_session) denied_modules = [] if not self.current_user.has_perm('pyplan.change_group_permissions'): denied_modules = self._getDeniedModules() if denied_modules and (pivotQuery.cube in denied_modules or calcEngine.isChild(pivotQuery.cube, denied_modules)): raise exceptions.NotAcceptable( 'Your department does not have access to this module.') return calcEngine.getCubeValues(PivotQuerySerializer(pivotQuery).data)
def executeForRefresh(self): """Executes a node from the refresh button""" value = random.randint(1, 10000000) calcEngine = CalcEngine.factory(self.client_session) calcEngine.setNodeProperties("pyplan_refresh", [{ "name": "definition", "value": "result = " + str(value) }]) return calcEngine.setNodeProperties( "cub_refresh", [{ "name": "definition", "value": "result = " + str(value) }])
def exportModuleToFile(self, exportData): """Export module to file""" calcEngine = CalcEngine.factory(self.client_session) file_path = join(settings.TMP_ROOT, f'{exportData.moduleId}.ppl') if exportData.exportType != "1": storage = FileSystemStorage( os.path.join(settings.MEDIA_ROOT, 'models')) currentPath = self.client_session.modelInfo.uri folderPath = currentPath[:currentPath.rfind('/') + 1] file_path = f'{storage.base_location}/{folderPath}{exportData.moduleId}.ppl' response = calcEngine.exportModule(exportData.moduleId, file_path) if response == 1: return open(file_path, 'rb'), file_path[file_path.rfind('/') + 1:] else: raise exceptions.NotAcceptable("Engine couldn't create file")
def evaluateNode(self, nodeQuery): calcEngine = CalcEngine.factory(self.client_session) denied_modules = [] if not self.current_user.has_perm('pyplan.change_group_permissions'): denied_modules = self._getDeniedModules() if denied_modules and (nodeQuery.node in denied_modules or calcEngine.isChild(nodeQuery.node, denied_modules)): raise exceptions.NotAcceptable( 'Your department does not have access to this module.') return self._evaluateNode( nodeQuery.node, nodeQuery.dims, nodeQuery.rows, nodeQuery.columns, nodeQuery.summaryBy, nodeQuery.fromRow, nodeQuery.toRow, nodeQuery.bottomTotal, nodeQuery.rightTotal, nodeQuery.timeFormat, nodeQuery.timeFormatType, nodeQuery.calendarType)
def _executeButtonThread(self, identifier): try: """ Dim thEngineUID As String = args(0) Dim thRestClient As RestApiClient.RestClient = args(1) Dim identifier As String = args(2) Dim token As String = args(3) Dim thCubengineManager As CubengineManager = args(4) Dim nodeJSClient As NodeJsClient = args(5) Dim modelData As Object = args(6) """ self.client_session.modelInfo.nodeIdInBackground = identifier self.saveSession() # TODO: Notify to nodejs that the thread has finished # Dim message As Object = New System.Dynamic.ExpandoObject() calcEngine = CalcEngine.factory(self.client_session) result = calcEngine.executeButton(identifier) #message.error = False #message.result = evalResult # Notify to WebSocket channel that the thread has finished sysMsg(self.client_session.session_key, ws_settings.MSG_TYPE_MESSAGE, ws_settings.NOTIFICATION_LEVEL_SUCCESS, content={ 'title': 'Finished processing.', 'message': f'ID: {identifier}', }) except Exception as ex: error_msg = f'Error when performing execute button thread: {str(ex)}' # Notify to WebSocket channel that the thread has finished with error sysMsg(self.client_session.session_key, ws_settings.MSG_TYPE_MESSAGE, ws_settings.NOTIFICATION_LEVEL_ERROR, content={ 'title': 'Finished processing with errors', 'message': error_msg, }) raise exceptions.NotAcceptable(error_msg) finally: self.client_session.modelInfo.nodeIdInBackground = '' self.saveSession()
def create(self, data): """ Creates DiagramShortcut using model and usercompany_id from client_session """ calcEngine = CalcEngine.factory(self.client_session) usercompany_id = self.client_session.userCompanyId model = self.client_session.modelInfo.modelId name = data['node_id'] if calcEngine.existNode(data['node_id']): node_title = calcEngine.getNodeProperty(data['node_id'], eNodeProperty.TITLE.value) if node_title: name = node_title return DiagramShortcut.objects.create( model=model, usercompany_id=usercompany_id, node_id=data['node_id'], name=name, )
def _openModel(self, file, reuse_instance=False): """ Opens model and sets modelInfo of current_session """ res = ModelInfo() calcEngine = CalcEngine.tryLoadFromAppPool(self.client_session, file) res.name = calcEngine.getModelName() res.uri = file res.daysToExpire = 30 res.modelId = calcEngine.getModelId() res.engineUID = calcEngine.getEngineUID() res.engineURI = calcEngine.getEngineURI() res.engineParams = calcEngine.getEngineParams() res.readonly = True current_session = self.getSession() current_session.modelInfo = res self.saveSession() return res