Merge pull request #319 from JunoLab/avi/weavedoc

remove weird default constructor for `WeaveDoc`
pull/313/head
Shuhei Kadowaki 2020-05-09 23:39:03 +09:00 committed by GitHub
commit a526cb8f15
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 117 additions and 108 deletions

View File

@ -3,6 +3,9 @@ import Highlights
using Mustache using Mustache
using Requires using Requires
const WEAVE_OPTION_NAME = "options" # TODO: rename to "weave_options"
function __init__() function __init__()
@require Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" Base.include( @require Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" Base.include(
Main, Main,
@ -123,7 +126,7 @@ function weave(
doc.doctype = doctype doc.doctype = doctype
# Read args from document header, overrides command line args # Read args from document header, overrides command line args
if haskey(doc.header, "options") if haskey(doc.header, WEAVE_OPTION_NAME)
( (
doctype, doctype,
informat, informat,
@ -248,7 +251,7 @@ function notebook(
end end
@info "Running nbconvert" @info "Running nbconvert"
out = read( return out = read(
`$jupyter_path nbconvert --ExecutePreprocessor.timeout=$timeout --to notebook --execute $outfile $nbconvert_options --output $outfile`, `$jupyter_path nbconvert --ExecutePreprocessor.timeout=$timeout --to notebook --execute $outfile $nbconvert_options --output $outfile`,
String, String,
) )

View File

@ -107,7 +107,7 @@ function header_args(
pandoc_options, pandoc_options,
latex_cmd, latex_cmd,
) )
args = get(doc.header, "options", Dict()) args = get(doc.header, WEAVE_OPTION_NAME, Dict())
doctype = get(args, "doctype", doc.doctype) doctype = get(args, "doctype", doc.doctype)
args = combine_args(args, doctype) args = combine_args(args, doctype)
informat = get(args, "informat", :auto) informat = get(args, "informat", :auto)
@ -145,16 +145,3 @@ function header_args(
latex_cmd, latex_cmd,
) )
end end
"""
header_chunk_defaults!(doc::WeaveDoc)
Get chunk defaults from header and update.
"""
function header_chunk_defaults!(doc::WeaveDoc)
for key in keys(doc.chunk_defaults)
if (val = get(doc.header["options"], string(key), nothing)) !== nothing
doc.chunk_defaults[key] = val
end
end
end

View File

@ -131,7 +131,7 @@ function strip_header!(docchunk::DocChunk, doctype)
else else
# only strips Weave headers # only strips Weave headers
header = YAML.load(m[:header]) header = YAML.load(m[:header])
delete!(header, "options") delete!(header, WEAVE_OPTION_NAME)
if isempty(header) if isempty(header)
lstrip(replace(content, HEADER_REGEX => "")) lstrip(replace(content, HEADER_REGEX => ""))
else else

View File

@ -2,20 +2,48 @@ using JSON, YAML
""" """
read_doc(source::AbstractString, format = :auto) -> WeaveDoc read_doc(source, format = :auto)
Read the input document from `source` and parse it into [`WeaveDoc`](@ref). Read the input document from `source` and parse it into [`WeaveDoc`](@ref).
""" """
function read_doc(source::AbstractString, format = :auto) function read_doc(source, format = :auto)
document = replace(read(source, String), "\r\n" => "\n") # fix line ending document = replace(read(source, String), "\r\n" => "\n") # fix line ending
format === :auto && (format = detect_informat(source)) format === :auto && (format = detect_informat(source))
chunks = parse_doc(document, format) chunks = parse_doc(document, format)
header = parse_header(first(chunks)) return WeaveDoc(source, chunks)
doc = WeaveDoc(source, chunks, header) end
haskey(header, "options") && header_chunk_defaults!(doc) # TODO: rename `options` => `weave_options`
return doc function WeaveDoc(source, chunks)
path, fname = splitdir(abspath(source))
basename = splitext(fname)[1]
header = parse_header(first(chunks))
# get chunk defaults from header and update
chunk_defaults = deepcopy(rcParams[:chunk_defaults])
if haskey(header, WEAVE_OPTION_NAME)
for key in keys(chunk_defaults)
if (val = get(header[WEAVE_OPTION_NAME], string(key), nothing)) !== nothing
chunk_defaults[key] = val
end
end
end
return WeaveDoc(
source,
basename,
path,
chunks,
"",
nothing,
"",
"",
header,
"",
"",
Highlights.Themes.DefaultTheme,
"",
chunk_defaults,
)
end end
""" """
@ -32,7 +60,7 @@ function detect_informat(source::AbstractString)
return "noweb" return "noweb"
end end
function parse_doc(document, format) function parse_doc(document, format)::Vector{WeaveChunk}
return if format == "markdown" return if format == "markdown"
parse_markdown(document) parse_markdown(document)
elseif format == "noweb" elseif format == "noweb"

View File

@ -17,26 +17,6 @@ mutable struct WeaveDoc
highlight_theme::Type{<:Highlights.AbstractTheme} highlight_theme::Type{<:Highlights.AbstractTheme}
fig_path::AbstractString fig_path::AbstractString
chunk_defaults::Dict{Symbol,Any} chunk_defaults::Dict{Symbol,Any}
function WeaveDoc(source, chunks, header)
path, fname = splitdir(abspath(source))
basename = splitext(fname)[1]
new(
source,
basename,
path,
chunks,
"",
nothing,
"",
"",
header,
"",
"",
Highlights.Themes.DefaultTheme,
"",
deepcopy(rcParams[:chunk_defaults]),
)
end
end end
struct ChunkOutput struct ChunkOutput

View File

@ -1,35 +0,0 @@
s1= """
```julia
using NonExisting
```
```julia
x =
```
```julia;term=true
plot(x)
y = 10
print(y
```
"""
p1 = Weave.parse_markdown(s1)
doc = Weave.WeaveDoc("dummy1.jmd", p1, Dict())
doc1 = run_doc(doc, doctype = "pandoc")
@test doc1.chunks[1].output == "Error: ArgumentError: Package NonExisting not found in current path:\n- Run `import Pkg; Pkg.add(\"NonExisting\")` to install the NonExisting package.\n\n"
@test doc1.chunks[2].output == "Error: syntax: incomplete: premature end of input\n"
@test doc1.chunks[3].output == "\njulia> plot(x)\nError: UndefVarError: plot not defined\n\njulia> y = 10\n10\n\njulia> print(y\nError: syntax: incomplete: premature end of input\n"
@test_throws ArgumentError run_doc(doc, doctype = "pandoc", throw_errors = true)
doc = Weave.WeaveDoc("dummy1.jmd", p1, Dict())
doc3 = run_doc(doc, doctype = "md2html")
@test doc3.chunks[1].rich_output == "<pre class=\"julia-error\">\nERROR: ArgumentError: Package NonExisting not found in current path:\n- Run &#96;import Pkg; Pkg.add&#40;&quot;NonExisting&quot;&#41;&#96; to install the NonExisting package.\n\n</pre>\n"
@test doc3.chunks[2].rich_output == "<pre class=\"julia-error\">\nERROR: syntax: incomplete: premature end of input\n</pre>\n"
@test doc3.chunks[3].output == "\njulia> plot(x)\nError: UndefVarError: plot not defined\n\njulia> y = 10\n10\n\njulia> print(y\nError: syntax: incomplete: premature end of input\n"
@test doc3.chunks[3].rich_output == ""

View File

@ -127,24 +127,21 @@ pformat.formatdict[:keep_unicode] = true
f = Weave.format_chunk(dchunk, pformat.formatdict, pformat) f = Weave.format_chunk(dchunk, pformat.formatdict, pformat)
@test f == "\\section{Test chunk}\nα\n\n" @test f == "\\section{Test chunk}\nα\n\n"
function doc_from_string(str)
parsed = Weave.parse_markdown(str)
header = Weave.parse_header(parsed[1])
Weave.WeaveDoc("",parsed,header)
end
doc_content = """ str = """
```julia ```julia
α = 10 α = 10
``` ```
""" """
parsed = doc_from_string(doc_content) let
ldoc = run_doc(parsed, doctype = "md2tex") doc = run_doc(mock_doc(str), doctype = "md2tex")
@test occursin(Weave.uc2tex("α"),Weave.format(ldoc)) @test occursin(Weave.uc2tex("α"), Weave.format(doc))
@test !occursin("α",Weave.format(ldoc)) @test !occursin("α", Weave.format(doc))
end
parsed = doc_from_string(doc_content) let
ldoc = run_doc(parsed, doctype = "md2tex",latex_keep_unicode=true) doc = run_doc(mock_doc(str), doctype = "md2tex",latex_keep_unicode = true)
@test occursin("α",Weave.format(ldoc)) @test occursin("α", Weave.format(doc))
@test !occursin(Weave.uc2tex("α"),Weave.format(ldoc)) @test !occursin(Weave.uc2tex("α"), Weave.format(doc))
end

View File

@ -6,16 +6,15 @@ using Test
# TODO: add test for header processsing # TODO: add test for header processsing
# TODO: add test for `include_weave` # TODO: add test for `include_weave`
# constructs `WeaveDoc` from `String`
mock_doc(str, chunk_parser = Weave.parse_markdown) = Weave.WeaveDoc("dummy", chunk_parser(str))
@testset "Weave" begin @testset "Weave" begin
@testset "Chunk options" begin @testset "Chunk options" begin
include("chunk_options.jl") include("chunk_options.jl")
end end
@testset "Error handling " begin
include("errors_test.jl")
end
@testset "module evaluation" begin @testset "module evaluation" begin
include("test_module_evaluation.jl") include("test_module_evaluation.jl")
end end
@ -24,6 +23,10 @@ using Test
include("test_header.jl") include("test_header.jl")
end end
@testset "error rendering" begin
include("test_error_rendering.jl")
end
@testset "Conversions" begin @testset "Conversions" begin
include("convert_test.jl") include("convert_test.jl")
end end

View File

@ -0,0 +1,49 @@
function get_err_str(ex)
try
eval(ex)
catch err
return sprint(showerror, err)
end
end
get_err_str(str::AbstractString) = get_err_str(Meta.parse(str; raise = false))
err_stmt1 = "using NonExisting"
err_stmt2 = "x = "
err_stmt3 = """
plot(x)
y = 10
f(y
"""
str = """
```julia
$err_stmt1
```
```julia
$err_stmt2
```
```julia; term=true
$err_stmt3
```
"""
err_str1 = get_err_str(err_stmt1)
err_str2 = get_err_str(err_stmt2)
err_str3_1 = get_err_str("plot(x)")
err_str3_2 = get_err_str("f(y")
let doc = run_doc(mock_doc(str), doctype = "pandoc")
get_output(i) = doc.chunks[i].output
@test occursin(err_str1, get_output(1))
@test occursin(err_str2, get_output(2))
@test occursin(err_str3_1, get_output(3))
@test occursin(err_str3_2, get_output(3))
end
@test_throws ArgumentError run_doc(mock_doc(str), doctype = "pandoc", throw_errors = true)
# TODO: test error rendering in `rich_output`

View File

@ -1,4 +1,4 @@
using YAML using Weave.YAML
# TODO: # TODO:
# - header stripping # - header stripping
@ -19,7 +19,7 @@ options:
--- ---
""") """)
let args = header["options"] let args = header[Weave.WEAVE_OPTION_NAME]
@test Weave.combine_args(args, "md2html") == Dict("fig_ext" => ".png", "out_path" => "html/") @test Weave.combine_args(args, "md2html") == Dict("fig_ext" => ".png", "out_path" => "html/")
@test Weave.combine_args(args, "github") == Dict("fig_ext" => ".png", "out_path" => "md/") @test Weave.combine_args(args, "github") == Dict("fig_ext" => ".png", "out_path" => "md/")
@test Weave.combine_args(args, "pandoc") == Dict("fig_ext" => ".png", "out_path" => "reports") @test Weave.combine_args(args, "pandoc") == Dict("fig_ext" => ".png", "out_path" => "reports")

View File

@ -1,23 +1,20 @@
@testset "evaluation module" begin @testset "evaluation module" begin
function mock_output(document, mod = nothing) function mock_output(str, mod = nothing)
parsed = Weave.parse_markdown(document) result_doc = run_doc(mock_doc(str), mod = mod)
doc = Weave.WeaveDoc("dummy.jmd", parsed, Dict())
result_doc = run_doc(doc, mod = mod)
@test isdefined(result_doc.chunks[1], :output)
return result_doc.chunks[1].output return result_doc.chunks[1].output
end end
document = """ str = """
```julia ```julia
@__MODULE__ @__MODULE__
``` ```
""" """
# in sandbox # in sandbox
@test occursin(r"\#+WeaveSandBox[\#\d]+", mock_output(document)) @test occursin(r"\#+WeaveSandBox[\#\d]+", mock_output(str))
# in Main # in Main
@test strip(mock_output(document, Main)) == "Main" @test strip(mock_output(str, Main)) == "Main"
end end
@testset "clear_module!" begin @testset "clear_module!" begin