Skip to content

Commit

Permalink
Merge pull request #10 from NHDaly/nhd-module-recursive-globals-args
Browse files Browse the repository at this point in the history
Add `kwargs...` to `module_recursive_globals()`, to allow imported modules
  • Loading branch information
NHDaly authored Sep 2, 2021
2 parents 61bbc63 + 514ecdc commit 8a9c0ef
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 20 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "LookingGlass"
uuid = "1fcbbee2-b350-4a01-aad8-439064dba09e"
authors = ["Nathan Daly"]
version = "0.3.2"
version = "0.3.3"

[deps]
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
Expand Down
38 changes: 20 additions & 18 deletions src/LookingGlass.jl
Original file line number Diff line number Diff line change
Expand Up @@ -145,27 +145,27 @@ By default, it skips Julia's `Base` and `Core` modules, but you can enable those
NOTE: currently, `module_submodules(Main, recursive=true, base=true)` will trigger a
StackOverflowError, since recursively listing submodules of `Core` or `Base` infinite loops.
"""
module_submodules(m::Module; recursive=true, base=false) =
module_submodules(m::Module; recursive=true, base=false, kwargs...) =
if recursive
_module_recursive_submodules(m, base=base, seen=Set{Module}())
_module_recursive_submodules(m; base=base, seen=Set{Module}(), kwargs...)
else
_module_direct_submodules(m, base=base)
_module_direct_submodules(m; base=base, kwargs...)
end

function _module_recursive_submodules(m; base, seen)
submodules = _module_direct_submodules(m, base=base; seen=seen)
function _module_recursive_submodules(m; base, seen, kwargs...)
submodules = _module_direct_submodules(m; base=base, seen=seen, kwargs...)
for m in submodules
push!(seen, m)
end
modules = collect(Iterators.flatten(
[x, _module_recursive_submodules(x, base=base, seen=seen)...]
[x, _module_recursive_submodules(x; base=base, seen=seen, kwargs...)...]
for x in submodules
))
return modules
end
_module_direct_submodules(m; base, seen) =
_module_direct_submodules(m; base, seen, kwargs...) =
Module[submodule
for x in filter(x->name_is_submodule(m,x), names(m, all=true))
for x in filter(x->name_is_submodule(m,x), names(m; all=true, kwargs...))
for submodule in (Core.eval(m, x),) # assign to temporary variable (comprehensions are weird)
if submodule seen]

Expand Down Expand Up @@ -219,8 +219,8 @@ argument to one of `constness=:const` or `constness=:nonconst`.
To return only mutable globals or only immutable globals, set the `mutability=` keyword
argument to one of `mutability=:mutable` or `mutability=:immutable`.
"""
module_globals_names(m::Module; constness=:all, mutability=:all) =
[n for n in names(m, all=true)
module_globals_names(m::Module; constness=:all, mutability=:all, kwargs...) =
[n for n in names(m, all=true; kwargs...)
if module_name_isglobal(m, n; constness=constness, mutability=mutability)]
function module_name_isglobal(m::Module, n::Symbol; constness, mutability)
@assert constness (:all, :const, :nonconst)
Expand Down Expand Up @@ -248,9 +248,9 @@ module_globals(m::Module) = Dict(n => Core.eval(m, n) for n in module_globals_na
Return a Dict mapping the fully qualified name to the value of all global variables in
Module `m` and all its recursive submodules.
"""
function module_recursive_globals(m::Module)
function module_recursive_globals(m::Module; kwargs...)
return Dict((mod,n) => Core.eval(mod, n)
for (mod,names) in module_recursive_globals_names(m)
for (mod,names) in module_recursive_globals_names(m; kwargs...)
for n in names
)
end
Expand Down Expand Up @@ -282,16 +282,18 @@ end
Return a list of the names of all global variables for each submodule in Module `m`.
Defaults to all globals, can toggle only const-globals or nonconst-globals via keyword args.
See [`module_recursive_globals`](@ref).
See Also:
- [`module_globals`](@ref)
- [`module_recursive_globals`](@ref)
"""
module_recursive_globals_names(m::Module; constness=:all, mutability=:all) =
module_recursive_globals_names(m::Module; constness=:all, mutability=:all, kwargs...) =
merge!(
Dict(m => module_globals_names(m, constness=constness, mutability=mutability)),
Dict(m => module_globals_names(m; constness=constness, mutability=mutability, kwargs...)),
Dict(
sm => names
for sm in module_submodules(m, recursive=true)
for names in (module_globals_names(sm; constness=constness, mutability=mutability),)
if !isempty(names)
for sm in module_submodules(m; recursive=true, kwargs...)
for names in (module_globals_names(sm; constness=constness, mutability=mutability, kwargs...),)
#if !isempty(names)
))

"""
Expand Down
43 changes: 42 additions & 1 deletion test/LookingGlass.jl
Original file line number Diff line number Diff line change
Expand Up @@ -27,28 +27,47 @@ end
@test length(first(LookingGlass.func_backedges(MF.foo))[2]) == 1
end

module Outer
const g_outer = 1
end
module MV
gv = 2
const cv = 2
vec = []
module A
const g_a = 1
end
module Inner
i_x = 3
const i_c = 2
const i_vec = [2]

import ...Outer
end
end

@test LookingGlass.module_recursive_globals_names(MV) ==
Dict(
MV => sort([:gv, :cv, :vec]),
MV.Inner => sort([:i_x, :i_c, :i_vec]),
MV.A => sort([:g_a]),
)

@test LookingGlass.module_recursive_globals_names(MV,
constness=:const, mutability=:mutable) ==
constness = :const, mutability = :mutable) ==
Dict(
MV => sort([]),
MV.Inner => sort([:i_vec]),
MV.A => sort([]),
)

@test LookingGlass.module_recursive_globals_names(MV,
constness = :const, imported = true) ==
Dict(
MV => sort([:cv]),
MV.Inner => sort([:i_c, :i_vec]),
MV.A => sort([:g_a]),
Outer => sort([:g_outer]), # imported via MV.Inner
)

@test LookingGlass.module_recursive_globals(MV) ==
Expand All @@ -59,4 +78,26 @@ end
(MV.Inner, :i_x) => MV.Inner.i_x,
(MV.Inner, :i_c) => MV.Inner.i_c,
(MV.Inner, :i_vec) => MV.Inner.i_vec,
(MV.A, :g_a) => MV.A.g_a,
)

@test LookingGlass.module_recursive_globals(MV, imported=true) ==
Dict(
(MV, :gv) => MV.gv,
(MV, :cv) => MV.cv,
(MV, :vec) => MV.vec,
(MV.Inner, :i_x) => MV.Inner.i_x,
(MV.Inner, :i_c) => MV.Inner.i_c,
(MV.Inner, :i_vec) => MV.Inner.i_vec,
(MV.A, :g_a) => MV.A.g_a,
(Outer, :g_outer) => MV.Inner.Outer.g_outer, # imported via MV.Inner
)

@test LookingGlass.module_recursive_globals(MV, imported=true, constness=:const) ==
Dict(
(MV, :cv) => MV.cv,
(MV.Inner, :i_c) => MV.Inner.i_c,
(MV.Inner, :i_vec) => MV.Inner.i_vec,
(MV.A, :g_a) => MV.A.g_a,
(Outer, :g_outer) => MV.Inner.Outer.g_outer, # imported via MV.Inner
)

2 comments on commit 8a9c0ef

@NHDaly
Copy link
Owner Author

@NHDaly NHDaly commented on 8a9c0ef Sep 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register()

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/44091

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.3.3 -m "<description of version>" 8a9c0efc06b894b7ab2e816f3931f94d74afbdc3
git push origin v0.3.3

Please sign in to comment.