Skip to content

Commit ed8a6e9

Browse files
committed
Merge pull request #64 from FilippoPolo/master
Protocol fixes
2 parents a820062 + 2595f7c commit ed8a6e9

File tree

10 files changed

+229
-54
lines changed

10 files changed

+229
-54
lines changed

ipython-profile/ipython_config.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
11
c = get_config()
2-
c.KernelManager.kernel_spec = [ "mono", r"%kexe", "{connection_file}"]
32
c.NotebookApp.extra_static_paths = [ r"%kstatic" ]

paket.dependencies

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ source https://www.nuget.org/api/v2
22

33
nuget FSharp.Compiler.Service 3.0.0 framework: >= net451
44
nuget FSharp.Core.Microsoft.Signed 3.1.1.1 framework: >= net45
5-
nuget NetMQ 3.3.0.11
5+
nuget NetMQ 3.3.3.1
66
nuget Newtonsoft.Json 5.0.8 framework: >= net45
77
nuget FSharp.Charting 0.90.5 framework: >= net45
88
nuget FAKE

paket.lock

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
NUGET
22
remote: https://www.nuget.org/api/v2
33
specs:
4+
AsyncIO (0.1.18)
45
FAKE (4.23.6)
56
FSharp.Charting (0.90.5) - framework: >= net45
67
FSharp.Compiler.Service (3.0) - framework: >= net451
78
FSharp.Core.Microsoft.Signed (3.1.1.1) - framework: >= net45
8-
NetMQ (3.3.0.11)
9+
NetMQ (3.3.3.1)
10+
AsyncIO (>= 0.1.18)
911
Newtonsoft.Json (5.0.8) - framework: >= net45
1012
xunit (2.1) - framework: >= net451
1113
xunit.assert (2.1)

src/IfSharp.Kernel/IfSharp.Kernel.fsproj

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,26 @@
122122
</Target>
123123
-->
124124
<Import Project="..\..\.paket\paket.targets" />
125+
<Choose>
126+
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v3.5'">
127+
<ItemGroup>
128+
<Reference Include="AsyncIO">
129+
<HintPath>..\..\packages\AsyncIO\lib\net35\AsyncIO.dll</HintPath>
130+
<Private>True</Private>
131+
<Paket>True</Paket>
132+
</Reference>
133+
</ItemGroup>
134+
</When>
135+
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.0' Or $(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.1' Or $(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6' Or $(TargetFrameworkVersion) == 'v4.6.1' Or $(TargetFrameworkVersion) == 'v4.6.2')">
136+
<ItemGroup>
137+
<Reference Include="AsyncIO">
138+
<HintPath>..\..\packages\AsyncIO\lib\net40\AsyncIO.dll</HintPath>
139+
<Private>True</Private>
140+
<Paket>True</Paket>
141+
</Reference>
142+
</ItemGroup>
143+
</When>
144+
</Choose>
125145
<Choose>
126146
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.1' Or $(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6' Or $(TargetFrameworkVersion) == 'v4.6.1' Or $(TargetFrameworkVersion) == 'v4.6.2')">
127147
<ItemGroup>
@@ -145,6 +165,15 @@
145165
</When>
146166
</Choose>
147167
<Choose>
168+
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And $(TargetFrameworkVersion) == 'v3.5'">
169+
<ItemGroup>
170+
<Reference Include="NetMQ">
171+
<HintPath>..\..\packages\NetMQ\lib\net35\NetMQ.dll</HintPath>
172+
<Private>True</Private>
173+
<Paket>True</Paket>
174+
</Reference>
175+
</ItemGroup>
176+
</When>
148177
<When Condition="$(TargetFrameworkIdentifier) == '.NETFramework' And ($(TargetFrameworkVersion) == 'v4.0' Or $(TargetFrameworkVersion) == 'v4.5' Or $(TargetFrameworkVersion) == 'v4.5.1' Or $(TargetFrameworkVersion) == 'v4.5.2' Or $(TargetFrameworkVersion) == 'v4.5.3' Or $(TargetFrameworkVersion) == 'v4.6' Or $(TargetFrameworkVersion) == 'v4.6.1' Or $(TargetFrameworkVersion) == 'v4.6.2')">
149178
<ItemGroup>
150179
<Reference Include="NetMQ">
@@ -166,4 +195,4 @@
166195
</ItemGroup>
167196
</When>
168197
</Choose>
169-
</Project>
198+
</Project>

src/IfSharp.Kernel/Kernel.fs

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,26 +16,30 @@ type IfSharpKernel(connectionInformation : ConnectionInformation) =
1616

1717
// startup 0mq stuff
1818
let context = NetMQContext.Create()
19-
2019
// heartbeat
21-
let hbSocket = context.CreateRequestSocket()
22-
do hbSocket.Bind(String.Format("{0}://{1}:{2}", connectionInformation.transport, connectionInformation.ip, connectionInformation.hb_port))
23-
24-
// shell
25-
let shellSocket = context.CreateRouterSocket()
26-
do shellSocket.Bind(String.Format("{0}://{1}:{2}", connectionInformation.transport, connectionInformation.ip, connectionInformation.shell_port))
20+
let hbSocket = context.CreateRouterSocket()
21+
let hbSocketURL =String.Format("{0}://{1}:{2}", connectionInformation.transport, connectionInformation.ip, connectionInformation.hb_port)
22+
do hbSocket.Bind(hbSocketURL)
2723

2824
// control
2925
let controlSocket = context.CreateRouterSocket()
30-
do controlSocket.Bind(String.Format("{0}://{1}:{2}", connectionInformation.transport, connectionInformation.ip, connectionInformation.control_port))
26+
let controlSocketURL = String.Format("{0}://{1}:{2}", connectionInformation.transport, connectionInformation.ip, connectionInformation.control_port)
27+
do controlSocket.Bind(controlSocketURL)
3128

3229
// stdin
3330
let stdinSocket = context.CreateRouterSocket()
34-
do stdinSocket.Bind(String.Format("{0}://{1}:{2}", connectionInformation.transport, connectionInformation.ip, connectionInformation.stdin_port))
31+
let stdinSocketURL = String.Format("{0}://{1}:{2}", connectionInformation.transport, connectionInformation.ip, connectionInformation.stdin_port)
32+
do stdinSocket.Bind(stdinSocketURL)
3533

3634
// iopub
3735
let ioSocket = context.CreatePublisherSocket()
38-
do ioSocket.Bind(String.Format("{0}://{1}:{2}", connectionInformation.transport, connectionInformation.ip, connectionInformation.iopub_port))
36+
let ioSocketURL = String.Format("{0}://{1}:{2}", connectionInformation.transport, connectionInformation.ip, connectionInformation.iopub_port)
37+
do ioSocket.Bind(ioSocketURL)
38+
39+
// shell
40+
let shellSocket = context.CreateRouterSocket()
41+
let shellSocketURL =String.Format("{0}://{1}:{2}", connectionInformation.transport, connectionInformation.ip, connectionInformation.shell_port)
42+
do shellSocket.Bind(shellSocketURL)
3943

4044
let data = new List<BinaryOutput>()
4145
let payload = new List<Payload>()
@@ -96,21 +100,20 @@ type IfSharpKernel(connectionInformation : ConnectionInformation) =
96100
ignore (hmac.TransformFinalBlock(Array.zeroCreate 0, 0, 0))
97101
BitConverter.ToString(hmac.Hash).Replace("-", "").ToLower()
98102

99-
let recvAll (socket: NetMQSocket) = socket.ReceiveMessages()
103+
let recvAll (socket: NetMQSocket) = socket.ReceiveMultipartBytes()
100104

101105
/// Constructs an 'envelope' from the specified socket
102106
let recvMessage (socket: NetMQSocket) =
103107

104108
// receive all parts of the message
105-
let message =
106-
recvAll (socket)
107-
|> Seq.map decode
108-
|> Seq.toArray
109+
let message = (recvAll (socket)) |> Array.ofSeq
110+
let asStrings = message |> Array.map decode
109111

110112
// find the delimiter between IDS and MSG
111-
let idx = Array.IndexOf(message, "<IDS|MSG>")
113+
let idx = Array.IndexOf(asStrings, "<IDS|MSG>")
114+
112115
let idents = message.[0..idx - 1]
113-
let messageList = message.[idx + 1..message.Length - 1]
116+
let messageList = asStrings.[idx + 1..message.Length - 1]
114117

115118
// detect a malformed message
116119
if messageList.Length < 4 then failwith ("Malformed message")
@@ -172,7 +175,7 @@ type IfSharpKernel(connectionInformation : ConnectionInformation) =
172175
msg.Append(encode parent_header)
173176
msg.Append(encode "{}")
174177
msg.Append(encode content)
175-
socket.SendMessage(msg)
178+
socket.SendMultipartMessage(msg)
176179

177180

178181
/// Convenience method for sending the state of the kernel
@@ -191,12 +194,25 @@ type IfSharpKernel(connectionInformation : ConnectionInformation) =
191194
let kernelInfoRequest(msg : KernelMessage) (content : KernelRequest) =
192195
let content =
193196
{
194-
protocol_version = [| 4; 0 |];
195-
ipython_version = Some [| 1; 0; 0 |];
196-
language_version = [| 1; 0; 0 |];
197+
protocol_version = "4.0.0";
198+
implementation = "ifsharp";
199+
implementation_version = "4.0.0";
200+
banner = "";
201+
help_links = [||];
197202
language = "fsharp";
203+
language_info =
204+
{
205+
name = "fsharp";
206+
version = "4.3.1.0";
207+
mimetype = "text/x-fsharp";
208+
file_extension = ".fs";
209+
pygments_lexer = "";
210+
codemirror_mode = "";
211+
nbconvert_exporter = "";
212+
};
198213
}
199214

215+
sendStateBusy msg
200216
sendMessage shellSocket msg "kernel_info_reply" content
201217

202218
/// Sends display data information immediately
@@ -407,11 +423,12 @@ type IfSharpKernel(connectionInformation : ConnectionInformation) =
407423

408424
/// Handles a 'shutdown_request' message
409425
let shutdownRequest (msg : KernelMessage) (content : ShutdownRequest) =
410-
426+
logMessage "shutdown request"
411427
// TODO: actually shutdown
412428
let reply = { restart = true; }
413429

414-
sendMessage shellSocket msg "shutdown_reply" reply
430+
sendMessage shellSocket msg "shutdown_reply" reply;
431+
System.Environment.Exit(0)
415432

416433
/// Handles a 'history_request' message
417434
let historyRequest (msg : KernelMessage) (content : HistoryRequest) =
@@ -442,7 +459,6 @@ type IfSharpKernel(connectionInformation : ConnectionInformation) =
442459
logMessage (sbOut.ToString())
443460

444461
while true do
445-
446462
let msg = recvMessage (shellSocket)
447463

448464
try
@@ -456,16 +472,27 @@ type IfSharpKernel(connectionInformation : ConnectionInformation) =
456472
| HistoryRequest(r) -> historyRequest msg r
457473
| ObjectInfoRequest(r) -> objectInfoRequest msg r
458474
| InspectRequest(r) -> inspectRequest msg r
459-
| _ -> logMessage (String.Format("Unknown content type. msg_type is `{0}`", msg.Header.msg_type))
475+
| _ -> logMessage (String.Format("Unknown content type on shell. msg_type is `{0}`", msg.Header.msg_type))
460476
with
461477
| ex -> handleException ex
462478

479+
let doControl() =
480+
while true do
481+
let msg = recvMessage (controlSocket)
482+
try
483+
match msg.Content with
484+
| ShutdownRequest(r) -> shutdownRequest msg r
485+
| _ -> logMessage (String.Format("Unexpected content type on control. msg_type is `{0}`", msg.Header.msg_type))
486+
with
487+
| ex -> handleException ex
488+
463489
/// Loops repeating message from the client
464490
let doHeartbeat() =
465491

466492
try
467493
while true do
468-
hbSocket.Send(hbSocket.Receive())
494+
let hb = hbSocket.ReceiveMultipartBytes() in
495+
hbSocket.SendMultipartBytes(hb)
469496
with
470497
| ex -> handleException ex
471498

@@ -485,5 +512,6 @@ type IfSharpKernel(connectionInformation : ConnectionInformation) =
485512
/// Starts the kernel asynchronously
486513
member __.StartAsync() =
487514

488-
Async.Start (async { doHeartbeat() } )
515+
//Async.Start (async { doHeartbeat() } )
489516
Async.Start (async { doShell() } )
517+
Async.Start (async { doControl() } )

src/IfSharp.Kernel/ShellMessages.fs

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -334,30 +334,68 @@ type CommOpen = obj
334334

335335
type KernelRequest = obj
336336

337+
type KernelReply_LanguageInfo =
338+
{
339+
// # Name of the programming language that the kernel implements.
340+
// # Kernel included in IPython returns 'python'.
341+
name: string;
342+
343+
// # Language version number.
344+
// # It is Python version number (e.g., '2.7.3') for the kernel
345+
// # included in IPython.
346+
version: string;
347+
348+
// # mimetype for script files in this language
349+
mimetype: string;
350+
351+
// # Extension including the dot, e.g. '.py'
352+
file_extension: string;
353+
354+
// # Pygments lexer, for highlighting
355+
// # Only needed if it differs from the 'name' field.
356+
pygments_lexer: string;
357+
358+
// # Codemirror mode, for for highlighting in the notebook.
359+
// # Only needed if it differs from the 'name' field.
360+
codemirror_mode: string;
361+
362+
// # Nbconvert exporter, if notebooks written with this kernel should
363+
// # be exported with something other than the general 'script'
364+
// # exporter.
365+
nbconvert_exporter: string;
366+
}
367+
368+
type KernelReply_HelpLink = { text: string; url: string; }
369+
337370
type KernelReply =
338371
{
339-
// # Version of messaging protocol (mandatory).
372+
// # Version of messaging protocol.
340373
// # The first integer indicates major version. It is incremented when
341374
// # there is any backward incompatible change.
342375
// # The second integer indicates minor version. It is incremented when
343376
// # there is any backward compatible change.
344-
protocol_version: array<int>;
345-
346-
// # IPython version number (optional).
347-
// # Non-python kernel backend may not have this version number.
348-
// # The last component is an extra field, which may be 'dev' or
349-
// # 'rc1' in development version. It is an empty string for
350-
// # released version.
351-
ipython_version: Option<array<obj>>;
352-
353-
// # Language version number (mandatory).
354-
// # It is Python version number (e.g., [2, 7, 3]) for the kernel
355-
// # included in IPython.
356-
language_version: array<int>;
357-
358-
// # Programming language in which kernel is implemented (mandatory).
359-
// # Kernel included in IPython returns 'python'.
360-
language: string
377+
protocol_version: string;
378+
379+
// # The kernel implementation name
380+
// # (e.g. 'ipython' for the IPython kernel)
381+
implementation: string;
382+
383+
// # Implementation version number.
384+
// # The version number of the kernel's implementation
385+
// # (e.g. IPython.__version__ for the IPython kernel)
386+
implementation_version: string;
387+
388+
// # Information about the language of code for the kernel
389+
language_info: KernelReply_LanguageInfo;
390+
language: string;
391+
392+
// # A banner of information about the kernel,
393+
// # which may be desplayed in console environments.
394+
banner : string;
395+
396+
// # Optional: A list of dictionaries, each with keys 'text' and 'url'.
397+
// # These will be displayed in the help menu in the notebook UI.
398+
help_links: KernelReply_HelpLink array;
361399
}
362400

363401
type KernelStatus =
@@ -483,7 +521,7 @@ type Header =
483521

484522
type KernelMessage =
485523
{
486-
Identifiers: list<string>;
524+
Identifiers: list<byte[]>;
487525
HmacSignature: string;
488526
Header: Header;
489527
ParentHeader: Header;

src/IfSharp.Kernel/app.config

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,18 @@
66
<assemblyIdentity name="FSharp.Core" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
77
<bindingRedirect oldVersion="0.0.0.0-4.3.1.0" newVersion="4.3.1.0" />
88
</dependentAssembly>
9+
<dependentAssembly>
10+
<assemblyIdentity name="Microsoft.Build" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
11+
<bindingRedirect oldVersion="0.0.0.0-14.0.0.0" newVersion="14.0.0.0" />
12+
</dependentAssembly>
13+
<dependentAssembly>
14+
<assemblyIdentity name="Microsoft.Build.Framework" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
15+
<bindingRedirect oldVersion="0.0.0.0-14.0.0.0" newVersion="14.0.0.0" />
16+
</dependentAssembly>
17+
<dependentAssembly>
18+
<assemblyIdentity name="Microsoft.Build.Engine" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
19+
<bindingRedirect oldVersion="0.0.0.0-14.0.0.0" newVersion="14.0.0.0" />
20+
</dependentAssembly>
921
</assemblyBinding>
1022
</runtime>
1123
</configuration>

0 commit comments

Comments
 (0)