jli  Linuxx86_641.10.3v1.10.30b4590a5507d3f3046e5bafc007cacbbfc9b310bIJuliabQusp*}*8~T=7./opt/julia/packages/IJulia/Vo51o/src/IJulia.jlEA#Q})ZMQyϱBTjޠ,hJSON /6IT4F_SoftGlobalScopej2 EY8pDates\Y_ɢ?Random_䇽UlD*Base64uavV͠?REPL!@'Z萠WL ~InteractiveUtils-/opt/julia/packages/IJulia/Vo51o/deps/deps.jlbA//opt/julia/packages/IJulia/Vo51o/src/jupyter.jlEA./opt/julia/packages/IJulia/Vo51o/deps/kspec.jlnA-x#GYMConda,/opt/julia/packages/IJulia/Vo51o/src/init.jlEAhUXM=T{VLoggingrz9[viqUUIDs,/opt/julia/packages/IJulia/Vo51o/src/hmac.jlEAmspAQ)sMbedTLS1/opt/julia/packages/IJulia/Vo51o/src/eventloop.jlEA-/opt/julia/packages/IJulia/Vo51o/src/stdio.jlEA׸QDg^cXPrintf+/opt/julia/packages/IJulia/Vo51o/src/msg.jlEA//opt/julia/packages/IJulia/Vo51o/src/display.jlEA./opt/julia/packages/IJulia/Vo51o/src/magics.jlEAz`sZPn7Markdown4/opt/julia/packages/IJulia/Vo51o/src/comm_manager.jlEA*}*bQuspIJulia CommManager7/opt/julia/packages/IJulia/Vo51o/src/execute_request.jlEAi߯rRZDPkg0/opt/julia/packages/IJulia/Vo51o/src/handlers.jlEA1/opt/julia/packages/IJulia/Vo51o/src/heartbeat.jlEA˗,uVW59Libdl./opt/julia/packages/IJulia/Vo51o/src/inline.jlEAYCoremуJ5Basemу]J5MainmуJ5ArgToolsBń x(mуF K5 Artifactsmr-V3|mу K5Base64UlD*_mу> K5CRC32c\y.jmуj K5 FileWatchingXzsy`{,zmуh& K5LibdluVW59˗,mу-" K5LoggingT{VhUXM=mуrU" K5MmapP~:xg,Omу|' K5NetworkOptionsC0YW,mуʠ, K5SHAQ<$!<%mу1 K5 Serialization [)*k1mу-G K5Sockets1V$ bdސݗmуYBY K5UnicodeP>I>Nrmуeszo K5 LinearAlgebraSm7̏mуuux K5 OpenBLAS_jll[(Śb6EcQ FmуDux K5libblastrampoline_jllLSۆ }lxӠmу^} K5MarkdownZPn7z`smу/Ed~ K5Printfg^cX׸QDmу;h K5Random_ɢ?\Ymу? K5TarOi>աmу!t, K5DatesEY8pj2 mуX K5FuturebS;3{I xVMmуsD K5InteractiveUtilsWL ~@'ZmуVg K5LibGit2Z[&RPTv3EКRmу8J K5 LibGit2_jll YXg}]$mуD K5 MbedTLS_jllAX 3ȡ_mу- K5 LibSSH2_jlloTZk)߆"set_next_input", "text"=>s, "replace"=>replace )) return nothing end """ load(filename, replace=false) Load the file given by `filename` into a new input code cell in the running IJulia notebook, analogous to the `%load` magics in IPython. If the optional argument `replace` is `true`, then the file contents replace the *current* cell rather than creating a new cell. """ load(filename::AbstractString, replace::Bool=false) = load_string(read(filename, String), replace) ####################################################################### # History: global In/Out and other exported history variables """ `In` is a global dictionary of input strings, where `In[n]` returns the string for input cell `n` of the notebook (as it was when it was *last evaluated*). """ const In = Dict{Int,String}() """ `Out` is a global dictionary of output values, where `Out[n]` returns the output from the last evaluation of cell `n` in the notebook. """ const Out = Dict{Int,Any}() """ `ans` is a global variable giving the value returned by the last notebook cell evaluated. """ ans = nothing # execution counter """ `IJulia.n` is the (integer) index of the last-evaluated notebook cell. """ n = 0 ####################################################################### # methods to clear history or any subset thereof function clear_history(indices) for n in indices delete!(In, n) if haskey(Out, n) delete!(Out, n) end end end # since a range could be huge, intersect it with 1:n first clear_history(r::AbstractRange{<:Integer}) = invoke(clear_history, Tuple{Any}, intersect(r, 1:n)) function clear_history() empty!(In) empty!(Out) global ans = nothing end """ clear_history([indices]) The `clear_history()` function clears all of the input and output history stored in the running IJulia notebook. This is sometimes useful because all cell outputs are remember in the `Out` global variable, which prevents them from being freed, so potentially this could waste a lot of memory in a notebook with many large outputs. The optional `indices` argument is a collection of indices indicating a subset of cell inputs/outputs to clear. """ clear_history ####################################################################### # methods to print history or any subset thereof function history(io::IO, indices::AbstractVector{<:Integer}) for n in intersect(indices, 1:IJulia.n) if haskey(In, n) print(io, In[n]) end end end history(io::IO, x::Union{Integer,AbstractVector{<:Integer}}...) = history(io, vcat(x...)) history(x...) = history(stdout, x...) history(io::IO, x...) = throw(MethodError(history, (io, x...,))) history() = history(1:n) """ history([io], [indices...]) The `history()` function prints all of the input history stored in the running IJulia notebook in a format convenient for copying. The optional `indices` argument is one or more indices or collections of indices indicating a subset input cells to print. The optional `io` argument is for specifying an output stream. The default is `stdout`. """ history ####################################################################### # Similar to the ipython kernel, we provide a mechanism by # which modules can register thunk functions to be called after # executing an input cell, e.g. to "close" the current plot in Pylab. # Modules should only use these if isdefined(Main, IJulia) is true. const postexecute_hooks = Function[] """ push_postexecute_hook(f::Function) Push a function `f()` onto the end of a list of functions to execute after executing any notebook cell. """ push_postexecute_hook(f::Function) = push!(postexecute_hooks, f) """ pop_postexecute_hook(f::Function) Remove a function `f()` from the list of functions to execute after executing any notebook cell. """ pop_postexecute_hook(f::Function) = splice!(postexecute_hooks, findlast(isequal(f), postexecute_hooks)) const preexecute_hooks = Function[] """ push_preexecute_hook(f::Function) Push a function `f()` onto the end of a list of functions to execute before executing any notebook cell. """ push_preexecute_hook(f::Function) = push!(preexecute_hooks, f) """ pop_preexecute_hook(f::Function) Remove a function `f()` from the list of functions to execute before executing any notebook cell. """ pop_preexecute_hook(f::Function) = splice!(preexecute_hooks, findlast(isequal(f), preexecute_hooks)) # similar, but called after an error (e.g. to reset plotting state) const posterror_hooks = Function[] """ pop_posterror_hook(f::Function) Remove a function `f()` from the list of functions to execute after an error occurs when a notebook cell is evaluated. """ push_posterror_hook(f::Function) = push!(posterror_hooks, f) """ pop_posterror_hook(f::Function) Remove a function `f()` from the list of functions to execute after an error occurs when a notebook cell is evaluated. """ pop_posterror_hook(f::Function) = splice!(posterror_hooks, findlast(isequal(f), posterror_hooks)) ####################################################################### # The user can call IJulia.clear_output() to clear visible output from the # front end, useful for simple animations. Using wait=true clears the # output only when new output is available, for minimal flickering. """ clear_output(wait=false) Call `clear_output()` to clear visible output from the current notebook cell. Using `wait=true` clears the output only when new output is available, which reduces flickering and is useful for simple animations. """ function clear_output(wait=false) # flush pending stdio flush_all() empty!(displayqueue) # discard pending display requests send_ipython(publish[], msg_reply(execute_msg::Msg, "clear_output", Dict("wait" => wait))) stdio_bytes[] = 0 # reset output throttling end """ set_max_stdio(max_output::Integer) Sets the maximum number of bytes, `max_output`, that can be written to stdout and stderr before getting truncated. A large value here allows a lot of output to be displayed in the notebook, potentially bogging down the browser. """ function set_max_stdio(max_output::Integer) max_output_per_request[] = max_output end ####################################################################### include("init.jl") include("hmac.jl") include("eventloop.jl") include("stdio.jl") include("msg.jl") include("display.jl") include("magics.jl") include("comm_manager.jl") include("execute_request.jl") include("handlers.jl") include("heartbeat.jl") include("inline.jl") end # IJulia -/opt/julia/packages/IJulia/Vo51o/deps/deps.jl= const IJULIA_DEBUG = false const JUPYTER = "jupyter" //opt/julia/packages/IJulia/Vo51o/src/jupyter.jlt# Code to launch and interact with Jupyter, not via messaging protocol ################################################################## include(joinpath("..","deps","kspec.jl")) ################################################################## import Conda isyes(s) = isempty(s) || lowercase(strip(s)) in ("y", "yes") function find_jupyter_subcommand(subcommand::AbstractString) jupyter = JUPYTER if jupyter == "jupyter" || jupyter == "jupyter.exe" # look in PATH jupyter = Sys.which(exe("jupyter")) if jupyter === nothing jupyter = joinpath(Conda.SCRIPTDIR, exe("jupyter")) end end isconda = dirname(jupyter) == abspath(Conda.SCRIPTDIR) if !Sys.isexecutable(jupyter) if isconda && isyes(Base.prompt("install Jupyter via Conda, y/n? [y]")) Conda.add(subcommand == "lab" ? "jupyterlab" : "jupyter") else error("$jupyter is not installed, cannot run $subcommand") end end cmd = `$jupyter $subcommand` # fails in Windows if jupyter directory is not in PATH (jupyter/jupyter_core#62) pathsep = Sys.iswindows() ? ';' : ':' withenv("PATH" => dirname(jupyter) * pathsep * get(ENV, "PATH", "")) do if isconda # sets PATH and other environment variables for Julia's Conda environment cmd = Conda._set_conda_env(cmd) else setenv(cmd, ENV) end end return cmd end ################################################################## function launch(cmd, dir, detached) @info("running $cmd") if Sys.isapple() # issue #551 workaround, remove after macOS 10.12.6 release? withenv("BROWSER"=>"open") do p = run(Cmd(cmd, detach=true, dir=dir); wait=false) end else p = run(Cmd(cmd, detach=true, dir=dir); wait=false) end if !detached try wait(p) catch e if isa(e, InterruptException) kill(p, 2) # SIGINT else kill(p) # SIGTERM rethrow() end end end return p end """ notebook(; dir=homedir(), detached=false) The `notebook()` function launches the Jupyter notebook, and is equivalent to running `jupyter notebook` at the operating-system command-line. The advantage of launching the notebook from Julia is that, depending on how Jupyter was installed, the user may not know where to find the `jupyter` executable. By default, the notebook server is launched in the user's home directory, but this location can be changed by passing the desired path in the `dir` keyword argument. e.g. `notebook(dir=pwd())` to use the current directory. By default, `notebook()` does not return; you must hit ctrl-c or quit Julia to interrupt it, which halts Jupyter. So, you must leave the Julia terminal open for as long as you want to run Jupyter. Alternatively, if you run `notebook(detached=true)`, the `jupyter notebook` will launch in the background, and will continue running even after you quit Julia. (The only way to stop Jupyter will then be to kill it in your operating system's process manager.) """ function notebook(; dir=homedir(), detached=false) inited && error("IJulia is already running") notebook = find_jupyter_subcommand("notebook") return launch(notebook, dir, detached) end """ jupyterlab(; dir=homedir(), detached=false) Similar to `IJulia.notebook()` but launches JupyterLab instead of the Jupyter notebook. """ function jupyterlab(; dir=homedir(), detached=false) inited && error("IJulia is already running") lab = find_jupyter_subcommand("lab") jupyter = first(lab) if dirname(jupyter) == abspath(Conda.SCRIPTDIR) && !Sys.isexecutable(exe(jupyter, "-lab")) && isyes(Base.prompt("install JupyterLab via Conda, y/n? [y]")) Conda.add("jupyterlab") end return launch(lab, dir, detached) end function qtconsole() qtconsole = find_jupyter_subcommand("qtconsole") if inited run(`$qtconsole --existing $connection_file`; wait=false) else error("IJulia is not running. qtconsole must be called from an IJulia session.") end end ./opt/julia/packages/IJulia/Vo51o/deps/kspec.jlimport JSON ####################################################################### # Install Jupyter kernel-spec files. copy_config(src, dest) = cp(src, joinpath(dest, basename(src)), force=true) # return the user kernelspec directory, according to # https://jupyter-client.readthedocs.io/en/latest/kernels.html#kernelspecs @static if Sys.iswindows() function appdata() # return %APPDATA% path = zeros(UInt16, 300) CSIDL_APPDATA = 0x001a result = ccall((:SHGetFolderPathW,:shell32), stdcall, Cint, (Ptr{Cvoid},Cint,Ptr{Cvoid},Cint,Ptr{UInt16}),C_NULL,CSIDL_APPDATA,C_NULL,0,path) return result == 0 ? transcode(String, resize!(path, findfirst(iszero, path)-1)) : get(ENV, "APPDATA", "") end function default_jupyter_data_dir() APPDATA = appdata() return !isempty(APPDATA) ? joinpath(APPDATA, "jupyter") : joinpath(get(ENV, "JUPYTER_CONFIG_DIR", joinpath(homedir(), ".jupyter")), "data") end elseif Sys.isapple() default_jupyter_data_dir() = joinpath(homedir(), "Library/Jupyter") else function default_jupyter_data_dir() xdg_data_home = get(ENV, "XDG_DATA_HOME", "") data_home = !isempty(xdg_data_home) ? xdg_data_home : joinpath(homedir(), ".local", "share") joinpath(data_home, "jupyter") end end function jupyter_data_dir() env_data_dir = get(ENV, "JUPYTER_DATA_DIR", "") !isempty(env_data_dir) ? env_data_dir : default_jupyter_data_dir() end kerneldir() = joinpath(jupyter_data_dir(), "kernels") # Since kernelspecs show up in URLs and other places, a kernelspec is required # to have a simple name, only containing ASCII letters, ASCII numbers, and the # simple separators: - hyphen, . period, _ underscore. According to # https://jupyter-client.readthedocs.io/en/stable/kernels.html function kernelspec_name(name::AbstractString) name = replace(lowercase(name), " "=>"-") replace(name, r"[^0-9a-z_\-\.]" => s"_") end if Sys.iswindows() exe(s::AbstractString) = endswith(s, ".exe") ? s : "$s.exe" exe(s::AbstractString, e::AbstractString) = string(endswith(s, ".exe") ? s[1:end-4] : s, e, ".exe") else exe(s::AbstractString) = s exe(s::AbstractString, e::AbstractString) = s * e end """ installkernel(name::AbstractString, options::AbstractString...; julia::Cmd, specname::AbstractString, env=Dict()) Install a new Julia kernel, where the given `options` are passed to the `julia` executable, the user-visible kernel name is given by `name` followed by the Julia version, and the `env` dictionary is added to the environment. The new kernel name is returned by `installkernel`. For example: ``` kernelpath = installkernel("Julia O3", "-O3", env=Dict("FOO"=>"yes")) ``` creates a new Julia kernel in which `julia` is launched with the `-O3` optimization flag and `FOO=yes` is included in the environment variables. The returned `kernelpath` is the path of the installed kernel directory, something like `/...somepath.../kernels/julia-o3-1.6` (in Julia 1.6). The `specname` argument can be passed to alter the name of this directory (which defaults to `name` with spaces replaced by hyphens, and special characters other than `-` hyphen, `.` period and `_` underscore replaced by `_` underscores). You can uninstall the kernel by calling `rm(kernelpath, recursive=true)`. You can specify a custom command to execute Julia via keyword argument `julia`. For example, you may want specify that the Julia kernel is running in a Docker container (but Jupyter will run outside of it), by calling `installkernel` from within such a container instance like this (or similar): ``` installkernel( "Julia via Docker", julia = `docker run --rm --net=host --volume=/home/USERNAME/.local/share/jupyter:/home/USERNAME/.local/share/jupyter some-container /opt/julia-1.x/bin/julia` ) ``` """ function installkernel(name::AbstractString, julia_options::AbstractString...; julia::Cmd = `$(joinpath(Sys.BINDIR,exe("julia")))`, specname::AbstractString = kernelspec_name(name), env::Dict{<:AbstractString}=Dict{String,Any}()) # Is IJulia being built from a debug build? If so, add "debug" to the description. debugdesc = ccall(:jl_is_debugbuild,Cint,())==1 ? "-debug" : "" # path of the Jupyter kernelspec directory to install juliakspec = joinpath(kerneldir(), "$specname-$(VERSION.major).$(VERSION.minor)$debugdesc") @info("Installing $name kernelspec in $juliakspec") rm(juliakspec, force=true, recursive=true) try kernelcmd_array = String[julia.exec..., "-i", "--color=yes"] append!(kernelcmd_array, julia_options) ijulia_dir = get(ENV, "IJULIA_DIR", dirname(@__DIR__)) # support non-Pkg IJulia installs append!(kernelcmd_array, [joinpath(ijulia_dir,"src","kernel.jl"), "{connection_file}"]) ks = Dict( "argv" => kernelcmd_array, "display_name" => name * " " * Base.VERSION_STRING * debugdesc, "language" => "julia", "env" => env, # Jupyter's signal interrupt mode is not supported on Windows "interrupt_mode" => Sys.iswindows() ? "message" : "signal", ) mkpath(juliakspec) open(joinpath(juliakspec, "kernel.json"), "w") do f # indent by 2 for readability of file write(f, JSON.json(ks, 2)) end copy_config(joinpath(ijulia_dir,"deps","logo-32x32.png"), juliakspec) copy_config(joinpath(ijulia_dir,"deps","logo-64x64.png"), juliakspec) copy_config(joinpath(ijulia_dir,"deps","logo-svg.svg"), juliakspec) return juliakspec catch rm(juliakspec, force=true, recursive=true) rethrow() end end ,/opt/julia/packages/IJulia/Vo51o/src/init.jlimport Random: seed! import Logging: ConsoleLogger # use our own random seed for msg_id so that we # don't alter the user-visible random state (issue #336) const IJulia_RNG = seed!(Random.MersenneTwister(0)) import UUIDs uuid4() = string(UUIDs.uuid4(IJulia_RNG)) const orig_stdin = Ref{IO}() const orig_stdout = Ref{IO}() const orig_stderr = Ref{IO}() const SOFTSCOPE = Ref{Bool}() function __init__() seed!(IJulia_RNG) orig_stdin[] = stdin orig_stdout[] = stdout orig_stderr[] = stderr SOFTSCOPE[] = lowercase(get(ENV, "IJULIA_SOFTSCOPE", "yes")) in ("yes", "true") end # the following constants need to be initialized in init(). const publish = Ref{Socket}() const raw_input = Ref{Socket}() const requests = Ref{Socket}() const control = Ref{Socket}() const heartbeat = Ref{Socket}() const profile = Dict{String,Any}() const read_stdout = Ref{Base.PipeEndpoint}() const read_stderr = Ref{Base.PipeEndpoint}() const socket_locks = Dict{Socket,ReentrantLock}() # similar to Pkg.REPLMode.MiniREPL, a minimal REPL-like emulator # for use with Pkg.do_cmd. We have to roll our own to # make sure it uses the redirected stdout, and because # we don't have terminal support. import REPL struct MiniREPL <: REPL.AbstractREPL display::TextDisplay end REPL.REPLDisplay(repl::MiniREPL) = repl.display const minirepl = Ref{MiniREPL}() function init(args) inited && error("IJulia is already running") if length(args) > 0 merge!(profile, open(JSON.parse,args[1])) verbose && println("PROFILE = $profile") global connection_file = args[1] else # generate profile and save let port0 = 5678 merge!(profile, Dict{String,Any}( "ip" => "127.0.0.1", "transport" => "tcp", "stdin_port" => port0, "control_port" => port0+1, "hb_port" => port0+2, "shell_port" => port0+3, "iopub_port" => port0+4, "key" => uuid4() )) fname = "profile-$(getpid()).json" global connection_file = "$(pwd())/$fname" println("connect ipython with --existing $connection_file") open(fname, "w") do f JSON.print(f, profile) end end end if !isempty(profile["key"]) signature_scheme = get(profile, "signature_scheme", "hmac-sha256") isempty(signature_scheme) && (signature_scheme = "hmac-sha256") sigschm = split(signature_scheme, "-") if sigschm[1] != "hmac" || length(sigschm) != 2 error("unrecognized signature_scheme $signature_scheme") end hmacstate[] = MbedTLS.MD(getfield(MbedTLS, Symbol("MD_", uppercase(sigschm[2]))), profile["key"]) end publish[] = Socket(PUB) raw_input[] = Socket(ROUTER) requests[] = Socket(ROUTER) control[] = Socket(ROUTER) heartbeat[] = Socket(ROUTER) sep = profile["transport"]=="ipc" ? "-" : ":" bind(publish[], "$(profile["transport"])://$(profile["ip"])$(sep)$(profile["iopub_port"])") bind(requests[], "$(profile["transport"])://$(profile["ip"])$(sep)$(profile["shell_port"])") bind(control[], "$(profile["transport"])://$(profile["ip"])$(sep)$(profile["control_port"])") bind(raw_input[], "$(profile["transport"])://$(profile["ip"])$(sep)$(profile["stdin_port"])") bind(heartbeat[], "$(profile["transport"])://$(profile["ip"])$(sep)$(profile["hb_port"])") # associate a lock with each socket so that multi-part messages # on a given socket don't get inter-mingled between tasks. for s in (publish[], raw_input[], requests[], control[], heartbeat[]) socket_locks[s] = ReentrantLock() end start_heartbeat(heartbeat[]) if capture_stdout read_stdout[], = redirect_stdout() redirect_stdout(IJuliaStdio(stdout,"stdout")) end if capture_stderr read_stderr[], = redirect_stderr() redirect_stderr(IJuliaStdio(stderr,"stderr")) end redirect_stdin(IJuliaStdio(stdin,"stdin")) minirepl[] = MiniREPL(TextDisplay(stdout)) logger = ConsoleLogger(Base.stderr) Base.CoreLogging.global_logger(logger) send_status("starting") global inited = true end ,/opt/julia/packages/IJulia/Vo51o/src/hmac.jlusing MbedTLS const hmacstate = Ref{MbedTLS.MD{true}}() function hmac(s1,s2,s3,s4) if !isdefined(hmacstate, :x) return "" else MbedTLS.reset!(hmacstate[]) for s in (s1, s2, s3, s4) write(hmacstate[], s) end # Take the digest (returned as a byte array) and convert it to hex string representation digest = MbedTLS.finish!(hmacstate[]) hexdigest = Vector{UInt8}(undef, length(digest)*2) for i = 1:length(digest) b = digest[i] d = b >> 4 hexdigest[2i-1] = UInt8('0')+d+39*(d>9) d = b & 0xf hexdigest[2i] = UInt8('0')+d+39*(d>9) end return String(hexdigest) end end 1/opt/julia/packages/IJulia/Vo51o/src/eventloop.jlfunction eventloop(socket) task_local_storage(:IJulia_task, "write task") try while true msg = recv_ipython(socket) try send_status("busy", msg) invokelatest(handlers[msg.header["msg_type"]], socket, msg) catch e # Try to keep going if we get an exception, but # send the exception traceback to the front-ends. # (Ignore SIGINT since this may just be a user-requested # kernel interruption to interrupt long calculations.) if !isa(e, InterruptException) content = error_content(e, msg="KERNEL EXCEPTION") map(s -> println(orig_stderr[], s), content["traceback"]) send_ipython(publish[], msg_pub(execute_msg, "error", content)) end finally flush_all() send_status("idle", msg) end end catch e # the Jupyter manager may send us a SIGINT if the user # chooses to interrupt the kernel; don't crash on this if isa(e, InterruptException) eventloop(socket) else rethrow() end end end const requests_task = Ref{Task}() function waitloop() @async eventloop(control[]) requests_task[] = @async eventloop(requests[]) while true try wait() catch e # send interrupts (user SIGINT) to the code-execution task if isa(e, InterruptException) @async Base.throwto(requests_task[], e) else rethrow() end end end end -/opt/julia/packages/IJulia/Vo51o/src/stdio.jlJ(# IJulia redirects stdout and stderr into "stream" messages sent to the # Jupyter front-end. # create a wrapper type around redirected stdio streams, # both for overloading things like `flush` and so that we # can set properties like `color`. struct IJuliaStdio{IO_t <: IO} <: Base.AbstractPipe io::IOContext{IO_t} end IJuliaStdio(io::IO, stream::AbstractString="unknown") = IJuliaStdio{typeof(io)}(IOContext(io, :color=>Base.have_color, :jupyter_stream=>stream, :displaysize=>displaysize())) Base.pipe_reader(io::IJuliaStdio) = io.io.io Base.pipe_writer(io::IJuliaStdio) = io.io.io Base.lock(io::IJuliaStdio) = lock(io.io.io) Base.unlock(io::IJuliaStdio) = unlock(io.io.io) Base.in(key_value::Pair, io::IJuliaStdio) = in(key_value, io.io) Base.haskey(io::IJuliaStdio, key) = haskey(io.io, key) Base.getindex(io::IJuliaStdio, key) = getindex(io.io, key) Base.get(io::IJuliaStdio, key, default) = get(io.io, key, default) Base.displaysize(io::IJuliaStdio) = displaysize(io.io) Base.unwrapcontext(io::IJuliaStdio) = Base.unwrapcontext(io.io) Base.setup_stdio(io::IJuliaStdio, readable::Bool) = Base.setup_stdio(io.io.io, readable) if VERSION < v"1.7.0-DEV.254" for s in ("stdout", "stderr", "stdin") f = Symbol("redirect_", s) sq = QuoteNode(Symbol(s)) @eval function Base.$f(io::IJuliaStdio) io[:jupyter_stream] != $s && throw(ArgumentError(string("expecting ", $s, " stream"))) Core.eval(Base, Expr(:(=), $sq, io)) return io end end end # logging in verbose mode goes to original stdio streams. Use macros # so that we do not even evaluate the arguments in no-verbose modes using Printf function get_log_preface() t = now() taskname = get(task_local_storage(), :IJulia_task, "") @sprintf("%02d:%02d:%02d(%s): ", Dates.hour(t),Dates.minute(t),Dates.second(t),taskname) end macro vprintln(x...) quote if verbose::Bool println(orig_stdout[], get_log_preface(), $(map(esc, x)...)) end end end macro verror_show(e, bt) quote if verbose::Bool showerror(orig_stderr[], $(esc(e)), $(esc(bt))) end end end #name=>iobuffer for each stream ("stdout","stderr") so they can be sent in flush const bufs = Dict{String,IOBuffer}() const stream_interval = 0.1 # maximum number of bytes in libuv/os buffer before emptying const max_bytes = 10*1024 # max output per code cell is 512 kb by default const max_output_per_request = Ref(1 << 19) """ Continually read from (size limited) Libuv/OS buffer into an `IObuffer` to avoid problems when the Libuv/OS buffer gets full (https://github.com/JuliaLang/julia/issues/8789). Send data immediately when buffer contains more than `max_bytes` bytes. Otherwise, if data is available it will be sent every `stream_interval` seconds (see the Timers set up in watch_stdio). Truncate the output to `max_output_per_request` bytes per execution request since excessive output can bring browsers to a grinding halt. """ function watch_stream(rd::IO, name::AbstractString) task_local_storage(:IJulia_task, "read $name task") try buf = IOBuffer() bufs[name] = buf while !eof(rd) # blocks until something is available nb = bytesavailable(rd) if nb > 0 stdio_bytes[] += nb # if this stream has surpassed the maximum output limit then ignore future bytes if stdio_bytes[] >= max_output_per_request[] read(rd, nb) # read from libuv/os buffer and discard if stdio_bytes[] - nb < max_output_per_request[] send_ipython(publish[], msg_pub(execute_msg, "stream", Dict("name" => "stderr", "text" => "Excessive output truncated after $(stdio_bytes[]) bytes."))) end else write(buf, read(rd, nb)) end end if buf.size > 0 if buf.size >= max_bytes #send immediately send_stream(name) end end end catch e # the IPython manager may send us a SIGINT if the user # chooses to interrupt the kernel; don't crash on this if isa(e, InterruptException) watch_stream(rd, name) else rethrow() end end end function send_stdio(name) if verbose::Bool && !haskey(task_local_storage(), :IJulia_task) task_local_storage(:IJulia_task, "send $name task") end send_stream(name) end send_stdout(t::Timer) = send_stdio("stdout") send_stderr(t::Timer) = send_stdio("stderr") """ Jupyter associates cells with message headers. Once a cell's execution state has been set as to idle, it will silently drop stream messages (i.e. output to stdout and stderr) - see https://github.com/jupyter/notebook/issues/518. When using Interact, and a widget's state changes, a new message header is sent to the IJulia kernel, and while Reactive is updating Signal graph state, it's execution state is busy, meaning Jupyter will not drop stream messages if Interact can set the header message under which the stream messages will be sent. Hence the need for this function. """ function set_cur_msg(msg) global execute_msg = msg end function send_stream(name::AbstractString) buf = bufs[name] if buf.size > 0 d = take!(buf) n = num_utf8_trailing(d) dextra = d[end-(n-1):end] resize!(d, length(d) - n) s = String(copy(d)) if isvalid(String, s) write(buf, dextra) # assume that the rest of the string will be written later length(d) == 0 && return else # fallback: base64-encode non-UTF8 binary data sbuf = IOBuffer() print(sbuf, "base64 binary data: ") b64 = Base64EncodePipe(sbuf) write(b64, d) write(b64, dextra) close(b64) print(sbuf, '\n') s = String(take!(sbuf)) end send_ipython(publish[], msg_pub(execute_msg, "stream", Dict("name" => name, "text" => s))) end end """ If `d` ends with an incomplete UTF8-encoded character, return the number of trailing incomplete bytes. Otherwise, return `0`. """ function num_utf8_trailing(d::Vector{UInt8}) i = length(d) # find last non-continuation byte in d: while i >= 1 && ((d[i] & 0xc0) == 0x80) i -= 1 end i < 1 && return 0 c = d[i] # compute number of expected UTF-8 bytes starting at i: n = c <= 0x7f ? 1 : c < 0xe0 ? 2 : c < 0xf0 ? 3 : 4 nend = length(d) + 1 - i # num bytes from i to end return nend == n ? 0 : nend end """ readprompt(prompt::AbstractString; password::Bool=false) Display the `prompt` string, request user input, and return the string entered by the user. If `password` is `true`, the user's input is not displayed during typing. """ function readprompt(prompt::AbstractString; password::Bool=false) if !execute_msg.content["allow_stdin"] error("IJulia: this front-end does not implement stdin") end send_ipython(raw_input[], msg_reply(execute_msg, "input_request", Dict("prompt"=>prompt, "password"=>password))) while true msg = recv_ipython(raw_input[]) if msg.header["msg_type"] == "input_reply" return msg.content["value"] else error("IJulia error: unknown stdin reply") end end end # override prompts using julia#28038 in 0.7 function check_prompt_streams(input::IJuliaStdio, output::IJuliaStdio) if get(input,:jupyter_stream,"unknown") != "stdin" || get(output,:jupyter_stream,"unknown") != "stdout" throw(ArgumentError("prompt on IJulia stdio streams only works for stdin/stdout")) end end function Base.prompt(input::IJuliaStdio, output::IJuliaStdio, message::AbstractString; default::AbstractString="") check_prompt_streams(input, output) val = chomp(readprompt(message * ": ")) return isempty(val) ? default : val end function Base.getpass(input::IJuliaStdio, output::IJuliaStdio, message::AbstractString) check_prompt_streams(input, output) # fixme: should we do more to zero memory associated with the password? # doing this properly might require working with the raw ZMQ message buffer here return Base.SecretBuffer!(Vector{UInt8}(codeunits(readprompt(message * ": ", password=true)))) end # IJulia issue #42: there doesn't seem to be a good way to make a task # that blocks until there is a read request from STDIN ... this makes # it very hard to properly redirect all reads from STDIN to pyin messages. # In the meantime, however, we can just hack it so that readline works: import Base.readline function readline(io::IJuliaStdio) if get(io,:jupyter_stream,"unknown") == "stdin" return readprompt("stdin> ") else readline(io.io) end end function watch_stdio() task_local_storage(:IJulia_task, "init task") if capture_stdout read_task = @async watch_stream(read_stdout[], "stdout") #send stdout stream msgs every stream_interval secs (if there is output to send) Timer(send_stdout, stream_interval, interval=stream_interval) end if capture_stderr readerr_task = @async watch_stream(read_stderr[], "stderr") #send STDERR stream msgs every stream_interval secs (if there is output to send) Timer(send_stderr, stream_interval, interval=stream_interval) end end function flush_all() flush_cstdio() # flush writes to stdout/stderr by external C code flush(stdout) flush(stderr) end function oslibuv_flush() #refs: https://github.com/JuliaLang/IJulia.jl/issues/347#issuecomment-144505862 # https://github.com/JuliaLang/IJulia.jl/issues/347#issuecomment-144605024 @static if Sys.iswindows() ccall(:SwitchToThread, stdcall, Cvoid, ()) end yield() yield() end import Base.flush function flush(io::IJuliaStdio) flush(io.io) oslibuv_flush() send_stream(get(io,:jupyter_stream,"unknown")) end +/opt/julia/packages/IJulia/Vo51o/src/msg.jl!import Base.show export Msg, msg_pub, msg_reply, send_status, send_ipython # IPython message structure mutable struct Msg idents::Vector{String} header::Dict content::Dict parent_header::Dict metadata::Dict function Msg(idents, header::Dict, content::Dict, parent_header=Dict{String,Any}(), metadata=Dict{String,Any}()) new(idents,header,content,parent_header,metadata) end end msg_header(m::Msg, msg_type::String) = Dict("msg_id" => uuid4(), "username" => m.header["username"], "session" => m.header["session"], "date" => now(), "msg_type" => msg_type, "version" => "5.3") # PUB/broadcast messages use the msg_type as the ident, except for # stream messages which use the stream name (e.g. "stdout"). # [According to minrk, "this isn't well defined, or even really part # of the spec yet" and is in practice currently ignored since "all # subscribers currently subscribe to all topics".] msg_pub(m::Msg, msg_type, content, metadata=Dict{String,Any}()) = Msg([ msg_type == "stream" ? content["name"] : msg_type ], msg_header(m, msg_type), content, m.header, metadata) msg_reply(m::Msg, msg_type, content, metadata=Dict{String,Any}()) = Msg(m.idents, msg_header(m, msg_type), content, m.header, metadata) function show(io::IO, msg::Msg) print(io, "IPython Msg [ idents ") print(io, join(msg.idents, ", ")) print(io, " ] {\n parent_header = $(msg.parent_header),\n header = $(msg.header),\n metadata = $(msg.metadata),\n content = $(msg.content)\n}") end function send_ipython(socket, m::Msg) lock(socket_locks[socket]) try @vprintln("SENDING ", m) for i in m.idents send(socket, i, more=true) end send(socket, "", more=true) header = json(m.header) parent_header = json(m.parent_header) metadata = json(m.metadata) content = json(m.content) send(socket, hmac(header, parent_header, metadata, content), more=true) send(socket, header, more=true) send(socket, parent_header, more=true) send(socket, metadata, more=true) send(socket, content) finally unlock(socket_locks[socket]) end end function recv_ipython(socket) lock(socket_locks[socket]) try idents = String[] s = recv(socket, String) @vprintln("got msg part $s") while s != "" push!(idents, s) s = recv(socket, String) @vprintln("got msg part $s") end signature = recv(socket, String) request = Dict{String,Any}() header = recv(socket, String) parent_header = recv(socket, String) metadata = recv(socket, String) content = recv(socket, String) if signature != hmac(header, parent_header, metadata, content) error("Invalid HMAC signature") # What should we do here? end m = Msg(idents, JSON.parse(header), JSON.parse(content), JSON.parse(parent_header), JSON.parse(metadata)) @vprintln("RECEIVED $m") return m finally unlock(socket_locks[socket]) end end function send_status(state::AbstractString, parent_msg::Msg=execute_msg) send_ipython(publish[], Msg([ "status" ], msg_header(parent_msg, "status"), Dict("execution_state" => state), parent_msg.header)) end //opt/julia/packages/IJulia/Vo51o/src/display.jli # define our own method to avoid type piracy with Base.showable _showable(a::AbstractVector{<:MIME}, x) = any(m -> showable(m, x), a) _showable(m, x) = showable(m, x) """ A vector of MIME types (or vectors of MIME types) that IJulia will try to render. IJulia will try to render every MIME type specified in the first level of the vector. If a vector of MIME types is specified, IJulia will include only the first MIME type that is renderable (this allows for the expression of priority and exclusion of redundant data). For example, since "text/plain" is specified as a first-child of the array, IJulia will always try to include a "text/plain" representation of anything that is displayed. Since markdown and html are specified within a sub-vector, IJulia will always try to render "text/markdown", and will only try to render "text/html" if markdown isn't possible. """ const ijulia_mime_types = Vector{Union{MIME, AbstractVector{MIME}}}([ MIME("text/plain"), MIME("image/svg+xml"), [MIME("image/png"),MIME("image/jpeg")], [ MIME("text/markdown"), MIME("text/html"), ], MIME("text/latex"), ]) """ MIME types that when rendered (via stringmime) return JSON data. See `ijulia_mime_types` for a description of how MIME types are selected. This is necessary to embed the JSON as is in the displaydata bundle (rather than as stringify'd JSON). """ const ijulia_jsonmime_types = Vector{Union{MIME, Vector{MIME}}}([ [[MIME("application/vnd.vegalite.v$n+json") for n in 4:-1:2]..., [MIME("application/vnd.vega.v$n+json") for n in 5:-1:3]...], MIME("application/vnd.dataresource+json"), MIME("application/vnd.plotly.v1+json") ]) register_mime(x::Union{MIME, Vector{MIME}})= push!(ijulia_mime_types, x) register_mime(x::AbstractVector{<:MIME}) = push!(ijulia_mime_types, Vector{Mime}(x)) register_jsonmime(x::Union{MIME, Vector{MIME}}) = push!(ijulia_jsonmime_types, x) register_jsonmime(x::AbstractVector{<:MIME}) = push!(ijulia_jsonmime_types, Vector{Mime}(x)) # return a String=>Any dictionary to attach as metadata # in Jupyter display_data and pyout messages metadata(x) = Dict() """ Generate the preferred MIME representation of x. Returns a tuple with the selected MIME type and the representation of the data using that MIME type. """ function display_mimestring(mime_array::Vector{MIME}, x) for m in mime_array if _showable(m, x) return display_mimestring(m, x) end end error("No displayable MIME types in mime array.") end display_mimestring(m::MIME, x) = (m, limitstringmime(m, x)) # text/plain output must have valid Unicode data to display in Jupyter function display_mimestring(m::MIME"text/plain", x) s = limitstringmime(m, x) return m, (isvalid(s) ? s : "(binary data)") end """ Generate the preferred json-MIME representation of x. Returns a tuple with the selected MIME type and the representation of the data using that MIME type (as a `JSONText`). """ function display_mimejson(mime_array::Vector{MIME}, x) for m in mime_array if _showable(m, x) return display_mimejson(m, x) end end error("No displayable MIME types in mime array.") end display_mimejson(m::MIME, x) = (m, JSON.JSONText(limitstringmime(m, x, true))) """ Generate a dictionary of `mime_type => data` pairs for all registered MIME types. This is the format that Jupyter expects in display_data and execute_result messages. """ function display_dict(x) data = Dict{String, Union{String, JSONText}}() for m in ijulia_mime_types try if _showable(m, x) mime, mime_repr = display_mimestring(m, x) data[string(mime)] = mime_repr end catch if m == MIME("text/plain") rethrow() # text/plain is required end end end for m in ijulia_jsonmime_types try if _showable(m, x) mime, mime_repr = display_mimejson(m, x) data[string(mime)] = mime_repr end catch end end return data end # queue of objects to display at end of cell execution const displayqueue = Any[] # remove x from the display queue function undisplay(x) i = findfirst(isequal(x), displayqueue) i !== nothing && splice!(displayqueue, i) return x end import Base: ip_matches_func function show_bt(io::IO, top_func::Symbol, t, set) # follow PR #17570 code in removing top_func from backtrace eval_ind = findlast(addr->ip_matches_func(addr, top_func), t) eval_ind !== nothing && (t = t[1:eval_ind-1]) Base.show_backtrace(io, t) end # wrapper for showerror(..., backtrace=false) since invokelatest # doesn't support keyword arguments. showerror_nobt(io, e, bt) = showerror(io, e, bt, backtrace=false) # return the content of a pyerr message for exception e function error_content(e, bt=catch_backtrace(); backtrace_top::Symbol=SOFTSCOPE[] && VERSION < v"1.5.0-DEV.263" ? :softscope_include_string : :include_string, msg::AbstractString="") tb = map(String, split(sprint(show_bt, backtrace_top, bt, 1:typemax(Int)), "\n", keepempty=true)) ename = string(typeof(e)) evalue = try # Peel away one LoadError layer that comes from running include_string on the cell isa(e, LoadError) && (e = e.error) sprint((io, e, bt) -> invokelatest(showerror_nobt, io, e, bt), e, bt; context=InlineIOContext(stderr)) catch "SYSTEM: show(lasterr) caused an error" end pushfirst!(tb, evalue) # fperez says this needs to be in traceback too if !isempty(msg) pushfirst!(tb, msg) end Dict("ename" => ename, "evalue" => evalue, "traceback" => tb) end ####################################################################### ./opt/julia/packages/IJulia/Vo51o/src/magics.jl?I# IJulia does not use IPython magic syntax, because there are better # alternatives in Julia, whereas "magics" are inherently limited to # running in Jupyter cells only. The alternatives in Julia, which # can work in any Julia code regardless of whether it is in a notebook # cell, are: # * To interact with the running kernel, we can use IJulia.foo(...), # since the running IJulia kernel is loaded into Main. # * For implementing special syntax, Julia has @macros and # stringmacros"....". # However, to ease the transition for users coming from other Jupyter kernels, # we implement some magics that tell the user how to do the corresponding # thing in Julia. These are executed whenever a cell beginning with % # is encountered. # regex to find the presence of magics in a code-cell string const magics_regex = r"^\s*(%%?[A-Za-z_][A-Za-z_0-9]*\b)\s*(.*)\s*$"m # given the cell contents "code" (which start with %foo) output help # that indicates the Julia equivalent, if possible. function magics_help(code::AbstractString) for m in eachmatch(magics_regex, code) display(get(magic_help, m[1], generic_magic_help)(m[1], m[2])) end end using Markdown const magic_help_string = """ Julia does not use the IPython `%magic` syntax. To interact with the IJulia kernel, use `IJulia.somefunction(...)`, for example. Julia macros, string macros, and functions can be used to accomplish most of the other functionalities of IPython magics.""" generic_magic_help(magic::AbstractString, args::AbstractString) = Markdown.parse(""" Unrecognized magic `$magic`. $magic_help_string""") lsmagic_help(magic::AbstractString, args::AbstractString) = Markdown.parse(""" $magic_help_string The Julia analogues of many IPython magics are printed if you try to input the IPython magic in a code cell.""") alias_magic_help(magic::AbstractString, args::AbstractString) = md""" The equivalent of `%alias` magic in Julia is simply to write a function that [runs a command object](http://docs.julialang.org/en/latest/manual/running-external-programs/). For example, the equivalent of `%alias bracket echo "Input in brackets: <%l>"` in IPython would be the Julia function bracket(l) = run(`echo "Input in brackets: <$l>"`) which you can then run with e.g. `bracket("hello world")`.""" function cd_magic_help(magic::AbstractString, args::AbstractString) if magic == "%cd" && !occursin(r"\s*-", args) return md"""The equivalent of `%cd 'dir'` in IPython is `cd("dir")` in Julia.""" else return md""" The equivalent of `%cd 'dir'` in IPython is `cd("dir")` in Julia. Julia does not keep a history of visited directories, so it has no built-in equivalent of IPython's `%cd -`, `%dhist`, `%pushd`, and `%popd`. However, if you are interested, it would be easy to write a Julia function `mycd(x)` that worked like IPython's `%cd` (accepting a string, `-`, `-n`, and so on, and keeping a stack of directory history). This might make a nice little Julia package if you are sufficiently motivated.""" end end debug_magic_help(magic::AbstractString, args::AbstractString) = md"""The Julia interactive debugger is provided by the [Gallium](https://github.com/Keno/Gallium.jl) package.""" edit_magic_help(magic::AbstractString, args::AbstractString) = md""" An analogue of IPython's `%edit` magic is provided by the `edit` function and the `@edit` macro in Julia, as described [in the Julia manual](http://docs.julialang.org/en/latest/stdlib/base/#Base.edit). For example, instead of `%edit -n line 'filename'` in IPython, you would do `edit("filename", line)` followed by `include("filename")` if you want to execute the file when you are done editing. The analogue of `%edit` (which creates a temporary file) is `n=tempname(); edit(n)` followed by `include(n)`. If you have a function `foo()`, then `%edit foo` in IPython opens the file where `foo` was defined. The analogue of this in Julia is to do `@edit foo()` Note that you need to supply sample arguments to `foo` (which is not actually called), so that Julia knows *which* method of `foo` you want to edit. If `s` is a string variable, IPython's `%edit s` loads its contents into an editor. In Julia, you would have to explicitly write to a temporary file with `n=tempname(); write(n, s); edit(n)` followed by `include(n)` to execute it.""" env_magic_help(magic::AbstractString, args::AbstractString) = md""" The equivalent of `%env` in IPython, which lists all environment variables, is `ENV` in Julia, and the equivalent of `%env var=val` is `ENV["var"]=val`. (The `ENV` built-in global variable in Julia provides a dictionary-like interface to the system environment variables.) """ gui_magic_help(magic::AbstractString, args::AbstractString) = md""" There is an analogue of IPython's `%gui` in the [PyCall package](https://github.com/stevengj/PyCall.jl) for calling Python from Julia. If you have done `using PyCall` to load PyCall, then the analogue of `%gui wx` is `pygui_start(:wx)`, and the analogue of `%gui` is `pygui_stop()`. See the PyCall documentation for more information. Other Julia packages for GUI toolkits, e.g. the [Tk package](https://github.com/JuliaGraphics/Tk.jl) or the [Gtk package](https://github.com/JuliaGraphics/Gtk.jl), also provide their own event-loop integration.""" history_magic_help(magic::AbstractString, args::AbstractString) = md""" An analogue of the `%history` or `%hist` magic of IPython, which provides access to the input history, is given by IJulia.history(). It is based on the global variable `In` in IJulia. `In` is a dictionary mapping cell numbers to the inputs. However, IJulia does not currently keep any other history, e.g. it discards input cells that you overwrite. """ load_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of `%load filename` in IPython is `IJulia.load("filename")` in IJulia (to load code from `filename` into the current frontend) The analogue of `%load url` is `IJulia.load(download("url"))`. """ paste_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of `%paste` in IPython is `IJulia.load_string(clipboard())` in IJulia (to load code from the clipboard into the current frontend). """ matplotlib_magic_help(magic::AbstractString, args::AbstractString) = Markdown.parse(""" The analogue of IPython's `$magic` in Julia is to use the [PyPlot package](https://github.com/stevengj/PyPlot.jl), which gives a Julia interface to Matplotlib including inline plots in IJulia notebooks. (The equivalent of `numpy` is already loaded by default in Julia.) Given PyPlot, the analogue of `$magic inline` is `using PyPlot`, since PyPlot defaults to inline plots in IJulia. To enable separate GUI windows in PyPlot, analogous to `$magic`, do `using PyPlot; pygui(true)`. To specify a particular gui backend, analogous to `$magic gui`, you can either do `using PyPlot; pygui(:gui); using PyPlot; pygui(true)` (where `gui` is `wx`, `qt`, `tk`, or `gtk`), or you can do `ENV["MPLBACKEND"]=backend; using PyPlot; pygui(true)` (where `backend` is the name of a Matplotlib backend, like `tkagg`). For more options, see the PyPlot documentation.""") pdef_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%pdef somefunction` in Julia is `methods(somefunction)`, which prints out all of the possible calling signatures of `somefunction`. (Note that, unlike Python, Julia is based on multiple dispatch, so a given function will often be callable with many different argument signatures.)""" pdoc_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%pdoc object` is `?object` in IJulia.""" pfile_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%pfile somefunction` (also `%psource`) is roughly `@less somefunction(somearguments...)` in Julia. The reason that you need to supply sample arguments (the function is not actually evaluated) is because Julia functions can have multiple definitions for different argument types. `@less somefunction(somearguments...)` will print (or run through the `less` pager) the `somefunction` definition corresponding to the arguments you supply.""" file_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%file somefunction` is roughly `methods(somefunction)` in Julia. This lists all the methods of `sumfunction` along with the locations where they are defined.""" precision_magic_help(magic::AbstractString, args::AbstractString) = md""" There currently is no way to globally set the output precision in Julia, analogous to `%precision` in IPython, as discussed in [Julia issue #6493](https://github.com/JuliaLang/julia/issues/6493).""" prun_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%prun statement` in Julia is `@profile statement`, which runs the [Julia profiler](http://docs.julialang.org/en/latest/manual/profile/). The analogue of `%%prun ...code...` is ``` @profile begin ...code... end ``` Note, however, that you should put all performance-critical code into a function, avoiding global variables, before doing performance measurements in Julia; see the [performance tips in the Julia manual](http://docs.julialang.org/en/latest/manual/performance-tips/). See also the [ProfileView package](https://github.com/timholy/ProfileView.jl) for richer graphical display of profiling output.""" psearch_magic_help(magic::AbstractString, args::AbstractString) = md""" A rough analogue of IPython's `%psearch PATTERN` in Julia might be `filter(s -> occursin(r"PATTERN", string(s)), names(Base))`, which searches all the symbols defined in the `Base` module for a given regular-expression pattern `PATTERN`.""" pwd_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%pwd` is `pwd()` in Julia.""" qtconsole_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%qtconsole` is `IJulia.qtconsole()` in Julia.""" recall_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%recall n` in IJulia is `IJulia.load_string(In[n])`, and the analogue of `%recall n-m` is `IJulia.load_string(join([get(In,i,"") for i in n:m],"\n"))`.""" run_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%run file` is `include("file")` in Julia. The analogue of `%run -t file`, to print timing information, is `@time include("file")` in Julia. The analogue of `%run -t -N n file` is `@time for i in 1:n; include("file"); end` in Julia. For running under a debugger, see the [Gallium Julia debugger](https://github.com/Keno/Gallium.jl). To run other IJulia notebooks, see the [NBInclude package](https://github.com/stevengj/NBInclude.jl).""" save_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%save filename n1-n2 n3-n4` is ``` open("filename","w") do io for i in [n1:n2; n3:n4] println(get(In,i,"")) end end ``` in IJulia.""" sc_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%sc shell command` is `; shell command` in IJulia, or read(`shell command`, String) to capture the output as a string in Julia.""" set_env_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%set_env var val` is `ENV["var"]=val` in Julia.""" sx_magic_help(magic::AbstractString, args::AbstractString) = Markdown.parse(""" The analogue of IPython's `$magic shell command` is split(read(`shell command`, String),'\n') in Julia.""") time_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%time statement` (also `%timeit`) in Julia is `@time statement`. The analogue of `%%time ...code...` is ``` @time begin ...code... end ``` Note, however, that you should put all performance-critical code into a function, avoiding global variables, before doing performance measurements in Julia; see the [performance tips in the Julia manual](http://docs.julialang.org/en/latest/manual/performance-tips/). The `@time` macro prints the timing results, and returns the value of evaluating the expression. To instead return the time (in seconds), use `@elapsed statement`. For more extensive benchmarking tools, including the ability to collect statistics from multiple runs, see the [BenchmarkTools package](https://github.com/JuliaCI/BenchmarkTools.jl).""" who_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%who` and `%whos` is `whos()` in Julia. You can also use `whos(r"PATTERN")` to find variables matching a given regular expression `PATTERN`.""" html_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%%html` is ``` HTML(""\" ...html text... ""\") ``` in Julia.""" javascript_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%%javascript ...code...` in Julia can be constructed by first evaluating ``` macro javascript_str(s) display("text/javascript", s); end ``` to define the `javascript"...."` [string macro](http://docs.julialang.org/en/latest/manual/strings/#non-standard-string-literals) in Julia. Subsequently, you can simply do: ``` javascript""\" ...code... ""\" ``` to execute the script in an IJulia notebook.""" latex_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%%latex` is ``` display("text/latex", ""\" ...latex text... ""\") ``` in Julia. Note, however, that `$` and `\` in the LaTeX text needs to be escaped as `\$` and `\\` so that they aren't interpreted by Julia. See, however, the [LaTeXStrings package](https://github.com/stevengj/LaTeXStrings.jl) for easier input of LaTeX text as L""\" ...latex text... ""\" without requiring any extra backslashes. """ function pipe_magic_help(magic::AbstractString, args::AbstractString) cmd = magic[3:end] # magic is "%%cmd" if cmd == "script" arglist = split(args) cmd = isempty(arglist) ? "someprogram" : arglist[end] magic = "%%script $cmd" end Markdown.parse(""" The analogue of IPython's `$magic ...code...` in Julia can be constructed by first evaluating ``` macro $(cmd)_str(s) open(`$cmd`,"w",stdout) do io; print(io, s); end; end ``` to define the `$cmd"...."` [string macro](http://docs.julialang.org/en/latest/manual/strings/#non-standard-string-literals) in Julia. Subsequently, you can simply do: ``` $cmd""\" ...code... ""\" ``` to evaluate the code in `$cmd` (outputting to `stdout`).""") end svg_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%%svg` is ``` display("image/svg+xml", ""\" ...svg text... ""\") ``` in Julia. To be even nicer, you can define ``` macro svg_str(s) display("image/svg+xml", s); end ``` to define the `svg"...."` [string macro](http://docs.julialang.org/en/latest/manual/strings/#non-standard-string-literals) in Julia. Subsequently, you can simply do: ``` svg""\" ...svg text... ""\" ``` to display the SVG image. Using a custom string macro like this has the advantage that you don't need to escape `$` and `\` if they appear in the SVG code.""" writefile_magic_help(magic::AbstractString, args::AbstractString) = md""" The analogue of IPython's `%%writefile filename` is `write("filename", In[IJulia.n])`. (`IJulia.n` is the index of the current code cell. Of course, you can also use `In[N]` for some other `N` to output the contents of a different input cell.)""" # map from magic to helpfunction(magic, magicargument) const magic_help = Dict{String, Function}( "%alias" => alias_magic_help, "%cd" => cd_magic_help, "%dhist" => cd_magic_help, "%dirs" => cd_magic_help, "%popd" => cd_magic_help, "%pushd" => cd_magic_help, "%debug" => debug_magic_help, "%pdb" => debug_magic_help, "%edit" => edit_magic_help, "%env" => env_magic_help, "%gui" => gui_magic_help, "%hist" => history_magic_help, "%history" => history_magic_help, "%load" => load_magic_help, "%loadpy" => load_magic_help, "%paste" => paste_magic_help, "%lsmagic" => lsmagic_help, "%matplotlib" => matplotlib_magic_help, "%pylab" => matplotlib_magic_help, "%pdef" => pdef_magic_help, "%pdoc" => pdoc_magic_help, "%pinfo" => pdoc_magic_help, "%pinfo2" => pdoc_magic_help, "%pfile" => pfile_magic_help, "%file" => file_magic_help, "%psource" => pfile_magic_help, "%precision" => precision_magic_help, "%prun" => prun_magic_help, "%%prun" => prun_magic_help, "%psearch" => psearch_magic_help, "%pwd" => pwd_magic_help, "%qtconsole" => qtconsole_magic_help, "%recall" => recall_magic_help, "%run" => run_magic_help, "%save" => save_magic_help, "%sc" => sc_magic_help, "%set_env" => set_env_magic_help, "%sx" => sx_magic_help, "%system" => sx_magic_help, "%time" => time_magic_help, "%%time" => time_magic_help, "%timeit" => time_magic_help, "%%timeit" => time_magic_help, "%who" => who_magic_help, "%who_ls" => who_magic_help, "%whos" => who_magic_help, "%%html" => html_magic_help, "%%javascript" => javascript_magic_help, "%%latex" => latex_magic_help, "%%bash" => pipe_magic_help, "%%perl" => pipe_magic_help, "%%python" => pipe_magic_help, "%%python2" => pipe_magic_help, "%%python3" => pipe_magic_help, "%%ruby" => pipe_magic_help, "%%script" => pipe_magic_help, "%%sh" => pipe_magic_help, "%%svg" => svg_magic_help, "%%writefile" => writefile_magic_help, ) 4/opt/julia/packages/IJulia/Vo51o/src/comm_manager.jl+module CommManager using IJulia import IJulia: Msg, uuid4, send_ipython, msg_pub export Comm, comm_target, msg_comm, send_comm, close_comm, register_comm, comm_msg, comm_open, comm_close, comm_info_request mutable struct Comm{target} id::String primary::Bool on_msg::Function on_close::Function function (::Type{Comm{target}})(id, primary, on_msg, on_close) where {target} comm = new{target}(id, primary, on_msg, on_close) comms[id] = comm return comm end end # This dict holds a map from CommID to Comm so that we can # pick out the right Comm object when messages arrive # from the front-end. const comms = Dict{String, Comm}() noop_callback(msg) = nothing function Comm(target, id=uuid4(), primary=true, on_msg=noop_callback, on_close=noop_callback; data=Dict(), metadata=Dict()) comm = Comm{Symbol(target)}(id, primary, on_msg, on_close) if primary # Request a secondary object be created at the front end send_ipython(IJulia.publish[], msg_comm(comm, IJulia.execute_msg, "comm_open", data, metadata, target_name=string(target))) end return comm end comm_target(comm :: Comm{target}) where {target} = target function comm_info_request(sock, msg) reply = if haskey(msg.content, "target_name") t = Symbol(msg.content["target_name"]) filter(kv -> comm_target(kv.second) == t, comms) else # reply with all comms. comms end _comms = Dict{String, Dict{Symbol,Symbol}}() for (comm_id,comm) in reply _comms[comm_id] = Dict(:target_name => comm_target(comm)) end content = Dict(:comms => _comms) send_ipython(IJulia.publish[], msg_reply(msg, "comm_info_reply", content)) end function msg_comm(comm::Comm, m::IJulia.Msg, msg_type, data=Dict{String,Any}(), metadata=Dict{String, Any}(); kwargs...) content = Dict("comm_id"=>comm.id, "data"=>data) for (k, v) in kwargs content[string(k)] = v end return msg_pub(m, msg_type, content, metadata) end function send_comm(comm::Comm, data::Dict, metadata::Dict = Dict(); kwargs...) msg = msg_comm(comm, IJulia.execute_msg, "comm_msg", data, metadata; kwargs...) send_ipython(IJulia.publish[], msg) end function close_comm(comm::Comm, data::Dict = Dict(), metadata::Dict = Dict(); kwargs...) msg = msg_comm(comm, IJulia.execute_msg, "comm_close", data, metadata; kwargs...) send_ipython(IJulia.publish[], msg) end function register_comm(comm::Comm, data) # no-op, widgets must override for their targets. # Method dispatch on Comm{t} serves # the purpose of register_target in IPEP 21. end # handlers for incoming comm_* messages function comm_open(sock, msg) if haskey(msg.content, "comm_id") comm_id = msg.content["comm_id"] if haskey(msg.content, "target_name") target = msg.content["target_name"] if !haskey(msg.content, "data") msg.content["data"] = Dict() end comm = Comm(target, comm_id, false) register_comm(comm, msg) comms[comm_id] = comm else # Tear down comm to maintain consistency # if a target_name is not present send_ipython(IJulia.publish[], msg_comm(Comm(:notarget, comm_id), msg, "comm_close")) end end end function comm_msg(sock, msg) if haskey(msg.content, "comm_id") comm_id = msg.content["comm_id"] if haskey(comms, comm_id) comm = comms[comm_id] else # We don't have that comm open return end if !haskey(msg.content, "data") msg.content["data"] = Dict() end comm.on_msg(msg) end end function comm_close(sock, msg) if haskey(msg.content, "comm_id") comm_id = msg.content["comm_id"] comm = comms[comm_id] if !haskey(msg.content, "data") msg.content["data"] = Dict() end comm.on_close(msg) delete!(comms, comm.id) end end end # module 7/opt/julia/packages/IJulia/Vo51o/src/execute_request.jl# Handers for execute_request and related messages, which are # the core of the Jupyter protocol: execution of Julia code and # returning results. import Base.Libc: flush_cstdio import Pkg # global variable so that display can be done in the correct Msg context execute_msg = Msg(["julia"], Dict("username"=>"jlkernel", "session"=>uuid4()), Dict()) # global variable tracking the number of bytes written in the current execution # request const stdio_bytes = Ref(0) import REPL: helpmode # use a global array to accumulate "payloads" for the execute_reply message const execute_payloads = Dict[] function execute_request(socket, msg) code = msg.content["code"] @vprintln("EXECUTING ", code) global execute_msg = msg global n, In, Out, ans stdio_bytes[] = 0 silent = msg.content["silent"] store_history = get(msg.content, "store_history", !silent) empty!(execute_payloads) if !silent n += 1 send_ipython(publish[], msg_pub(msg, "execute_input", Dict("execution_count" => n, "code" => code))) end silent = silent || REPL.ends_with_semicolon(code) if store_history In[n] = code end # "; ..." cells are interpreted as shell commands for run code = replace(code, r"^\s*;.*$" => m -> string(replace(m, r"^\s*;" => "Base.repl_cmd(`"), "`, stdout)")) # "] ..." cells are interpreted as pkg shell commands if occursin(r"^\].*$", code) code = "IJulia.Pkg.REPLMode.do_cmd(IJulia.minirepl[], \"" * escape_string(code[2:end]) * "\"; do_rethrow=true)" end # a cell beginning with "? ..." is interpreted as a help request hcode = replace(code, r"^\s*\?" => "") try for hook in preexecute_hooks invokelatest(hook) end ans = result = if hcode != code # help request Core.eval(Main, helpmode(hcode)) else #run the code! occursin(magics_regex, code) && match(magics_regex, code).offset == 1 ? magics_help(code) : SOFTSCOPE[] ? softscope_include_string(current_module[], code, "In[$n]") : include_string(current_module[], code, "In[$n]") end if silent result = nothing elseif result !== nothing if store_history Out[n] = result end end user_expressions = Dict() for (v,ex) in msg.content["user_expressions"] try value = include_string(current_module[], ex) # Like the IPython reference implementation, we return # something that looks like a `display_data` but also has a # `status` field: # https://github.com/ipython/ipython/blob/master/IPython/core/interactiveshell.py#L2609-L2614 user_expressions[v] = Dict("status" => "ok", "data" => display_dict(value), "metadata" => metadata(value)) catch e # The format of user_expressions[v] is like `error` except that # it also has a `status` field: # https://jupyter-client.readthedocs.io/en/stable/messaging.html#execution-errors user_expressions[v] = Dict("status" => "error", error_content(e, catch_backtrace())...) end end for hook in postexecute_hooks invokelatest(hook) end # flush pending stdio flush_all() undisplay(result) # dequeue if needed, since we display result in pyout invokelatest(display) # flush pending display requests if result !== nothing result_metadata = invokelatest(metadata, result) result_data = invokelatest(display_dict, result) send_ipython(publish[], msg_pub(msg, "execute_result", Dict("execution_count" => n, "metadata" => result_metadata, "data" => result_data))) end send_ipython(requests[], msg_reply(msg, "execute_reply", Dict("status" => "ok", "payload" => execute_payloads, "execution_count" => n, "user_expressions" => user_expressions))) empty!(execute_payloads) catch e bt = catch_backtrace() try # flush pending stdio flush_all() for hook in posterror_hooks invokelatest(hook) end catch end empty!(displayqueue) # discard pending display requests on an error content = error_content(e,bt) send_ipython(publish[], msg_pub(msg, "error", content)) content["status"] = "error" content["execution_count"] = n send_ipython(requests[], msg_reply(msg, "execute_reply", content)) end end 0/opt/julia/packages/IJulia/Vo51o/src/handlers.jlf-using .CommManager # Don't send previous lines to the completions function, # due to issue #380. Find the start of the first line # (if any) where the expression is parseable. Replace # with find_parsestart(c,p) = start(c) once julia#9467 is merged. parseok(s) = !Meta.isexpr(Meta.parse(s, raise=false), :error) function find_parsestart(code, cursorpos) s = firstindex(code) while s < cursorpos parseok(code[s:cursorpos]) && return s s = nextind(code, s) while s < cursorpos && code[s] ∉ ('\n','\r') s = nextind(code, s) end end return firstindex(code) # failed to find parseable lines end # As described in jupyter/jupyter_client#259, Jupyter's cursor # positions are actually measured in UTF-16 code units, not # Unicode characters. Hence, these functions are similar to # Base.chr2ind and Base.ind2chr but count non-BMP characters # as 2 code units. function utf16_to_ind(str, ic) i = 0 e = lastindex(str) while ic > 0 && i < e i = nextind(str, i) ic -= UInt32(str[i]) < 0x10000 ? 1 : 2 end return i end function ind_to_utf16(str, i) ic = 0 i = min(i, lastindex(str)) while i > 0 ic += UInt32(str[i]) < 0x10000 ? 1 : 2 i = prevind(str, i) end return ic end # protocol change in Jupyter 5.2 (jupyter/jupyter_client#262) chr2ind(m::Msg, str::String, ic::Integer) = ic == 0 ? 0 : VersionNumber(m.header["version"]) ≥ v"5.2" ? nextind(str, 0, ic) : utf16_to_ind(str, ic) ind2chr(m::Msg, str::String, i::Integer) = i == 0 ? 0 : VersionNumber(m.header["version"]) ≥ v"5.2" ? length(str, 1, i) : ind_to_utf16(str, i) #Compact display of types for Jupyterlab completion import REPL: REPLCompletions import REPL.REPLCompletions: sorted_keywords, emoji_symbols, latex_symbols complete_type(::Type{<:Function}) = "function" complete_type(::Type{<:Type}) = "type" complete_type(::Type{<:Tuple}) = "tuple" complete_type(::Any) = "" function complete_type(T::DataType) s = string(T) (textwidth(s) ≤ 20 || isempty(T.parameters)) && return s buf = IOBuffer() print(buf, T.name) position(buf) > 19 && return String(take!(buf)) print(buf, '{') comma = false for p in T.parameters s = string(p) if position(buf) + sizeof(s) > 20 comma || print(buf, '…') break end comma && print(buf, ',') comma = true print(buf, s) end print(buf, '}') return String(take!(buf)) end #Get typeMap for Jupyter completions function complete_types(comps) typeMap = [] for c in comps ctype = "" if !isempty(searchsorted(sorted_keywords, c)) ctype = "keyword" elseif startswith(c, "\\:") ctype = get(emoji_symbols, c, "") isempty(ctype) || (ctype = "emoji: $ctype") elseif startswith(c, "\\") ctype = get(latex_symbols, c, "") else expr = Meta.parse(c, raise=false) if typeof(expr) == Symbol try ctype = complete_type(Core.eval(current_module[], :(typeof($expr)))) catch end elseif !isa(expr, Expr) ctype = complete_type(expr) elseif expr.head == :macrocall ctype = "macro" end end isempty(ctype) || push!(typeMap, Dict("text" => c, "type" => ctype)) end return typeMap end function complete_request(socket, msg) code = msg.content["code"] cursor_chr = msg.content["cursor_pos"] cursorpos = chr2ind(msg, code, cursor_chr) if all(isspace, code[1:cursorpos]) send_ipython(requests[], msg_reply(msg, "complete_reply", Dict("status" => "ok", "metadata" => Dict(), "matches" => String[], "cursor_start" => cursor_chr, "cursor_end" => cursor_chr))) return end codestart = find_parsestart(code, cursorpos) comps_, positions, should_complete = REPLCompletions.completions(code[codestart:end], cursorpos-codestart+1, current_module[]) comps = unique!(REPLCompletions.completion_text.(comps_)) # julia#26930 # positions = positions .+ (codestart - 1) on Julia 0.7 positions = (first(positions) + codestart - 1):(last(positions) + codestart - 1) metadata = Dict() if isempty(comps) # issue #530: REPLCompletions returns inconsistent results # for positions when no completions are found cursor_start = cursor_end = cursor_chr elseif isempty(positions) # true if comps to be inserted without replacement cursor_start = (cursor_end = ind2chr(msg, code, last(positions))) else cursor_start = ind2chr(msg, code, prevind(code, first(positions))) cursor_end = ind2chr(msg, code, last(positions)) if should_complete metadata["_jupyter_types_experimental"] = complete_types(comps) else # should_complete is false for cases where we only want to show # a list of possible completions but not complete, e.g. foo(\t pushfirst!(comps, code[positions]) end end send_ipython(requests[], msg_reply(msg, "complete_reply", Dict("status" => "ok", "matches" => comps, "metadata" => metadata, "cursor_start" => cursor_start, "cursor_end" => cursor_end))) end function kernel_info_request(socket, msg) send_ipython(requests[], msg_reply(msg, "kernel_info_reply", Dict("protocol_version" => "5.0", "implementation" => "ijulia", # TODO: "implementation_version" => IJulia version string from Pkg "language_info" => Dict("name" => "julia", "version" => string(VERSION.major, '.', VERSION.minor, '.', VERSION.patch), "mimetype" => "application/julia", "file_extension" => ".jl"), "banner" => "Julia: A fresh approach to technical computing.", "help_links" => [ Dict("text"=>"Julia Home Page", "url"=>"http://julialang.org/"), Dict("text"=>"Julia Documentation", "url"=>"http://docs.julialang.org/"), Dict("text"=>"Julia Packages", "url"=>"https://juliahub.com/ui/Packages") ], "status" => "ok"))) end function connect_request(socket, msg) send_ipython(requests[], msg_reply(msg, "connect_reply", Dict("shell_port" => profile["shell_port"], "iopub_port" => profile["iopub_port"], "stdin_port" => profile["stdin_port"], "hb_port" => profile["hb_port"]))) end function shutdown_request(socket, msg) send_ipython(requests[], msg_reply(msg, "shutdown_reply", msg.content)) sleep(0.1) # short delay (like in ipykernel), to hopefully ensure shutdown_reply is sent exit() end docdict(s::AbstractString) = display_dict(Core.eval(Main, helpmode(devnull, s))) import Base: is_id_char, is_id_start_char function get_token(code, pos) # given a string and a cursor position, find substring to request # help on by: # 1) searching backwards, skipping invalid identifier chars # ... search forward for end of identifier # 2) search backwards to find the biggest identifier (including .) # 3) if nothing found, do return empty string # TODO: detect operators? startpos = pos while startpos > firstindex(code) if is_id_char(code[startpos]) break else startpos = prevind(code, startpos) end end endpos = startpos while startpos >= firstindex(code) && (is_id_char(code[startpos]) || code[startpos] == '.') startpos = prevind(code, startpos) end startpos = startpos < pos ? nextind(code, startpos) : pos if !is_id_start_char(code[startpos]) return "" end while endpos < lastindex(code) && is_id_char(code[endpos]) endpos = nextind(code, endpos) end if !is_id_char(code[endpos]) endpos = prevind(code, endpos) end return code[startpos:endpos] end function inspect_request(socket, msg) try code = msg.content["code"] s = get_token(code, chr2ind(msg, code, msg.content["cursor_pos"])) if isempty(s) content = Dict("status" => "ok", "found" => false) else d = docdict(s) content = Dict("status" => "ok", "found" => !isempty(d), "data" => d) end send_ipython(requests[], msg_reply(msg, "inspect_reply", content)) catch e content = error_content(e, backtrace_top=:inspect_request); content["status"] = "error" send_ipython(requests[], msg_reply(msg, "inspect_reply", content)) end end function history_request(socket, msg) # we will just send back empty history for now, pending clarification # as requested in ipython/ipython#3806 send_ipython(requests[], msg_reply(msg, "history_reply", Dict("history" => []))) end function is_complete_request(socket, msg) ex = Meta.parse(msg.content["code"], raise=false) status = Meta.isexpr(ex, :incomplete) ? "incomplete" : Meta.isexpr(ex, :error) ? "invalid" : "complete" send_ipython(requests[], msg_reply(msg, "is_complete_reply", Dict("status"=>status, "indent"=>""))) end function interrupt_request(socket, msg) @async Base.throwto(requests_task[], InterruptException()) send_ipython(requests[], msg_reply(msg, "interrupt_reply", Dict())) end const handlers = Dict{String,Function}( "execute_request" => execute_request, "complete_request" => complete_request, "kernel_info_request" => kernel_info_request, "inspect_request" => inspect_request, "connect_request" => connect_request, "shutdown_request" => shutdown_request, "history_request" => history_request, "is_complete_request" => is_complete_request, "interrupt_request" => interrupt_request, "comm_open" => comm_open, "comm_info_request" => comm_info_request, "comm_msg" => comm_msg, "comm_close" => comm_close ) 1/opt/julia/packages/IJulia/Vo51o/src/heartbeat.jl-# Spawn a thread (using pthreads on Unix/OSX and Windows threads on Windows) # to implement the "heartbeat" message channel, which is just a ZMQ # socket that echoes all messages. This is implemented with the zmq_proxy # call in libzmq, which simply blocks forever, so the usual lack of # thread safety in Julia should not be an issue here. import Libdl const threadid = zeros(Int, 128) # sizeof(uv_thread_t) <= 8 on Linux, OSX, Win const zmq_proxy = Ref(C_NULL) # entry point for new thread function heartbeat_thread(sock::Ptr{Cvoid}) @static if VERSION ≥ v"1.9.0-DEV.1588" # julia#46609 # julia automatically "adopts" this thread because # we entered a Julia cfunction. We then have to enable # a GC "safe" region to prevent us from grabbing the # GC lock with the call to zmq_proxy, which never returns. # (see julia#47196) ccall(:jl_gc_safe_enter, Int8, ()) end ccall(zmq_proxy[], Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}), sock, sock, C_NULL) nothing end function start_heartbeat(sock) zmq_proxy[] = Libdl.dlsym(Libdl.dlopen(ZMQ.libzmq), :zmq_proxy) heartbeat_c = @cfunction(heartbeat_thread, Cvoid, (Ptr{Cvoid},)) ccall(:uv_thread_create, Cint, (Ptr{Int}, Ptr{Cvoid}, Ptr{Cvoid}), threadid, heartbeat_c, sock) end ./opt/julia/packages/IJulia/Vo51o/src/inline.jlFimport Base: display, redisplay struct InlineDisplay <: AbstractDisplay end # supported MIME types for inline display in IPython, in descending order # of preference (descending "richness") const ipy_mime = [ "application/vnd.dataresource+json", ["application/vnd.vegalite.v$n+json" for n in 4:-1:2]..., ["application/vnd.vega.v$n+json" for n in 5:-1:3]..., "application/vnd.plotly.v1+json", "text/html", "text/latex", "image/svg+xml", "image/png", "image/jpeg", "text/plain", "text/markdown", "application/javascript" ] # need special handling for showing a string as a textmime # type, since in that case the string is assumed to be # raw data unless it is text/plain israwtext(::MIME, x::AbstractString) = true israwtext(::MIME"text/plain", x::AbstractString) = false israwtext(::MIME, x) = false InlineIOContext(io, KVs::Pair...) = IOContext( io, :limit=>true, :color=>true, :jupyter=>true, KVs... ) # convert x to a string of type mime, making sure to use an # IOContext that tells the underlying show function to limit output function limitstringmime(mime::MIME, x, forcetext=false) buf = IOBuffer() if forcetext || istextmime(mime) if israwtext(mime, x) return String(x) else show(InlineIOContext(buf), mime, x) end else b64 = Base64EncodePipe(buf) if isa(x, Vector{UInt8}) write(b64, x) # x assumed to be raw binary data else show(InlineIOContext(b64), mime, x) end close(b64) end return String(take!(buf)) end for mime in ipy_mime @eval begin function display(d::InlineDisplay, ::MIME{Symbol($mime)}, x) flush_all() # so that previous stream output appears in order send_ipython(publish[], msg_pub(execute_msg, "display_data", Dict( "metadata" => metadata(x), # optional "data" => Dict($mime => limitstringmime(MIME($mime), x))))) end displayable(d::InlineDisplay, ::MIME{Symbol($mime)}) = true end end # deal with annoying application/x-latex == text/latex synonyms display(d::InlineDisplay, m::MIME"application/x-latex", x) = display(d, MIME("text/latex"), limitstringmime(m, x)) # deal with annoying text/javascript == application/javascript synonyms display(d::InlineDisplay, m::MIME"text/javascript", x) = display(d, MIME("application/javascript"), limitstringmime(m, x)) # If the user explicitly calls display("foo/bar", x), we send # the display message, also sending text/plain for text data. displayable(d::InlineDisplay, M::MIME) = istextmime(M) function display(d::InlineDisplay, M::MIME, x) sx = limitstringmime(M, x) d = Dict(string(M) => sx) if istextmime(M) d["text/plain"] = sx # directly show text data, e.g. text/csv end flush_all() # so that previous stream output appears in order send_ipython(publish[], msg_pub(execute_msg, "display_data", Dict("metadata" => metadata(x), # optional "data" => d))) end # override display to send IPython a dictionary of all supported # output types, so that IPython can choose what to display. function display(d::InlineDisplay, x) undisplay(x) # dequeue previous redisplay(x) flush_all() # so that previous stream output appears in order send_ipython(publish[], msg_pub(execute_msg, "display_data", Dict("metadata" => metadata(x), # optional "data" => display_dict(x)))) end # we overload redisplay(d, x) to add x to a queue of objects to display, # with the actual display occuring when display() is called or when # an input cell has finished executing. function redisplay(d::InlineDisplay, x) if !in(x,displayqueue) push!(displayqueue, x) end end function display() q = copy(displayqueue) empty!(displayqueue) # so that undisplay in display(x) is no-op for x in q display(x) end end uU_