Skip to content

Commit

Permalink
Fix cwd and apparent source file when executing markdown. (#195)
Browse files Browse the repository at this point in the history
  • Loading branch information
fredrikekre authored Apr 22, 2022
1 parent d009153 commit 53a9d26
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 22 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
47 changes: 26 additions & 21 deletions src/Literate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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" :
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -543,10 +544,13 @@ 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
execute_markdown!(iomd, sb, join(chunk.lines, '\n'), outputdir;
inputfile=config["literate_inputfile"],
flavor=config["flavor"],
image_formats=config["image_formats"])
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
Expand All @@ -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````"
Expand Down Expand Up @@ -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: " *
Expand All @@ -709,15 +714,15 @@ 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"]
cell["cell_type"] == "code" || continue
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)
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Down
8 changes: 7 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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())
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 53a9d26

Please sign in to comment.