Skip to content

Commit 76ac73b

Browse files
committed
Add the InteractiveUtils.diagnostics() function
1 parent 983598a commit 76ac73b

File tree

6 files changed

+111
-2
lines changed

6 files changed

+111
-2
lines changed

stdlib/InteractiveUtils/src/InteractiveUtils.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ include("editless.jl")
1919
include("codeview.jl")
2020
include("macros.jl")
2121
include("clipboard.jl")
22+
include("diagnostics.jl")
2223

2324
"""
2425
varinfo(m::Module=Main, pattern::Regex=r""; all::Bool = false, imported::Bool = false, sortby::Symbol = :name, minsize::Int = 0)
@@ -163,7 +164,6 @@ function versioninfo(io::IO=stdout; verbose::Bool=false)
163164
end
164165
end
165166

166-
167167
function type_close_enough(@nospecialize(x), @nospecialize(t))
168168
x == t && return true
169169
# TODO: handle UnionAll properly
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
"""
2+
InteractiveUtils.diagnostics(io::IO=stderr)
3+
4+
Print a variety of useful debugging info.
5+
6+
!!! warning "Warning"
7+
The output of this function may contain sensitive information. Before sharing the output,
8+
please review the output and remove any data that should not be shared publicly.
9+
10+
See also: [`versioninfo`](@ref).
11+
"""
12+
function diagnostics(io::IO=stderr)
13+
loaded_modules = copy(Base.loaded_modules_array())
14+
sort!(loaded_modules; by = nameof)
15+
loaded_names = nameof.(loaded_modules)
16+
for m in loaded_modules
17+
_module_diagnostics(io, m)
18+
end
19+
return nothing
20+
end
21+
22+
function _module_diagnostics(io::IO, m::Module)
23+
module_name = nameof(m)
24+
if isdefined(m, :__diagnostics__) && applicable(m.__diagnostics__, io)
25+
header = "# $(module_name)"
26+
println(io, header)
27+
try
28+
m.__diagnostics__(io)
29+
catch ex
30+
bt = catch_backtrace()
31+
msg = "Warning: encountered an error while running $(module_name).__diagnostics__()"
32+
println(io, msg)
33+
Base.showerror(io, ex)
34+
Base.show_backtrace(io, bt)
35+
end
36+
end
37+
return nothing
38+
end
39+
40+
# InteractiveUtils.__diagnostics__()
41+
function __diagnostics__(io::IO)
42+
indent = " "
43+
versioninfo(io; verbose = true) # InteractiveUtils.versioninfo()
44+
println(io, "Miscellaneous Info:")
45+
if !_is_tagged_commit()
46+
println(io, "It looks like you are probably not using the official binaries from julialang.org")
47+
end
48+
startup_files = [
49+
"Global" => _global_julia_startup_file(),
50+
"Local" => _local_julia_startup_file(),
51+
]
52+
for pair in startup_files
53+
filename = pair[2]
54+
if filename === nothing
55+
description = "does not exist"
56+
else
57+
str = strip(read(filename, String))
58+
expr = Base.Meta.parse(str; raise = false)
59+
if expr === nothing
60+
description = "is empty"
61+
else
62+
description = "exists and contains code ($(filename))"
63+
end
64+
end
65+
println(io, indent, pair[1], " startup file: ", description)
66+
end
67+
println(io, indent, "Base.julia_cmd(): ", Base.julia_cmd())
68+
return nothing
69+
end
70+
71+
# We can't say with 100% certainty whether or not this is the official binary
72+
# from julialang.org, but we can make an educated guess.
73+
function _is_tagged_commit()
74+
tagged_commit = Base.GIT_VERSION_INFO.tagged_commit
75+
if !tagged_commit
76+
return false
77+
end
78+
banner = Base.TAGGED_RELEASE_BANNER
79+
if banner == "Official https://julialang.org/ release"
80+
return true
81+
end
82+
return false
83+
end

stdlib/InteractiveUtils/test/runtests.jl

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ module A
222222
end
223223

224224
# PR #23075
225-
@testset "versioninfo" begin
225+
@testset "versioninfo()" begin
226226
# check that versioninfo(io; verbose=true) doesn't error, produces some output
227227
mktempdir() do dir
228228
buf = PipeBuffer()
@@ -239,6 +239,17 @@ end
239239
end
240240
end
241241

242+
@testset "diagnostics()" begin
243+
# check that diagnostics(io) doesn't error, produces some output
244+
buf = PipeBuffer()
245+
InteractiveUtils.diagnostics(buf)
246+
output = read(buf, String)
247+
@test occursin("Julia Version $VERSION", output)
248+
@test occursin("Environment:", ver)
249+
250+
InteractiveUtils.diagnostics(stdout) # TODO: delete this line before merging the PR
251+
end
252+
242253
const curmod = @__MODULE__
243254
const curmod_name = fullname(curmod)
244255
const curmod_str = curmod === Main ? "Main" : join(curmod_name, ".")
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# LinearAlgebra.__diagnostics__()
2+
function __diagnostics__(io::IO)
3+
versioninfo(io) # LinearAlgebra.versioninfo()
4+
return nothing
5+
end
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
@testset "__diagnostics__()" begin
2+
# check that `LinearAlgebra.__diagnostics__(io)` doesn't error, produces some output
3+
buf = PipeBuffer()
4+
LinearAlgebra.__diagnostics__(buf)
5+
output = read(buf, String)
6+
@test !isempty(strip(output))
7+
8+
NetworkOptions.__diagnostics__(stdout) # TODO: delete this line before merging the PR
9+
end

stdlib/LinearAlgebra/test/testgroups

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,4 @@ structuredbroadcast
2626
addmul
2727
ldlt
2828
factorization
29+
diagnostics

0 commit comments

Comments
 (0)