From 1bc1d77cb7e7986a0d14e4c19d1f0a003206ac59 Mon Sep 17 00:00:00 2001 From: Fredrik Ekre Date: Wed, 15 Aug 2018 17:12:22 +0200 Subject: [PATCH] Define include in sandbox-modules, fix #793. (#794) --- src/DocTests.jl | 8 ++------ src/Expanders.jl | 13 +++++++++++-- test/examples/src/index.md | 31 +++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/DocTests.jl b/src/DocTests.jl index 11f7a2d3e8..89171944ab 100644 --- a/src/DocTests.jl +++ b/src/DocTests.jl @@ -8,6 +8,7 @@ using DocStringExtensions import ..Documenter: Documenter, Documents, + Expanders, Utilities import Markdown, REPL @@ -64,12 +65,7 @@ function doctest(block::Markdown.Code, meta::Dict, doc::Documents.Document, page # Define new module or reuse an old one from this page if we have a named doctest. name = match(r"jldoctest[ ]?(.*)$", split(lang, ';', limit = 2)[1])[1] sym = isempty(name) ? gensym("doctest-") : Symbol("doctest-", name) - sandbox = get!(page.globals.meta, sym) do - newmod = Module(sym) - # eval(expr) is available in the REPL (i.e. Main) so we emulate that for the sandbox - Core.eval(newmod, :(eval(x) = Core.eval($newmod, x))) - newmod - end + sandbox = get!(() -> Expanders.get_new_sandbox(sym), page.globals.meta, sym) # Normalise line endings. block.code = replace(block.code, "\r\n" => "\n") diff --git a/src/Expanders.jl b/src/Expanders.jl index d66758105b..81e0abb869 100644 --- a/src/Expanders.jl +++ b/src/Expanders.jl @@ -459,7 +459,7 @@ function Selectors.runner(::Type{ExampleBlocks}, x, page, doc) # The sandboxed module -- either a new one or a cached one from this page. name = match(r"^@example[ ]?(.*)$", first(split(x.language, ';', limit = 2)))[1] sym = isempty(name) ? gensym("ex-") : Symbol("ex-", name) - mod = get!(page.globals.meta, sym, Module(sym))::Module + mod = get!(() -> get_new_sandbox(sym), page.globals.meta, sym) # "parse" keyword arguments to example (we only need to look for continued = true) continued = occursin(r"continued\s*=\s*true", x.language) @@ -529,7 +529,7 @@ function Selectors.runner(::Type{REPLBlocks}, x, page, doc) matched === nothing && error("invalid '@repl' syntax: $(x.language)") name = matched[1] sym = isempty(name) ? gensym("ex-") : Symbol("ex-", name) - mod = get!(page.globals.meta, sym, Module(sym))::Module + mod = get!(() -> get_new_sandbox(sym), page.globals.meta, sym) code = split(x.code, '\n'; limit = 2)[end] result, out = nothing, IOBuffer() for (ex, str) in Utilities.parseblock(x.code, doc, page) @@ -633,4 +633,13 @@ function prepend_prompt(input) rstrip(String(take!(out))) end +function get_new_sandbox(name::Symbol) + m = Module(name) + # eval(expr) is available in the REPL (i.e. Main) so we emulate that for the sandbox + Core.eval(m, :(eval(x) = Core.eval($m, x))) + # modules created with Module() does not have include defined + Core.eval(m, :(include(x) = Base.include($m, x))) + return m +end + end diff --git a/test/examples/src/index.md b/test/examples/src/index.md index 1bc9588884..197f30466a 100644 --- a/test/examples/src/index.md +++ b/test/examples/src/index.md @@ -341,6 +341,37 @@ julia> eval(ex) 3 ``` +```@repl +ex = :(1 + 5) +eval(ex) +``` + +```@example +ex = :(1 + 5) +eval(ex) +``` + +# Issue #793 +```jldoctest +julia> write("issue793.jl", "\"Hello!\""); + +julia> include("issue793.jl") +"Hello!" + +julia> rm("issue793.jl"); +``` +```@repl +write("issue793.jl", "\"Hello!\"") +include("issue793.jl") +rm("issue793.jl") +``` +```@example +write("issue793.jl", "\"Hello!\"") +r = include("issue793.jl") +rm("issue793.jl") +r +``` + ```jldoctest julia> a = 1