Skip to content

Commit

Permalink
Make should_show_banner work with julia 1.11 and nightly (Nemocas#1758
Browse files Browse the repository at this point in the history
)

* Make `should_show_banner` work with julia 1.11 and nightly

* Enable banner tests on now working versions

* Add try-catch

(cherry picked from commit b6081d2)
  • Loading branch information
lgoettgens committed Aug 20, 2024
1 parent ee4321c commit 8f0483b
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 86 deletions.
60 changes: 40 additions & 20 deletions src/utils.jl
Original file line number Diff line number Diff line change
@@ -1,22 +1,42 @@
function should_show_banner()
# Check if were loaded from another package
# if VERSION < 1.7.*, only the "other" package will have the
# _tryrequire_from_serialized in the backtrace.
# if VERSION >= 1.8, also doing 'using Package' will have
# _tryrequire_from_serialized the backtrace.
#
# To still distinguish both scenarios, notice that
# 'using OtherPackage' will either have _tryrequire_from_serialized at least twice,
# or one with four arguments (hence five as the function name is the first argument)
# 'using Package' serialized will have a version with less arguments
bt = Base.process_backtrace(Base.backtrace())
Base.filter!(sf -> sf[1].func === :_tryrequire_from_serialized, bt)
isinteractive_manual =
length(bt) == 0 || (length(bt) == 1 && length(only(bt)[1].linfo.specTypes.parameters) < 4)
function is_loaded_directly()
try
@static if VERSION < v"1.11.0-"
# Check if were loaded from another package
# if VERSION < 1.7.*, only the "other" package will have the
# _tryrequire_from_serialized in the backtrace.
# if VERSION >= 1.8, also doing 'using Package' will have
# _tryrequire_from_serialized the backtrace.
#
# To still distinguish both scenarios, notice that
# 'using OtherPackage' will either have _tryrequire_from_serialized at least twice,
# or one with four arguments (hence five as the function name is the first argument)
# 'using Package' serialized will have a version with less arguments
bt = Base.process_backtrace(Base.backtrace())
Base.filter!(sf -> sf[1].func === :_tryrequire_from_serialized, bt)
return length(bt) == 0 ||
(length(bt) == 1 && length(only(bt)[1].linfo.specTypes.parameters) < 4)
else
# Starting with julia 1.11, the package loading was completely revamped.
# The only difference in the callstack is the line number of the call to _include_from_serialized
# inside of the _require_search_from_serialized function.
# To make it a bit more robust, we check the difference between the line number of the beginning
# of _require_search_from_serialized and the call to _include_from_serialized.
# For `using OtherPackage`, the difference is 61, while for `using Package`, the difference is 75 or 78
# (on all 1.11 pre-releases up to 1.11.0-rc1 and 1.12.0-DEV.896, which are the newest at the time of writing this).
bt = Base.process_backtrace(Base.backtrace())
Base.filter!(sf -> contains(string(sf[1].func), "_require_search_from_serialized"), bt)
bt_entry = only(bt)[1]
return bt_entry.line - bt_entry.linfo.def.line >= 70
end
catch e
@debug "Error while checking if loaded directly" exception=(e, Base.catch_backtrace())
return true
end
end

# Respect the -q flag
isquiet = Bool(Base.JLOptions().quiet)
show_banner = !isquiet && isinteractive_manual && isinteractive() &&
Base.JLOptions().banner != 0
return show_banner
function should_show_banner()
# Respect the -q flag
isquiet = Bool(Base.JLOptions().quiet)
show_banner = !isquiet && is_loaded_directly() && isinteractive() && Base.JLOptions().banner != 0
return show_banner
end
130 changes: 64 additions & 66 deletions test/utils/Banners/banners.jl
Original file line number Diff line number Diff line change
@@ -1,77 +1,75 @@
using Pkg

if VERSION>=v"1.9"
@testset "Banners" begin
@testset "Banners" begin

function run_repl_code(code::String, proj::String)
bin = Base.julia_cmd()
opts = ["--project=$proj", "-i", "-e", "$code; exit();"]
cmd = Cmd(`$bin $opts`, ignorestatus=true)
outs = IOBuffer()
errs = IOBuffer()
proc = run(pipeline(`$cmd`, stderr=errs, stdout=outs))
result = String(take!(outs))
err = String(take!(errs))
return result, err, proc.exitcode
end
function run_repl_code(code::String, proj::String)
bin = Base.julia_cmd()
opts = ["--project=$proj", "-i", "-e", "$code; exit();"]
cmd = Cmd(`$bin $opts`, ignorestatus=true)
outs = IOBuffer()
errs = IOBuffer()
proc = run(pipeline(`$cmd`, stderr=errs, stdout=outs))
result = String(take!(outs))
err = String(take!(errs))
return result, err, proc.exitcode
end

# Set up a separate temporary project for some modules that depend on each
# other with some of them showing banners. Chain is
# AA -> ModA -> ModB -> ModC
path = dirname(@__FILE__)
aadir = dirname(dirname(pathof(AbstractAlgebra)))
modadir = joinpath(path, "ModA")
modbdir = joinpath(path, "ModB")
modcdir = joinpath(path, "ModC")
# Set up a separate temporary project for some modules that depend on each
# other with some of them showing banners. Chain is
# AA -> ModA -> ModB -> ModC
path = dirname(@__FILE__)
aadir = dirname(dirname(pathof(AbstractAlgebra)))
modadir = joinpath(path, "ModA")
modbdir = joinpath(path, "ModB")
modcdir = joinpath(path, "ModC")

# generate temp project
td = mktempdir()
code = """
using Pkg;
Pkg.develop(path=raw"$aadir");
Pkg.develop(path=raw"$modadir");
Pkg.develop(path=raw"$modbdir");
Pkg.develop(path=raw"$modcdir");
Pkg.precompile();
"""
out,err,exitcode = run_repl_code(code, td)
res = @test exitcode == 0
if res isa Test.Fail
println("out\n$out")
println("err\n$err")
end
# generate temp project
td = mktempdir()
code = """
using Pkg;
Pkg.develop(path=raw"$aadir");
Pkg.develop(path=raw"$modadir");
Pkg.develop(path=raw"$modbdir");
Pkg.develop(path=raw"$modcdir");
Pkg.precompile();
"""
out,err,exitcode = run_repl_code(code, td)
res = @test exitcode == 0
if res isa Test.Fail
println("out\n$out")
println("err\n$err")
end

# Banner of ModA shows
out, err = run_repl_code("using ModA;", td)
res = @test strip(out) == "Banner of ModA"
if res isa Test.Fail
println("out\n$out")
println("err\n$err")
end
# Banner of ModA shows
out, err = run_repl_code("using ModA;", td)
res = @test strip(out) == "Banner of ModA"
if res isa Test.Fail
println("out\n$out")
println("err\n$err")
end

# Banner of ModB shows, but ModA is supressed
out, err = run_repl_code("using ModB;", td)
res = @test strip(out) == "Banner of ModB" broken=VERSION>=v"1.11.0-DEV"
if res isa Test.Fail
println("out\n$out")
println("err\n$err")
end
# Banner of ModB shows, but ModA is supressed
out, err = run_repl_code("using ModB;", td)
res = @test strip(out) == "Banner of ModB"
if res isa Test.Fail
println("out\n$out")
println("err\n$err")
end

# Banner of ModB shows, but ModA is supressed, even if ModA is specifically
# used after ModB
out, err = run_repl_code("using ModB; using ModA;", td)
res = @test strip(out) == "Banner of ModB" broken=VERSION>=v"1.11.0-DEV"
if res isa Test.Fail
println("out\n$out")
println("err\n$err")
end
# Banner of ModB shows, but ModA is supressed, even if ModA is specifically
# used after ModB
out, err = run_repl_code("using ModB; using ModA;", td)
res = @test strip(out) == "Banner of ModB"
if res isa Test.Fail
println("out\n$out")
println("err\n$err")
end

# Banner does not show when our module is a dependency
out, err = run_repl_code("using ModC;", td)
res = @test strip(out) == "" broken=VERSION>=v"1.11.0-DEV"
if res isa Test.Fail
println("out\n$out")
println("err\n$err")
end
# Banner does not show when our module is a dependency
out, err = run_repl_code("using ModC;", td)
res = @test strip(out) == ""
if res isa Test.Fail
println("out\n$out")
println("err\n$err")
end
end

0 comments on commit 8f0483b

Please sign in to comment.