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

tbonelee 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 03de344818 [ZEPPELIN-6153] Add display_name to the kernelspec when 
exporting to ipynb
03de344818 is described below

commit 03de344818b8153a8ab017da91475d53e91c5dbf
Author: minjcho <[email protected]>
AuthorDate: Sun Aug 9 15:42:59 2026 +0900

    [ZEPPELIN-6153] Add display_name to the kernelspec when exporting to ipynb
    
    ### What is this PR for?
    
    Exporting a Zeppelin note to ipynb produces a `kernelspec` with only 
`language` and `name`:
    
    ```java
    JsonObject kernelspecJson = new JsonObject();
    kernelspecJson.addProperty("language", "scala");
    kernelspecJson.addProperty("name", "spark2-scala");
    ```
    
    The nbformat schema requires `kernelspec.display_name`, so renderers that 
validate the schema — GitHub in particular — refuse to display the exported 
notebook. The import side already models the field (`nbformat/Kernelspec.java` 
has `display_name`); only the export path in `JupyterUtil.getNbformat()` omits 
it.
    
    This PR writes `"display_name": "Zeppelin"` into the exported kernelspec, 
the default suggested in the JIRA issue. The value is kept as a constant 
(`JupyterUtil.KERNEL_DISPLAY_NAME`) and `Kernelspec` gains getters following 
the pattern of the sibling nbformat classes (`Metadata`, `Nbformat`), so the 
new round-trip test can assert on the deserialized object. The test exports 
`spark_example_notebook.zpln`, reads the result back, and checks the kernelspec 
carries both `name` and `display_name`.
    
    ### What type of PR is it?
    Bug Fix
    
    ### Todos
    * [x] Write `display_name` into the exported kernelspec
    * [x] Expose `Kernelspec` fields through getters
    * [x] Pin the behaviour with a round-trip test
    
    ### What is the Jira issue?
    * https://issues.apache.org/jira/browse/ZEPPELIN-6153
    
    ### How should this be tested?
    
    ```bash
    ./mvnw test -pl zeppelin-jupyter -Dtest=JupyterUtilTest 
-DfailIfNoTests=false
    ```
    
    `Tests run: 5, Failures: 0, Errors: 0, Skipped: 0`
    
    To verify end-to-end: export any note to ipynb and push it to a GitHub 
repository — the notebook now renders instead of showing "Invalid Notebook".
    
    ### Screenshots (if appropriate)
    N/A
    
    ### Questions:
    * Does the license files need to update? No
    * Is there breaking changes for older versions? No
    * Does this needs documentation? No
    
    Closes #5397 from minjcho/ZEPPELIN-6153.
    
    Signed-off-by: ChanHo Lee <[email protected]>
---
 .../java/org/apache/zeppelin/jupyter/JupyterUtil.java   |  5 +++++
 .../apache/zeppelin/jupyter/nbformat/Kernelspec.java    |  8 ++++++++
 .../zeppelin/jupyter/nbformat/JupyterUtilTest.java      | 17 +++++++++++++++++
 3 files changed, 30 insertions(+)

diff --git 
a/zeppelin-jupyter/src/main/java/org/apache/zeppelin/jupyter/JupyterUtil.java 
b/zeppelin-jupyter/src/main/java/org/apache/zeppelin/jupyter/JupyterUtil.java
index 81fda1a39d..3135d57212 100644
--- 
a/zeppelin-jupyter/src/main/java/org/apache/zeppelin/jupyter/JupyterUtil.java
+++ 
b/zeppelin-jupyter/src/main/java/org/apache/zeppelin/jupyter/JupyterUtil.java
@@ -64,6 +64,8 @@ public class JupyterUtil {
 
   private static final Gson PRETTY_GSON = new 
GsonBuilder().setPrettyPrinting().create();
 
+  public static final String KERNEL_DISPLAY_NAME = "Zeppelin";
+
   private final RuntimeTypeAdapterFactory<Cell> cellTypeFactory;
   private final RuntimeTypeAdapterFactory<Output> outputTypeFactory;
 
@@ -239,6 +241,9 @@ public class JupyterUtil {
     JsonObject kernelspecJson = new JsonObject();
     kernelspecJson.addProperty("language", "scala");
     kernelspecJson.addProperty("name", "spark2-scala");
+    // display_name is required by the nbformat schema. Renderers such as 
GitHub
+    // fail to display the notebook when it is missing.
+    kernelspecJson.addProperty("display_name", KERNEL_DISPLAY_NAME);
 
     JsonObject languageInfoJson = new JsonObject();
     languageInfoJson.addProperty("codemirror_mode", "text/x-scala");
diff --git 
a/zeppelin-jupyter/src/main/java/org/apache/zeppelin/jupyter/nbformat/Kernelspec.java
 
b/zeppelin-jupyter/src/main/java/org/apache/zeppelin/jupyter/nbformat/Kernelspec.java
index 6232416851..ddfd7e99af 100644
--- 
a/zeppelin-jupyter/src/main/java/org/apache/zeppelin/jupyter/nbformat/Kernelspec.java
+++ 
b/zeppelin-jupyter/src/main/java/org/apache/zeppelin/jupyter/nbformat/Kernelspec.java
@@ -28,4 +28,12 @@ public class Kernelspec {
 
   @SerializedName("display_name")
   private String displayName;
+
+  public String getName() {
+    return name;
+  }
+
+  public String getDisplayName() {
+    return displayName;
+  }
 }
diff --git 
a/zeppelin-jupyter/src/test/java/org/apache/zeppelin/jupyter/nbformat/JupyterUtilTest.java
 
b/zeppelin-jupyter/src/test/java/org/apache/zeppelin/jupyter/nbformat/JupyterUtilTest.java
index 7ae8e2449f..ba30607f6e 100644
--- 
a/zeppelin-jupyter/src/test/java/org/apache/zeppelin/jupyter/nbformat/JupyterUtilTest.java
+++ 
b/zeppelin-jupyter/src/test/java/org/apache/zeppelin/jupyter/nbformat/JupyterUtilTest.java
@@ -114,4 +114,21 @@ class JupyterUtilTest {
     assertEquals(3 , nbformat.getCells().stream().filter(c -> c instanceof 
MarkdownCell).count());
     assertEquals(4 , nbformat.getCells().stream().filter(c -> c instanceof 
CodeCell).count());
   }
+
+  @Test
+  void testGetNbformatKernelspec() {
+    InputStream resource = 
getClass().getResourceAsStream("/spark_example_notebook.zpln");
+    String text = new BufferedReader(
+        new InputStreamReader(resource, StandardCharsets.UTF_8))
+        .lines()
+        .collect(Collectors.joining("\n"));
+    JupyterUtil util = new JupyterUtil();
+    Nbformat nbformat = util.getNbformat(new 
StringReader(util.getNbformat(text)));
+
+    Kernelspec kernelspec = nbformat.getMetadata().getKernelspec();
+    assertNotNull(kernelspec);
+    assertEquals("spark2-scala", kernelspec.getName());
+    // display_name is required by the nbformat schema, see ZEPPELIN-6153
+    assertEquals(JupyterUtil.KERNEL_DISPLAY_NAME, kernelspec.getDisplayName());
+  }
 }

Reply via email to