Skip to content
New issue

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

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

Already on GitHub? # to your account

support @lazyload for lazy loading of script dependencies #205

Merged
merged 5 commits into from
Jun 18, 2022
Merged
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
30 changes: 30 additions & 0 deletions example/lazyload.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Comonicon

@lazyload using Random @cast function random()
isdefined(Main, :Random) && println("Random is loaded")
isdefined(Main, :LinearAlgebra) && println("LinearAlgebra is loaded")
end

@lazyload using Random, LinearAlgebra @cast function both()
isdefined(Main, :Random) && println("Random is loaded")
isdefined(Main, :LinearAlgebra) && println("LinearAlgebra is loaded")
end

# this will throw an error
@cast function none()
isdefined(Main, :Random) && println("Random is loaded")
isdefined(Main, :LinearAlgebra) && println("LinearAlgebra is loaded")
end

@main

# You will see the following output if you run this script.
#
# shell> julia --project example/lazyload.jl random
# Random is loaded

# shell> julia --project example/lazyload.jl both
# Random is loaded
# LinearAlgebra is loaded

# shell> julia --project example/lazyload.jl none
2 changes: 1 addition & 1 deletion src/Comonicon.jl
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ using Pkg
using Markdown
using ExproniconLite

export @cast, @main, cmd_error, cmd_exit
export @cast, @main, cmd_error, cmd_exit, @lazyload

include("compat.jl")
include("configs.jl")
41 changes: 41 additions & 0 deletions src/frontend/cast.jl
Original file line number Diff line number Diff line change
@@ -652,3 +652,44 @@ function cast_options(doc::JLMD, options::Vector{JLOption}, line)
end
return cmd_options
end

"""
@lazyload expr @cast <valid castable expr>

Evaluate `expr` if command `f` is called. This is useful
for reducing the latency of scripts that has subcmds depend
on plotting, serialization etc.

Please see [`@cast`](@ref) for valid expression specifications.

!!! warning

This macro only works at top-level command and thus can only be
used in `Main` and only works in scripts. Using this macro in any
other module or a project module will not work.
"""
macro lazyload(load_expr, casted_expr)
return esc(lazyload_m(__module__, __source__, load_expr, casted_expr))
end

function lazyload_m(m::Module, line, load_expr, casted_expr::Expr)
m === Main || throw(ArgumentError("`@lazyload` can only be used in `Main`, got $m"))
Meta.isexpr(casted_expr, :macrocall) && casted_expr.args[1] === Symbol("@cast") ||
throw(ArgumentError("`@lazyload` only accept `@cast`ed objects in `Main`"))

if is_function(casted_expr.args[3])
fname = JLFunction(casted_expr.args[3]).name
cmd_name = default_name(fname)
elseif Meta.isexpr(casted_expr.args[3], :module)
cmd_name = default_name(casted_expr.args[3].args[2])
end

return quote
if !isempty(ARGS) && ARGS[1] == $cmd_name
$load_expr
end

$line
Core.@__doc__ $casted_expr
end
end
7 changes: 4 additions & 3 deletions test/Project.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
[deps]
FromFile = "ff7dd447-1dcb-4ce3-b8ac-22a812192de7"
PackageCompiler = "9b87118b-4619-50d2-8e1e-99f35a4d4d9d"
ComoniconTestUtils = "53b67e40-53a7-4335-973f-e3e901fe4865"
ExproniconLite = "55351af7-c7e9-48d6-89ff-24e801d99491"
Faker = "0efc519c-db33-5916-ab87-703215c3906f"
FromFile = "ff7dd447-1dcb-4ce3-b8ac-22a812192de7"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
PackageCompiler = "9b87118b-4619-50d2-8e1e-99f35a4d4d9d"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Scratch = "6c6a2e73-6563-6170-7368-637461726353"
SimpleMock = "a896ed2c-15a5-4479-b61d-a0e88e2a1d25"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Scratch = "6c6a2e73-6563-6170-7368-637461726353"
20 changes: 20 additions & 0 deletions test/examples.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using Test
using Comonicon

example_dir(xs...) = pkgdir(Comonicon, "example", xs...)

function execute(name, args::String="")
path = example_dir("$name.jl")
cmd = Base.julia_cmd()
return run(`$cmd --project=$(Base.active_project()) $(path) $args`)
end

@testset "lazyload $args" for args in [
"",
"random",
"both",
"none",
]
p = execute("lazyload", args)
@test p.exitcode == 0
end
42 changes: 42 additions & 0 deletions test/frontend/markdown.jl
Original file line number Diff line number Diff line change
@@ -235,3 +235,45 @@ end
end

end # TestMarkdown

module TestLazyLoad

using Test
using Comonicon
using ExproniconLite

@testset "lazyload" begin
ex = @expr @cast function f()
end
generated = Comonicon.lazyload_m(Main, nothing, :(using Pkg), ex)

@test_expr generated == quote
if !(isempty(ARGS)) && ARGS[1] == "f"
using Pkg
end

Core.@__doc__ @cast function f()
end
end

ex = @expr @cast module nodecmd
using Comonicon
@cast function f()
end
end

generated = Comonicon.lazyload_m(Main, nothing, :(using Pkg), ex)
@test_expr generated == quote
if !(isempty(ARGS)) && ARGS[1] == "nodecmd"
using Pkg
end

Core.@__doc__ @cast module nodecmd
using Comonicon
@cast function f()
end
end
end
end

end
4 changes: 4 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -37,6 +37,10 @@ end
include("scripts.jl")
end

@testset "example scripts" begin
include("examples.jl")
end

# the script workaround doesn't work on MacOS
# https://github.com/actions/runner/issues/241
# @testset "tools" begin