Skip to content

Commit

Permalink
updates for Microsoft.DotNet.Interactive.Documents API stabilization
Browse files Browse the repository at this point in the history
  • Loading branch information
jonsequitur committed Sep 11, 2023
1 parent 82cadfa commit 34cc09c
Show file tree
Hide file tree
Showing 12 changed files with 56 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Microsoft.DotNet.Interactive.Documents
public System.Collections.Generic.IAsyncEnumerable<InteractiveDocument> GetImportsAsync(System.Boolean recursive = False)
public System.Collections.Generic.IEnumerable<InputField> GetInputFields()
public System.Collections.Generic.IEnumerable<System.String> GetMagicCommandLines()
public System.Boolean TryGetKernelInfosFromMetadata(ref KernelInfoCollection& kernelInfos)
public class InteractiveDocumentElement
.ctor()
.ctor(System.String contents = null, System.String kernelName = null, System.Collections.Generic.IEnumerable<InteractiveDocumentOutputElement> outputs = null)
Expand Down Expand Up @@ -60,30 +61,22 @@ Microsoft.DotNet.Interactive.Documents
public System.Boolean Contains(System.String nameOrAlias)
public System.Void CopyTo(KernelInfo[] array, System.Int32 arrayIndex)
public System.Boolean Remove(KernelInfo item)
public System.Boolean TryGetByAlias(System.String alias, ref KernelInfo& info)
public class ReturnValueElement : InteractiveDocumentOutputElement, IDataElement
.ctor(System.Collections.Generic.IDictionary<System.String,System.Object> data)
.ctor()
public System.Collections.Generic.IDictionary<System.String,System.Object> Data { get;}
public System.Int32 ExecutionOrder { get; set;}
public System.Collections.Generic.IDictionary<System.String,System.Object> Metadata { get;}
public class TextElement : InteractiveDocumentOutputElement
.ctor(System.String text, System.String name)
.ctor(System.String text, System.String name = stdout)
public System.String Name { get;}
public System.String Text { get;}
Microsoft.DotNet.Interactive.Documents.Jupyter
public class InputCellMetadata
.ctor(System.String kernelName = null, System.String language = null)
public System.String KernelName { get;}
public System.String Language { get;}
public static class InteractiveDocumentExtensions
public static Microsoft.DotNet.Interactive.Documents.InteractiveDocument WithJupyterMetadata(System.String language = C#)
public static class Notebook
public static System.Text.Encoding Encoding { get;}
public static System.Text.Json.JsonSerializerOptions JsonSerializerOptions { get;}
public static Microsoft.DotNet.Interactive.Documents.InteractiveDocument Parse(System.String json, Microsoft.DotNet.Interactive.Documents.KernelInfoCollection kernelInfos = null)
public static Microsoft.DotNet.Interactive.Documents.InteractiveDocument Read(System.IO.Stream stream, Microsoft.DotNet.Interactive.Documents.KernelInfoCollection kernelInfos)
public static System.String ToJupyterJson(System.String defaultLanguage = null)
public static System.Void Write(Microsoft.DotNet.Interactive.Documents.InteractiveDocument document, System.IO.Stream stream)
public static System.Void Write(Microsoft.DotNet.Interactive.Documents.InteractiveDocument document, System.IO.Stream stream, Microsoft.DotNet.Interactive.Documents.KernelInfoCollection kernelInfos)
public static System.Void Write(Microsoft.DotNet.Interactive.Documents.InteractiveDocument document, System.IO.TextWriter writer)
public static System.Void Write(Microsoft.DotNet.Interactive.Documents.InteractiveDocument document, System.IO.TextWriter writer, Microsoft.DotNet.Interactive.Documents.KernelInfoCollection kernelInfos)
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public void notebook_metadata_default_language_is_honored_in_cells_without_langu
[InlineData("PowerShell", "powershell")]
public void Metadata_default_kernel_name_is_based_on_specified_language(string languageName, string kernelName)
{
var document = new InteractiveDocument().WithJupyterMetadata(languageName);
var document = Notebook.Parse(new InteractiveDocument().ToJupyterJson(languageName));

document.GetDefaultKernelName()
.Should()
Expand All @@ -102,7 +102,7 @@ public void Metadata_default_kernel_name_is_based_on_specified_language(string l
[InlineData("PowerShell", "powershell")]
public void Metadata_default_kernel_name_is_based_on_specified_language_when_serialized_and_deserialized(string languageName, string kernelName)
{
var originalDoc = new InteractiveDocument().WithJupyterMetadata(languageName);
var originalDoc = Notebook.Parse(new InteractiveDocument().ToJupyterJson(languageName));

var parsedDoc = Notebook.Parse(originalDoc.ToJupyterJson());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public static InteractiveDocument Parse(

metadata = JsonSerializer.Deserialize<Dictionary<string, object>>(metadataString, InteractiveDocument.JsonSerializerOptions);

if (InteractiveDocument.TryGetKernelInfoFromMetadata(metadata, out var kernelInfoFromMetadata))
if (InteractiveDocument.TryGetKernelInfosFromMetadata(metadata, out var kernelInfoFromMetadata))
{
InteractiveDocument.MergeKernelInfos(kernelInfos, kernelInfoFromMetadata);
document.Metadata["kernelInfo"] = kernelInfoFromMetadata;
Expand Down
39 changes: 19 additions & 20 deletions src/Microsoft.DotNet.Interactive.Documents/InteractiveDocument.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public async IAsyncEnumerable<InteractiveDocument> GetImportsAsync(bool recursiv
{
EnsureImportFieldParserIsInitialized();

if (!TryGetKernelInfoFromMetadata(Metadata, out var kernelInfos))
if (!TryGetKernelInfosFromMetadata(out var kernelInfos))
{
kernelInfos = new();
}
Expand Down Expand Up @@ -198,7 +198,7 @@ public static async Task<InteractiveDocument> LoadAsync(

public string? GetDefaultKernelName()
{
if (TryGetKernelInfoFromMetadata(Metadata, out var kernelInfo))
if (TryGetKernelInfosFromMetadata(Metadata, out var kernelInfo))
{
return kernelInfo.DefaultKernelName;
}
Expand All @@ -208,16 +208,11 @@ public static async Task<InteractiveDocument> LoadAsync(

internal string? GetDefaultKernelName(KernelInfoCollection kernelInfos)
{
if (TryGetKernelInfoFromMetadata(Metadata, out var kernelInfoCollection))
if (TryGetKernelInfosFromMetadata(Metadata, out var kernelInfoCollection))
{
return kernelInfoCollection.DefaultKernelName;
}

if (Metadata is null)
{
return null;
}

if (Metadata.TryGetValue("kernelspec", out var kernelspecObj))
{
if (kernelspecObj is IDictionary<string, object> kernelspecDict)
Expand All @@ -243,7 +238,7 @@ public static async Task<InteractiveDocument> LoadAsync(

internal static void MergeKernelInfos(InteractiveDocument document, KernelInfoCollection kernelInfos)
{
if (TryGetKernelInfoFromMetadata(document.Metadata, out var kernelInfoCollection))
if (TryGetKernelInfosFromMetadata(document.Metadata, out var kernelInfoCollection))
{
MergeKernelInfos(kernelInfoCollection, kernelInfos);
}
Expand All @@ -264,19 +259,23 @@ internal static void MergeKernelInfos(KernelInfoCollection destination, KernelIn
destination.AddRange(source.Where(ki => added.Add(ki.Name)));
}

internal static bool TryGetKernelInfoFromMetadata(
public bool TryGetKernelInfosFromMetadata(
[NotNullWhen(true)] out KernelInfoCollection? kernelInfos) =>
TryGetKernelInfosFromMetadata(Metadata, out kernelInfos);

internal static bool TryGetKernelInfosFromMetadata(
IDictionary<string, object>? metadata,
[NotNullWhen(true)] out KernelInfoCollection? kernelInfo)
[NotNullWhen(true)] out KernelInfoCollection? kernelInfos)
{
if (metadata is not null)
{
if (metadata.TryGetValue("kernelInfo", out var kernelInfoObj))
{
if (kernelInfoObj is JsonElement kernelInfoJson &&
JsonSerializer.Deserialize<KernelInfoCollection>(kernelInfoJson, JsonSerializerOptions) is
kernelInfoJson.Deserialize<KernelInfoCollection>(JsonSerializerOptions) is
{ } kernelInfoDeserialized)
{
kernelInfo = kernelInfoDeserialized;
kernelInfos = kernelInfoDeserialized;
return true;
}

Expand Down Expand Up @@ -319,15 +318,15 @@ internal static bool TryGetKernelInfoFromMetadata(
deserializedKernelInfo.Add(new KernelInfo(name, language, aliases));
}
}
kernelInfo = deserializedKernelInfo;
kernelInfos = deserializedKernelInfo;
return true;
}
}
}

if (kernelInfoObj is KernelInfoCollection kernelInfoCollection)
{
kernelInfo = kernelInfoCollection;
kernelInfos = kernelInfoCollection;
return true;
}
}
Expand All @@ -338,17 +337,17 @@ internal static bool TryGetKernelInfoFromMetadata(
{
case KernelInfoCollection kernelInfoCollection:

kernelInfo = kernelInfoCollection;
kernelInfos = kernelInfoCollection;
return true;

case IDictionary<string, object> dotnetInteractiveDict:
{
kernelInfo = new();
kernelInfos = new();

if (dotnetInteractiveDict.TryGetValue("defaultKernelName", out var nameObj) &&
nameObj is string name)
{
kernelInfo.DefaultKernelName = name;
kernelInfos.DefaultKernelName = name;
}

return true;
Expand All @@ -364,7 +363,7 @@ internal static bool TryGetKernelInfoFromMetadata(
if (kernelspecDict.TryGetValue("language", out var languageObj) &&
languageObj is string defaultLanguage)
{
kernelInfo = new KernelInfoCollection
kernelInfos = new KernelInfoCollection
{
DefaultKernelName = defaultLanguage
};
Expand All @@ -375,7 +374,7 @@ internal static bool TryGetKernelInfoFromMetadata(
}

// check if a KernelInfoCollection was directly serialized into the metadata
kernelInfo = default;
kernelInfos = default;
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ namespace Microsoft.DotNet.Interactive.Documents.Jupyter;

public class InputCellMetadata
{
public InputCellMetadata(string? kernelName = null, string ? language = null)
public InputCellMetadata(string? kernelName = null, string? language = null)
{
KernelName = kernelName;
Language = language;
}

[JsonPropertyName("kernelName")] public string? KernelName { get; }
[JsonPropertyName("language")] public string? Language { get; }
[JsonPropertyName("kernelName")]
public string? KernelName { get; }

[JsonPropertyName("language")]
public string? Language { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace Microsoft.DotNet.Interactive.Documents.Jupyter;

public static class InteractiveDocumentExtensions
internal static class InteractiveDocumentExtensions
{
public static InteractiveDocument WithJupyterMetadata(
this InteractiveDocument document,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,16 @@ public override InteractiveDocumentOutputElement Read(
break;

case "execute_result":
var returnValueElement = new ReturnValueElement(data ?? new Dictionary<string, object>())
var returnValueElement = new ReturnValueElement
{
ExecutionOrder = executionCount ?? 0
};


if (data is not null)
{
returnValueElement.Data.MergeWith(data);
}

if (metadata is not null)
{
returnValueElement.Metadata.MergeWith(metadata);
Expand Down
35 changes: 8 additions & 27 deletions src/Microsoft.DotNet.Interactive.Documents/Jupyter/Notebook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ namespace Microsoft.DotNet.Interactive.Documents.Jupyter;

public static class Notebook
{
private static readonly Encoding _encoding = new UTF8Encoding(false);

static Notebook()
{
JsonSerializerOptions = new JsonSerializerOptions
Expand All @@ -33,12 +35,7 @@ static Notebook()
};
}

public static JsonSerializerOptions JsonSerializerOptions { get; }

public const string MetadataNamespace = "dotnet_interactive";
public const string PolyglotMetadataNamespace = "polyglot_notebook";

public static Encoding Encoding => new UTF8Encoding(false);
internal static JsonSerializerOptions JsonSerializerOptions { get; }

public static InteractiveDocument Parse(
string json,
Expand All @@ -59,24 +56,11 @@ public static InteractiveDocument Read(
Stream stream,
KernelInfoCollection kernelInfos)
{
using var reader = new StreamReader(stream, Encoding);
using var reader = new StreamReader(stream, _encoding);
var content = reader.ReadToEnd();
return Parse(content, kernelInfos);
}

public static void Write(InteractiveDocument document, Stream stream)
{
using var writer = new StreamWriter(stream, Encoding, 1024, true);
Write(document, writer);
writer.Flush();
}

public static void Write(InteractiveDocument document, Stream stream, KernelInfoCollection kernelInfos)
{
InteractiveDocument.MergeKernelInfos(document, kernelInfos);
Write(document, stream);
}

public static string ToJupyterJson(
this InteractiveDocument document,
string? defaultLanguage = null)
Expand All @@ -97,15 +81,12 @@ public static string ToJupyterJson(
return singleSpaceIndentedJson;
}

public static void Write(InteractiveDocument document, TextWriter writer)
public static void Write(InteractiveDocument document, Stream stream, KernelInfoCollection kernelInfos)
{
InteractiveDocument.MergeKernelInfos(document, kernelInfos);
using var writer = new StreamWriter(stream, _encoding, 1024, true);
var content = document.ToJupyterJson();
writer.Write(content);
writer.Flush();
}
public static void Write(InteractiveDocument document, TextWriter writer, KernelInfoCollection kernelInfos)
{
InteractiveDocument.MergeKernelInfos(document, kernelInfos);
Write(document, writer);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public KernelInfoCollection Clone()
return clone;
}

public bool TryGetByAlias(string alias, out KernelInfo info)
internal bool TryGetByAlias(string alias, out KernelInfo info)
{
return _kernelInfoByNameOrAlias!.TryGetValue(alias, out info);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.Collections.Generic;

namespace Microsoft.DotNet.Interactive.Documents;

public class ReturnValueElement : InteractiveDocumentOutputElement, IDataElement
{
public ReturnValueElement(IDictionary<string, object>? data)
{
Data = data ?? throw new ArgumentNullException(nameof(data));
}
public IDictionary<string, object> Data { get; } = new Dictionary<string, object>();

public IDictionary<string, object> Data { get; }

public int ExecutionOrder { get; set; }

public IDictionary<string, object> Metadata { get; } = new Dictionary<string, object>();
Expand Down
2 changes: 1 addition & 1 deletion src/Microsoft.DotNet.Interactive.Documents/TextElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Microsoft.DotNet.Interactive.Documents;

public class TextElement : InteractiveDocumentOutputElement
{
public TextElement(string? text, string? name)
public TextElement(string? text, string? name = "stdout")
{
Text = text ?? "";
Name = name ?? "stdout";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ public static class JupyterRequestContextExtensions
public static string GetKernelName(this JupyterRequestContext context)
{
string kernelName = null;
if (context.JupyterRequestMessageEnvelope.MetaData.TryGetValue(Notebook.MetadataNamespace, out var candidateDotnetMetadata) &&
if (context.JupyterRequestMessageEnvelope.MetaData.TryGetValue(
"dotnet_interactive",
out var candidateDotnetMetadata) &&
candidateDotnetMetadata is InputCellMetadata dotnetMetadata)
{
kernelName = dotnetMetadata.Language;
}

if (context.JupyterRequestMessageEnvelope.MetaData.TryGetValue(Notebook.PolyglotMetadataNamespace, out var candidatePolyglotMetadata) &&
if (context.JupyterRequestMessageEnvelope.MetaData.TryGetValue(
"polyglot_notebook",
out var candidatePolyglotMetadata) &&
candidatePolyglotMetadata is InputCellMetadata polyglotMetadata)
{
kernelName = polyglotMetadata.KernelName;
Expand Down

0 comments on commit 34cc09c

Please sign in to comment.