Skip to content

Commit 9380011

Browse files
committed
Prototype sending multiple mime types (for Plotly initially)
#142
1 parent c5e4202 commit 9380011

File tree

5 files changed

+38
-27
lines changed

5 files changed

+38
-27
lines changed

Diff for: src/IfSharp.Kernel/App.fs

+3-4
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,12 @@ module App =
4848

4949
if value <> null then
5050
if sbPrint.Length > 0 then
51-
Kernel.Value.SendDisplayData("text/plain", sbPrint.ToString())
51+
Kernel.Value.SendDisplayData( Map.ofList [("text/plain", sbPrint.ToString() :> obj)])
5252
sbPrint.Clear() |> ignore
5353

5454
let printer = Printers.findDisplayPrinter (value.GetType())
55-
let (_, callback) = printer
56-
let callbackValue = callback(value)
57-
Kernel.Value.SendDisplayData(callbackValue.ContentType, callbackValue.Data)
55+
let callbackValue = printer(value)
56+
Kernel.Value.SendDisplayData callbackValue
5857

5958
/// Global help function
6059
let Help (value : obj) =

Diff for: src/IfSharp.Kernel/Kernel.fs

+11-14
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ type IfSharpKernel(connectionInformation : ConnectionInformation) =
8585
/// Serializes any object into JSON
8686
let serialize (obj) =
8787
let ser = JsonSerializer()
88-
let sw = new StringWriter()
88+
use sw = new StringWriter()
8989
ser.Serialize(sw, obj)
9090
sw.ToString()
9191

@@ -214,17 +214,14 @@ type IfSharpKernel(connectionInformation : ConnectionInformation) =
214214
sendMessage shellSocket msg "kernel_info_reply" content
215215

216216
/// Sends display data information immediately
217-
let sendDisplayData (contentType) (displayItem) (messageType) =
217+
let sendDisplayData (data: Map<string, obj>) (messageType) =
218218
if lastMessage.IsSome then
219219

220-
let d = Dictionary<string,obj>()
221-
d.Add(contentType, displayItem)
222-
223-
let reply = { execution_count = executionCount; data = d; metadata = Dictionary<string,obj>() }
220+
let reply = { execution_count = executionCount; data = data; metadata = Dictionary<string,obj>() }
224221
sendMessage ioSocket lastMessage.Value messageType reply
225222

226223
/// Sends a message to pyout
227-
let pyout (message) = sendDisplayData "text/plain" message "pyout"
224+
let pyout (message) = sendDisplayData (Map.ofList[("text/plain", message)]) "pyout"
228225

229226
/// Preprocesses the code and evaluates it
230227
let preprocessCode(code) =
@@ -343,9 +340,9 @@ type IfSharpKernel(connectionInformation : ConnectionInformation) =
343340
if it.ReflectionType <> typeof<unit> then
344341
let printer =
345342
Printers.findDisplayPrinter it.ReflectionType
346-
let (_, callback) = printer
347-
let callbackValue = callback(it.ReflectionValue)
348-
sendDisplayData callbackValue.ContentType callbackValue.Data "pyout"
343+
let callbackValue = printer(it.ReflectionValue)
344+
sendDisplayData callbackValue "pyout"
345+
349346

350347
| None -> ()
351348

@@ -360,7 +357,7 @@ type IfSharpKernel(connectionInformation : ConnectionInformation) =
360357
sendError err
361358

362359
if sbPrint.Length > 0 then
363-
sendDisplayData "text/plain" (sbPrint.ToString()) "display_data"
360+
sendDisplayData (Map.ofList[("text/plain", sbPrint.ToString() :> obj)]) "display_data"
364361

365362
// we are now idle
366363
sendStateIdle msg
@@ -431,7 +428,7 @@ type IfSharpKernel(connectionInformation : ConnectionInformation) =
431428
|]
432429
|> Array.filter (fun x -> x.Subcategory <> "parse")
433430

434-
sendDisplayData "errors" newErrors "display_data"
431+
sendDisplayData (Map.ofList[("errors", newErrors :> obj)]) "display_data"
435432
sendMessage (shellSocket) (msg) ("complete_reply") (newContent)
436433

437434
/// Handles a 'connect_request' message
@@ -533,8 +530,8 @@ type IfSharpKernel(connectionInformation : ConnectionInformation) =
533530
payload.Add( { html = ""; source = "page"; start_line_number = 1; text = text })
534531

535532
/// Adds display data to the list of display data to send to the client
536-
member __.SendDisplayData (contentType, displayItem) =
537-
sendDisplayData contentType displayItem "display_data"
533+
member __.SendDisplayData data =
534+
sendDisplayData data "display_data"
538535

539536
/// Starts the kernel asynchronously
540537
member __.StartAsync() =

Diff for: src/IfSharp.Kernel/Printers.fs

+22-8
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,24 @@ open System.Web
66

77
module Printers =
88

9-
let mutable internal displayPrinters : list<Type * (obj -> BinaryOutput)> = []
9+
let mutable internal displayPrinters : list<Type * (obj -> Map<string,obj>)> = []
10+
let mutable internal displayMultiPrinters : list<Type * (obj -> Map<string,obj>)> = []
1011

1112
/// Convenience method for encoding a string within HTML
1213
let internal htmlEncode(str) = HttpUtility.HtmlEncode(str)
1314

1415
/// Adds a custom display printer for extensibility
1516
let addDisplayPrinter(printer : 'T -> BinaryOutput) =
16-
displayPrinters <- (typeof<'T>, (fun (x:obj) -> printer (unbox x))) :: displayPrinters
17+
displayPrinters <- (typeof<'T>, (fun (x:obj) ->
18+
let binaryOutput = printer (unbox x)
19+
Map.ofList [(binaryOutput.ContentType, binaryOutput.Data)])) :: displayPrinters
20+
21+
let addDisplayMultiPrinter(printer : 'T -> Map<string,obj>) =
22+
displayMultiPrinters <- (typeof<'T>, (fun (x:obj) -> printer (unbox x))) :: displayMultiPrinters
1723

1824
/// Default display printer
1925
let defaultDisplayPrinter(x) =
20-
{ ContentType = "text/plain"; Data = sprintf "%A" x }
26+
Map.ofList [("text/plain", sprintf "%A" x :> obj)]
2127

2228
//https://technet.microsoft.com/en-us/ee353649(v=vs.85)
2329
let mapToFSharpAliases fullType name =
@@ -59,7 +65,7 @@ module Printers =
5965

6066
let functionPrinter(func:obj) =
6167
let funcArguments = possiblyAFuncAsString (func.GetType())
62-
{ ContentType = "text/plain"; Data = sprintf "%A : %s" func funcArguments }
68+
Map.ofList [("text/plain", sprintf "%A : %s" func funcArguments :> obj)]
6369

6470
/// Finds a display printer based off of the type
6571
let findDisplayPrinter(findType) =
@@ -70,19 +76,27 @@ module Printers =
7076
|> Seq.map (fun (t, p) -> t, fun o ->
7177
let extras, html = p o
7278
let extras = extras |> Seq.map snd |> String.concat ""
73-
{ ContentType = "text/html"; Data = extras + html })
79+
//let binaryOutput = { ContentType = "text/html"; Data = extras + html }
80+
Map.ofList [("text/html", (extras + html) :> obj)])
7481

7582
let printers =
7683
Seq.append displayPrinters extraPrinters
7784
|> Seq.filter (fun (t, _) -> t.IsAssignableFrom(findType))
7885
|> Seq.toList
7986

87+
let multiPrinters =
88+
displayMultiPrinters
89+
|> Seq.filter (fun (t, _) -> t.IsAssignableFrom(findType))
90+
|> Seq.toList
91+
8092
if printers.Length > 0 then
81-
printers.Head
93+
snd printers.Head
94+
elif multiPrinters.Length > 0 then
95+
snd multiPrinters.Head
8296
elif FSharp.Reflection.FSharpType.IsFunction findType then
83-
(typeof<Type>, functionPrinter)
97+
functionPrinter
8498
else
85-
(typeof<obj>, defaultDisplayPrinter)
99+
defaultDisplayPrinter
86100

87101
/// Adds default display printers
88102
let addDefaultDisplayPrinters() =

Diff for: src/IfSharp.Kernel/ShellMessages.fs

+1-1
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ type Pyout =
450450
// # data and metadata are identical to a display_data message.
451451
// # the object being displayed is that passed to the display hook,
452452
// # i.e. the *result* of the execution.
453-
data: Dictionary<string,obj>;
453+
data: Map<string,obj>;
454454
metadata: Dictionary<string,obj>;
455455
}
456456

Diff for: src/IfSharp.Kernel/helpers/XPlot.Plotly.fsx

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ open IfSharp.Kernel.Globals
88

99
do
1010
Printers.addDisplayPrinter(fun (plot: PlotlyChart) ->
11+
1112
{ ContentType = "text/html"; Data = plot.GetInlineHtml() })
1213

1314
//System.Net.ServicePointManager.SecurityProtocol <- System.Net.SecurityProtocolType.Tls12

0 commit comments

Comments
 (0)