public void error_cell_outputs_are_serialized() { var cells = new List <InteractiveDocumentElement>() { new InteractiveDocumentElement("csharp", "//", new[] { new ErrorElement("e-name", "e-value", new[] { "at func1()", "at func2()" }) }) }; var notebook = new InteractiveDocument(cells); var serialized = SerializeJupyter(notebook, "\n"); var jupyter = JToken.Parse(serialized); jupyter["cells"] .Should() .ContainSingleItem() .Which["outputs"] .Should() .ContainSingleItem() .Which .Should() .BeEquivalentTo(JToken.Parse(JsonConvert.SerializeObject( new { output_type = "error", ename = "e-name", evalue = "e-value", traceback = new[] { "at func1()", "at func2()" } } ))); }
public async Task parser_can_parse_teacher_notebook_with_two_challenges_with_all_components_defined() { InteractiveDocument document = await ReadDibAsync("forParsing1.dib"); NotebookLessonParser.Parse(document, out var lesson, out var challenges); lesson.Setup.Select(sc => sc.Code).Join("\r\n").Should().ContainAll("lessonSetupCell1", "lessonSetupCell2"); challenges[0].Name.Should().Be("Challenge1Name"); challenges[0].Setup.Select(sc => sc.Code).Join("\r\n") .Should().ContainAll("challenge1SetupCell1", "challenge1SetupCell2"); challenges[0].EnvironmentSetup.Select(sc => sc.Code).Join("\r\n") .Should().ContainAll("challenge1EnvironmentSetupCell1", "challenge1EnvironmentSetupCell2"); challenges[0].Contents.Select(sec => sec.Code).Join("\r\n") .Should().ContainAll("challenge1QuestionCell1", "challenge1QuestionCell2"); challenges[1].Name.Should().Be("Challenge2Name"); challenges[1].Setup.Select(sc => sc.Code).Join("\r\n") .Should().ContainAll("challenge2SetupCell1", "challenge2SetupCell2"); challenges[1].EnvironmentSetup.Select(sc => sc.Code).Join("\r\n") .Should().ContainAll("challenge2EnvironmentSetupCell1", "challenge2EnvironmentSetupCell2"); challenges[1].Contents.Select(sec => sec.Code).Join("\r\n") .Should().ContainAll("challenge2QuestionCell1", "challenge2QuestionCell2"); }
public void text_cell_outputs_are_serialized() { var cells = new List <InteractiveDocumentElement>() { new InteractiveDocumentElement("csharp", "//", new[] { new TextElement("this is text") }) }; var notebook = new InteractiveDocument(cells); var serialized = SerializeJupyter(notebook, "\n"); var jupyter = JToken.Parse(serialized); jupyter["cells"] .Should() .ContainSingleItem() .Which["outputs"] .Should() .ContainSingleItem() .Which .Should() .BeEquivalentTo(JToken.Parse(JsonConvert.SerializeObject( new { output_type = "stream", name = "stdout", text = "this is text" } ))); }
public void serialized_code_cells_have_appropriate_shape() { var cells = new List <InteractiveDocumentElement>() { new InteractiveDocumentElement("csharp", "//") }; var notebook = new InteractiveDocument(cells); var serialized = SerializeJupyter(notebook, "\n"); var jupyter = JToken.Parse(serialized); jupyter["cells"] .Should() .ContainSingleItem() .Which .Should() .BeEquivalentTo(JToken.Parse(JsonConvert.SerializeObject( new { cell_type = "code", execution_count = 1, metadata = new { dotnet_interactive = new { language = "csharp" } }, source = new[] { "//" }, outputs = Array.Empty <object>() } ))); }
public void serialized_markdown_cells_have_appropriate_shape() { var cells = new List <InteractiveDocumentElement>() { new InteractiveDocumentElement("markdown", "This is `markdown`.\nThis is more `markdown`.") }; var notebook = new InteractiveDocument(cells); var serialized = SerializeJupyter(notebook, "\n"); var jupyter = JToken.Parse(serialized); jupyter["cells"] .Should() .ContainSingleItem() .Which .Should() .BeEquivalentTo(JToken.Parse(JsonConvert.SerializeObject( new { cell_type = "markdown", metadata = new { }, source = new[] { "This is `markdown`.\n", "This is more `markdown`.", } } ))); }
public void serialized_code_cells_with_non_default_jupyter_kernel_language_have_language_metadata_and_no_language_specifier() { var cells = new List <InteractiveDocumentElement>() { new InteractiveDocumentElement("fsharp", "let x = 1") }; var notebook = new InteractiveDocument(cells); var serialized = SerializeJupyter(notebook, "\n"); var jupyter = JToken.Parse(serialized); jupyter["cells"][0] .Should() .BeEquivalentTo(JToken.Parse(JsonConvert.SerializeObject(new { cell_type = "code", execution_count = 1, metadata = new { dotnet_interactive = new { language = "fsharp" } }, source = new[] { "let x = 1" }, outputs = new object[] { } }))); }
public void serialized_notebook_has_appropriate_metadata() { var notebook = new InteractiveDocument(new List <InteractiveDocumentElement>()); var serialized = SerializeJupyter(notebook, "\n"); var jupyter = JToken.Parse(serialized); using var _ = new AssertionScope(); jupyter["metadata"] .Should() .BeEquivalentTo(JToken.Parse(JsonConvert.SerializeObject(new { kernelspec = new { display_name = ".NET (C#)", language = "C#", name = ".net-csharp" }, language_info = new { file_extension = ".cs", mimetype = "text/x-csharp", name = "C#", pygments_lexer = "csharp", version = "8.0" } }))); jupyter["nbformat"] .ToObject <int>() .Should() .Be(4); jupyter["nbformat_minor"] .ToObject <int>() .Should() .Be(4); }
public void multiple_cells_are_serialized_with_appropriate_separators(string newline) { var cells = new[] { new InteractiveDocumentElement("csharp", $"// C# line 1{newline}// C# line 2"), new InteractiveDocumentElement("fsharp", $"// F# line 1{newline}// F# line 2"), new InteractiveDocumentElement("markdown", "This is `markdown`.") }; var notebook = new InteractiveDocument(cells); var serialized = SerializeDib(notebook, newline); var expectedLines = new[] { "#!csharp", "", "// C# line 1", "// C# line 2", "", "#!fsharp", "", "// F# line 1", "// F# line 2", "", "#!markdown", "", "This is `markdown`.", "" }; var expected = string.Join(newline, expectedLines); serialized .Should() .Be(expected); }
public async Task duplicate_challenge_name_causes_parser_to_throw_exception() { InteractiveDocument document = await ReadDibAsync("forParsing2DuplicateChallengeName.dib"); Action parsingDuplicateChallengeName = () => NotebookLessonParser.Parse(document, out var _, out var _); parsingDuplicateChallengeName .Should().Throw <ArgumentException>() .Which.Message.Should().Contain("conflicts"); }
public async Task notebook_with_no_challenge_causes_parser_to_throw_exception() { InteractiveDocument document = await ReadDibAsync("noChallenge.dib"); Action parsingDuplicateChallengeName = () => NotebookLessonParser.Parse(document, out var _, out var _); parsingDuplicateChallengeName .Should().Throw <ArgumentException>() .Which.Message.Should().Contain("This lesson has no challenges"); }
public async Task a_challenge_with_no_question_causes_parser_to_throw_exception() { InteractiveDocument document = await ReadDibAsync("challengeWithNoQuestion.dib"); Action parsingDuplicateChallengeName = () => NotebookLessonParser.Parse(document, out var _, out var _); parsingDuplicateChallengeName .Should().Throw <ArgumentException>() .Which.Message.Should().Contain("empty question"); }
public void serialized_code_cells_with_default_jupyter_kernel_language_dont_have_language_specifier() { var cells = new List <InteractiveDocumentElement>() { new InteractiveDocumentElement("csharp", "var x = 1;") }; var notebook = new InteractiveDocument(cells); var serialized = SerializeJupyter(notebook, "\n"); var jupyter = JToken.Parse(serialized); jupyter["cells"][0]["source"] .Should() .BeEquivalentTo(JToken.Parse(JsonConvert.SerializeObject(new object[] { "var x = 1;" }))); }
public void code_cells_with_multi_line_text_are_serialized_as_an_array() { var cells = new List <InteractiveDocumentElement>() { new InteractiveDocumentElement("csharp", "var x = 1;\nvar y = 2;") }; var notebook = new InteractiveDocument(cells); var serialized = SerializeJupyter(notebook, "\n"); var jupyter = JToken.Parse(serialized); jupyter["cells"][0]["source"] .Should() .BeEquivalentTo(JToken.Parse(JsonConvert.SerializeObject(new object[] { "var x = 1;\n", "var y = 2;" }))); }
public void serialize_entire_file_to_verify_indention() { var configuration = new Configuration() .UsingExtension("json") .SetInteractive(Debugger.IsAttached); var cells = new List <InteractiveDocumentElement>() { new InteractiveDocumentElement("csharp", "// this is csharp", new[] { new DisplayElement(new Dictionary <string, object>() { { "text/html", "this is html" } }) }), new InteractiveDocumentElement("markdown", "This is `markdown`.") }; var notebook = new InteractiveDocument(cells); var json = SerializeJupyter(notebook, "\n"); this.Assent(json, configuration); }
public void extra_blank_lines_are_removed_from_beginning_and_end_on_save() { var cells = new[] { new InteractiveDocumentElement("csharp", "\n\n\n\n// this is csharp\n\n\n") }; var notebook = new InteractiveDocument(cells); var serialized = SerializeDib(notebook, "\n"); var expectedLines = new[] { "#!csharp", "", "// this is csharp", "" }; var expected = string.Join("\n", expectedLines); serialized .Should() .Be(expected); }
public void empty_cells_are_not_serialized() { var cells = new[] { new InteractiveDocumentElement("csharp", ""), new InteractiveDocumentElement("fsharp", "// this is fsharp"), new InteractiveDocumentElement("csharp", "") }; var notebook = new InteractiveDocument(cells); var serialized = SerializeDib(notebook, "\n"); var expectedLines = new[] { "#!fsharp", "", "// this is fsharp", "" }; var expected = string.Join("\n", expectedLines); serialized .Should() .Be(expected); }
public void rich_cell_outputs_are_serialized() { var cells = new List <InteractiveDocumentElement>() { new InteractiveDocumentElement("csharp", "//", new[] { new DisplayElement(new Dictionary <string, object> { { "text/html", "this is html" } }) }) }; var notebook = new InteractiveDocument(cells); var serialized = SerializeJupyter(notebook, "\n"); var jupyter = JToken.Parse(serialized); jupyter["cells"] .Should() .ContainSingleItem() .Which["outputs"] .Should() .ContainSingleItem() .Which .Should() .BeEquivalentTo(JToken.Parse(JsonConvert.SerializeObject( new { output_type = "execute_result", data = new Dictionary <string, string>() { { "text/html", "this is html" } }, execution_count = 1, metadata = new { } } ))); }
public NotebookSerializeRequest(string id, DocumentSerializationType serializationType, string defaultLanguage, string newLine, InteractiveDocument document) : base(id, serializationType, defaultLanguage) { NewLine = newLine ?? throw new ArgumentNullException(nameof(newLine)); Document = document ?? throw new ArgumentNullException(nameof(document)); }
public string SerializeDib(InteractiveDocument interactive, string newLine) { return(interactive.ToCodeSubmissionContent(newLine)); }
public override NotebookParseOrSerializeRequest Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { EnsureStartObject(reader, typeToConvert); RequestType?type = null; string id = null; DocumentSerializationType?serializationType = null; string defaultLanguage = null; byte[] rawData = null; string newLine = null; InteractiveDocument document = null; while (reader.Read()) { if (reader.TokenType == JsonTokenType.PropertyName) { switch (reader.GetString()) { case "type": if (reader.Read() && reader.TokenType == JsonTokenType.String) { type = JsonSerializer.Deserialize <RequestType>(ref reader, options); } break; case "id": if (reader.Read() && reader.TokenType == JsonTokenType.String) { id = reader.GetString(); } break; case "serializationType": if (reader.Read() && reader.TokenType == JsonTokenType.String) { serializationType = JsonSerializer.Deserialize <DocumentSerializationType>(ref reader, options); } break; case "defaultLanguage": if (reader.Read() && reader.TokenType == JsonTokenType.String) { defaultLanguage = reader.GetString(); } break; case "rawData": if (reader.Read() && reader.TokenType == JsonTokenType.String) { rawData = JsonSerializer.Deserialize <byte[]>(ref reader, options); } break; case "newLine": if (reader.Read() && reader.TokenType == JsonTokenType.String) { newLine = reader.GetString(); } break; case "document": if (reader.Read() && reader.TokenType == JsonTokenType.StartObject) { document = JsonSerializer.Deserialize <InteractiveDocument>(ref reader, options); } break; } } else if (reader.TokenType == JsonTokenType.EndObject) { if (type is null || id is null || serializationType is null || defaultLanguage is null) { throw new JsonException("Missing properties on request object"); } switch (type.GetValueOrDefault()) { case RequestType.Parse: if (rawData is null) { throw new JsonException($"Missing property for {nameof(NotebookParseRequest)}"); } return(new NotebookParseRequest(id, serializationType.GetValueOrDefault(), defaultLanguage, rawData)); case RequestType.Serialize: if (newLine is null || document is null) { throw new JsonException($"Missing property for {nameof(NotebookSerializeRequest)}"); } return(new NotebookSerializeRequest(id, serializationType.GetValueOrDefault(), defaultLanguage, newLine, document)); default: throw new JsonException($"Unsupported request type '{type}'"); } } } throw new JsonException($"Cannot deserialize {typeToConvert.Name}"); }
public NotebookParseResponse(string id, InteractiveDocument document) : base(id) { Document = document ?? throw new ArgumentNullException(nameof(document)); }
public override NotebookParserServerResponse Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { EnsureStartObject(reader, typeToConvert); string id = null; InteractiveDocument document = null; byte[] rawData = null; string errorMessage = null; while (reader.Read()) { if (reader.TokenType == JsonTokenType.PropertyName) { switch (reader.GetString()) { case "id": if (reader.Read() && reader.TokenType == JsonTokenType.String) { id = reader.GetString(); } break; case "document": if (reader.Read() && reader.TokenType == JsonTokenType.StartObject) { document = JsonSerializer.Deserialize <InteractiveDocument>(ref reader, options); } break; case "rawData": if (reader.Read() && reader.TokenType == JsonTokenType.String) { rawData = JsonSerializer.Deserialize <byte[]>(ref reader, options); } break; case "errorMessage": if (reader.Read() && reader.TokenType == JsonTokenType.String) { errorMessage = reader.GetString(); } break; } } else if (reader.TokenType == JsonTokenType.EndObject) { if (id is null) { throw new JsonException("Missing properties on response object"); } if (document is not null) { return(new NotebookParseResponse(id, document)); } if (rawData is not null) { return(new NotebookSerializeResponse(id, rawData)); } if (errorMessage is not null) { return(new NotebookErrorResponse(id, errorMessage)); } throw new JsonException($"Cannot deserialize {typeToConvert.Name} due to missing properties"); } } throw new JsonException($"Cannot deserialize {typeToConvert.Name}"); }
public static CompositeKernel UseProgressiveLearning( this CompositeKernel kernel, HttpClient httpClient = null) { kernel.Bootstrapping(); var fromUrlOption = new Option <Uri>( "--from-url", "Specify lesson source URL"); var fromFileOption = new Option <FileInfo>( "--from-file", description: "Specify lesson source file", parseArgument: result => { var filePath = result.Tokens.Single().Value; var fromUrlResult = result.FindResultFor(fromUrlOption); if (fromUrlResult is not null) { result.ErrorMessage = $"The {fromUrlResult.Token.Value} and {(result.Parent as OptionResult).Token.Value} options cannot be used together"; return(null); } if (!File.Exists(filePath)) { result.ErrorMessage = Resources.Instance.FileDoesNotExist(filePath); return(null); } return(new FileInfo(filePath)); }); var startCommand = new Command("#!start-lesson") { fromFileOption, fromUrlOption }; startCommand.Handler = CommandHandler.Create <Uri, FileInfo, KernelInvocationContext>(StartCommandHandler); kernel.AddDirective(startCommand); return(kernel); async Task StartCommandHandler(Uri fromUrl, FileInfo fromFile, KernelInvocationContext context) { InteractiveDocument document = fromFile switch { { } => await NotebookLessonParser.ReadFileAsInteractiveDocument(fromFile, kernel), _ => await NotebookLessonParser.LoadNotebookFromUrl(fromUrl, httpClient) }; NotebookLessonParser.Parse(document, out var lessonDefinition, out var challengeDefinitions); var challenges = challengeDefinitions.Select(b => b.ToChallenge()).ToList(); challenges.SetDefaultProgressionHandlers(); Lesson.From(lessonDefinition); Lesson.SetChallengeLookup(queryName => { return(challenges.FirstOrDefault(c => c.Name == queryName)); }); await kernel.StartLesson(); await Lesson.StartChallengeAsync(challenges.First()); await kernel.InitializeChallenge(Lesson.CurrentChallenge); }
public string SerializeJupyter(InteractiveDocument interactive, string newLine) { return(interactive.ToJupyterNotebookContent(newLine)); }