From 5ea04beef70a7140c19777b3ec0c083719550395 Mon Sep 17 00:00:00 2001 From: Jon Sequeira Date: Tue, 18 Oct 2022 18:26:25 -0700 Subject: [PATCH] add kernel name to Jupyter metadata --- .../JupyterFormatTests.cs | 23 +++++++++++----- .../InteractiveDocument.cs | 19 ++++++++++++- .../Jupyter/InteractiveDocumentExtensions.cs | 27 +++++++++++-------- .../Kernel.Static.cs | 9 ++++--- 4 files changed, 57 insertions(+), 21 deletions(-) diff --git a/src/Microsoft.DotNet.Interactive.Documents.Tests/JupyterFormatTests.cs b/src/Microsoft.DotNet.Interactive.Documents.Tests/JupyterFormatTests.cs index b4473be08d..7331607f2d 100644 --- a/src/Microsoft.DotNet.Interactive.Documents.Tests/JupyterFormatTests.cs +++ b/src/Microsoft.DotNet.Interactive.Documents.Tests/JupyterFormatTests.cs @@ -81,19 +81,22 @@ public void notebook_metadata_default_language_is_honored_in_cells_without_langu }); } - [Fact] - public void Default_language_can_be_specified_in_metadata() + [Theory] + [InlineData("C#", "csharp")] + [InlineData("F#", "fsharp")] + [InlineData("f#", "fsharp")] + [InlineData("PowerShell", "powershell")] + public void Metadata_default_kernel_name_is_based_on_specified_language(string languageName, string kernelName) { - var originalDoc = new InteractiveDocument().WithJupyterMetadata("fsharp"); + var originalDoc = new InteractiveDocument().WithJupyterMetadata(languageName); var parsedDoc = Notebook.Parse(originalDoc.ToJupyterJson()); parsedDoc.GetDefaultKernelName() - .Should() - .Be("fsharp"); + .Should() + .Be(kernelName); } - [Fact] public void missing_metadata_defaults_to_csharp_kernel() { @@ -983,6 +986,14 @@ public void serialized_notebook_has_appropriate_metadata() name = "C#", pygments_lexer = "csharp", version = "10.0" + }, + dotnet_interactive = new + { + defaultKernelName = "csharp", + items = new object[] + { + new { name = "csharp" } + } } }))); jupyter["nbformat"] diff --git a/src/Microsoft.DotNet.Interactive.Documents/InteractiveDocument.cs b/src/Microsoft.DotNet.Interactive.Documents/InteractiveDocument.cs index d0956ba15e..29ff87ff44 100644 --- a/src/Microsoft.DotNet.Interactive.Documents/InteractiveDocument.cs +++ b/src/Microsoft.DotNet.Interactive.Documents/InteractiveDocument.cs @@ -226,6 +226,24 @@ internal static bool TryGetKernelInfoFromMetadata( return true; } + if (metadata.TryGetValue("dotnet_interactive", out var dotnetInteractiveObj)) + { + if (dotnetInteractiveObj is IDictionary dotnetInteractiveDict) + { + kernelInfo = new(); + + if (dotnetInteractiveDict.TryGetValue("defaultKernelName", out var nameObj) && + nameObj is string name) + { + kernelInfo.DefaultKernelName = name; + } + + return true; + + // FIX: (TryGetKernelInfoFromMetadata) add items + } + } + // check for .ipynb / Jupyter metadata if (metadata.TryGetValue("kernelspec", out var kernelspecObj)) { @@ -242,7 +260,6 @@ internal static bool TryGetKernelInfoFromMetadata( } } } - } // check if a KernelInfoCollection was directly serialized into the metadata diff --git a/src/Microsoft.DotNet.Interactive.Documents/Jupyter/InteractiveDocumentExtensions.cs b/src/Microsoft.DotNet.Interactive.Documents/Jupyter/InteractiveDocumentExtensions.cs index cafaad47a1..2371dca1d1 100644 --- a/src/Microsoft.DotNet.Interactive.Documents/Jupyter/InteractiveDocumentExtensions.cs +++ b/src/Microsoft.DotNet.Interactive.Documents/Jupyter/InteractiveDocumentExtensions.cs @@ -13,33 +13,38 @@ public static InteractiveDocument WithJupyterMetadata( this InteractiveDocument document, string language = "C#") { - var (moniker, langVersion, fileExtension) = - language switch + var (kernelName, canonicalLanguageName, langVersion, fileExtension) = + language.ToLowerInvariant() switch { - "C#" or "csharp" => ("csharp", "10.0", ".cs"), - "F#" or "fsharp" => ("fsharp", "6.0", ".fs"), - "PowerShell" or "pwsh" => ("powershell", "7.0", ".ps1"), + "c#" or "csharp" => ("csharp","C#", "10.0", ".cs"), + "f#" or "fsharp" => ("fsharp","F#", "6.0", ".fs"), + "powershell" or "pwsh" => ("powershell", "PowerShell", "7.0", ".ps1"), _ => throw new ArgumentException($"Unrecognized language: {language}") }; document.Metadata.GetOrAdd("kernelspec", _ => new Dictionary()) .MergeWith(new Dictionary { - ["display_name"] = $".NET ({language})", - ["language"] = language, - ["name"] = $".net-{moniker}" + ["display_name"] = $".NET ({canonicalLanguageName})", + ["language"] = canonicalLanguageName, + ["name"] = $".net-{kernelName}" }); document.Metadata.GetOrAdd("language_info", _ => new Dictionary()) .MergeWith(new Dictionary { ["file_extension"] = fileExtension, - ["mimetype"] = $"text/x-{moniker}", - ["name"] = language, - ["pygments_lexer"] = moniker, + ["mimetype"] = $"text/x-{kernelName}", + ["name"] = canonicalLanguageName, + ["pygments_lexer"] = kernelName, ["version"] = langVersion }); + var kernelInfos = document.Metadata.GetOrAdd("dotnet_interactive", _ => new KernelInfoCollection()); + + kernelInfos.DefaultKernelName = kernelName; + kernelInfos.Add(new(kernelName)); + return document; } } \ No newline at end of file diff --git a/src/Microsoft.DotNet.Interactive/Kernel.Static.cs b/src/Microsoft.DotNet.Interactive/Kernel.Static.cs index cff0293773..944bb3b1da 100644 --- a/src/Microsoft.DotNet.Interactive/Kernel.Static.cs +++ b/src/Microsoft.DotNet.Interactive/Kernel.Static.cs @@ -40,7 +40,7 @@ public static DisplayedValue display( /// The user input value. public static async Task GetInputAsync(string prompt = "", string typeHint = "text") { - return await GetInputAsync(prompt, false); + return await GetInputAsync(prompt, false, typeHint); } public static async Task GetPasswordAsync(string prompt = "") @@ -48,9 +48,12 @@ public static async Task GetPasswordAsync(string prompt = "") return await GetInputAsync(prompt, true); } - private static async Task GetInputAsync(string prompt, bool isPassword) + private static async Task GetInputAsync(string prompt, bool isPassword, string typeHint = "text") { - var command = new RequestInput(prompt, isPassword ? "password" : default); + var command = new RequestInput( + prompt, + isPassword ? "password" : default, + inputTypeHint: typeHint); var results = await Root.SendAsync(command, CancellationToken.None);