This is an automated email from the ASF dual-hosted git repository.

liuxun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/zeppelin.git


The following commit(s) were added to refs/heads/master by this push:
     new f58f8d8  [ZEPPELIN-4171] Configuration paragraph is empty to execute
f58f8d8 is described below

commit f58f8d88866f7d2c7d041e1a410b82f2bf25e24f
Author: Xun Liu <liu...@apache.org>
AuthorDate: Mon May 27 11:34:07 2019 +0800

    [ZEPPELIN-4171] Configuration paragraph is empty to execute
    
    ### What is this PR for?
    In some cases,
    For example: `%sh.terminal` interpreter
    The paragraph is empty and can be executed
    
    Add the config configuration section in the `interpreter-setting.json` file 
of the interpreter.
    
    ```
    "config": {
       "checkEmpty": true
    }
    ```
    
    ### What type of PR is it?
    [Improvement]
    
    ### Todos
    * [ ] - Task
    
    ### What is the Jira issue?
    * https://issues.apache.org/jira/browse/ZEPPELIN-4171
    
    ### How should this be tested?
    * [CI Pass](https://travis-ci.org/liuxunorg/zeppelin/builds/537325588)
    
    ### Screenshots (if appropriate)
    
![checkEmpty](https://user-images.githubusercontent.com/3677382/58377742-cad2ca00-7fb9-11e9-98ce-ffc8743cfe4c.gif)
    
    ### Questions:
    * Does the licenses files need update?
    * Is there breaking changes for older versions?
    * Does this needs documentation?
    
    Author: Xun Liu <liu...@apache.org>
    
    Closes #3371 from liuxunorg/ZEPPELIN-4171 and squashes the following 
commits:
    
    753a8a3c7 [Xun Liu] Modify according to review comments.
    ef1889574 [Xun Liu] Improve document description.
    5abd7fc86 [Xun Liu] [ZEPPELIN-4171] Check paragraph is empty before 
execution
---
 docs/development/writing_zeppelin_interpreter.md   | 14 +++++++-
 .../apache/zeppelin/service/NotebookService.java   |  2 +-
 .../org/apache/zeppelin/notebook/Paragraph.java    | 38 ++++++++++++++++++----
 .../org/apache/zeppelin/notebook/NotebookTest.java | 23 ++++++++-----
 .../src/test/resources/conf/interpreter.json       |  3 +-
 .../config_test/interpreter-setting.json           |  3 +-
 6 files changed, 63 insertions(+), 20 deletions(-)

diff --git a/docs/development/writing_zeppelin_interpreter.md 
b/docs/development/writing_zeppelin_interpreter.md
index c613204..27843ac 100644
--- a/docs/development/writing_zeppelin_interpreter.md
+++ b/docs/development/writing_zeppelin_interpreter.md
@@ -121,7 +121,8 @@ Here is an example of `interpreter-setting.json` on your 
own interpreter.
     },
     "config": {
       "runOnSelectionChange": true/false,
-      "title": true/false
+      "title": true/false,
+      "checkEmpty": true/false
     }
   },
   {
@@ -207,6 +208,17 @@ You can make the dynamic form in the notebook not trigger 
execution after select
 }
 ```
 
+
+### Check if the paragraph is empty before running (Optional)
+The notebook's paragraph default will not run if it is empty.
+You can set `config.checkEmpty=false`, to run even when the paragraph of the 
notebook is empty.
+
+```json
+"config": {
+  "checkEmpty": false # default: true
+}
+```
+
 ## Install your interpreter binary
 
 Once you have built your interpreter, you can place it under the interpreter 
directory with all its dependencies.
diff --git 
a/zeppelin-server/src/main/java/org/apache/zeppelin/service/NotebookService.java
 
b/zeppelin-server/src/main/java/org/apache/zeppelin/service/NotebookService.java
index bb42ce2..ccd6639 100644
--- 
a/zeppelin-server/src/main/java/org/apache/zeppelin/service/NotebookService.java
+++ 
b/zeppelin-server/src/main/java/org/apache/zeppelin/service/NotebookService.java
@@ -453,7 +453,7 @@ public class NotebookService {
       throw new NoteNotFoundException(noteId);
     }
     Paragraph newPara = note.insertNewParagraph(index, context.getAutheInfo());
-    newPara.setConfig(config);
+    newPara.mergeConfig(config);
     notebook.saveNote(note, context.getAutheInfo());
     callback.onSuccess(newPara, context);
     return newPara;
diff --git 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java
index 81b5250..1cc0ba7 100644
--- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java
+++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java
@@ -105,10 +105,12 @@ public class Paragraph extends 
JobWithProgressPoller<InterpreterResult> implemen
   private transient Map<String, String> localProperties = new HashMap<>();
   private transient Map<String, ParagraphRuntimeInfo> runtimeInfos = new 
HashMap<>();
 
-  private static String  PARAGRAPH_CONFIG_RUNONSELECTIONCHANGE = 
"runOnSelectionChange";
+  public static String  PARAGRAPH_CONFIG_RUNONSELECTIONCHANGE = 
"runOnSelectionChange";
   private static boolean PARAGRAPH_CONFIG_RUNONSELECTIONCHANGE_DEFAULT = true;
-  private static String  PARAGRAPH_CONFIG_TITLE = "title";
+  public static String  PARAGRAPH_CONFIG_TITLE = "title";
   private static boolean PARAGRAPH_CONFIG_TITLE_DEFAULT = false;
+  public static String  PARAGRAPH_CONFIG_CHECK_EMTPY = "checkEmpty";
+  private static boolean PARAGRAPH_CONFIG_CHECK_EMTPY_DEFAULT = true;
 
   @VisibleForTesting
   Paragraph() {
@@ -343,12 +345,30 @@ public class Paragraph extends 
JobWithProgressPoller<InterpreterResult> implemen
     return null;
   }
 
-  public boolean isBlankParagraph() {
+  public boolean shouldSkipRunParagraph() {
+    // check interpreter-setting.json `config.checkEmpty` is equal false
+    Object configCheckEmpty = this.config.get(PARAGRAPH_CONFIG_CHECK_EMTPY);
+    if (null != configCheckEmpty) {
+      boolean checkEmtpy = PARAGRAPH_CONFIG_CHECK_EMTPY_DEFAULT;
+      try {
+        checkEmtpy = (boolean) configCheckEmpty;
+      } catch (ClassCastException e) {
+        LOGGER.error(e.getMessage(), e);
+      } catch (Exception e) {
+        LOGGER.error(e.getMessage(), e);
+      }
+      if (!checkEmtpy) {
+        LOGGER.info("This interpreter config `interpreter-setting.json` set 
config.{} = false", 
+            PARAGRAPH_CONFIG_CHECK_EMTPY);
+        return false;
+      }
+    }
+
     return Strings.isNullOrEmpty(scriptText);
   }
 
   public boolean execute(boolean blocking) {
-    if (isBlankParagraph()) {
+    if (shouldSkipRunParagraph()) {
       LOGGER.info("Skip to run blank paragraph. {}", getId());
       setStatus(Job.Status.FINISHED);
       return true;
@@ -478,7 +498,7 @@ public class Paragraph extends 
JobWithProgressPoller<InterpreterResult> implemen
               String name = ((ManagedInterpreterGroup) 
intpGroup).getInterpreterSetting().getName();
               Map<String, Object> config
                       = intpSettingManager.getConfigSetting(name);
-              applyConfigSetting(config);
+              mergeConfig(config);
             }
           }
         }
@@ -601,10 +621,13 @@ public class Paragraph extends 
JobWithProgressPoller<InterpreterResult> implemen
     return config;
   }
 
+  // NOTE: function setConfig(...) will overwrite all configuration
+  // Merge configuration, you need to use function mergeConfig(...)
   public void setConfig(Map<String, Object> config) {
     this.config = config;
   }
 
+  // [ZEPPELIN-3919] Paragraph config default value can be customized
   // apply the `interpreter-setting.json` config
   // When creating a paragraph, it will update some of the configuration
   // parameters of the paragraph from the web side.
@@ -615,13 +638,13 @@ public class Paragraph extends 
JobWithProgressPoller<InterpreterResult> implemen
   // 2. The user manually modified the  interpreter types of this paragraph.
   //    Need to delete the existing configuration of this paragraph,
   //    update with the specified interpreter configuration
-  public void applyConfigSetting(Map<String, Object> newConfig) {
+  public void mergeConfig(Map<String, Object> newConfig) {
     if (null == newConfig || 0 == newConfig.size()) {
       newConfig = getDefaultConfigSetting();
     }
 
     List<String> keysToRemove = 
Arrays.asList(PARAGRAPH_CONFIG_RUNONSELECTIONCHANGE,
-        PARAGRAPH_CONFIG_TITLE);
+        PARAGRAPH_CONFIG_TITLE, PARAGRAPH_CONFIG_CHECK_EMTPY);
     for (String removeKey : keysToRemove) {
       if ((false == newConfig.containsKey(removeKey))
           && (true == config.containsKey(removeKey))) {
@@ -637,6 +660,7 @@ public class Paragraph extends 
JobWithProgressPoller<InterpreterResult> implemen
     Map<String, Object> config = new HashMap<>();
     config.put(PARAGRAPH_CONFIG_RUNONSELECTIONCHANGE, 
PARAGRAPH_CONFIG_RUNONSELECTIONCHANGE_DEFAULT);
     config.put(PARAGRAPH_CONFIG_TITLE, PARAGRAPH_CONFIG_TITLE_DEFAULT);
+    config.put(PARAGRAPH_CONFIG_CHECK_EMTPY, 
PARAGRAPH_CONFIG_CHECK_EMTPY_DEFAULT);
 
     return config;
   }
diff --git 
a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java 
b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java
index 1629ab2..49023e7 100644
--- 
a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java
+++ 
b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java
@@ -1094,16 +1094,19 @@ public class NotebookTest extends 
AbstractInterpreterTest implements ParagraphJo
     // create paragraphs
     Paragraph p1 = note.addNewParagraph(anonymous);
     Map<String, Object> config = p1.getConfig();
-    assertTrue(config.containsKey("runOnSelectionChange"));
-    assertTrue(config.containsKey("title"));
-    assertEquals(config.get("runOnSelectionChange"), false);
-    assertEquals(config.get("title"), true);
+    
assertTrue(config.containsKey(Paragraph.PARAGRAPH_CONFIG_RUNONSELECTIONCHANGE));
+    assertTrue(config.containsKey(Paragraph.PARAGRAPH_CONFIG_TITLE));
+    assertTrue(config.containsKey(Paragraph.PARAGRAPH_CONFIG_CHECK_EMTPY));
+    assertEquals(config.get(Paragraph.PARAGRAPH_CONFIG_RUNONSELECTIONCHANGE), 
false);
+    assertEquals(config.get(Paragraph.PARAGRAPH_CONFIG_TITLE), true);
+    assertEquals(config.get(Paragraph.PARAGRAPH_CONFIG_CHECK_EMTPY), false);
 
     // The config_test interpreter sets the default parameters
     // in interpreter/config_test/interpreter-setting.json
     //    "config": {
     //      "runOnSelectionChange": false,
-    //      "title": true
+    //      "title": true,
+    //      "checkEmpty": true
     //    },
     p1.setText("%config_test sleep 1000");
     note.runAll(AuthenticationInfo.ANONYMOUS, false);
@@ -1113,8 +1116,9 @@ public class NotebookTest extends AbstractInterpreterTest 
implements ParagraphJo
 
     // Check if the config_test interpreter default parameter takes effect
     LOGGER.info("p1.getConfig() =  " + p1.getConfig());
-    assertEquals(config.get("runOnSelectionChange"), false);
-    assertEquals(config.get("title"), true);
+    assertEquals(config.get(Paragraph.PARAGRAPH_CONFIG_RUNONSELECTIONCHANGE), 
false);
+    assertEquals(config.get(Paragraph.PARAGRAPH_CONFIG_TITLE), true);
+    assertEquals(config.get(Paragraph.PARAGRAPH_CONFIG_CHECK_EMTPY), false);
 
     // The mock1 interpreter does not set default parameters
     p1.setText("%mock1 sleep 1000");
@@ -1125,8 +1129,9 @@ public class NotebookTest extends AbstractInterpreterTest 
implements ParagraphJo
 
     // Check if the mock1 interpreter parameter is updated
     LOGGER.info("changed intp p1.getConfig() =  " + p1.getConfig());
-    assertEquals(config.get("runOnSelectionChange"), true);
-    assertEquals(config.get("title"), false);
+    assertEquals(config.get(Paragraph.PARAGRAPH_CONFIG_RUNONSELECTIONCHANGE), 
true);
+    assertEquals(config.get(Paragraph.PARAGRAPH_CONFIG_TITLE), false);
+    assertEquals(config.get(Paragraph.PARAGRAPH_CONFIG_CHECK_EMTPY), true);
   }
 
   @Test
diff --git a/zeppelin-zengine/src/test/resources/conf/interpreter.json 
b/zeppelin-zengine/src/test/resources/conf/interpreter.json
index dc3e8ce..62ae850 100644
--- a/zeppelin-zengine/src/test/resources/conf/interpreter.json
+++ b/zeppelin-zengine/src/test/resources/conf/interpreter.json
@@ -132,7 +132,8 @@
         "fontSize": 9,
         "colWidth": 12,
         "runOnSelectionChange": false,
-        "title": true
+        "title": true,
+        "checkEmpty": false
       },
       "option": {
         "remote": true,
diff --git 
a/zeppelin-zengine/src/test/resources/interpreter/config_test/interpreter-setting.json
 
b/zeppelin-zengine/src/test/resources/interpreter/config_test/interpreter-setting.json
index 6fd39fc..08d4ac7 100644
--- 
a/zeppelin-zengine/src/test/resources/interpreter/config_test/interpreter-setting.json
+++ 
b/zeppelin-zengine/src/test/resources/interpreter/config_test/interpreter-setting.json
@@ -8,7 +8,8 @@
     },
     "config": {
       "runOnSelectionChange": false,
-      "title": true
+      "title": true,
+      "checkEmpty": false
     },
     "option": {
       "remote": true,

Reply via email to