See More

/* * Project Name : Visual Python * Description : GUI-based Python code generator * File Name : com_Kernel.js * Author : Black Logic * Note : Interface between vp and jupyter * License : GNU GPLv3 with Visual Python special exception * Date : 2021. 09. 16 * Change Date : */ //============================================================================ // [CLASS] Kernel //============================================================================ define([ './com_util', './com_String' ], function(com_util, com_String) { /** * Kernel interface class */ class Kernel { /** constructor */ constructor(app=null) { this.app = app; // LAB: app needed for kernel this.data = [ { varName: 'df1', varType: 'DataFrame' }, { varName: 'df2', varType: 'DataFrame' }, { varName: 'df3', varType: 'DataFrame' }, { varName: 's1', varType: 'Series' }, { varName: 's2', varType: 'Series' }, { varName: 's3', varType: 'Series' }, { varName: 'l1', varType: 'List' }, { varName: 'l2', varType: 'List' }, { varName: 'l3', varType: 'List' } ] this.config = { 'vpcfg': { }, 'vpudf': { }, 'vpimport': { }, 'vppackman': { } } } getNotebookPath() { if (vpConfig.extensionType === 'notebook') { return Jupyter.notebook.notebook_path; } else if (vpConfig.extensionType === 'colab') { return colab.global.notebookModel.metadata.colab.name; } return ''; } //==================================================================== // Executing command api //==================================================================== execute(command, isSilent = false) { let that = this; return new Promise(function(resolve, reject) { if (vpConfig.extensionType === 'notebook') { Jupyter.notebook.kernel.execute( command, { iopub: { output: function (msg) { var result = ''; var type = ''; if (msg.msg_type == 'error') { reject({result: msg.content, type: 'error', msg: msg}); } else { if (msg.content) { try { if (msg.content['name'] == 'stderr') { reject(msg); } else { if (msg.content.data) { if (msg.content.data['text/html']) { result = String(msg.content.data['text/html']); type = 'text/html'; } else if (msg.content.data['image/png']) { result = String(msg.content.data['image/png']); type = 'image/png'; } else if (msg.content.data['text/plain']) { result = String(msg.content.data['text/plain']); type = 'text/plain'; } } else if (msg.content['text']) { result = String(msg.content['text']); type = 'text'; } resolve({result: result, type: type, msg: msg}); } } catch(ex) { reject(ex); } } else { resolve({result: result, type: type, msg: msg}); } } } } }, { silent: isSilent } ); } else if (vpConfig.extensionType === 'colab') { // CHROME: TODO: 3: return background execution if (isSilent) { if (!colab.global.notebook.kernel.isConnected()) { reject({status: 'error', ename: 'Kernel Error', evalue: 'Kernel is not connected...'}); return; } if (!colab.global.notebook.kernel.isRunning()) { reject({status: 'error', ename: 'Kernel Error', evalue: 'Kernel is not running...'}); return; } colab.global.notebook.kernel.execute(command).then(function(msg) { if (msg.status === 'ok') { resolve(true); } else { reject(msg); } }).catch(function(msg) { reject(msg); }); return; } // get focused index let lastFocusedCellId = ''; let lastFocusedCellIdx = 0; try { // get focused cell id lastFocusedCellId = colab.global.notebook.focusedCell? colab.global.notebook.focusedCell.getId() : null; // get focused cell index lastFocusedCellIdx = colab.global.notebook.cells.findIndex(cell => cell.getId() === lastFocusedCellId); } catch (err) { vpLog.display(VP_LOG_TYPE.ERROR, err); } // create cell to execute colab.global.notebook.insertCell('code', {after:true, index:lastFocusedCellIdx}); // get cell let cell = colab.global.notebook.focusedCell; // hide cell using class // cell.element_.style.display = "none"; $(cell.element_).addClass('vp-background-cell'); // set cell command cell.setText(command); // add execution complete listener cell.model.listenOnce('execution_completed', function() { let result = ''; let type = ''; let msg = { content: { name: type } }; let cellJson = cell.model.toJson(); if (cellJson.outputs.length > 0) { // {output_type: 'stream', name: 'stdout', text: Array(1)} /** * { * output_type: stream/execute_result/display_data/error * name: stdout, * // if output_type==stream * text: [ ... ] * // if output_type==execute_result/display_data * data: { * 'image/png': '...' * 'text/html': '...' * 'text/plain': '...' * } * // if output_type==error * ename: 'NameError/...' * evalue: 'ignored/...' * } */ cellJson.outputs.forEach(output => { vpLog.display(VP_LOG_TYPE.DEVELOP, 'kernel output', cellJson.outputs); try { if (output.output_type === 'error') { // convert traceback as evalue let simpleEvalue = ''; let convertedEvalue = ''; if (output.traceback.length > 0) { let traceback = output.traceback.join('\n'); convertedEvalue = traceback.replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, ''); simpleEvalue = output.traceback[output.traceback.length - 1].replace(/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, ''); } reject({result: output, type: 'error', msg: { content: { ename: output.ename, evalue: simpleEvalue, detail: convertedEvalue } }}); } else { if (output.output_type === 'stream') { result = String(output.text.join('\n')); type = 'text'; msg = { content: { name: type, [type]: result } }; } else if (output.output_type === 'execute_result' || output.output_type === 'display_data') { if (output.data['image/png']) { result = String(output.data['image/png']); type = 'image/png'; } else if (output.data['text/html']) { result = String(output.data['text/html'].join('')); type = 'text/html'; } else if (output.data['text/plain']) { result = String(output.data['text/plain'].join('')); type = 'text/plain'; } msg = { content: { name: type, data: { [type]: result } } }; } resolve({result: result, type: type, msg: msg}); } } catch(ex) { reject(ex); } }); } // delete cell colab.global.notebook.notebookModel.deleteCells([cell.model]); // set last focused cell // colab.global.notebook.focusCell(lastFocusedCellId); }) // run cell cell.runButton.click(); // set last focused cell colab.global.notebook.focusCell(lastFocusedCellId); } else if (vpConfig.extensionType === 'lab' || vpConfig.extensionType === 'lite') { // LAB: // { code, stdin, stop_on_error, silent, ... } var codeObj = { code: command, silent: isSilent, stop_on_error: true } var kernelConnection = that.getLabKernel(); if (kernelConnection) { var onIOPub = function(msg) { const msgType = msg.header.msg_type; switch(msgType) { case 'status': return; case 'execute_input': return; case 'stream': var content = msg.content; var type = content.name; switch(type){ case 'stdout': var message = content.text; resolve({ result: message, type: 'text', msg: { content: { name: 'text', data: { 'text': message } } } }); break; case 'stderr': var message = content.text; reject({status: 'stderr', ename: 'stderr', evalue: message}); break; default: var message = '[jupyterLabTerminal]: Unknown stream type ' + type; reject({status: 'error', ename: 'Unknown stream type', evalue: message}); } break; case 'error': // check if it has a problem on restarting vp inner function // ex) "name '_vp_print' is not defined" if (msg.content.ename === 'NameError' && msg.content.evalue.includes('_vp_') && msg.content.evalue.includes('is not defined')) { // restart vp vpConfig.readKernelFunction().then(function() { // re-try executing code vpLog.display(VP_LOG_TYPE.LOG, 'Re-try executing code after restarting vp...'); var future2 = kernelConnection.requestExecute(codeObj); future2.onIOPub = onIOPub; }).catch(function(err) { reject({status: 'error', ename: msg.content.ename, evalue: msg.content.evalue}); }); } else { reject({status: 'error', ename: msg.content.ename, evalue: msg.content.evalue}); } break; case 'execute_result': var type = 'text'; if (msg.content) { try { if (msg.content['text']) { result = String(msg.content['text']); type = 'text'; } else if (msg.content.data) { if (msg.content.data['image/png']) { result = String(msg.content.data['image/png']); type = 'image/png'; } else if (msg.content.data['text/html']) { result = String(msg.content.data['text/html']); type = 'text/html'; } else if (msg.content.data['text/plain']) { result = String(msg.content.data['text/plain']); type = 'text/plain'; } } resolve({result: result, type: type, msg: msg}); } catch(ex) { reject(ex); } } else { resolve({result: result, type: type, msg: msg}); } break; case 'display_data': var type = 'text'; if (msg.content) { try { if (msg.content['text']) { result = String(msg.content['text']); type = 'text'; } else if (msg.content.data) { if (msg.content.data['image/png']) { result = String(msg.content.data['image/png']); type = 'image/png'; } else if (msg.content.data['text/html']) { result = String(msg.content.data['text/html']); type = 'text/html'; } else if (msg.content.data['text/plain']) { result = String(msg.content.data['text/plain']); type = 'text/plain'; } } resolve({result: result, type: type, msg: msg}); } catch(ex) { reject(ex); } } else { resolve({result: result, type: type, msg: msg}); } break; case 'update_display_data': var result = msg.content; resolve({ result: result, type: msgType, msg: { content: { name: msgType, data: { [msgType]: result } } } }); break; default: var message = '[jupyterLabTerminal]: Unknown message type ' + msgType; reject({status: 'error', ename: 'Unknown message type', evalue: message}); }; return; } var future; if (vpConfig.isReady === false) { vpConfig.isReady = true; vpConfig.hideProtector(); vpConfig.readKernelFunction().then(function() { future = kernelConnection.requestExecute(codeObj); future.onIOPub = onIOPub; }); } else { future = kernelConnection.requestExecute(codeObj); future.onIOPub = onIOPub; } } } }); } /** * LAB: get lab notebook panel */ getLabKernel(){ var notebookPanel = this.getLabNotebookPanel(); if (notebookPanel) { var kernelConnection = notebookPanel.sessionContext.session?.kernel; return kernelConnection; } return null; } async executeLabCell(pythonCode, cellType='code'){ var { NotebookActions } = require('@jupyterlab/notebook'); var notebookPanel = this.getLabNotebookPanel(); return new Promise(async (resolve, reject) => { if (notebookPanel){ var notebook = notebookPanel.content; var notebookModel = notebook.model; var sessionContext = notebookPanel.sessionContext; var options = { }; var cellModel = notebookModel.contentFactory.createCell(cellType, options); cellModel.value.text = pythonCode; const activeCellIndexBackup = notebook.activeCellIndex; // 셀 추가 notebookModel.cells.insert(activeCellIndexBackup + 1, cellModel); notebook.activeCellIndex = newCellIndex; var cell = notebook.activeCell; try{ await NotebookActions.run(notebook, sessionContext) .catch(error=>{ reject(error); }); } catch(error){ reject(error); } var htmlArray = []; for(var output of cell.outputArea.node.children){ htmlArray.push(output.innerHTML); } // 셀 삭제 // await NotebookActions.deleteCells(notebook); // notebook.activeCellIndex = activeCellIndexBackup; resolve(htmlArray); } }); } createLabCell(code, type='code') { var { CellModel, CodeCellModel, MarkdownCellModel } = require('@jupyterlab/cells'); return new CellModel({ cell_type: 'code', source: "print('hi')", metadata: { trusted: false } }) } /** * LAB: get lab notebook panel */ getLabNotebookPanel(){ var mainWidgets = this.app.shell.widgets('main'); var widget = mainWidgets.next(); while (widget) { if (widget.sessionContext) { var type = widget.sessionContext.type; if(type == 'notebook' || type == 'console'){ //other wigets might be of type DocumentWidget if (widget.isVisible){ return widget; } } } else if (widget.value !== undefined && widget.done === false) { // for upper lab 4 let widgetObj = widget.value; if (widgetObj.sessionContext) { var type = widgetObj.sessionContext.type; if(type == 'notebook' || type == 'console'){ //other wigets might be of type DocumentWidget if (widgetObj.isVisible){ return widgetObj; } } } } else if (widget.done === true) { break; } widget = mainWidgets.next(); } return null; } get labWidgets() { let mainWidgets = this.app.shell.widgets('main'); let widget = mainWidgets.next(); let widgetList = []; while (widget) { if (widget.sessionContext) { widgetList.push(widget); } else if (widget.value !== undefined && widget.done === false) { // for upper lab 4 let widgetObj = widget.value; if (widgetObj.sessionContext) { widgetList.push(widgetObj); } } else if (widget.done === true) { break; } widget = mainWidgets.next(); } return widgetList; } getLabPanelId() { let currentPanel = vpKernel.getLabNotebookPanel(); if (currentPanel) { return currentPanel.id; } return undefined; } /** * Check if module/function is loaded already * @param {*} moduleList */ checkModule(moduleList) { var that = this; return new Promise(function(resolve, reject) { that.execute(com_util.formatString('_vp_print(_vp_check_module_loaded({0}))', JSON.stringify(moduleList))).then(function(resultObj) { // resolve resolve(resultObj); }).catch(function(err) { // reject reject(err); }) }); } getDataList(dataTypeList=[], excludeList=[], allowModule=false) { // use function command to get variable list of selected data types var cmdSB = '_vp_print(_vp_get_variables_list(None))'; if (!dataTypeList || dataTypeList.length <= 0) { dataTypeList = []; } cmdSB = com_util.formatString('_vp_print(_vp_get_variables_list({0}, {1}, {2}))', JSON.stringify(dataTypeList), JSON.stringify(excludeList), allowModule?'True':'False'); var that = this; return new Promise(function(resolve, reject) { that.execute(cmdSB.toString()).then(function(resultObj) { // resolve resolve(resultObj); }).catch(function(err) { // reject reject(err); }) }) } getColumnList(dataframe) { var that = this; return new Promise(function(resolve, reject) { that.execute(com_util.formatString('_vp_print(_vp_get_columns_list({0}))', dataframe)) .then(function(resultObj) { resolve(resultObj); }).catch(function(err) { // reject reject(err); }) }); } getCommonColumnList(dataframeList) { var that = this; return new Promise(function(resolve, reject) { that.execute(com_util.formatString('_vp_print(_vp_get_multi_columns_list([{0}]))', dataframeList.join(','))) .then(function(resultObj) { resolve(resultObj); }).catch(function(err) { // reject reject(err); }) }); } getColumnCategory(dataframe, columnName) { var that = this; return new Promise(function(resolve, reject) { that.execute(com_util.formatString('_vp_print(_vp_get_column_category({0}, {1}))', dataframe, columnName)) .then(function(resultObj) { resolve(resultObj); }).catch(function(err) { // reject reject(err); }) }); } /** * Get rows list * @param {*} dataframe * @returns */ getRowList(dataframe) { var that = this; return new Promise(function(resolve, reject) { that.execute(com_util.formatString('_vp_print(_vp_get_rows_list({0}))', dataframe)) .then(function(resultObj) { resolve(resultObj); }).catch(function(err) { // reject reject(err); }) }); } getSweetvizList() { var that = this; return new Promise(function(resolve, reject) { that.execute('_vp_print(_vp_get_sweetviz_list())') .then(function(resultObj) { resolve(resultObj); }).catch(function(err) { // reject reject(err); }) }); } getProfilingList() { var that = this; return new Promise(function(resolve, reject) { that.execute('_vp_print(_vp_get_profiling_list())') .then(function(resultObj) { resolve(resultObj); }).catch(function(err) { // reject reject(err); }) }); } //==================================================================== // FileNavigation //==================================================================== getCurrentDirectory() { var that = this; return new Promise(function(resolve, reject) { that.execute('%pwd') .then(function(resultObj) { resolve(resultObj.result); }).catch(function(err) { // reject reject(err); }) }); } getFileList(path, useFunction=false) { var that = this; if (path === '') { path = '.'; } if (!useFunction) { path = "'" + path + "'"; } var cmd = com_util.formatString('_vp_print(_vp_search_path({0}))', path); return new Promise(function(resolve, reject) { that.execute(cmd) .then(function(resultObj) { resolve(resultObj.result); }).catch(function(err) { // reject reject(err); }) }); } /** * Get if colab mounted (If mounted, create .visualpython directory) * - '/content/drive/MyDrive/.visualpython' * @returns Promise(resolve(true/false), reject(err)) */ getColabMounted() { var that = this; return new Promise(function(resolve, reject) { that.execute('_vp_get_colab_mounted()') .then(function(resultObj) { resolve(resultObj.result); }).catch(function(err) { // reject reject(err); }) }); } /** * Get colab's vp config file content * @param {String} configType vpudf, vpcfg * @returns */ getColabConfig(configType='vpudf') { var that = this; var configFile = ''; switch (configType) { case 'vpudf': configFile = 'snippets'; break; case 'vpcfg': configFile = 'configure'; break; case 'vpimport': configFile = 'import'; break; case 'vppackman': configFile = 'packman'; break; } var cmd = com_util.formatString("print(_vp_get_colab_vpcfg('{0}'))", configFile); return new Promise(function(resolve, reject) { that.execute(cmd) .then(function(resultObj) { resolve(resultObj); }).catch(function(err) { // reject reject(err); }) }); } /** * Set colab's vp config file content * @param {String} content file content to write * @param {String} configType vpudf, vpcfg * @returns */ setColabConfig(content, configType='vpudf') { var that = this; var configFile = ''; switch (configType) { case 'vpudf': configFile = 'snippets'; break; case 'vpcfg': configFile = 'configure'; break; case 'vpimport': configFile = 'import'; break; case 'vppackman': configFile = 'packman'; break; } // write file var sbfileSaveCmd = new com_String(); sbfileSaveCmd.appendFormatLine('%%writefile "/content/drive/MyDrive/.visualpython/{0}"', configFile); sbfileSaveCmd.appendLine(content); return new Promise(function(resolve, reject) { that.execute(sbfileSaveCmd.toString()) .then(function(resultObj) { resolve(resultObj.result); }).catch(function(err) { // reject reject(err); }) }); } /** * Get jupyterlab's vp config file content * @param {String} configType vpudf, vpcfg * @returns */ getLabConfig(configType='vpudf') { var that = this; var configFile = ''; switch (configType) { case 'vpudf': configFile = 'snippets'; break; case 'vpcfg': configFile = 'configure'; break; case 'vpimport': configFile = 'import'; break; case 'vppackman': configFile = 'packman'; break; } var cmd = com_util.formatString("print(_vp_get_lab_vpcfg('{0}'))", configFile); return new Promise(function(resolve, reject) { that.execute(cmd) .then(function(resultObj) { resolve(resultObj); }).catch(function(err) { // reject reject(err); }) }); } /** * Set jupyterlab's vp config file content * @param {String} content file content to write * @param {String} configType vpudf, vpcfg * @returns */ setLabConfig(content={}, configType='vpudf') { var that = this; var configFile = ''; switch (configType) { case 'vpudf': configFile = 'snippets'; break; case 'vpcfg': configFile = 'configure'; break; case 'vpimport': configFile = 'import'; break; case 'vppackman': configFile = 'packman'; break; } // write file var sbfileSaveCmd = new com_String(); sbfileSaveCmd.appendFormat("_vp_set_lab_vpcfg('{0}', {1})", configFile, content); return new Promise(function(resolve, reject) { that.execute(sbfileSaveCmd.toString()) .then(function(resultObj) { resolve(resultObj.result); }).catch(function(err) { // reject reject(err); }) }); } //==================================================================== // Image data //==================================================================== getImageFile(path) { var that = this; let code = com_util.formatString("_vp_get_image_by_path('{0}')", path); return new Promise(function(resolve, reject) { that.execute(code) .then(function(resultObj) { resolve(resultObj); }).catch(function(err) { // reject reject(err); }) }); } //==================================================================== // Read File //==================================================================== readFile(filePath) { let that = this; let code = com_util.formatString("print(_vp_read_file('{0}'))", filePath); return new Promise(function(resolve, reject) { that.execute(code) .then(function(resultObj) { resolve(resultObj); }).catch(function(err) { // reject reject(err); }) }); } //==================================================================== // Write File //==================================================================== saveFile(fileName, filePath, saveData) { let that = this; fetch(filePath).then(function(data) { // overwrite confirmation if (data.status == 200) { if (!confirm(com_util.formatString("{0} already exists.\nDo you want to replace it?", fileName))) { return false; } } // write file var sbfileSaveCmd = new com_String(); sbfileSaveCmd.appendFormatLine('%%writefile "{0}"', filePath); sbfileSaveCmd.appendLine(saveData); that.execute(sbfileSaveCmd.toString()).then(function(resultObj) { com_util.renderSuccessMessage('Successfully saved file. (' + fileName + ')'); }).catch(function(err) { com_util.renderAlertModal("Couldn't save file. "+err.message); vpLog.display(VP_LOG_TYPE.ERROR, err); }); }); } //==================================================================== // Machine Learning //==================================================================== getModelList(modelCategory='') { // use function command to get variable list of selected data types var cmdSB = `_vp_print(_vp_get_variables_list(${JSON.stringify(vpConfig.getMLDataTypes())}))`; if (modelCategory != '') { cmdSB = `_vp_print(_vp_get_variables_list(${JSON.stringify(vpConfig.getMLDataDict(modelCategory))}))`; } var that = this; return new Promise(function(resolve, reject) { that.execute(cmdSB).then(function(resultObj) { // resolve resolve(resultObj); }).catch(function(err) { // reject reject(err); }) }) } //==================================================================== // Package Manager //==================================================================== getPackageList(packList=[]) { var that = this; let code = com_util.formatString("_vp_print(_vp_check_package_list({0}))", JSON.stringify(packList)); return new Promise(function(resolve, reject) { that.execute(code).then(function(resultObj) { // resolve resolve(resultObj); }).catch(function(err) { // reject reject(err); }) }); } //==================================================================== // Configuration api //==================================================================== loadConfig() { } getConfig() { } setConfig() { } } return Kernel; });