How to use Pkg.dependencies() instead of Pkg.installed()

From Julia v1.4, Pkg.installed() shows deprecation message.
Using Pkg.dependencies() is recommended instead of Pkg.installed() in this issue:

However, Pkg.dependencies return all packages, not top level packages like Pkg.installed.
How can I get same results using Pkg.dependencies instead of Pkg.installed?

2 Likes

Just take a look at the current implementation of Pkg.installed():


function installed()
    @warn "Pkg.installed() is deprecated"
    deps = dependencies()
    installs = Dict{String, VersionNumber}()
    for (uuid, dep) in deps
        dep.is_direct_dep || continue
        dep.version === nothing && continue
        installs[dep.name] = dep.version
    end
    return installs
end

You just need to look at the field is_direct_dep :smile:.

5 Likes

Why do you need Pkg.installed()?

Oh. Great!!. Your answer is totally what I want!!

Sometimes, I want to check a certain package is installed or not in a Julia script for dependency management.

For such cases Requires is also super helpful by the way:

2 Likes

So, what is the best way to check if a package is already installed ? I often want to say “If package xxx is not present, add it”.

In my system:

haskey(Pkg.installed(), "StatsPlots") # true
haskey(Pkg.dependencies(), "StatsPlots") #false

Use the UUID of StatsPlots as the key instead.

1 Like

Thank you, I found it:

haskey(Pkg.installed(), "StatsPlots") # true
haskey(Pkg.dependencies(), Base.UUID("f3b207a7-027a-5e70-b257-86293d7955fd")) # true

However on a usability prospective it is terrible, it is a regression compared to the first line… I need to know what a UUID is, where to find it,…

Why Pkg.installed(PackageName) has been deprecated ? Shouldn’t be a higher-level function like it (or better Pkg.isavailable("PackageName"), returning directly a bool ) made available ?

The first one had the problem in that it only showed packages that were direct dependencies. It’s API was fundamentally incompatible with showing packages in the manifest since you can have multiple packages with the same name there and the key for installed was the package name. To have an API that gives information about all dependencies (including recursive) you pretty much must use the UUID as the key since that is what identifies the package.

You can however easily recreate the old API as:

isinstalled(pkg::String) = any(x -> x.name == pkg && x.is_direct_dep, values(Pkg.dependencies()))

Note that this only checks if a package with the name pkg is installed, not that it actually is the package you want.

2 Likes

But I am interested in just knowing if a package is already available for using or not.

If name collision is a (remote, i.e. not possible if you just use the standard repository) possibility one could have just a function that returns the number of available packages by name and then use it as:

if Pkg.availablecount("pkgName") == 0
  Pkg.add("pkgName")
elseif Pkg.availablecount("pkgName") > 1
  @error "More than one package is available with the given name. Please use UUID"
end

using pkgName

You can use the snippet I gave you then.

It’s also possible to just try to use it and do something in a catch:

try
    using Foo
catch
   # do something
end
2 Likes