Skip to content

Commit

Permalink
further improve tests
Browse files Browse the repository at this point in the history
  • Loading branch information
disberd committed Jun 28, 2024
1 parent db01046 commit 3f53f05
Show file tree
Hide file tree
Showing 6 changed files with 166 additions and 141 deletions.
34 changes: 19 additions & 15 deletions src/frompackage/helpers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,10 @@ function extract_nested_module(starting_module::Module, nested_path; first_dot_s
return m
end

# This will create a unique name for a module by translating the PkgId into a symbol
unique_module_name(m::Module) = Symbol(Base.PkgId(m))
unique_module_name(uuid::Base.UUID, name::AbstractString) = Symbol(Base.PkgId(uuid,name))

function get_temp_module()
if isdefined(Main, TEMP_MODULE_NAME)
getproperty(Main, TEMP_MODULE_NAME)::Module
Expand All @@ -254,6 +258,7 @@ function get_temp_module(::FromPackageController{name}) where {name}
end

get_loaded_modules_mod() = get_temp_module(:_LoadedModules_)::Module
get_direct_deps_mod() = get_temp_module(:_DirectDeps_)::Module

function populate_loaded_modules()
loaded_modules = get_loaded_modules_mod()
Expand All @@ -266,26 +271,25 @@ function populate_loaded_modules()
end
callbacks = Base.package_callbacks
if mirror_package_callback callbacks
# We just make sure to delete previous instances of the package callbacks when reloading this package itself
for i in reverse(eachindex(callbacks))
f = callbacks[i]
nameof(f) === :mirror_package_callback || continue
nameof(parentmodule(f)) === nameof(@__MODULE__) || continue
# We delete this as it's a previous version of the mirror_package_callback function
@warn "Deleting previous version of package_callback function"
deleteat!(callbacks, i)
end
# # We just make sure to delete previous instances of the package callbacks when reloading this package itself
# for i in reverse(eachindex(callbacks))
# f = callbacks[i]
# nameof(f) === :mirror_package_callback || continue
# nameof(parentmodule(f)) === nameof(@__MODULE__) || continue
# # We delete this as it's a previous version of the mirror_package_callback function
# @warn "Deleting previous version of package_callback function"
# deleteat!(callbacks, i)
# end
# Add the package callback if not already present
push!(callbacks, mirror_package_callback)
end
end

# This function will extract a module from the _LoadedModules_ module which will be populated when each package is loaded in julia
function get_dep_from_loaded_modules(id::Base.PkgId)
function get_dep_from_loaded_modules(key::Symbol)
loaded_modules = get_loaded_modules_mod()
key = Symbol(id)
isdefined(loaded_modules, key) || error("The module $key can not be found in the loaded modules.")
m = getproperty(loaded_modules, Symbol(id))::Module
m = getproperty(loaded_modules, key)::Module
return m
end
# This is internally calls the previous function, allowing to control which packages can be loaded (by default only direct dependencies and stdlibs are allowed)
Expand All @@ -303,7 +307,7 @@ function get_dep_from_loaded_modules(p::FromPackageController{name}, base_name::
end
if allow_stdlibs
uuid = get(STDLIBS_DATA, package_name, nothing)
uuid !== nothing && return get_dep_from_loaded_modules(Base.PkgId(uuid, package_name))
uuid !== nothing && return get_dep_from_loaded_modules(unique_module_name(uuid, package_name))
end
proj = p.project
uuid = get(proj.deps, package_name) do
Expand All @@ -317,8 +321,8 @@ function get_dep_from_loaded_modules(p::FromPackageController{name}, base_name::
end
error(error_msg)
end
id = Base.PkgId(uuid, package_name)
return get_dep_from_loaded_modules(id)
key = unique_module_name(uuid, package_name)
return get_dep_from_loaded_modules(key)
end

# Basically Base.names but ignores names that are not defined in the module and allows to restrict to only exported names (since 1.11 added also public names as out of names). It also defaults `all` and `imported` to true (to be more precise, to the opposite of `only_exported`)
Expand Down
12 changes: 7 additions & 5 deletions src/frompackage/imports_helpers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ function ImportAs(original::Vector)
@assert all(nm -> isa(nm, Symbol), original) "Only vectors containing just symbols are valid inputs to the ImportAs constructor."
ImportAs(Symbol.(original), nothing)
end
ImportAs(original::Symbol, as::Symbol) = ImportAs([original], as)
function ImportAs(ex::Expr)
if ex.head === :.
ImportAs(ex.args)
Expand Down Expand Up @@ -110,17 +109,18 @@ function process_modpath!(mwn::ModuleWithNames, p::FromPackageController{name};
path = modname.original
root_name = popfirst!(path)
if root_name in (:ParentModule, :<)
@assert !isnothing(p.target_module) "You can't import from the Parent Module when the calling file is not a file `included` in the target package."
m = p.target_module
prepend!(path, fullname(m))
elseif root_name in (:PackageModule, :^, name)
m = get_temp_module(p)
prepend!(path, fullname(m))
elseif root_name === :>
# Deps import
@assert :* mwn.imported "You can't use the catch-all expression when importing from dependencies"
@assert !is_catchall(mwn) "You can't use the catch-all expression when importing from dependencies"
m = get_dep_from_loaded_modules(p, first(path); allow_manifest=true)
# Replace the deps name with the uuid_name symbol from loaded modules
path[1] = Symbol(Base.PkgId(m))
path[1] = unique_module_name(m)
# Add the loaded module path
prepend!(path, fullname(get_loaded_modules_mod()))
elseif root_name === :*
Expand All @@ -131,10 +131,12 @@ function process_modpath!(mwn::ModuleWithNames, p::FromPackageController{name};
prepend!(path, fullname(m))
push!(mwn.imported, ImportAs(:*))
elseif root_name === :.
m = extract_nested_module(p.current_module, path; first_dot_skipped=true)
@assert inner || !isnothing(p.target_module) "You can't use relative imports when the calling file is not a file `included` in the target package."
starting_module = @something p.target_module get_temp_module(p)
m = extract_nested_module(starting_module, path; first_dot_skipped=true)
modname.original = fullname(m) |> collect
else
error("The provided import statement is not a valid input for the @frompackage macro.")
error("The provided import statement is not a valid input for the @frompackage macro.\nIf you want to import from a dependency of the target package, prepend `>.` in front of the package name, e.g. `using >.BenchmarkTools`.")
end
return
end
Expand Down
1 change: 1 addition & 0 deletions src/frompackage/input_parsing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ function process_outside_pluto(p::FromPackageController, ex::Expr)
# Relative import, we just make sure it's not a catch all
is_catchall(mwn) && continue
elseif root_name === :>
@assert !is_catchall(mwn) "You can't use the catch-all expression when importing from dependencies"
# Deps import, we have to make sure we are only importing direct dependencies
# We remove the first symbol as its :>
popfirst!(modname_path)
Expand Down
8 changes: 4 additions & 4 deletions src/frompackage/loading.jl
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ function try_load_extensions!(p::FromPackageController)
nactive = 0
for trigger_name in triggers
trigger_uuid = weakdeps[trigger_name]
id = Base.PkgId(trigger_uuid, trigger_name)
is_loaded = isdefined(loaded_modules, Symbol(id))
unique_name = unique_module_name(trigger_uuid, trigger_name)
is_loaded = isdefined(loaded_modules, unique_name)
nactive += is_loaded
end
if nactive === length(triggers)
Expand All @@ -88,9 +88,9 @@ end
### Load Module ###
function load_direct_deps(p::FromPackageController)
@nospecialize
deps_mod = get_temp_module(:_DirectDeps_)::Module
deps_mod = get_direct_deps_mod()
for (name, uuid) in p.project.deps
name_uuid = Base.PkgId(uuid, name) |> Symbol
name_uuid = unique_module_name(uuid, name)
isdefined(deps_mod, name_uuid) && continue
Core.eval(deps_mod, :(import $(Symbol(name)) as $name_uuid))
end
Expand Down
Loading

0 comments on commit 3f53f05

Please sign in to comment.