From 472a61e2cf12302a253338809e8bdd4737939898 Mon Sep 17 00:00:00 2001 From: Diego Date: Fri, 13 Sep 2019 12:05:41 +0100 Subject: [PATCH 1/7] interrupt handler --- .../CompleteRequestHandlerTests.cs | 2 - .../InterruptRequestHandlerTests.cs | 8 +++- .../InterruptRequestHandler.cs | 44 ++++++++++--------- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/Microsoft.DotNet.Interactive.Jupyter.Tests/CompleteRequestHandlerTests.cs b/Microsoft.DotNet.Interactive.Jupyter.Tests/CompleteRequestHandlerTests.cs index c4df564c16..44251f842a 100644 --- a/Microsoft.DotNet.Interactive.Jupyter.Tests/CompleteRequestHandlerTests.cs +++ b/Microsoft.DotNet.Interactive.Jupyter.Tests/CompleteRequestHandlerTests.cs @@ -1,7 +1,6 @@ // 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.Threading.Tasks; using Clockwise; using FluentAssertions; @@ -24,7 +23,6 @@ public async Task send_completeReply_on_CompleteRequest() { var scheduler = CreateScheduler(); var request = Message.Create(new CompleteRequest("System.Console.", 15), null); - var context = new JupyterRequestContext(_serverChannel, _ioPubChannel, request); await scheduler.Schedule(context); diff --git a/Microsoft.DotNet.Interactive.Jupyter.Tests/InterruptRequestHandlerTests.cs b/Microsoft.DotNet.Interactive.Jupyter.Tests/InterruptRequestHandlerTests.cs index d06362ece5..feb90c1164 100644 --- a/Microsoft.DotNet.Interactive.Jupyter.Tests/InterruptRequestHandlerTests.cs +++ b/Microsoft.DotNet.Interactive.Jupyter.Tests/InterruptRequestHandlerTests.cs @@ -5,7 +5,9 @@ using FluentAssertions; using System.Linq; using System.Threading.Tasks; +using FluentAssertions.Extensions; using Microsoft.DotNet.Interactive.Jupyter.Protocol; +using Recipes; using Xunit; using Xunit.Abstractions; @@ -22,9 +24,11 @@ public async Task sends_InterruptReply() { var scheduler = CreateScheduler(); var request = Message.Create(new InterruptRequest(), null); - await scheduler.Schedule(new JupyterRequestContext(_serverChannel, _ioPubChannel, request)); + var context = new JupyterRequestContext(_serverChannel, _ioPubChannel, request); - await _kernel.Idle(); + await scheduler.Schedule(context); + + await context.Done().Timeout(5.Seconds()); _serverRecordingSocket.DecodedMessages .SingleOrDefault(message => diff --git a/Microsoft.DotNet.Interactive.Jupyter/InterruptRequestHandler.cs b/Microsoft.DotNet.Interactive.Jupyter/InterruptRequestHandler.cs index bb8e4e9e34..4c7788a02c 100644 --- a/Microsoft.DotNet.Interactive.Jupyter/InterruptRequestHandler.cs +++ b/Microsoft.DotNet.Interactive.Jupyter/InterruptRequestHandler.cs @@ -16,44 +16,46 @@ public InterruptRequestHandler(IKernel kernel, IScheduler scheduler = null) : base(kernel, scheduler ?? CurrentThreadScheduler.Instance) { } - - protected override void OnKernelEvent(IKernelEvent @event) + + protected override void OnKernelEventReceived( + IKernelEvent @event, + JupyterRequestContext context) { + switch (@event) { case CurrentCommandCancelled kernelInterrupted: - OnExecutionInterrupted(kernelInterrupted); + OnExecutionInterrupted(kernelInterrupted, context.Request, context.ServerChannel); break; } + } - private void OnExecutionInterrupted(CurrentCommandCancelled currentCommandCancelled) + protected override void OnKernelEvent(IKernelEvent @event) { - if (InFlightRequests.TryRemove(currentCommandCancelled.Command, out var openRequest)) - { - // reply - var interruptReplyPayload = new InterruptReply(); - // send to server - var interruptReply = Message.CreateResponse( - interruptReplyPayload, - openRequest.Context.Request); - - openRequest.Context.ServerChannel.Send(interruptReply); - } } - public async Task Handle(JupyterRequestContext context) + private void OnExecutionInterrupted(CurrentCommandCancelled currentCommandCancelled, Message request, IMessageSender serverChannel) { - var interruptRequest = GetJupyterRequest(context); - var command = new CancelCurrentCommand(); + // reply + var interruptReplyPayload = new InterruptReply(); + + // send to server + var interruptReply = Message.CreateResponse( + interruptReplyPayload, + request); + + serverChannel.Send(interruptReply); - var openRequest = new InflightRequest(context, interruptRequest, 0); + } - InFlightRequests[command] = openRequest; + public async Task Handle(JupyterRequestContext context) + { + var command = new CancelCurrentCommand(); - await Kernel.SendAsync(command); + await SendTheThingAndWaitForTheStuff(context, command); } } } \ No newline at end of file From 3953e95158942cddc61b18192c6d50777b076a44 Mon Sep 17 00:00:00 2001 From: Diego Date: Fri, 13 Sep 2019 13:13:24 +0100 Subject: [PATCH 2/7] delete unused code --- .../IsCompleteRequestHandlerTests.cs | 13 +++++--- .../CompleteRequestHandler.cs | 4 --- .../ExecuteRequestHandler.cs | 4 --- .../InterruptRequestHandler.cs | 7 ----- .../IsCompleteRequestHandler.cs | 21 ++++++------- .../RequestHandlerBase.cs | 31 +++---------------- 6 files changed, 22 insertions(+), 58 deletions(-) diff --git a/Microsoft.DotNet.Interactive.Jupyter.Tests/IsCompleteRequestHandlerTests.cs b/Microsoft.DotNet.Interactive.Jupyter.Tests/IsCompleteRequestHandlerTests.cs index 58a2c37a3b..219a3ecfe6 100644 --- a/Microsoft.DotNet.Interactive.Jupyter.Tests/IsCompleteRequestHandlerTests.cs +++ b/Microsoft.DotNet.Interactive.Jupyter.Tests/IsCompleteRequestHandlerTests.cs @@ -6,6 +6,7 @@ using FluentAssertions; using System.Linq; using System.Threading.Tasks; +using FluentAssertions.Extensions; using Microsoft.DotNet.Interactive.Jupyter.Protocol; using Pocket; using Recipes; @@ -25,9 +26,10 @@ public async Task sends_isCompleteReply_with_complete_if_the_code_is_a_complete_ { var scheduler = CreateScheduler(); var request = Message.Create(new IsCompleteRequest("var a = 12;"), null); + var context = new JupyterRequestContext(_serverChannel, _ioPubChannel, request); - await scheduler.Schedule(new JupyterRequestContext(_serverChannel, _ioPubChannel, request)); - await _kernel.Idle(); + await scheduler.Schedule(context); + await context.Done().Timeout(5.Seconds()); Logger.Log.Info("DecodedMessages: {messages}", _serverRecordingSocket.DecodedMessages); @@ -47,8 +49,11 @@ public async Task sends_isCompleteReply_with_incomplete_and_indent_if_the_code_i { var scheduler = CreateScheduler(); var request = Message.Create(new IsCompleteRequest("var a = 12"), null); - await scheduler.Schedule(new JupyterRequestContext(_serverChannel, _ioPubChannel, request)); - await _kernel.Idle(); + var context = new JupyterRequestContext(_serverChannel, _ioPubChannel, request); + + await scheduler.Schedule(context); + await context.Done().Timeout(5.Seconds()); + _serverRecordingSocket.DecodedMessages.SingleOrDefault(message => message.Contains(MessageTypeValues.IsCompleteReply)) .Should() diff --git a/Microsoft.DotNet.Interactive.Jupyter/CompleteRequestHandler.cs b/Microsoft.DotNet.Interactive.Jupyter/CompleteRequestHandler.cs index b2f5463e0e..f9fbd39cd3 100644 --- a/Microsoft.DotNet.Interactive.Jupyter/CompleteRequestHandler.cs +++ b/Microsoft.DotNet.Interactive.Jupyter/CompleteRequestHandler.cs @@ -46,10 +46,6 @@ protected override void OnKernelEventReceived( } } - protected override void OnKernelEvent(IKernelEvent @event) - { - } - private static void OnCompletionRequestCompleted(CompletionRequestCompleted completionRequestCompleted, Message request, IMessageSender serverChannel) { var command = completionRequestCompleted.Command as RequestCompletion; diff --git a/Microsoft.DotNet.Interactive.Jupyter/ExecuteRequestHandler.cs b/Microsoft.DotNet.Interactive.Jupyter/ExecuteRequestHandler.cs index 73301982db..7a66d15d1a 100644 --- a/Microsoft.DotNet.Interactive.Jupyter/ExecuteRequestHandler.cs +++ b/Microsoft.DotNet.Interactive.Jupyter/ExecuteRequestHandler.cs @@ -62,10 +62,6 @@ private static Dictionary CreateTransient(string displayId) return transient; } - protected override void OnKernelEvent(IKernelEvent @event) - { - } - private void OnCommandFailed( CommandFailed commandFailed, Message request, diff --git a/Microsoft.DotNet.Interactive.Jupyter/InterruptRequestHandler.cs b/Microsoft.DotNet.Interactive.Jupyter/InterruptRequestHandler.cs index 4c7788a02c..78e1e565d8 100644 --- a/Microsoft.DotNet.Interactive.Jupyter/InterruptRequestHandler.cs +++ b/Microsoft.DotNet.Interactive.Jupyter/InterruptRequestHandler.cs @@ -21,19 +21,12 @@ protected override void OnKernelEventReceived( IKernelEvent @event, JupyterRequestContext context) { - switch (@event) { case CurrentCommandCancelled kernelInterrupted: OnExecutionInterrupted(kernelInterrupted, context.Request, context.ServerChannel); break; } - - } - - protected override void OnKernelEvent(IKernelEvent @event) - { - } private void OnExecutionInterrupted(CurrentCommandCancelled currentCommandCancelled, Message request, IMessageSender serverChannel) diff --git a/Microsoft.DotNet.Interactive.Jupyter/IsCompleteRequestHandler.cs b/Microsoft.DotNet.Interactive.Jupyter/IsCompleteRequestHandler.cs index c595c9797d..11790299de 100644 --- a/Microsoft.DotNet.Interactive.Jupyter/IsCompleteRequestHandler.cs +++ b/Microsoft.DotNet.Interactive.Jupyter/IsCompleteRequestHandler.cs @@ -2,8 +2,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System; -using System.Linq; using System.Reactive.Concurrency; using System.Threading.Tasks; using Microsoft.DotNet.Interactive.Commands; @@ -26,6 +24,7 @@ public async Task Handle(JupyterRequestContext context) await SendTheThingAndWaitForTheStuff(context, command); } + protected override void OnKernelEventReceived( IKernelEvent @event, @@ -34,20 +33,18 @@ protected override void OnKernelEventReceived( switch (@event) { case CompleteCodeSubmissionReceived completeCodeSubmissionReceived: - OnKernelEvent(completeCodeSubmissionReceived, true); + Reply( true, context.Request, context.ServerChannel); break; case IncompleteCodeSubmissionReceived incompleteCodeSubmissionReceived: - OnKernelEvent(incompleteCodeSubmissionReceived, false); + Reply( false, context.Request, context.ServerChannel); break; } } - protected override void OnKernelEvent(IKernelEvent @event){} - - private void OnKernelEvent(IKernelEvent @event, bool isComplete) + private void Reply(bool isComplete, Message request, IMessageSender serverChannel) { - if (InFlightRequests.TryRemove(@event.Command, out var openRequest)) - { + + var status = isComplete ? "complete" : "incomplete"; var indent = isComplete ? string.Empty : "*"; // reply @@ -56,10 +53,10 @@ private void OnKernelEvent(IKernelEvent @event, bool isComplete) // send to server var executeReply = Message.CreateResponse( isCompleteReplyPayload, - openRequest.Context.Request); + request); - openRequest.Context.ServerChannel.Send(executeReply); - } + serverChannel.Send(executeReply); + } } } \ No newline at end of file diff --git a/Microsoft.DotNet.Interactive.Jupyter/RequestHandlerBase.cs b/Microsoft.DotNet.Interactive.Jupyter/RequestHandlerBase.cs index 170e23b969..a1111657cf 100644 --- a/Microsoft.DotNet.Interactive.Jupyter/RequestHandlerBase.cs +++ b/Microsoft.DotNet.Interactive.Jupyter/RequestHandlerBase.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using System.Collections.Concurrent; using System.Reactive.Concurrency; using System.Reactive.Disposables; using System.Reactive.Linq; @@ -17,7 +16,7 @@ namespace Microsoft.DotNet.Interactive.Jupyter public abstract class RequestHandlerBase : IDisposable where T : JupyterMessageContent { - + private readonly CompositeDisposable _disposables = new CompositeDisposable(); protected IObservable KernelEvents { get; } @@ -27,19 +26,15 @@ protected RequestHandlerBase(IKernel kernel, IScheduler scheduler) KernelEvents = Kernel.KernelEvents.ObserveOn(scheduler ?? throw new ArgumentNullException(nameof(scheduler))); - // FIX: (RequestHandlerBase) do we care about this? - _disposables.Add(KernelEvents.Subscribe(OnKernelEvent)); } - protected abstract void OnKernelEvent(IKernelEvent @event); - protected async Task SendTheThingAndWaitForTheStuff( - JupyterRequestContext context, + JupyterRequestContext context, IKernelCommand command) { var sub = Kernel.KernelEvents.Subscribe(e => OnKernelEventReceived(e, context)); - await ((KernelBase) Kernel).SendAsync( + await ((KernelBase)Kernel).SendAsync( command, CancellationToken.None, onDone: () => sub.Dispose()); @@ -57,29 +52,11 @@ protected static T GetJupyterRequest(JupyterRequestContext context) return request; } - protected IKernel Kernel { get; } - - protected ConcurrentDictionary InFlightRequests { get; } = new ConcurrentDictionary(); + protected IKernel Kernel { get; } public void Dispose() { _disposables.Dispose(); } - - protected class InflightRequest - { - public JupyterRequestContext Context { get; } - - public T Request { get; } - - public int ExecutionCount { get; } - - public InflightRequest(JupyterRequestContext context, T request, int executionCount) - { - Context = context; - Request = request; - ExecutionCount = executionCount; - } - } } } \ No newline at end of file From dd45f3ad6d59b44f0e2e6887ebbb804b1466a272 Mon Sep 17 00:00:00 2001 From: Diego Date: Fri, 13 Sep 2019 13:51:03 +0100 Subject: [PATCH 3/7] update test --- .../IsCompleteRequestHandlerTests.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Microsoft.DotNet.Interactive.Jupyter.Tests/IsCompleteRequestHandlerTests.cs b/Microsoft.DotNet.Interactive.Jupyter.Tests/IsCompleteRequestHandlerTests.cs index 219a3ecfe6..663dc3802d 100644 --- a/Microsoft.DotNet.Interactive.Jupyter.Tests/IsCompleteRequestHandlerTests.cs +++ b/Microsoft.DotNet.Interactive.Jupyter.Tests/IsCompleteRequestHandlerTests.cs @@ -1,7 +1,6 @@ // 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 Clockwise; using FluentAssertions; using System.Linq; From 9992d215199ff5b0db852ad30be7b34f7ae60e6b Mon Sep 17 00:00:00 2001 From: Diego Date: Fri, 13 Sep 2019 14:39:52 +0100 Subject: [PATCH 4/7] align tests --- .../ExecuteRequestHandlerTests.cs | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/Microsoft.DotNet.Interactive.Jupyter.Tests/ExecuteRequestHandlerTests.cs b/Microsoft.DotNet.Interactive.Jupyter.Tests/ExecuteRequestHandlerTests.cs index a37f1460f3..d78d7e6aaf 100644 --- a/Microsoft.DotNet.Interactive.Jupyter.Tests/ExecuteRequestHandlerTests.cs +++ b/Microsoft.DotNet.Interactive.Jupyter.Tests/ExecuteRequestHandlerTests.cs @@ -5,7 +5,9 @@ using System.Threading.Tasks; using Clockwise; using FluentAssertions; +using FluentAssertions.Extensions; using Microsoft.DotNet.Interactive.Jupyter.Protocol; +using Recipes; using Xunit; using Xunit.Abstractions; @@ -22,9 +24,10 @@ public async Task sends_ExecuteInput_when_ExecuteRequest_is_handled() { var scheduler = CreateScheduler(); var request = Message.Create(new ExecuteRequest("var a =12;"), null); - await scheduler.Schedule(new JupyterRequestContext(_serverChannel, _ioPubChannel, request)); + var context = new JupyterRequestContext(_serverChannel, _ioPubChannel, request); + await scheduler.Schedule(context); - await _kernel.Idle(); + await context.Done().Timeout(5.Seconds()); _serverRecordingSocket.DecodedMessages .Should().Contain(message => @@ -40,9 +43,10 @@ public async Task sends_ExecuteReply_message_on_when_code_submission_is_handled( { var scheduler = CreateScheduler(); var request = Message.Create(new ExecuteRequest("var a =12;"), null); - await scheduler.Schedule(new JupyterRequestContext(_serverChannel, _ioPubChannel, request)); + var context = new JupyterRequestContext(_serverChannel, _ioPubChannel, request); + await scheduler.Schedule(context); - await _kernel.Idle(); + await context.Done().Timeout(5.Seconds()); _serverRecordingSocket.DecodedMessages .Should().Contain(message => @@ -54,9 +58,10 @@ public async Task sends_ExecuteReply_with_error_message_on_when_code_submission_ { var scheduler = CreateScheduler(); var request = Message.Create(new ExecuteRequest("asdes"), null); - await scheduler.Schedule(new JupyterRequestContext(_serverChannel, _ioPubChannel, request)); + var context = new JupyterRequestContext(_serverChannel, _ioPubChannel, request); + await scheduler.Schedule(context); - await _kernel.Idle(); + await context.Done().Timeout(5.Seconds()); _serverRecordingSocket.DecodedMessages .Should() @@ -74,9 +79,10 @@ public async Task sends_DisplayData_message_on_ValueProduced() { var scheduler = CreateScheduler(); var request = Message.Create(new ExecuteRequest("Console.WriteLine(2+2);"), null); - await scheduler.Schedule(new JupyterRequestContext(_serverChannel, _ioPubChannel, request)); + var context = new JupyterRequestContext(_serverChannel, _ioPubChannel, request); + await scheduler.Schedule(context); - await _kernel.Idle(); + await context.Done().Timeout(5.Seconds()); _serverRecordingSocket.DecodedMessages .Should().Contain(message => @@ -92,9 +98,10 @@ public async Task sends_ExecuteReply_message_on_ReturnValueProduced() { var scheduler = CreateScheduler(); var request = Message.Create(new ExecuteRequest("2+2"), null); - await scheduler.Schedule(new JupyterRequestContext(_serverChannel, _ioPubChannel, request)); + var context = new JupyterRequestContext(_serverChannel, _ioPubChannel, request); + await scheduler.Schedule(context); - await _kernel.Idle(); + await context.Done().Timeout(5.Seconds()); _serverRecordingSocket.DecodedMessages .Should().Contain(message => @@ -110,9 +117,10 @@ public async Task sends_ExecuteReply_message_when_submission_contains_only_a_dir { var scheduler = CreateScheduler(); var request = Message.Create(new ExecuteRequest("%%csharp"), null); - await scheduler.Schedule(new JupyterRequestContext(_serverChannel, _ioPubChannel, request)); + var context = new JupyterRequestContext(_serverChannel, _ioPubChannel, request); + await scheduler.Schedule(context); - await _kernel.Idle(); + await context.Done().Timeout(5.Seconds()); _serverRecordingSocket.DecodedMessages .Should().Contain(message => From cc3269fb2137cb407402d48014fc9f77bf222097 Mon Sep 17 00:00:00 2001 From: Diego Date: Fri, 13 Sep 2019 14:54:24 +0100 Subject: [PATCH 5/7] unused namespaces --- .../ExecuteRequestHandlerTests.cs | 1 - WorkspaceServer.Tests/Kernel/KernelInvocationContextTests.cs | 1 - 2 files changed, 2 deletions(-) diff --git a/Microsoft.DotNet.Interactive.Jupyter.Tests/ExecuteRequestHandlerTests.cs b/Microsoft.DotNet.Interactive.Jupyter.Tests/ExecuteRequestHandlerTests.cs index d78d7e6aaf..2a318ebbd8 100644 --- a/Microsoft.DotNet.Interactive.Jupyter.Tests/ExecuteRequestHandlerTests.cs +++ b/Microsoft.DotNet.Interactive.Jupyter.Tests/ExecuteRequestHandlerTests.cs @@ -1,7 +1,6 @@ // 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.Threading.Tasks; using Clockwise; using FluentAssertions; diff --git a/WorkspaceServer.Tests/Kernel/KernelInvocationContextTests.cs b/WorkspaceServer.Tests/Kernel/KernelInvocationContextTests.cs index e67f62c282..41e97bea78 100644 --- a/WorkspaceServer.Tests/Kernel/KernelInvocationContextTests.cs +++ b/WorkspaceServer.Tests/Kernel/KernelInvocationContextTests.cs @@ -1,7 +1,6 @@ // 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 FluentAssertions; using System.Linq; using System.Reactive.Linq; From 24b2d9bab1785224cd28709619f052880e492942 Mon Sep 17 00:00:00 2001 From: Diego Date: Fri, 13 Sep 2019 17:47:31 +0100 Subject: [PATCH 6/7] down to 1 test broken --- .../ExecuteRequestHandlerTests.cs | 2 +- Microsoft.DotNet.Interactive.Jupyter/ExecuteRequestHandler.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Microsoft.DotNet.Interactive.Jupyter.Tests/ExecuteRequestHandlerTests.cs b/Microsoft.DotNet.Interactive.Jupyter.Tests/ExecuteRequestHandlerTests.cs index 2a318ebbd8..62143c608a 100644 --- a/Microsoft.DotNet.Interactive.Jupyter.Tests/ExecuteRequestHandlerTests.cs +++ b/Microsoft.DotNet.Interactive.Jupyter.Tests/ExecuteRequestHandlerTests.cs @@ -81,7 +81,7 @@ public async Task sends_DisplayData_message_on_ValueProduced() var context = new JupyterRequestContext(_serverChannel, _ioPubChannel, request); await scheduler.Schedule(context); - await context.Done().Timeout(5.Seconds()); + await context.Done().Timeout(10.Seconds()); _serverRecordingSocket.DecodedMessages .Should().Contain(message => diff --git a/Microsoft.DotNet.Interactive.Jupyter/ExecuteRequestHandler.cs b/Microsoft.DotNet.Interactive.Jupyter/ExecuteRequestHandler.cs index 7a66d15d1a..14e5e612cd 100644 --- a/Microsoft.DotNet.Interactive.Jupyter/ExecuteRequestHandler.cs +++ b/Microsoft.DotNet.Interactive.Jupyter/ExecuteRequestHandler.cs @@ -48,7 +48,7 @@ protected override void OnKernelEventReceived( OnValueProduced(valueProduced, context.Request, context.IoPubChannel); break; case CommandHandled commandHandled: - OnCommandHandled(commandHandled, context.Request, context.IoPubChannel); + OnCommandHandled(commandHandled, context.Request, context.ServerChannel); break; case CommandFailed commandFailed: OnCommandFailed(commandFailed, context.Request, context.ServerChannel, context.IoPubChannel); From 08ddc8dd38fa8a62960af4f758eecab094d9aeff Mon Sep 17 00:00:00 2001 From: Diego Date: Fri, 13 Sep 2019 18:05:55 +0100 Subject: [PATCH 7/7] including raw value in display and update commands --- .../Commands/DisplayValue.cs | 5 ++++- .../Commands/UpdateDisplayedValue.cs | 5 ++++- .../DisplayedValueProduced.cs | 2 +- Microsoft.DotNet.Interactive/Kernel.cs | 4 ++-- Microsoft.DotNet.Interactive/KernelBase.cs | 4 ++-- .../Kernel/KernelInvocationContextTests.cs | 12 +++++++----- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/Microsoft.DotNet.Interactive/Commands/DisplayValue.cs b/Microsoft.DotNet.Interactive/Commands/DisplayValue.cs index 4d22459772..52c4ac2045 100644 --- a/Microsoft.DotNet.Interactive/Commands/DisplayValue.cs +++ b/Microsoft.DotNet.Interactive/Commands/DisplayValue.cs @@ -5,12 +5,15 @@ namespace Microsoft.DotNet.Interactive.Commands { public class DisplayValue : KernelCommandBase { - public DisplayValue(FormattedValue formattedValue, string valueId = null) + public DisplayValue(object value, FormattedValue formattedValue, string valueId = null) { + Value = value; FormattedValue = formattedValue; ValueId = valueId; } + public object Value { get; } + public FormattedValue FormattedValue { get; } public string ValueId { get; } diff --git a/Microsoft.DotNet.Interactive/Commands/UpdateDisplayedValue.cs b/Microsoft.DotNet.Interactive/Commands/UpdateDisplayedValue.cs index 5523ccb08a..848989b8f1 100644 --- a/Microsoft.DotNet.Interactive/Commands/UpdateDisplayedValue.cs +++ b/Microsoft.DotNet.Interactive/Commands/UpdateDisplayedValue.cs @@ -7,16 +7,19 @@ namespace Microsoft.DotNet.Interactive.Commands { public class UpdateDisplayedValue : KernelCommandBase { - public UpdateDisplayedValue(FormattedValue formattedValue, string valueId) + public UpdateDisplayedValue(object value, FormattedValue formattedValue, string valueId) { if (string.IsNullOrWhiteSpace(valueId)) { throw new ArgumentException("Value cannot be null or whitespace.", nameof(valueId)); } + + Value = value; FormattedValue = formattedValue; ValueId = valueId; } + public object Value { get; } public FormattedValue FormattedValue { get; } public string ValueId { get; } } diff --git a/Microsoft.DotNet.Interactive/DisplayedValueProduced.cs b/Microsoft.DotNet.Interactive/DisplayedValueProduced.cs index cf7459b275..1b389534e6 100644 --- a/Microsoft.DotNet.Interactive/DisplayedValueProduced.cs +++ b/Microsoft.DotNet.Interactive/DisplayedValueProduced.cs @@ -37,7 +37,7 @@ public void Update(object updatedValue) var kernel = KernelInvocationContext.Current.HandlingKernel; Task.Run(() => - kernel.SendAsync(new UpdateDisplayedValue(formatted, _displayId))) + kernel.SendAsync(new UpdateDisplayedValue(updatedValue, formatted, _displayId))) .Wait(); } } diff --git a/Microsoft.DotNet.Interactive/Kernel.cs b/Microsoft.DotNet.Interactive/Kernel.cs index d0888e78b7..d4bad3f70b 100644 --- a/Microsoft.DotNet.Interactive/Kernel.cs +++ b/Microsoft.DotNet.Interactive/Kernel.cs @@ -23,7 +23,7 @@ public static DisplayedValue display( var kernel = KernelInvocationContext.Current.HandlingKernel; Task.Run(() => - kernel.SendAsync(new DisplayValue(formatted, displayId))) + kernel.SendAsync(new DisplayValue(value, formatted, displayId))) .Wait(); return new DisplayedValue(displayId, mimeType); } @@ -43,7 +43,7 @@ public static void Javascript( var kernel = KernelInvocationContext.Current.HandlingKernel; Task.Run(() => - kernel.SendAsync(new DisplayValue(formatted))) + kernel.SendAsync(new DisplayValue(value,formatted))) .Wait(); } } diff --git a/Microsoft.DotNet.Interactive/KernelBase.cs b/Microsoft.DotNet.Interactive/KernelBase.cs index 6b2b23abe4..8eb3031271 100644 --- a/Microsoft.DotNet.Interactive/KernelBase.cs +++ b/Microsoft.DotNet.Interactive/KernelBase.cs @@ -218,7 +218,7 @@ private async Task HandleDisplayValue( { invocationContext.Publish( new DisplayedValueProduced( - displayValue.FormattedValue, + displayValue.Value, displayValue, formattedValues: new[] { displayValue.FormattedValue }, valueId: displayValue.ValueId)); @@ -238,7 +238,7 @@ private async Task HandleUpdateDisplayValue( { invocationContext.Publish( new DisplayedValueUpdated( - displayedValue.FormattedValue, + displayedValue.Value, valueId: displayedValue.ValueId, command: displayedValue, formattedValues: new[] { displayedValue.FormattedValue } diff --git a/WorkspaceServer.Tests/Kernel/KernelInvocationContextTests.cs b/WorkspaceServer.Tests/Kernel/KernelInvocationContextTests.cs index 41e97bea78..69088c4449 100644 --- a/WorkspaceServer.Tests/Kernel/KernelInvocationContextTests.cs +++ b/WorkspaceServer.Tests/Kernel/KernelInvocationContextTests.cs @@ -1,9 +1,10 @@ // 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.Collections.Generic; using FluentAssertions; +using System; using System.Linq; -using System.Reactive.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.DotNet.Interactive; @@ -60,17 +61,18 @@ public async Task When_a_command_spawns_another_command_then_parent_context_is_n kernel.Pipeline.AddMiddleware(async (command, context, next) => { - context.Publish(new DisplayedValueProduced("1", command)); + context.Publish(new DisplayedValueProduced(1, command)); await next(command, context); - context.Publish(new DisplayedValueProduced("3", command)); + context.Publish(new DisplayedValueProduced(3, command)); }); var result = await kernel.SendAsync(new SubmitCode("display(2);")); + var events = new List(); - var events = result.KernelEvents.ToEnumerable(); - + result.KernelEvents.Subscribe(e => events.Add(e)); + events.OfType() .Select(v => v.Value) .Should()