diff --git a/build.sh b/build.sh index a57eb271..906b2c0c 100755 --- a/build.sh +++ b/build.sh @@ -11,8 +11,8 @@ #============================================================================= # Set version and replace it #============================================================================= -VP_ORG_VER=2.4.5 -VP_NEW_VER=2.4.6 +VP_ORG_VER=2.4.6 +VP_NEW_VER=2.4.7 # update version info grep -REil "VP_ORG_VER=.+$" colab/build.colab.sh jupyterlab/build.jupyterlab.sh jupyternotebook/build.jupyternotebook.sh | xargs sed -i "s/VP_ORG_VER=.\+$/VP_ORG_VER=${VP_ORG_VER}/g" diff --git a/colab/build.colab.sh b/colab/build.colab.sh index e95c57cc..014dfeb6 100755 --- a/colab/build.colab.sh +++ b/colab/build.colab.sh @@ -11,8 +11,8 @@ #============================================================================= # Replace Version #============================================================================= -VP_ORG_VER=2.4.5 -VP_NEW_VER=2.4.6 +VP_ORG_VER=2.4.6 +VP_NEW_VER=2.4.7 # update version info # update manifest version with new numbering for new version diff --git a/colab/manifest.json b/colab/manifest.json index f17632c1..007cc77c 100644 --- a/colab/manifest.json +++ b/colab/manifest.json @@ -1,7 +1,7 @@ { "name": "Visual Python for Colab", "description": "GUI-based Python code generator for Google Colab as an extension", - "version": "2.4.6", + "version": "2.4.7", "manifest_version": 3, "icons": { "48": "icon.png", diff --git a/jupyterlab/build.jupyterlab.sh b/jupyterlab/build.jupyterlab.sh index 8a010b9b..dcfee5a2 100755 --- a/jupyterlab/build.jupyterlab.sh +++ b/jupyterlab/build.jupyterlab.sh @@ -11,8 +11,8 @@ #============================================================================= # Replace Version and Basic Files #============================================================================= -VP_ORG_VER=2.4.5 -VP_NEW_VER=2.4.6 +VP_ORG_VER=2.4.6 +VP_NEW_VER=2.4.7 # update version info grep -REil "\"version\": \"${VP_ORG_VER}\"" package.json | xargs sed -i "s/\"version\": \"${VP_ORG_VER//\./\\.}\"/\"version\": \"${VP_NEW_VER}\"/g" diff --git a/jupyterlab/package-lock.json b/jupyterlab/package-lock.json index 5bd56c66..7472a84d 100644 --- a/jupyterlab/package-lock.json +++ b/jupyterlab/package-lock.json @@ -1,12 +1,12 @@ { "name": "jupyterlab-visualpython", - "version": "2.4.5", + "version": "2.4.6", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "jupyterlab-visualpython", - "version": "2.4.5", + "version": "2.4.6", "license": "GPLv3 with Visual Python special exception", "dependencies": { "@jupyterlab/cells": "^3.5.2", diff --git a/jupyterlab/package.json b/jupyterlab/package.json index d99e9f8e..da347cc1 100644 --- a/jupyterlab/package.json +++ b/jupyterlab/package.json @@ -1,6 +1,6 @@ { "name": "jupyterlab-visualpython", - "version": "2.4.6", + "version": "2.4.7", "description": "GUI-based Python code generator for Jupyter Lab as an extension", "keywords": [ "jupyter", diff --git a/jupyterlab/pyproject.toml b/jupyterlab/pyproject.toml index 65f53c95..c32f299d 100644 --- a/jupyterlab/pyproject.toml +++ b/jupyterlab/pyproject.toml @@ -32,7 +32,7 @@ classifiers = [ "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", ] -version = "2.4.6" +version = "2.4.7" [project.license] file = "LICENSE" @@ -92,7 +92,7 @@ file = [ ] [tool.tbump.version] -current = "2.4.6" +current = "2.4.7" regex = "(?P\\d+)\\.(?P\\d+)\\.(?P\\d+)((?Pa|b|rc|.dev)(?P\\d+))?" [tool.tbump.git] diff --git a/jupyternotebook/build.jupyternotebook.sh b/jupyternotebook/build.jupyternotebook.sh index c67b8f37..c56d37e7 100755 --- a/jupyternotebook/build.jupyternotebook.sh +++ b/jupyternotebook/build.jupyternotebook.sh @@ -11,8 +11,8 @@ #============================================================================= # Replace Version and Basic Files #============================================================================= -VP_ORG_VER=2.4.5 -VP_NEW_VER=2.4.6 +VP_ORG_VER=2.4.6 +VP_NEW_VER=2.4.7 # update version info grep -REil ${VP_ORG_VER//\./\\.} setup.py visualpython/js/com/com_Config.js visualpython/js/com/com_Const.js | xargs sed -i --follow-symlinks "s/${VP_ORG_VER//\./\\.}/${VP_NEW_VER}/g" diff --git a/jupyternotebook/setup.py b/jupyternotebook/setup.py index 9e3b7428..2f141da0 100644 --- a/jupyternotebook/setup.py +++ b/jupyternotebook/setup.py @@ -10,7 +10,7 @@ setup( name = name, - version = '2.4.6', + version = '2.4.7', packages = find_packages(), package_data = {"": ["*"], 'visualpython' : ['visualpython.yaml', 'README.md']}, scripts = ['visualpython/bin/visualpy', 'visualpython/bin/visualpy.bat'], diff --git a/visualpython/js/com/com_Config.js b/visualpython/js/com/com_Config.js index 12ef6e7f..b94ec7aa 100644 --- a/visualpython/js/com/com_Config.js +++ b/visualpython/js/com/com_Config.js @@ -1052,7 +1052,7 @@ define([ /** * Version */ - Config.version = "2.4.6"; + Config.version = "2.4.7"; /** * Type of mode diff --git a/visualpython/js/com/com_Const.js b/visualpython/js/com/com_Const.js index e9f8a642..b0ed00fa 100644 --- a/visualpython/js/com/com_Const.js +++ b/visualpython/js/com/com_Const.js @@ -19,7 +19,7 @@ define ([ class Constants { } Constants.TOOLBAR_BTN_INFO = { - HELP: "Visual Python 2.4.6" + HELP: "Visual Python 2.4.7" , ICON: "vp-main-icon" , ID: "vpBtnToggle" , NAME: "toggle-vp" diff --git a/visualpython/js/m_ml/Pipeline.js b/visualpython/js/m_ml/Pipeline.js index 1c2e2bcc..da0f7181 100644 --- a/visualpython/js/m_ml/Pipeline.js +++ b/visualpython/js/m_ml/Pipeline.js @@ -83,7 +83,7 @@ define([ modelStep: 1, step: [ { name: 'ml_dataSplit', label: 'Data Split', useApp: true }, - { name: 'ml_regression', label: 'Regressor', useApp: true }, + { name: 'ml_regression', label: 'Regressor', useApp: true, child: ['pp_fit', 'pp_predict'] }, { name: 'pp_fit', label: 'Fit' }, { name: 'pp_predict', label: 'Predict' }, { name: 'ml_evaluation', label: 'Evaluation', useApp: true, state: { modelType: 'rgs' } }, @@ -94,7 +94,7 @@ define([ modelStep: 1, step: [ { name: 'ml_dataSplit', label: 'Data Split', useApp: true }, - { name: 'ml_classification', label: 'Classifier', useApp: true }, + { name: 'ml_classification', label: 'Classifier', useApp: true, child: ['pp_fit', 'pp_predict'] }, { name: 'pp_fit', label: 'Fit' }, { name: 'pp_predict', label: 'Predict' }, { name: 'ml_evaluation', label: 'Evaluation', useApp: true, state: { modelType: 'clf' } }, @@ -104,7 +104,7 @@ define([ label: 'Clustering', modelStep: 0, step: [ - { name: 'ml_clustering', label: 'Clustering', useApp: true }, + { name: 'ml_clustering', label: 'Clustering', useApp: true, child: ['pp_fit', 'pp_predict', 'pp_transform'] }, { name: 'pp_fit', label: 'Fit' }, { name: 'pp_predict', label: 'Predict' }, { name: 'pp_transform', label: 'Transform' }, @@ -115,7 +115,7 @@ define([ label: 'Dimension Reduction', modelStep: 0, step: [ - { name: 'ml_dimensionReduction', label: 'Dimension Reduction', useApp: true }, + { name: 'ml_dimensionReduction', label: 'Dimension Reduction', useApp: true, child: ['pp_fit', 'pp_transform'] }, { name: 'pp_fit', label: 'Fit' }, { name: 'pp_transform', label: 'Transform' } ] @@ -125,7 +125,7 @@ define([ modelStep: 1, step: [ { name: 'ml_dataSplit', label: 'Data Split', useApp: true }, - { name: 'ml_gridSearch', label: 'GridSearch', useApp: true }, + { name: 'ml_gridSearch', label: 'GridSearch', useApp: true, child: ['pp_fit', 'pp_predict'] }, { name: 'pp_fit', label: 'Fit' }, { name: 'pp_predict', label: 'Predict' }, { name: 'ml_evaluation', label: 'Evaluation', useApp: true }, @@ -134,7 +134,22 @@ define([ } // menu libraries for ml - let libObj = JSON.parse(librariesJson); + let libObj = {}; + if (vpConfig.extensionType === 'lab' || vpConfig.extensionType === 'lite') { + libObj = librariesJson; + + this.MlAppComponent = {}; + this.MlAppComponent['ml_dataSplit'] = require('./dataSplit'); + this.MlAppComponent['ml_dataPrep'] = require('./DataPrep'); + this.MlAppComponent['ml_regression'] = require('./Regression'); + this.MlAppComponent['ml_classification'] = require('./Classification'); + this.MlAppComponent['ml_clustering'] = require('./Clustering'); + this.MlAppComponent['ml_dimensionReduction'] = require('./DimensionReduction'); + this.MlAppComponent['ml_gridSearch'] = require('./GridSearch'); + this.MlAppComponent['ml_evaluation'] = require('./evaluation'); + } else { + libObj = JSON.parse(librariesJson); + } this.mlAppList = libObj.library.item.filter(x => x.id === 'pkg_ml')[0].item; this.modelConfig = ML_LIBRARIES; @@ -268,7 +283,7 @@ define([ let appFileList = []; // load pipeline items tplObj.step.forEach((stepObj, idx) => { - let { name, label, useApp=false, state={} } = stepObj; + let { name, label, useApp=false, child=[], state={} } = stepObj; ppTag.appendFormatLine(`
{3}
@@ -280,7 +295,7 @@ define([ if (useApp === true) { let mlObj = that.mlAppList.filter(x => x.id === name)[0]; if (vpConfig.extensionType === 'lab' || vpConfig.extensionType === 'lite') { - appFileList.push({ index: idx, name: name, file: './' + mlObj.file}); + appFileList.push({ index: idx, name: name, file: 'vp_base/js/' + mlObj.file}); } else { appFileList.push({ index: idx, name: name, file: 'vp_base/js/' + mlObj.file}); } @@ -293,6 +308,7 @@ define([ }; if (tplObj.modelStep === idx) { pipeObj.modelStep = true; + pipeObj.child = child; } that.state.pipeline.push(pipeObj); // append pages @@ -311,14 +327,15 @@ define([ // for lite and lab if (vpConfig.extensionType === 'lab' || vpConfig.extensionType === 'lite') { appFileList.forEach((obj, argIdx) => { - let MlComponent = require(obj.file); + let MlComponent = that.MlAppComponent[obj.name]; if (MlComponent) { // DUP AREA: pp-1 - let { name, label, index, file } = obj; + let { name, index, file } = obj; let mlComponent = new MlComponent({ - config: { id: name, name: label, path: file, category: 'Pipeline', resizable: false }, + config: { id: name, name: that.state.pipeline[index].label, path: file, category: 'Pipeline', resizable: false }, ...that.state.pipeline[index].state }); + mlComponent.loadState(); // mlComponent.open($(that.wrapSelector(`.vp-pp-step-page[data-name="${appId}"]`))); that.state.pipeline[index].app = mlComponent; @@ -328,6 +345,10 @@ define([ that.state.modelType = mlComponent.state.modelType; let modelObj = that.modelConfig[that.state.modelType]; that.state.modelTypeName = modelObj.code.split('(')[0]; + + that.state.pipeline[index].child.forEach(childId => { + that.renderApp(childId); + }); } // handle app view that.handleAppView(name, mlComponent); @@ -345,19 +366,25 @@ define([ let MlComponent = arguments[argIdx]; if (MlComponent) { // DUP AREA: pp-1 - let { name, label, index, file } = obj; + let { name, index, file } = obj; let mlComponent = new MlComponent({ - config: { id: name, name: label, path: file, category: 'Pipeline', resizable: false }, + config: { id: name, name: that.state.pipeline[index].label, path: file, category: 'Pipeline', resizable: false }, ...that.state.pipeline[index].state }); + mlComponent.loadState(); // mlComponent.open($(that.wrapSelector(`.vp-pp-step-page[data-name="${appId}"]`))); that.state.pipeline[index].app = mlComponent; if (that.state.pipeline[index].modelStep === true) { // set default model type + that.state.model = mlComponent.state.allocateToCreation; that.state.modelType = mlComponent.state.modelType; let modelObj = that.modelConfig[that.state.modelType]; that.state.modelTypeName = modelObj.code.split('(')[0]; + + that.state.pipeline[index].child.forEach(childId => { + that.renderApp(childId); + }); } // handle app view that.handleAppView(name, mlComponent); @@ -460,12 +487,69 @@ define([ label = com_util.optionToLabel(label); optBox.appendFormatLine('' , opt.name, opt.name, label); - let content = com_generator.renderContent(this, opt.component[0], opt, this.state); + let tmpState = {}; + if (opt.value && opt.value !== '') { + tmpState[opt.name] = opt.value; + } + let content = com_generator.renderContent(this, opt.component[0], opt, tmpState); optBox.appendLine(content[0].outerHTML); }); return optBox.toString(); } + checkBeforeRun() { + let that = this; + var result = true; + for (let idx = 0; idx < this.state.pipeline.length; idx++) { + let ppObj = this.state.pipeline[idx]; + var { name, label, useApp, app } = ppObj; + let requiredList = []; + result = true; + let isVisible = $(that.wrapSelector(`.vp-pp-item[data-seq="${idx}"]`)).is(':visible') === true; + let isEnabled = $(that.wrapSelector(`.vp-pp-item[data-seq="${idx}"]`)).attr('data-flag') === 'enabled'; + if (isVisible && isEnabled) { + switch (name) { + case 'ml_dataSplit': + requiredList = ['featureData', 'targetData']; + // check required data + for (let i = 0; i < requiredList.length; i++) { + let reqKey = requiredList[i]; + result = that._checkIsEmpty($(app.wrapSelector('#' + reqKey))); + if (result === false) { + // show page and focus it + $(that.wrapSelector(`.vp-pp-item[data-name="${name}"]`)).click(); + $(app.wrapSelector('#' + reqKey)).focus(); + break; + } + } + break; + case 'ml_gridSearch': + result = app.checkBeforeRun(); + if (result === false) { + // show page + $(that.wrapSelector(`.vp-pp-item[data-name="${name}"]`)).click(); + break; + } + break; + } + } + if (result === false) { + break; + } + } + return result; + + } + + _checkIsEmpty(tag) { + let requiredFilled = true; + // if it's empty, focus on it + if (tag && $(tag) && $(tag).val() == '') { + requiredFilled = false; + } + return requiredFilled; + } + generateCodeForOptionPage(appId) { let actions = this.modelEditor.getAction(this.state.modelTypeName); let actObj = {}; @@ -514,24 +598,36 @@ define([ // check disabled let isVisible = $(that.wrapSelector(`.vp-pp-item[data-seq="${idx}"]`)).is(':visible') === true; - let isEnabled = $(that.wrapSelector(`.vp-pp-item[data-seq="${idx}"]`)).data('flag') === 'enabled'; + let isEnabled = $(that.wrapSelector(`.vp-pp-item[data-seq="${idx}"]`)).attr('data-flag') === 'enabled'; if (isVisible && isEnabled) { if (code.toString() !== '') { code.appendLine(); code.appendLine(); } - code.appendFormatLine("# [{0}] {1}", stepNo, label); if (useApp) { - code.append(app.generateCode()); + let appCode = app.generateCode(); + if (appCode instanceof Array) { + appCode = appCode.join('\n'); + } + if (appCode && appCode.trim() !== '') { + code.appendFormatLine("# [{0}] {1}", stepNo++, label); + if (name === 'ml_evaluation') { + // import auto generate + code.appendLine(app.generateImportCode().join('\n')); + } + code.append(appCode); + } // save state that.state.pipeline[idx].state = app.state; } else { let ppResult = that.generateCodeForOptionPage(name); - code.append(ppResult.code); + if (ppResult && ppResult?.code?.trim() !== '') { + code.appendFormatLine("# [{0}] {1}", stepNo++, label); + code.append(ppResult.code); + } // save state that.state.pipeline[idx].state = ppResult.state; } - stepNo++; } });