Browse Source

Fix cwd and apparent source file when executing markdown. (#195)

pull/203/head
Fredrik Ekre 4 years ago committed by GitHub
parent
commit
53a9d26ff8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      CHANGELOG.md
  2. 39
      src/Literate.jl
  3. 8
      test/runtests.jl

5
CHANGELOG.md

@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Fixed
- Set current working directory for markdown execution to the output directory, just like
notebook execution. ([#195][github-195])
- Set the apparent source file to the output file for markdown and notebook execution.
([#195][github-195])
## [2.13.1] - 2022-04-12
### Fixed

39
src/Literate.jl

@ -405,6 +405,12 @@ function preprocessor(inputfile, outputdir; user_config, user_kwargs, type) @@ -405,6 +405,12 @@ function preprocessor(inputfile, outputdir; user_config, user_kwargs, type)
inputfile = realpath(abspath(inputfile))
mkpath(outputdir)
outputdir = realpath(abspath(outputdir))
isdir(outputdir) || error("not a directory: $(outputdir)")
ext = type === (:nb) ? ".ipynb" : ".$(type)"
outputfile = joinpath(outputdir, config["name"]::String * ext)
if inputfile == outputfile
throw(ArgumentError("outputfile (`$outputfile`) is identical to inputfile (`$inputfile`)"))
end
output_thing = type === (:md) ? "markdown page" :
type === (:nb) ? "notebook" :
@ -414,7 +420,8 @@ function preprocessor(inputfile, outputdir; user_config, user_kwargs, type) @@ -414,7 +420,8 @@ function preprocessor(inputfile, outputdir; user_config, user_kwargs, type)
# Add some information for passing around Literate methods
config["literate_inputfile"] = inputfile
config["literate_outputdir"] = outputdir
config["literate_ext"] = type === (:nb) ? ".ipynb" : ".$(type)"
config["literate_ext"] = ext
config["literate_outputfile"] = outputfile
# read content
content = read(inputfile, String)
@ -445,13 +452,7 @@ function preprocessor(inputfile, outputdir; user_config, user_kwargs, type) @@ -445,13 +452,7 @@ function preprocessor(inputfile, outputdir; user_config, user_kwargs, type)
end
function write_result(content, config; print=print)
inputfile = config["literate_inputfile"]
outputdir = config["literate_outputdir"]
isdir(outputdir) || error("not a directory: $(outputdir)")
outputfile = joinpath(outputdir, config["name"]::String * config["literate_ext"])
if inputfile == outputfile
throw(ArgumentError("outputfile (`$outputfile`) is identical to inputfile (`$inputfile`)"))
end
outputfile = config["literate_outputfile"]
@info "writing result to `$(Base.contractuser(outputfile))`"
open(outputfile, "w") do io
print(io, content)
@ -543,12 +544,15 @@ function markdown(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwarg @@ -543,12 +544,15 @@ function markdown(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwarg
write(iocode, codefence.second, '\n')
any(write_line, chunk.lines) && write(iomd, seekstart(iocode))
if execute
cd(config["literate_outputdir"]) do
execute_markdown!(iomd, sb, join(chunk.lines, '\n'), outputdir;
inputfile=config["literate_inputfile"],
fake_source=config["literate_outputfile"],
flavor=config["flavor"],
image_formats=config["image_formats"])
end
end
end
write(iomd, '\n') # add a newline between each chunk
end
@ -561,10 +565,10 @@ function markdown(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwarg @@ -561,10 +565,10 @@ function markdown(inputfile, outputdir=pwd(); config::AbstractDict=Dict(), kwarg
end
function execute_markdown!(io::IO, sb::Module, block::String, outputdir;
inputfile::String="<unknown>", flavor::AbstractFlavor,
image_formats::Vector)
inputfile::String, fake_source::String,
flavor::AbstractFlavor, image_formats::Vector)
# TODO: Deal with explicit display(...) calls
r, str, _ = execute_block(sb, block; inputfile=inputfile)
r, str, _ = execute_block(sb, block; inputfile=inputfile, fake_source=fake_source)
# issue #101: consecutive codefenced blocks need newline
# issue #144: quadruple backticks allow for triple backticks in the output
plain_fence = "\n````\n" => "\n````"
@ -698,7 +702,8 @@ function jupyter_notebook(chunks, config) @@ -698,7 +702,8 @@ function jupyter_notebook(chunks, config)
@info "executing notebook `$(config["name"] * ".ipynb")`"
try
cd(config["literate_outputdir"]) do
nb = execute_notebook(nb; inputfile=config["literate_inputfile"])
nb = execute_notebook(nb; inputfile=config["literate_inputfile"],
fake_source=config["literate_outputfile"])
end
catch err
@error "error when executing notebook based on input file: " *
@ -709,7 +714,7 @@ function jupyter_notebook(chunks, config) @@ -709,7 +714,7 @@ function jupyter_notebook(chunks, config)
return nb
end
function execute_notebook(nb; inputfile::String="<unknown>")
function execute_notebook(nb; inputfile::String, fake_source::String)
sb = sandbox()
execution_count = 0
for cell in nb["cells"]
@ -717,7 +722,7 @@ function execute_notebook(nb; inputfile::String="<unknown>") @@ -717,7 +722,7 @@ function execute_notebook(nb; inputfile::String="<unknown>")
execution_count += 1
cell["execution_count"] = execution_count
block = join(cell["source"])
r, str, display_dicts = execute_block(sb, block; inputfile=inputfile)
r, str, display_dicts = execute_block(sb, block; inputfile=inputfile, fake_source=fake_source)
# str should go into stream
if !isempty(str)
@ -799,7 +804,7 @@ function Base.display(ld::LiterateDisplay, mime::MIME, x) @@ -799,7 +804,7 @@ function Base.display(ld::LiterateDisplay, mime::MIME, x)
end
# Execute a code-block in a module and capture stdout/stderr and the result
function execute_block(sb::Module, block::String; inputfile::String="<unknown>")
function execute_block(sb::Module, block::String; inputfile::String, fake_source::String)
@debug """execute_block($sb, block)
```
$(block)
@ -815,13 +820,13 @@ function execute_block(sb::Module, block::String; inputfile::String="<unknown>") @@ -815,13 +820,13 @@ function execute_block(sb::Module, block::String; inputfile::String="<unknown>")
# `rethrow = Union{}` means that we try-catch all the exceptions thrown in the do-block
# and return them via the return value (they get handled below).
c = IOCapture.capture(rethrow = Union{}) do
include_string(sb, block)
include_string(sb, block, fake_source)
end
popdisplay(disp) # IOCapture.capture has a try-catch so should always end up here
if c.error
error("""
$(sprint(showerror, c.value))
when executing the following code block in file `$(Base.contractuser(inputfile))`
when executing the following code block from inputfile `$(Base.contractuser(inputfile))`
```julia
$block

8
test/runtests.jl

@ -824,6 +824,10 @@ end end @@ -824,6 +824,10 @@ end end
print("a: ", a); nothing #hide
#-
47 #hide
#-
(@__DIR__) == pwd() ? "cwd correct" : "cwd incorrect"
#-
basename(@__FILE__)
""")
Literate.markdown(inputfile, outdir; execute=true)
markdown = read(joinpath(outdir, "inputfile.md"), String)
@ -846,6 +850,8 @@ end end @@ -846,6 +850,8 @@ end end
@test !occursin("```julia\n47 #hide\n```", markdown) # line with `#hide` removed
@test !occursin("```julia\n```", markdown) # no empty code block
@test occursin("```\n47\n```", markdown) # return value (even though line/block removed)
@test occursin("```\n\"cwd correct\"\n```", markdown) # Correct cwd (@__DIR__)
@test occursin("```\n\"inputfile.md\"\n```", markdown) # Correct source file (@__FILE__)
# FranklinFlavor
Literate.markdown(inputfile, outdir; execute=true, flavor=Literate.FranklinFlavor())
@ -1179,7 +1185,7 @@ end end @@ -1179,7 +1185,7 @@ end end
err
end)
@test isa(r, ErrorException)
@test occursin("when executing the following code block in file ", r.msg)
@test occursin("when executing the following code block from inputfile ", r.msg)
@test occursin(inputfile, r.msg)
# verify that inputfile exists

Loading…
Cancel
Save