Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make should_show_banner work with julia 1.11 and nightly #1758

Merged
merged 3 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 warning on line 3 in src/utils.jl

View check run for this annotation

Codecov / codecov/patch

src/utils.jl#L3

Added line #L3 was not covered by tests
# 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

Check warning on line 33 in src/utils.jl

View check run for this annotation

Codecov / codecov/patch

src/utils.jl#L32-L33

Added lines #L32 - L33 were not covered by tests
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
Loading