Browse Source

Apply Runic formatting

pull/266/head
Fredrik Ekre 12 months ago
parent
commit
2964c2758d
No known key found for this signature in database
GPG Key ID: DE82E6D5E364C0A2
  1. 23
      .github/workflows/Check.yml
  2. 2
      README.md
  3. 4
      docs/make.jl
  4. 4
      docs/src/outputformats.jl
  5. 2
      examples/README.jl
  6. 6
      examples/example.jl
  7. 6
      src/IJulia.jl
  8. 227
      src/Literate.jl
  9. 2336
      test/runtests.jl

23
.github/workflows/Check.yml

@ -0,0 +1,23 @@
---
name: Check
on:
push:
branches:
- 'master'
- 'release-'
tags:
- '*'
pull_request:
jobs:
runic:
name: Runic formatting
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: julia-actions/setup-julia@v2
with:
version: '1.11'
- uses: julia-actions/cache@v2
- uses: fredrikekre/runic-action@v1
with:
version: '1.2'

2
README.md

@ -21,7 +21,7 @@ running these commands from the package root of Literate.jl:
````julia ````julia
using Literate using Literate
Literate.markdown("examples/README.jl", "."; flavor=Literate.CommonMarkFlavor()) Literate.markdown("examples/README.jl", "."; flavor = Literate.CommonMarkFlavor())
```` ````
### Related packages ### Related packages

4
docs/make.jl

@ -5,7 +5,7 @@ if haskey(ENV, "GITHUB_ACTIONS")
end end
deployconfig = Documenter.auto_detect_deploy_system() deployconfig = Documenter.auto_detect_deploy_system()
Documenter.post_status(deployconfig; type="pending", repo="github.com/fredrikekre/Literate.jl.git") Documenter.post_status(deployconfig; type = "pending", repo = "github.com/fredrikekre/Literate.jl.git")
using Literate using Literate
using Plots # to not capture precompilation output using Plots # to not capture precompilation output
@ -14,7 +14,7 @@ EXAMPLE = joinpath(@__DIR__, "..", "examples", "example.jl")
OUTPUT = joinpath(@__DIR__, "src/generated") OUTPUT = joinpath(@__DIR__, "src/generated")
function preprocess(str) function preprocess(str)
str = replace(str, "x = 123" => "y = 321"; count=1) str = replace(str, "x = 123" => "y = 321"; count = 1)
return str return str
end end

4
docs/src/outputformats.jl

@ -3,9 +3,9 @@
# In julia rational numbers can be constructed with the `//` operator. # In julia rational numbers can be constructed with the `//` operator.
# Lets define two rational numbers, `x` and `y`: # Lets define two rational numbers, `x` and `y`:
x = 1//3 x = 1 // 3
#- #-
y = 2//5 y = 2 // 5
# When adding `x` and `y` together we obtain a new rational number: # When adding `x` and `y` together we obtain a new rational number:

2
examples/README.jl

@ -20,7 +20,7 @@
# running these commands from the package root of Literate.jl: # running these commands from the package root of Literate.jl:
using Literate using Literate
Literate.markdown("examples/README.jl", "."; flavor=Literate.CommonMarkFlavor()) Literate.markdown("examples/README.jl", "."; flavor = Literate.CommonMarkFlavor())
# ### Related packages # ### Related packages

6
examples/example.jl

@ -33,8 +33,8 @@
# as markdown, and all the other lines are interpreted as code. Here is some code: # as markdown, and all the other lines are interpreted as code. Here is some code:
#nb %% A slide [code] {"slideshow": {"slide_type": "fragment"}} #nb %% A slide [code] {"slideshow": {"slide_type": "fragment"}}
x = 1//3 x = 1 // 3
y = 2//5 y = 2 // 5
#nb # %% A slide [markdown] {"slideshow": {"slide_type": "subslide"}} #nb # %% A slide [markdown] {"slideshow": {"slide_type": "subslide"}}
# In markdown sections we can use markdown syntax. For example, we can # In markdown sections we can use markdown syntax. For example, we can
@ -96,7 +96,7 @@ foo()
#nb %% A slide [code] {"slideshow": {"slide_type": "subslide"}} #nb %% A slide [code] {"slideshow": {"slide_type": "subslide"}}
using Plots using Plots
x = range(0, stop=6π, length=1000) x = range(0, stop = 6π, length = 1000)
y1 = sin.(x) y1 = sin.(x)
y2 = cos.(x) y2 = cos.(x)
plot(x, [y1, y2]) plot(x, [y1, y2])

6
src/IJulia.jl

@ -17,7 +17,7 @@ const application_vnd_vegalite_v2 = MIME("application/vnd.vegalite.v2+json")
# return a String=>String dictionary of mimetype=>data # return a String=>String dictionary of mimetype=>data
# for passing to Jupyter display_data and execute_result messages. # for passing to Jupyter display_data and execute_result messages.
function display_dict(x) function display_dict(x)
data = Dict{String,Any}("text/plain" => limitstringmime(text_plain, x)) data = Dict{String, Any}("text/plain" => limitstringmime(text_plain, x))
if showable(application_vnd_vegalite_v2, x) if showable(application_vnd_vegalite_v2, x)
data[string(application_vnd_vegalite_v2)] = JSON.parse(limitstringmime(application_vnd_vegalite_v2, x)) data[string(application_vnd_vegalite_v2)] = JSON.parse(limitstringmime(application_vnd_vegalite_v2, x))
end end
@ -57,14 +57,14 @@ function limitstringmime(mime::MIME, x)
if israwtext(mime, x) if israwtext(mime, x)
return String(x) return String(x)
else else
show(IOContext(buf, :limit=>true, :color=>true), mime, x) show(IOContext(buf, :limit => true, :color => true), mime, x)
end end
else else
b64 = Base64EncodePipe(buf) b64 = Base64EncodePipe(buf)
if isa(x, Vector{UInt8}) if isa(x, Vector{UInt8})
write(b64, x) # x assumed to be raw binary data write(b64, x) # x assumed to be raw binary data
else else
show(IOContext(b64, :limit=>true, :color=>true), mime, x) show(IOContext(b64, :limit => true, :color => true), mime, x)
end end
close(b64) close(b64)
end end

227
src/Literate.jl

@ -39,7 +39,7 @@ struct QuartoFlavor <: AbstractFlavor end
# Parser # Parser
abstract type Chunk end abstract type Chunk end
struct MDChunk <: Chunk struct MDChunk <: Chunk
lines::Vector{Pair{String,String}} # indent and content lines::Vector{Pair{String, String}} # indent and content
end end
MDChunk() = MDChunk(String[]) MDChunk() = MDChunk(String[])
mutable struct CodeChunk <: Chunk mutable struct CodeChunk <: Chunk
@ -133,29 +133,27 @@ function parse(flavor::AbstractFlavor, content; allow_continued = true)
return chunks return chunks
end end
function replace_default(content, sym; function replace_default(
config::Dict, content, sym; config::Dict, branch = "gh-pages", commit = "master"
branch = "gh-pages", )
commit = "master" repls = Pair{Any, Any}[]
)
repls = Pair{Any,Any}[]
# add some shameless advertisement # add some shameless advertisement
if config["credit"]::Bool if config["credit"]::Bool
if sym === :jl if sym === :jl
content *= """ content *= """
#- #-
## This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl ## This file was generated using Literate.jl, https://github.com/fredrikekre/Literate.jl
""" """
else else
content *= """ content *= """
#- #-
# --- # ---
# #
# *This $(sym === :md ? "page" : "notebook") was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).* # *This $(sym === :md ? "page" : "notebook") was generated using [Literate.jl](https://github.com/fredrikekre/Literate.jl).*
""" """
end end
end end
@ -168,7 +166,7 @@ function replace_default(content, sym;
newlines = sprint() do io newlines = sprint() do io
foreach(l -> println(io, "# ", l), eachline(IOBuffer(m[1]))) foreach(l -> println(io, "# ", l), eachline(IOBuffer(m[1])))
end end
str = replace(str, multiline_r => chop(newlines); count=1) str = replace(str, multiline_r => chop(newlines); count = 1)
end end
return str return str
end end
@ -229,7 +227,7 @@ function replace_default(content, sym;
push!(repls, r"\[([^]]+?)\]\(@id .*?\)"s => s"\1") # [foo](@id bar) => foo push!(repls, r"\[([^]]+?)\]\(@id .*?\)"s => s"\1") # [foo](@id bar) => foo
# Convert Documenter admonitions to markdown quotes # Convert Documenter admonitions to markdown quotes
r = r"^# !!! (?<type>\w+)(?: \"(?<title>.+)\")?(?<lines>(\v^# .*$)+)"m r = r"^# !!! (?<type>\w+)(?: \"(?<title>.+)\")?(?<lines>(\v^# .*$)+)"m
adm_to_quote = function(s) adm_to_quote = function (s)
m = match(r, s)::RegexMatch m = match(r, s)::RegexMatch
io = IOBuffer() io = IOBuffer()
print(io, "# > **") print(io, "# > **")
@ -259,11 +257,13 @@ end
filename(str) = first(splitext(last(splitdir(str)))) filename(str) = first(splitext(last(splitdir(str))))
isdocumenter(cfg) = cfg["flavor"]::AbstractFlavor isa DocumenterFlavor isdocumenter(cfg) = cfg["flavor"]::AbstractFlavor isa DocumenterFlavor
_DEFAULT_IMAGE_FORMATS = [(MIME("image/svg+xml"), ".svg"), (MIME("image/png"), ".png"), _DEFAULT_IMAGE_FORMATS = [
(MIME("image/jpeg"), ".jpeg")] (MIME("image/svg+xml"), ".svg"), (MIME("image/png"), ".png"),
(MIME("image/jpeg"), ".jpeg"),
]
# Cache of inputfile => head branch # Cache of inputfile => head branch
const HEAD_BRANCH_CACHE = Dict{String,String}() const HEAD_BRANCH_CACHE = Dict{String, String}()
# Guess the package (or repository) root url with "master" as fallback # Guess the package (or repository) root url with "master" as fallback
# see JuliaDocs/Documenter.jl#1751 # see JuliaDocs/Documenter.jl#1751
@ -277,8 +277,8 @@ function edit_commit(inputfile, user_config)
git_root = try git_root = try
readchomp( readchomp(
pipeline( pipeline(
setenv(`$(git) rev-parse --show-toplevel`; dir=dirname(inputfile)); setenv(`$(git) rev-parse --show-toplevel`; dir = dirname(inputfile));
stderr=devnull, stderr = devnull,
) )
) )
catch catch
@ -298,8 +298,8 @@ function edit_commit(inputfile, user_config)
str = try str = try
read( read(
pipeline( pipeline(
setenv(`$(git) remote show origin`, env; dir=dirname(inputfile)), setenv(`$(git) remote show origin`, env; dir = dirname(inputfile)),
stderr=devnull, stderr = devnull,
), ),
String, String,
) )
@ -332,30 +332,38 @@ function pick_codefence(::QuartoFlavor, execute::Bool, name::AbstractString)
return "```{julia}" => "```" return "```{julia}" => "```"
end end
function create_configuration(inputfile; user_config, user_kwargs, type=nothing) function create_configuration(inputfile; user_config, user_kwargs, type = nothing)
# Combine user config with user kwargs # Combine user config with user kwargs
user_config = Dict{String,Any}(string(k) => v for (k, v) in user_config) user_config = Dict{String, Any}(string(k) => v for (k, v) in user_config)
user_kwargs = Dict{String,Any}(string(k) => v for (k, v) in user_kwargs) user_kwargs = Dict{String, Any}(string(k) => v for (k, v) in user_kwargs)
user_config = merge!(user_config, user_kwargs) user_config = merge!(user_config, user_kwargs)
# deprecation of documenter kwarg # deprecation of documenter kwarg
if (d = get(user_config, "documenter", nothing); d !== nothing) if (d = get(user_config, "documenter", nothing); d !== nothing)
if type === :md if type === :md
Base.depwarn("The documenter=$(d) keyword to Literate.markdown is deprecated." * Base.depwarn(
" Pass `flavor = Literate.$(d ? "DocumenterFlavor" : "CommonMarkFlavor")()`" * "The documenter=$(d) keyword to Literate.markdown is deprecated." *
" instead.", Symbol("Literate.markdown")) " Pass `flavor = Literate.$(d ? "DocumenterFlavor" : "CommonMarkFlavor")()`" *
" instead.", Symbol("Literate.markdown")
)
user_config["flavor"] = d ? DocumenterFlavor() : CommonMarkFlavor() user_config["flavor"] = d ? DocumenterFlavor() : CommonMarkFlavor()
elseif type === :nb elseif type === :nb
Base.depwarn("The documenter=$(d) keyword to Literate.notebook is deprecated." * Base.depwarn(
" It is not used anymore for notebook output.", Symbol("Literate.notebook")) "The documenter=$(d) keyword to Literate.notebook is deprecated." *
" It is not used anymore for notebook output.",
Symbol("Literate.notebook")
)
elseif type === :jl elseif type === :jl
Base.depwarn("The documenter=$(d) keyword to Literate.script is deprecated." * Base.depwarn(
" It is not used anymore for script output.", Symbol("Literate.script")) "The documenter=$(d) keyword to Literate.script is deprecated." *
" It is not used anymore for script output.",
Symbol("Literate.script")
)
end end
end end
# Add default config # Add default config
cfg = Dict{String,Any}() cfg = Dict{String, Any}()
cfg["name"] = filename(inputfile) cfg["name"] = filename(inputfile)
cfg["preprocess"] = identity cfg["preprocess"] = identity
cfg["postprocess"] = identity cfg["postprocess"] = identity
@ -419,7 +427,7 @@ function create_configuration(inputfile; user_config, user_kwargs, type=nothing)
cfg["repo_root_url"] = "$(url)/blob/$(cfg["edit_commit"])" cfg["repo_root_url"] = "$(url)/blob/$(cfg["edit_commit"])"
end end
if (url = get(ENV, "CI_PAGES_URL", nothing)) !== nothing && if (url = get(ENV, "CI_PAGES_URL", nothing)) !== nothing &&
(m = match(r"https://(.+)", url)) !== nothing (m = match(r"https://(.+)", url)) !== nothing
cfg["nbviewer_root_url"] = "https://nbviewer.jupyter.org/urls/$(m[1])" cfg["nbviewer_root_url"] = "https://nbviewer.jupyter.org/urls/$(m[1])"
end end
end end
@ -479,12 +487,13 @@ Available options:
`$(_DEFAULT_IMAGE_FORMATS)`. Results which are `showable` with a MIME type are saved with `$(_DEFAULT_IMAGE_FORMATS)`. Results which are `showable` with a MIME type are saved with
the first match, with the corresponding extension. the first match, with the corresponding extension.
""" """
const DEFAULT_CONFIGURATION=nothing # Dummy const for documentation const DEFAULT_CONFIGURATION = nothing # Dummy const for documentation
function preprocessor(inputfile, outputdir; user_config, user_kwargs, type) function preprocessor(inputfile, outputdir; user_config, user_kwargs, type)
# Create configuration by merging default and userdefined # Create configuration by merging default and userdefined
config = create_configuration(inputfile; user_config=user_config, config = create_configuration(
user_kwargs=user_kwargs, type=type) inputfile; user_config = user_config, user_kwargs = user_kwargs, type = type
)
# Quarto output does not support execute = true # Quarto output does not support execute = true
if config["flavor"] isa QuartoFlavor && config["execute"] if config["flavor"] isa QuartoFlavor && config["execute"]
@ -505,8 +514,8 @@ function preprocessor(inputfile, outputdir; user_config, user_kwargs, type)
end end
output_thing = type === (:md) ? "markdown page" : output_thing = type === (:md) ? "markdown page" :
type === (:nb) ? "notebook" : type === (:nb) ? "notebook" :
type === (:jl) ? "plain script file" : error("nope") type === (:jl) ? "plain script file" : error("nope")
@info "generating $(output_thing) from `$(Base.contractuser(inputfile))`" @info "generating $(output_thing) from `$(Base.contractuser(inputfile))`"
# Add some information for passing around Literate methods # Add some information for passing around Literate methods
@ -526,16 +535,17 @@ function preprocessor(inputfile, outputdir; user_config, user_kwargs, type)
# change the Edit on GitHub link # change the Edit on GitHub link
edit_url = relpath(inputfile, config["literate_outputdir"]) edit_url = relpath(inputfile, config["literate_outputdir"])
edit_url = replace(edit_url, "\\" => "/") edit_url = replace(edit_url, "\\" => "/")
content = """ meta_block = """
# ```@meta # ```@meta
# EditURL = "$(edit_url)" # EditURL = "$(edit_url)"
# ``` # ```
""" * content """
content = meta_block * content
end end
# default replacements # default replacements
content = replace_default(content, type; config=config) content = replace_default(content, type; config = config)
# parse the content into chunks # parse the content into chunks
chunks = parse(config["flavor"], content; allow_continued = type !== :nb) chunks = parse(config["flavor"], content; allow_continued = type !== :nb)
@ -543,7 +553,7 @@ function preprocessor(inputfile, outputdir; user_config, user_kwargs, type)
return chunks, config return chunks, config
end end
function write_result(content, config; print=print) function write_result(content, config; print = print)
outputfile = config["literate_outputfile"] outputfile = config["literate_outputfile"]
@info "writing result to `$(Base.contractuser(outputfile))`" @info "writing result to `$(Base.contractuser(outputfile))`"
open(outputfile, "w") do io open(outputfile, "w") do io
@ -560,10 +570,10 @@ Generate a plain script file from `inputfile` and write the result to `outputdir
See the manual section on [Configuration](@ref) for documentation See the manual section on [Configuration](@ref) for documentation
of possible configuration with `config` and other keyword arguments. of possible configuration with `config` and other keyword arguments.
""" """
function script(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwargs...) function script(inputfile, outputdir = pwd(); config::AbstractDict = Dict(), kwargs...)
# preprocessing and parsing # preprocessing and parsing
chunks, config = chunks, config =
preprocessor(inputfile, outputdir; user_config=config, user_kwargs=kwargs, type=:jl) preprocessor(inputfile, outputdir; user_config = config, user_kwargs = kwargs, type = :jl)
# create the script file # create the script file
ioscript = IOBuffer() ioscript = IOBuffer()
@ -600,10 +610,10 @@ to the directory `outputdir`.
See the manual section on [Configuration](@ref) for documentation See the manual section on [Configuration](@ref) for documentation
of possible configuration with `config` and other keyword arguments. of possible configuration with `config` and other keyword arguments.
""" """
function markdown(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwargs...) function markdown(inputfile, outputdir = pwd(); config::AbstractDict = Dict(), kwargs...)
# preprocessing and parsing # preprocessing and parsing
chunks, config = chunks, config =
preprocessor(inputfile, outputdir; user_config=config, user_kwargs=kwargs, type=:md) preprocessor(inputfile, outputdir; user_config = config, user_kwargs = kwargs, type = :md)
# create the markdown file # create the markdown file
sb = sandbox() sb = sandbox()
@ -637,15 +647,16 @@ function markdown(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwarg
any(write_line, chunk.lines) && write(iomd, seekstart(iocode)) any(write_line, chunk.lines) && write(iomd, seekstart(iocode))
if execute if execute
cd(config["literate_outputdir"]) do cd(config["literate_outputdir"]) do
execute_markdown!(iomd, sb, join(chunk.lines, '\n'), execute_markdown!(
config["literate_outputdir"]; iomd, sb, join(chunk.lines, '\n'),
inputfile=config["literate_inputfile"], config["literate_outputdir"];
fake_source=config["literate_outputfile"], inputfile = config["literate_inputfile"],
flavor=config["flavor"], fake_source = config["literate_outputfile"],
image_formats=config["image_formats"], flavor = config["flavor"],
file_prefix="$(config["name"])-$(chunknum)", image_formats = config["image_formats"],
softscope=config["softscope"], file_prefix = "$(config["name"])-$(chunknum)",
continue_on_error=config["continue_on_error"], softscope = config["softscope"],
continue_on_error = config["continue_on_error"],
) )
end end
end end
@ -661,19 +672,23 @@ function markdown(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwarg
return outputfile return outputfile
end end
function execute_markdown!(io::IO, sb::Module, block::String, outputdir; function execute_markdown!(
inputfile::String, fake_source::String, io::IO, sb::Module, block::String, outputdir;
flavor::AbstractFlavor, image_formats::Vector, file_prefix::String, inputfile::String, fake_source::String, flavor::AbstractFlavor,
softscope::Bool, continue_on_error::Bool) image_formats::Vector, file_prefix::String, softscope::Bool,
continue_on_error::Bool
)
# TODO: Deal with explicit display(...) calls # TODO: Deal with explicit display(...) calls
r, str, _ = execute_block(sb, block; inputfile=inputfile, fake_source=fake_source, r, str, _ = execute_block(
softscope=softscope, continue_on_error=continue_on_error) sb, block; inputfile = inputfile, fake_source = fake_source,
softscope = softscope, continue_on_error = continue_on_error
)
# issue #101: consecutive codefenced blocks need newline # issue #101: consecutive codefenced blocks need newline
# issue #144: quadruple backticks allow for triple backticks in the output # issue #144: quadruple backticks allow for triple backticks in the output
plain_fence = "\n````\n" => "\n````" plain_fence = "\n````\n" => "\n````"
if r !== nothing && !REPL.ends_with_semicolon(block) if r !== nothing && !REPL.ends_with_semicolon(block)
if (flavor isa FranklinFlavor || flavor isa DocumenterFlavor) && if (flavor isa FranklinFlavor || flavor isa DocumenterFlavor) &&
Base.invokelatest(showable, MIME("text/html"), r) Base.invokelatest(showable, MIME("text/html"), r)
htmlfence = flavor isa FranklinFlavor ? ("~~~" => "~~~") : ("```@raw html" => "```") htmlfence = flavor isa FranklinFlavor ? ("~~~" => "~~~") : ("```@raw html" => "```")
write(io, "\n", htmlfence.first, "\n") write(io, "\n", htmlfence.first, "\n")
Base.invokelatest(show, io, MIME("text/html"), r) Base.invokelatest(show, io, MIME("text/html"), r)
@ -731,16 +746,16 @@ Generate a notebook from `inputfile` and write the result to `outputdir`.
See the manual section on [Configuration](@ref) for documentation See the manual section on [Configuration](@ref) for documentation
of possible configuration with `config` and other keyword arguments. of possible configuration with `config` and other keyword arguments.
""" """
function notebook(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwargs...) function notebook(inputfile, outputdir = pwd(); config::AbstractDict = Dict(), kwargs...)
# preprocessing and parsing # preprocessing and parsing
chunks, config = chunks, config =
preprocessor(inputfile, outputdir; user_config=config, user_kwargs=kwargs, type=:nb) preprocessor(inputfile, outputdir; user_config = config, user_kwargs = kwargs, type = :nb)
# create the notebook # create the notebook
nb = jupyter_notebook(chunks, config) nb = jupyter_notebook(chunks, config)
# write to file # write to file
outputfile = write_result(nb, config; print = (io, c)->JSON.print(io, c, 1)) outputfile = write_result(nb, config; print = (io, c) -> JSON.print(io, c, 1))
return outputfile return outputfile
end end
@ -761,10 +776,12 @@ function jupyter_notebook(chunks, config)
else else
metadata = Dict{String, Any}() metadata = Dict{String, Any}()
end end
lines = isa(chunk, MDChunk) ? if isa(chunk, MDChunk)
String[x.second for x in chunk.lines] : # skip indent lines = String[x.second for x in chunk.lines] # skip indent
chunk.lines else
@views map!(x -> x * '\n', lines[1:end-1], lines[1:end-1]) lines = chunk.lines
end
@views map!(x -> x * '\n', lines[1:(end - 1)], lines[1:(end - 1)])
cell["cell_type"] = chunktype cell["cell_type"] = chunktype
cell["metadata"] = metadata cell["metadata"] = metadata
cell["source"] = lines cell["source"] = lines
@ -780,15 +797,15 @@ function jupyter_notebook(chunks, config)
metadata = Dict() metadata = Dict()
kernelspec = Dict() kernelspec = Dict()
kernelspec["language"] = "julia" kernelspec["language"] = "julia"
kernelspec["name"] = "julia-$(VERSION.major).$(VERSION.minor)" kernelspec["name"] = "julia-$(VERSION.major).$(VERSION.minor)"
kernelspec["display_name"] = "Julia $(string(VERSION))" kernelspec["display_name"] = "Julia $(string(VERSION))"
metadata["kernelspec"] = kernelspec metadata["kernelspec"] = kernelspec
language_info = Dict() language_info = Dict()
language_info["file_extension"] = ".jl" language_info["file_extension"] = ".jl"
language_info["mimetype"] = "application/julia" language_info["mimetype"] = "application/julia"
language_info["name"]= "julia" language_info["name"] = "julia"
language_info["version"] = string(VERSION) language_info["version"] = string(VERSION)
metadata["language_info"] = language_info metadata["language_info"] = language_info
@ -801,23 +818,26 @@ function jupyter_notebook(chunks, config)
@info "executing notebook `$(config["name"] * ".ipynb")`" @info "executing notebook `$(config["name"] * ".ipynb")`"
try try
cd(config["literate_outputdir"]) do cd(config["literate_outputdir"]) do
nb = execute_notebook(nb; inputfile=config["literate_inputfile"], nb = execute_notebook(
fake_source=config["literate_outputfile"], nb; inputfile = config["literate_inputfile"],
softscope=config["softscope"], fake_source = config["literate_outputfile"],
continue_on_error=config["continue_on_error"], softscope = config["softscope"],
) continue_on_error = config["continue_on_error"],
)
end end
catch err catch err
@error "error when executing notebook based on input file: " * @error "error when executing notebook based on input file: " *
"`$(Base.contractuser(config["literate_inputfile"]))`" "`$(Base.contractuser(config["literate_inputfile"]))`"
rethrow(err) rethrow(err)
end end
end end
return nb return nb
end end
function execute_notebook(nb; inputfile::String, fake_source::String, softscope::Bool, function execute_notebook(
continue_on_error=continue_on_error) nb; inputfile::String, fake_source::String, softscope::Bool,
continue_on_error = continue_on_error
)
sb = sandbox() sb = sandbox()
execution_count = 0 execution_count = 0
for cell in nb["cells"] for cell in nb["cells"]
@ -825,13 +845,14 @@ function execute_notebook(nb; inputfile::String, fake_source::String, softscope:
execution_count += 1 execution_count += 1
cell["execution_count"] = execution_count cell["execution_count"] = execution_count
block = join(cell["source"]) block = join(cell["source"])
r, str, display_dicts = execute_block(sb, block; inputfile=inputfile, r, str, display_dicts = execute_block(
fake_source=fake_source, softscope=softscope, sb, block; inputfile = inputfile, fake_source = fake_source,
continue_on_error=continue_on_error) softscope = softscope, continue_on_error = continue_on_error
)
# str should go into stream # str should go into stream
if !isempty(str) if !isempty(str)
stream = Dict{String,Any}() stream = Dict{String, Any}()
stream["output_type"] = "stream" stream["output_type"] = "stream"
stream["name"] = "stdout" stream["name"] = "stdout"
stream["text"] = collect(Any, eachline(IOBuffer(String(str)), keep = true)) stream["text"] = collect(Any, eachline(IOBuffer(String(str)), keep = true))
@ -852,7 +873,7 @@ function execute_notebook(nb; inputfile::String, fake_source::String, softscope:
# Any explicit calls to display(...) # Any explicit calls to display(...)
for dict in display_dicts for dict in display_dicts
display_data = Dict{String,Any}() display_data = Dict{String, Any}()
display_data["output_type"] = "display_data" display_data["output_type"] = "display_data"
display_data["metadata"] = Dict() display_data["metadata"] = Dict()
display_data["data"] = split_mime(dict) display_data["data"] = split_mime(dict)
@ -864,7 +885,7 @@ function execute_notebook(nb; inputfile::String, fake_source::String, softscope:
# r should go into execute_result # r should go into execute_result
if r !== nothing if r !== nothing
execute_result = Dict{String,Any}() execute_result = Dict{String, Any}()
execute_result["output_type"] = "execute_result" execute_result["output_type"] = "execute_result"
execute_result["metadata"] = Dict() execute_result["metadata"] = Dict()
execute_result["execution_count"] = execution_count execute_result["execution_count"] = execution_count
@ -899,7 +920,7 @@ end
# TODO: Problematic to accept mime::MIME here? # TODO: Problematic to accept mime::MIME here?
function Base.display(ld::LiterateDisplay, mime::MIME, x) function Base.display(ld::LiterateDisplay, mime::MIME, x)
r = Base.invokelatest(IJulia.limitstringmime, mime, x) r = Base.invokelatest(IJulia.limitstringmime, mime, x)
display_dicts = Dict{String,Any}(string(mime) => r) display_dicts = Dict{String, Any}(string(mime) => r)
# TODO: IJulia does this part below for unknown mimes # TODO: IJulia does this part below for unknown mimes
# if istextmime(mime) # if istextmime(mime)
# display_dicts["text/plain"] = r # display_dicts["text/plain"] = r
@ -909,8 +930,10 @@ function Base.display(ld::LiterateDisplay, mime::MIME, x)
end end
# Execute a code-block in a module and capture stdout/stderr and the result # Execute a code-block in a module and capture stdout/stderr and the result
function execute_block(sb::Module, block::String; inputfile::String, fake_source::String, function execute_block(
softscope::Bool, continue_on_error::Bool) sb::Module, block::String; inputfile::String, fake_source::String,
softscope::Bool, continue_on_error::Bool
)
@debug """execute_block($sb, block) @debug """execute_block($sb, block)
``` ```
$(block) $(block)
@ -945,14 +968,16 @@ function execute_block(sb::Module, block::String; inputfile::String, fake_source
all_output = c.output * "\n\nERROR: " * sprint(showerror, err) all_output = c.output * "\n\nERROR: " * sprint(showerror, err)
return nothing, all_output, disp.data return nothing, all_output, disp.data
else else
error(""" error(
$(sprint(showerror, c.value)) """
when executing the following code block from inputfile `$(Base.contractuser(inputfile))` $(sprint(showerror, c.value))
when executing the following code block from inputfile `$(Base.contractuser(inputfile))`
```julia
$block ```julia
``` $block
""") ```
"""
)
end end
end end
return c.value, c.output, disp.data return c.value, c.output, disp.data

2336
test/runtests.jl

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save