mirror of
https://github.com/WolframResearch/WolframLanguageForJupyter.git
synced 2025-04-17 20:26:04 +00:00
Merge branch 'master' into feature/README-md-cleanup
This commit is contained in:
commit
ab6ab8a2e7
@ -6,7 +6,7 @@
|
||||
|
||||
Paclet[
|
||||
Name -> "WolframLanguageForJupyter",
|
||||
Version -> "0.9.1",
|
||||
Version -> "0.9.2",
|
||||
MathematicaVersion -> "11.2+",
|
||||
Extensions -> {
|
||||
{"Kernel", Context -> {"WolframLanguageForJupyter`"}},
|
||||
|
@ -71,8 +71,9 @@ If[
|
||||
sends output to Jupyter
|
||||
*************************************)
|
||||
|
||||
(* redirect Print calls into a message to Jupyter, in order to print in the Jupyter notebook *)
|
||||
(* redirect Print calls into a message to Jupyter, in order to print in Jupyter *)
|
||||
(* TODO: review other methods: through EvaluationData or WSTP so we don't redefine Print *)
|
||||
(* TODO: remove this and just permanently set $Output to {..., loopState["WolframLanguageForJupyter-stdout"], ...} *)
|
||||
Unprotect[Print];
|
||||
Print[ourArgs___, opts:OptionsPattern[]] :=
|
||||
Block[
|
||||
@ -95,6 +96,76 @@ If[
|
||||
] /; !TrueQ[$inPrint];
|
||||
Protect[Print];
|
||||
|
||||
(************************************
|
||||
version of Write that
|
||||
sends output to Jupyter
|
||||
*************************************)
|
||||
|
||||
(* redirect Write["stdout", ourArgs___] calls to Write[loopState["WolframLanguageForJupyter-stdout"], ourArgs___],
|
||||
in order to print in Jupyter *)
|
||||
Unprotect[Write];
|
||||
Write["stdout", ourArgs___, opts:OptionsPattern[]] :=
|
||||
Block[
|
||||
{
|
||||
$inWrite = True
|
||||
},
|
||||
If[
|
||||
loopState["WolframLanguageForJupyter-stdout"] =!= False,
|
||||
Write[loopState["WolframLanguageForJupyter-stdout"], ourArgs]
|
||||
];
|
||||
] /; !TrueQ[$inWrite];
|
||||
Protect[Write];
|
||||
(* redirect Write[{before___, "stdout", after___}, ourArgs___] calls to
|
||||
Write[{before___, "WolframLanguageForJupyter-stdout", after___}, ourArgs___],
|
||||
in order to print in Jupyter *)
|
||||
Unprotect[Write];
|
||||
Write[{before___, "stdout", after___}, ourArgs___, opts:OptionsPattern[]] :=
|
||||
Block[
|
||||
{
|
||||
$inWrite = True
|
||||
},
|
||||
If[
|
||||
loopState["WolframLanguageForJupyter-stdout"] =!= False,
|
||||
Write[{before, loopState["WolframLanguageForJupyter-stdout"], after}, ourArgs]
|
||||
];
|
||||
] /; !TrueQ[$inWrite];
|
||||
Protect[Write];
|
||||
|
||||
(************************************
|
||||
version of WriteString that
|
||||
sends output to Jupyter
|
||||
*************************************)
|
||||
|
||||
(* redirect WriteString["stdout", ourArgs___] calls to WriteString[loopState["WolframLanguageForJupyter-stdout"], ourArgs___],
|
||||
in order to print in Jupyter *)
|
||||
Unprotect[WriteString];
|
||||
WriteString["stdout", ourArgs___, opts:OptionsPattern[]] :=
|
||||
Block[
|
||||
{
|
||||
$inWriteString = True
|
||||
},
|
||||
If[
|
||||
loopState["WolframLanguageForJupyter-stdout"] =!= False,
|
||||
WriteString[loopState["WolframLanguageForJupyter-stdout"], ourArgs]
|
||||
];
|
||||
] /; !TrueQ[$inWriteString];
|
||||
Protect[WriteString];
|
||||
(* redirect WriteString[{before___, "stdout", after___}, ourArgs___] calls to
|
||||
WriteString[{before___, "WolframLanguageForJupyter-stdout", after___}, ourArgs___],
|
||||
in order to print in Jupyter *)
|
||||
Unprotect[WriteString];
|
||||
WriteString[{before___, "stdout", after___}, ourArgs___, opts:OptionsPattern[]] :=
|
||||
Block[
|
||||
{
|
||||
$inWriteString = True
|
||||
},
|
||||
If[
|
||||
loopState["WolframLanguageForJupyter-stdout"] =!= False,
|
||||
WriteString[{before, loopState["WolframLanguageForJupyter-stdout"], after}, ourArgs]
|
||||
];
|
||||
] /; !TrueQ[$inWriteString];
|
||||
Protect[WriteString];
|
||||
|
||||
(************************************
|
||||
versions of Quit and Exit that
|
||||
ask the Jupyter console
|
||||
|
@ -5,12 +5,14 @@ Description:
|
||||
Initialization for
|
||||
WolframLanguageForJupyter
|
||||
Symbols defined:
|
||||
$defaultPageWidth,
|
||||
loopState,
|
||||
applyHook,
|
||||
$canUseFrontEnd,
|
||||
$outputSetToTraditionalForm,
|
||||
$outputSetToTeXForm,
|
||||
$trueFormatType,
|
||||
$truePageWidth,
|
||||
connectionAssoc,
|
||||
bannerWarning,
|
||||
keyString,
|
||||
@ -57,7 +59,8 @@ If[
|
||||
*************************************)
|
||||
|
||||
(* make Short[] work *)
|
||||
SetOptions[$Output, PageWidth -> 89];
|
||||
$defaultPageWidth = 89;
|
||||
SetOptions[$Output, PageWidth -> $defaultPageWidth];
|
||||
|
||||
(* do not output messages to the jupyter notebook invocation
|
||||
$Messages = {};
|
||||
@ -192,6 +195,9 @@ If[
|
||||
(* flag for if an is_complete_request has ever been sent to the kernel *)
|
||||
"isCompleteRequestSent" -> False,
|
||||
|
||||
(* OutputStream for Jupyter's stdout *)
|
||||
"WolframLanguageForJupyter-stdout" -> False,
|
||||
|
||||
(* local to an iteration *)
|
||||
(* a received frame as an Association *)
|
||||
"frameAssoc" -> Null,
|
||||
@ -224,6 +230,14 @@ If[
|
||||
TraditionalForm,
|
||||
If[$outputSetToTeXForm, TeXForm, #&]
|
||||
];
|
||||
$truePageWidth :=
|
||||
Replace[
|
||||
Lookup[Options[$Output], PageWidth],
|
||||
Except[
|
||||
pageWidth_ /; ((IntegerQ[pageWidth]) && (pageWidth > 0))
|
||||
] ->
|
||||
$defaultPageWidth
|
||||
];
|
||||
|
||||
(* hard-coded base64 rasterization of $Failed *)
|
||||
failedInBase64 = "iVBORw0KGgoAAAANSUhEUgAAADcAAAARCAIAAAD2TKM6AAAAhXpUWHRSYXcgcHJvZmlsZSB0eXBlIGV4aWYAAHjaVYvBDcMwDAP/mqIjyLJM2uMYiQNkg45fuu0n9yApgbT1vi97felp2dgxABc5csRU6P6juNciDXn+X9MfZGWgoRhTluEkhnJXkqKFN+LCAahYcIbnIV8gNQN3o86928QyPusLVffpbh/5eCey76LuBgAAAAlwSFlzAAALEwAACxMBAJqcGAAAADx0RVh0U29mdHdhcmUAQ3JlYXRlZCB3aXRoIHRoZSBXb2xmcmFtIExhbmd1YWdlIDogd3d3LndvbGZyYW0uY29tXKKmhQAAACF0RVh0Q3JlYXRpb24gVGltZQAyMDE5OjA3OjAyIDAzOjExOjExSFD8JQAAA8xJREFUSInVlk9IKl8Ux68ajjThLynMwCKLICSDjBbRxpVSFhFkCtFfBMMKAhcu3GXhQopaJBEFISjhsn9YUGE6zSJqkRURFVpKLQqNcYgZHectpszfez9exoP33u+zmnPm3HO/c865w2XRNA3+eth/WkBOfKjEMAzH8T8o5Sd8qJybm1tcXPz1jCaTyeVyMc8URXV3d2s0Go1GEwgEvppqZGQERdEPldfX1yiKIghydnaWCerp6WFn0dbW9mlekiTdbrfX62VMNpvd398/MDAQCATu7u6+qnJ9fT0SiQAA8gAAJycnzc3NnZ2dfD5foVA4nc7W1lYAQDqd1uv1drudWZOXl/dpXi6XG4lEOBwOY7JYLLVaDQDIz8//qsRs2AAAt9vd2NjodrsXFhYuLy9VKlXmNQRB/7wDwzAAIBaLmc1miUTC5/MHBwfPz8+ZSJvNJpVKpVKpTCazWq2fbkySpMViEYvFAoFAp9M9Pz8z/v39/bq6Oj6fr9FoMueEDQBQKpUoihqNxtvb2+Li4kwlAADxePz6nXQ6DQC4uroKBoPz8/MoimIYZjabmciuri6Hw+FwOMRi8ePj46cqLRaLx+NZXV1dW1u7v78fGxsDAESj0fb29qamJp/PV19f//Ly8hZN0zRN016vVy6Xs9nsoaGh19dXxqnT6QAAzFByOJxYLEa/Q5Lk6enp9PQ0BEE4jtNZ9Pb2Go1G+t9UVla6XK6MmUwmIQja3t5mzI2NjYKCApqm7Xa7RCJJpVKMv6yszOPx0DT9dnpUKtXx8fHW1tbm5ubk5GTmi0dHRymKoigqlUoVFhYCAAiCMBqNQqFweHj48PCQIIh4PP5p5b4jHA4TBNHS0sLlcrlcbkdHB0EQOI7f3NzU1tZmN/Oj4wcHBxiGMVpVKlVm1P6TqakpBEEuLi4QBJmdnc1RFovFoigqY4pEIhaL5ff7SZIkSTKVSpEkCcOwQCAIBoM/LmcDACYmJqqrq/v6+rRarcfjYRr9kzJUVVWJRKJEImGz2XJU2dDQsLu7m06nHx4eAAAwDKvVapPJxExwNBpFEAQAoFAoQqHQ0tISSZIrKytM8JvKnZ0dxoVhmM/n02q1mQL8uJ/BYPD7/UKhsKKioqioCIKgXFTq9fq9vT0YhuVyOVPU5eXlkpKS8vLy0tJSqVTK/POVSuX4+LjBYODxeE6ns6am5m19ZqKtVuvMzAydAwRBhEIhiqJyCc5AUVQoFEomk9lOHMfD4fB3qRKJxNPTU7aHRb/fiY6Ojng8nkwmy7GJv5MPlX8z/4+b2zdkknhkRbjZsAAAAABJRU5ErkJggg==";
|
||||
@ -252,6 +266,44 @@ If[
|
||||
inputString = StringJoin[baseString, connectionAssoc["stdin_port"]];
|
||||
shellString = StringJoin[baseString, connectionAssoc["shell_port"]];
|
||||
|
||||
Block[
|
||||
{
|
||||
(* for storing the result of defining a new OutputStream method *)
|
||||
customOutputStreamMethod
|
||||
},
|
||||
|
||||
(* define an OutputStream method that will allow writing to Jupyter's stdout *)
|
||||
customOutputStreamMethod =
|
||||
DefineOutputStreamMethod[
|
||||
"for-WolframLanguageForJupyter-stdout",
|
||||
{
|
||||
"ConstructorFunction" -> Function[{name, isAppend, caller, opts}, {True, {}}],
|
||||
"WriteFunction" ->
|
||||
Function[
|
||||
{state, bytes},
|
||||
If[
|
||||
loopState["frameAssoc"] =!= Null,
|
||||
redirectPrint[loopState["frameAssoc"], FromCharacterCode[bytes]];
|
||||
];
|
||||
{Length[bytes], {}}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
(* if defining a new OutputStream method did not fail,
|
||||
open an OutputStream using the new method, and store it in loopState *)
|
||||
If[
|
||||
!FailureQ[customOutputStreamMethod],
|
||||
loopState["WolframLanguageForJupyter-stdout"] =
|
||||
OpenWrite["WolframLanguageForJupyter-stdout", Method -> "for-WolframLanguageForJupyter-stdout"];
|
||||
(* -- also, if opening the OutputStream failed, reset loopState["WolframLanguageForJupyter-stdout"] back to False *)
|
||||
If[
|
||||
FailureQ[loopState["WolframLanguageForJupyter-stdout"]],
|
||||
loopState["WolframLanguageForJupyter-stdout"] = False;
|
||||
];
|
||||
];
|
||||
];
|
||||
|
||||
(************************************
|
||||
open all the non-heartbeat
|
||||
sockets
|
||||
|
@ -108,7 +108,7 @@ If[
|
||||
(* the message type to be used for the reply message frame *)
|
||||
replyType_String,
|
||||
(* the content to be used for the reply message frame *)
|
||||
replyContent_String,
|
||||
replyContent : (_String | _ByteArray),
|
||||
(* whether to list sourceFrame as a parent for the reply message frame *)
|
||||
branchOff:(True|False)
|
||||
] :=
|
||||
@ -157,7 +157,7 @@ If[
|
||||
result["header"],
|
||||
result["pheader"],
|
||||
result["metadata"],
|
||||
result["content"]
|
||||
If[StringQ[result["content"]], result["content"], ByteArrayToString[result["content"]]]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
@ -32,7 +32,8 @@ If[
|
||||
|
||||
Get[FileNameJoin[{DirectoryName[$InputFileName], "Initialization.wl"}]]; (* $canUseFrontEnd, $outputSetToTeXForm,
|
||||
$outputSetToTraditionalForm,
|
||||
$trueFormatType, failedInBase64 *)
|
||||
$trueFormatType, $truePageWidth,
|
||||
failedInBase64 *)
|
||||
|
||||
(************************************
|
||||
private symbols
|
||||
@ -182,7 +183,16 @@ If[
|
||||
(* generate the textual form of a result *)
|
||||
(* NOTE: the OutputForm (which ToString uses) of any expressions wrapped with, say, InputForm should
|
||||
be identical to the string result of an InputForm-wrapped expression itself *)
|
||||
toText[result_] := ToString[If[Head[result] =!= TeXForm, $trueFormatType[result], result]];
|
||||
toText[result_] :=
|
||||
ToString[
|
||||
If[
|
||||
Head[result] =!= TeXForm,
|
||||
$trueFormatType[result],
|
||||
result
|
||||
],
|
||||
(* also, use the current PageWidth setting for $Output *)
|
||||
PageWidth -> $truePageWidth
|
||||
];
|
||||
|
||||
(* generate HTML for the textual form of a result *)
|
||||
toOutTextHTML[result_] :=
|
||||
|
@ -283,7 +283,7 @@ If[
|
||||
toOut = toOutImageHTML
|
||||
];
|
||||
(* prepare the content for a reply message frame to be sent on the IO Publish socket *)
|
||||
ioPubReplyContent = ExportString[
|
||||
ioPubReplyContent = ExportByteArray[
|
||||
Association[
|
||||
(* the first output index *)
|
||||
"execution_count" -> First[totalResult["EvaluationResultOutputLineIndices"]],
|
||||
@ -292,52 +292,58 @@ If[
|
||||
{
|
||||
(* generate HTML for the results and messages *)
|
||||
"text/html" ->
|
||||
(* output the results in a grid *)
|
||||
If[
|
||||
Length[totalResult["EvaluationResult"]] > 1,
|
||||
StringJoin[
|
||||
(* add grid style *)
|
||||
"<style>
|
||||
.grid-container {
|
||||
display: inline-grid;
|
||||
grid-template-columns: auto;
|
||||
}
|
||||
</style>
|
||||
loopState["isCompleteRequestSent"],
|
||||
(* if an is_complete_request has been sent, assume jupyter-console is running the kernel,
|
||||
and do not generate HTML *)
|
||||
"",
|
||||
(* otherwise, output the results in a grid *)
|
||||
If[
|
||||
Length[totalResult["EvaluationResult"]] > 1,
|
||||
StringJoin[
|
||||
(* add grid style *)
|
||||
"<style>
|
||||
.grid-container {
|
||||
display: inline-grid;
|
||||
grid-template-columns: auto;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div>",
|
||||
(* display error message *)
|
||||
errorMessage,
|
||||
(* start the grid *)
|
||||
"<div class=\"grid-container\">",
|
||||
(* display the output lines *)
|
||||
Table[
|
||||
{
|
||||
(* start the grid item *)
|
||||
"<div class=\"grid-item\">",
|
||||
(* show the output line *)
|
||||
toOut[totalResult["EvaluationResult"][[outIndex]]],
|
||||
(* end the grid item *)
|
||||
"</div>"
|
||||
},
|
||||
{outIndex, 1, Length[totalResult["EvaluationResult"]]}
|
||||
<div>",
|
||||
(* display error message *)
|
||||
errorMessage,
|
||||
(* start the grid *)
|
||||
"<div class=\"grid-container\">",
|
||||
(* display the output lines *)
|
||||
Table[
|
||||
{
|
||||
(* start the grid item *)
|
||||
"<div class=\"grid-item\">",
|
||||
(* show the output line *)
|
||||
toOut[totalResult["EvaluationResult"][[outIndex]]],
|
||||
(* end the grid item *)
|
||||
"</div>"
|
||||
},
|
||||
{outIndex, 1, Length[totalResult["EvaluationResult"]]}
|
||||
],
|
||||
(* end the element *)
|
||||
"</div></div>"
|
||||
],
|
||||
(* end the element *)
|
||||
"</div></div>"
|
||||
],
|
||||
StringJoin[
|
||||
(* start the element *)
|
||||
"<div>",
|
||||
(* display error message *)
|
||||
errorMessage,
|
||||
(* if there are messages, but no results, do not display a result *)
|
||||
If[
|
||||
Length[totalResult["EvaluationResult"]] == 0,
|
||||
"",
|
||||
(* otherwise, display a result *)
|
||||
toOut[First[totalResult["EvaluationResult"]]]
|
||||
],
|
||||
(* end the element *)
|
||||
"</div>"
|
||||
StringJoin[
|
||||
(* start the element *)
|
||||
"<div>",
|
||||
(* display error message *)
|
||||
errorMessage,
|
||||
(* if there are messages, but no results, do not display a result *)
|
||||
If[
|
||||
Length[totalResult["EvaluationResult"]] == 0,
|
||||
"",
|
||||
(* otherwise, display a result *)
|
||||
toOut[First[totalResult["EvaluationResult"]]]
|
||||
],
|
||||
(* end the element *)
|
||||
"</div>"
|
||||
]
|
||||
]
|
||||
],
|
||||
(* provide, as a backup, plain text for the results *)
|
||||
|
@ -74,7 +74,7 @@ If[
|
||||
|
||||
socketWriteFunction[
|
||||
socket,
|
||||
StringToByteArray[frame["content"]],
|
||||
If[ByteArrayQ[frame["content"]], frame["content"], StringToByteArray[frame["content"]]],
|
||||
"Multipart" -> False
|
||||
];
|
||||
];
|
||||
|
@ -139,7 +139,7 @@ splitPath :=
|
||||
|
||||
(* find Jupyter installation path *)
|
||||
(* returns above *)
|
||||
findJupyerPath[] :=
|
||||
findJupyterPath[] :=
|
||||
SelectFirst[
|
||||
splitPath,
|
||||
(* check every directory in PATH to see if a Jupyter binary is a member *)
|
||||
@ -211,7 +211,7 @@ configureJupyter[specs_Association, removeQ_?BooleanQ, removeAllQ_?BooleanQ] :=
|
||||
(* if no Jupyter installation path provided, determine it from PATH *)
|
||||
If[
|
||||
MissingQ[jupyterPath],
|
||||
jupyterPath = findJupyerPath[];
|
||||
jupyterPath = findJupyterPath[];
|
||||
(* if Jupyter not on PATH, message *)
|
||||
If[MissingQ[jupyterPath],
|
||||
Message[ConfigureJupyter::notfound, "Jupyter"];
|
||||
|
@ -160,7 +160,7 @@ attemptPathRegeneration[] := If[
|
||||
|
||||
(* find Jupyter installation path *)
|
||||
(* returns kernel IDs in Jupyter *)
|
||||
findJupyerPath[] :=
|
||||
findJupyterPath[] :=
|
||||
SelectFirst[
|
||||
splitPath,
|
||||
(* check every directory in PATH to see if a Jupyter binary is a member *)
|
||||
@ -231,7 +231,7 @@ configureJupyter[specs_Association, removeQ_?BooleanQ, removeAllQ_?BooleanQ] :=
|
||||
(* if no Jupyter installation path provided, determine it from PATH *)
|
||||
If[
|
||||
MissingQ[jupyterPath],
|
||||
jupyterPath = findJupyerPath[];
|
||||
jupyterPath = findJupyterPath[];
|
||||
(* if Jupyter not on PATH, message *)
|
||||
If[MissingQ[jupyterPath],
|
||||
Print[notfound];
|
||||
|
Loading…
x
Reference in New Issue
Block a user