How to get ALL variable names currently accessible

I know about Base.names, however it ignores all the variables which are imported via using.

Is there a function which also includes these?

Or is there a way to tell whether a module was imported like using DataFrames? Then I could apply names once again to get the exported names of these imported packages and add them

EDIT: I just realized that when using using DataFrames, then :DataFrames itself is also not part of names.

I found one workaround

modules(m::Module) = ccall(:jl_module_usings, Any, (Any,), m)

this will list all Modules which were imported via using THatModule

EDIT: then you can call names on those modules

1 Like

Would this help (code by @bkamins):
println(Main.varinfo(@__MODULE__; all=true, imported=true))

1 Like

Just pass imported=true to names.

3 Likes

varinfo and names both do not work as described. They just don’t list the names

What’s wrong with, for example:

julia> import Statistics

julia> names(Main, imported=true)
8-element Vector{Symbol}:
 :Base
 :Core
 :InteractiveUtils
 :Main
 :Pkg
 :Statistics
 :eval
 :include

(Note that names itself does not print anything — it returns an array of the symbols. When you evaluate this in the REPL, it calls display(...) on the return value, which prints the text output as above. You can also call display or print or some other I/O function yourself on the return value.)

2 Likes

you are using import Statistics, try it with using Statistics.
It is really surprising

1 Like

From the docs:

If imported is true, then names explicitly imported from other modules are also included.

julia> import Statistics: mean

julia> names(Main, imported=true)
8-element Vector{Symbol}:
 :Base
 :Core
 :InteractiveUtils
 :Main
 :Pkg
 :eval
 :include
 :mean

That is, you have to import the name explicitly, not just be using it.

So, I agree, this is not what you want. The REPLCompletions module seems to call the internal function jl_module_usings in order to also fetch symbols imported by using, as you noted above.

You can call the REPLCompletions module, I guess, but this also relies on undocumented internals:

using REPL: REPLCompletions
REPLCompletions.complete_symbol(nothing, "", (mod, s) -> true, Main)
4 Likes

names treats Main specially so it does show up:

julia> using Statistics

julia> names(Main; all=true,imported=true)
8-element Vector{Symbol}:
 Symbol("##meta#58")
 :Base
 :Core
 :InteractiveUtils
 :Main
 :Statistics
 :eval
 :include

Here’s an example for a different module:

julia> module A using Statistics end; # avoid Main because treated specially

julia> names(A; all=true,imported=true)
5-element Vector{Symbol}:
 Symbol("#eval")
 Symbol("#include")
 :A
 :eval
 :include

julia> module A import Statistics end; # avoid Main because treated specially
WARNING: replacing module A.

julia> names(A; all=true,imported=true)
6-element Vector{Symbol}:
 Symbol("#eval")
 Symbol("#include")
 :A
 :Statistics
 :eval
 :include

julia> module A using Statistics: Statistics, mean; s = mean(1:5) + Statistics.var(1:3) end; # avoid Main because treated specially
WARNING: replacing module A.

julia> names(A; all=true, imported=true)
6-element Vector{Symbol}:
 Symbol("#eval")
 Symbol("#include")
 :A
 :eval
 :include
 :s

julia> module A import Statistics: Statistics, mean; s = mean(1:5) + Statistics.var(1:3) end; # avoid Main because treated specially
WARNING: replacing module A.

julia> names(A; all=true, imported=true)
8-element Vector{Symbol}:
 Symbol("#eval")
 Symbol("#include")
 :A
 :Statistics
 :eval
 :include
 :mean
 :s

Is there a good reason for this? I’m surprised that names imported by import and using are even delineated so strictly because colon-specified names and the module names in bare using/import statements can’t be shadowed like the export list names accessed by bare using statements. I’d consider the former to be essentially explicit imports, and like schlictsanders I think they should be reported by the imported=true option, especially the modules in bare using statements because I’d need to use names to check their export lists the most. I’d also prefer if the imported=true option reported any names from bare using statements after they were accessed and thus made unshadowable, but those imports don’t seem explicit in any sense.

2 Likes

imported names are treated very differently for method definitions.

I guess the basic issue here is that people mostly use names to obtain the API defined in a module, and it’s rare that they want to pull in 1000+ additional symbols defined in Base etcetera. But it would be nice to have that option.

That link doesn’t involve imports, but do you mean how function names from import statements don’t need module name qualification to add methods?

That’s true, I’d probably just want to check the already accessed, implicitly imported symbols at the most. Still, I’d think using Base itself should let Base show up, and using Base: +, ^ should let + and ^ show up, just like if I used the import keyword. Those don’t risk unintended bloat. Those 1000+ symbols can be checked with names(Base), so if names(A;imported=true) reported Base, that’ll be enough for me to know what to check further. Or perhaps bare using Base should be reported under another keyword option for that purpose, it’s not like I need to check names(+).

Getting names from “used” modules.


module M1
    f1(x) = x
    f2(x) = 2x
    export f2
end

module M3
    f3(x) = 3x
    export f3
end

module M2
using ..M1, ..M3
    mods = ccall(:jl_module_usings, Any, (Any,), @__MODULE__)::Vector
    setdiff!(mods, [Base, Core])
    mnames = [string(m) => names(m) for m in mods]
    @show mnames
end 

julia> 
mnames = ["Main.M3" => [:M3, :f3], "Main.M1" => [:M1, :f2]]

anybody knows, is there any way to get also variable names imported like following?

using Unitful: Na 

names wouldn’t list them, and jl_module_usings only list modules.

1 Like