From e6c789ab80821bd855ef6cff690ed48cf78c0e2f Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Tue, 31 Jul 2018 11:51:49 -0400 Subject: [PATCH] add pathof(::Module) (#28310) --- NEWS.md | 2 ++ base/exports.jl | 1 + base/loading.jl | 12 ++++++++++++ doc/src/base/base.md | 1 + stdlib/Pkg/src/API.jl | 10 +++++----- test/loading.jl | 8 ++++++++ 6 files changed, 29 insertions(+), 5 deletions(-) diff --git a/NEWS.md b/NEWS.md index 3a753e812ca37..ae8aae50a88d9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -549,6 +549,8 @@ Library improvements * `Char` is now a subtype of `AbstractChar`, and most of the functions that take character arguments now accept any `AbstractChar` ([#26286]). + * `pathof(module)` returns the path a module was imported from ([#28310]). + * `bytes2hex` now accepts an optional `io` argument to output to a hexadecimal stream without allocating a `String` first ([#27121]). diff --git a/base/exports.jl b/base/exports.jl index 73e11eb65ddec..d979ec2080be2 100644 --- a/base/exports.jl +++ b/base/exports.jl @@ -739,6 +739,7 @@ export methods, nameof, parentmodule, + pathof, names, which, @isdefined, diff --git a/base/loading.jl b/base/loading.jl index 1bca9ee0b1049..00c6c4e02fbae 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -249,6 +249,18 @@ function locate_package(pkg::PkgId)::Union{Nothing,String} end locate_package(::Nothing) = nothing +""" + pathof(m::Module) + +Return the path of `m.jl` file that was used to `import` module `m`, +or `nothing` if `m` was not imported from a package. +""" +function pathof(m::Module) + pkgid = get(Base.module_keys, m, nothing) + pkgid === nothing && return nothing + return Base.locate_package(pkgid) +end + ## generic project & manifest API ## const project_names = ("JuliaProject.toml", "Project.toml") diff --git a/doc/src/base/base.md b/doc/src/base/base.md index d2a6dd168c875..33554927d5a4a 100644 --- a/doc/src/base/base.md +++ b/doc/src/base/base.md @@ -332,6 +332,7 @@ Base.AsyncCondition(::Function) ```@docs Base.nameof(::Module) Base.parentmodule +Base.pathof(::Module) Base.moduleroot Base.@__MODULE__ Base.fullname diff --git a/stdlib/Pkg/src/API.jl b/stdlib/Pkg/src/API.jl index af6e35729cb52..afdc7e9c4e2bc 100644 --- a/stdlib/Pkg/src/API.jl +++ b/stdlib/Pkg/src/API.jl @@ -432,13 +432,13 @@ function clone(url::String, name::String = "") develop(ctx, [Pkg.REPLMode.parse_package(url; add_or_develop=true)]) end -function dir(pkg::String, paths::String...) - @warn "Pkg.dir is only kept for legacy CI script reasons" maxlog=1 +function dir(pkg::String, paths::AbstractString...) + @warn "`Pkg.dir(pkgname, paths...)` is deprecated; instead, do `import $pkg; joinpath(dirname(pathof($pkg)), \"..\", paths...)`." maxlog=1 pkgid = Base.identify_package(pkg) - pkgid == nothing && return nothing + pkgid === nothing && return nothing path = Base.locate_package(pkgid) - pkgid == nothing && return nothing - return joinpath(abspath(path, "..", "..", paths...)) + path === nothing && return nothing + return abspath(path, "..", "..", paths...) end precompile() = precompile(Context()) diff --git a/test/loading.jl b/test/loading.jl index 0517511d66e18..289c25e582b0a 100644 --- a/test/loading.jl +++ b/test/loading.jl @@ -218,6 +218,8 @@ Base.ACTIVE_PROJECT[] = nothing end end +module NotPkgModule; end + @testset "project & manifest import" begin @test !@isdefined Foo @test !@isdefined Bar @@ -254,6 +256,12 @@ end end end @test Foo.which == "path" + + @testset "pathof" begin + @test pathof(Foo) == normpath(abspath(@__DIR__, "project/deps/Foo1/src/Foo.jl")) + @test pathof(NotPkgModule) === nothing + end + end ## systematic generation of test environments ##