Skip to content

Commit 1826335

Browse files
authored
deprecate whos to varinfo returning a markdown table. fixes #12131. (#24671)
1 parent 5dcb44a commit 1826335

File tree

10 files changed

+62
-72
lines changed

10 files changed

+62
-72
lines changed

NEWS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,9 @@ Deprecated or removed
419419
* Using Bool values directly as indices is now deprecated and will be an error in the future. Convert
420420
them to `Int` before indexing if you intend to access index `1` for `true` and `0` for `false`.
421421

422+
* `whos` has been renamed `varinfo`, and now returns a markdown table instead of printing
423+
output ([#12131]).
424+
422425
* `writecsv(io, a; opts...)` has been deprecated in favor of
423426
`writedlm(io, a, ','; opts...)` ([#23529]).
424427

base/deprecated.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1842,6 +1842,14 @@ end
18421842
nothing
18431843
end
18441844

1845+
@deprecate whos(io::IO, m::Module, pat::Regex) show(io, varinfo(m, pat))
1846+
@deprecate whos(io::IO, m::Module) show(io, varinfo(m))
1847+
@deprecate whos(io::IO) show(io, varinfo())
1848+
@deprecate whos(m::Module, pat::Regex) varinfo(m, pat)
1849+
@deprecate whos(m::Module) varinfo(m)
1850+
@deprecate whos(pat::Regex) varinfo(pat)
1851+
@deprecate whos() varinfo()
1852+
18451853
# indexing with A[true] will throw an argument error in the future
18461854
function to_index(i::Bool)
18471855
depwarn("indexing with Bool values is deprecated. Convert the index to an integer first with `Int(i)`.", (:getindex, :setindex!, :view))

base/exports.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -953,9 +953,9 @@ export
953953
module_name,
954954
module_parent,
955955
names,
956+
varinfo,
956957
versioninfo,
957958
which,
958-
whos,
959959
workspace,
960960
@isdefined,
961961

base/interactiveutil.jl

Lines changed: 15 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -731,54 +731,24 @@ end
731731

732732

733733
"""
734-
whos(io::IO=STDOUT, m::Module=Main, pattern::Regex=r"")
734+
varinfo(m::Module=Main, pattern::Regex=r"")
735735
736-
Print information about exported global variables in a module, optionally restricted to those matching `pattern`.
736+
Return a markdown table giving information about exported global variables in a module, optionally restricted
737+
to those matching `pattern`.
737738
738739
The memory consumption estimate is an approximate lower bound on the size of the internal structure of the object.
739740
"""
740-
function whos(io::IO=STDOUT, m::Module=Main, pattern::Regex=r"")
741-
maxline = displaysize(io)[2]
742-
line = zeros(UInt8, maxline)
743-
head = PipeBuffer(maxline + 1)
744-
for v in sort!(names(m))
745-
s = string(v)
746-
if isdefined(m, v) && ismatch(pattern, s)
747-
value = getfield(m, v)
748-
@printf head "%30s " s
749-
try
750-
if value (Base, Main, Core)
751-
print(head, " ")
752-
else
753-
bytes = summarysize(value)
754-
if bytes < 10_000
755-
@printf(head, "%6d bytes ", bytes)
756-
else
757-
@printf(head, "%6d KB ", bytes ÷ (1024))
758-
end
759-
end
760-
print(head, summary(value))
761-
catch e
762-
print(head, "#=ERROR: unable to show value=#")
763-
end
764-
newline = search(head, UInt8('\n')) - 1
765-
if newline < 0
766-
newline = nb_available(head)
767-
end
768-
if newline > maxline
769-
newline = maxline - 1 # make space for ...
770-
end
771-
line = resize!(line, newline)
772-
line = read!(head, line)
741+
function varinfo(m::Module=Main, pattern::Regex=r"")
742+
rows =
743+
Any[ let value = getfield(m, v)
744+
Any[string(v),
745+
(value (Base, Main, Core) ? "" : format_bytes(summarysize(value))),
746+
summary(value)]
747+
end
748+
for v in sort!(names(m)) if isdefined(m, v) && ismatch(pattern, string(v)) ]
773749

774-
write(io, line)
775-
if nb_available(head) > 0 # more to read? replace with ...
776-
print(io, '\u2026') # hdots
777-
end
778-
println(io)
779-
seekend(head) # skip the rest of the text
780-
end
781-
end
750+
unshift!(rows, Any["name", "size", "summary"])
751+
752+
return Markdown.MD(Any[Markdown.Table(rows, Symbol[:l, :r, :l])])
782753
end
783-
whos(m::Module, pat::Regex=r"") = whos(STDOUT, m, pat)
784-
whos(pat::Regex) = whos(STDOUT, Main, pat)
754+
varinfo(pat::Regex) = varinfo(Main, pat)

base/util.jl

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,21 +96,25 @@ function padded_nonzero_print(value,str)
9696
end
9797
end
9898

99+
function format_bytes(bytes)
100+
bytes, mb = prettyprint_getunits(bytes, length(_mem_units), Int64(1024))
101+
if mb == 1
102+
@sprintf("%d %s%s", bytes, _mem_units[mb], bytes==1 ? "" : "s")
103+
else
104+
@sprintf("%.3f %s", bytes, _mem_units[mb])
105+
end
106+
end
107+
99108
function time_print(elapsedtime, bytes, gctime, allocs)
100109
@printf("%10.6f seconds", elapsedtime/1e9)
101110
if bytes != 0 || allocs != 0
102-
bytes, mb = prettyprint_getunits(bytes, length(_mem_units), Int64(1024))
103111
allocs, ma = prettyprint_getunits(allocs, length(_cnt_units), Int64(1000))
104112
if ma == 1
105113
@printf(" (%d%s allocation%s: ", allocs, _cnt_units[ma], allocs==1 ? "" : "s")
106114
else
107115
@printf(" (%.2f%s allocations: ", allocs, _cnt_units[ma])
108116
end
109-
if mb == 1
110-
@printf("%d %s%s", bytes, _mem_units[mb], bytes==1 ? "" : "s")
111-
else
112-
@printf("%.3f %s", bytes, _mem_units[mb])
113-
end
117+
print(format_bytes(bytes))
114118
if gctime > 0
115119
@printf(", %.2f%% gc time", 100*gctime/elapsedtime)
116120
end

doc/src/manual/faq.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -566,12 +566,13 @@ julia> gvar_self = "Node1"
566566
julia> remotecall_fetch(()->gvar_self, 2)
567567
"Node1"
568568
569-
julia> remotecall_fetch(whos, 2)
570-
From worker 2: Base 41762 KB Module
571-
From worker 2: Core 27337 KB Module
572-
From worker 2: Foo 2477 bytes Module
573-
From worker 2: Main 46191 KB Module
574-
From worker 2: gvar_self 13 bytes String
569+
julia> remotecall_fetch(varinfo, 2)
570+
name size summary
571+
––––––––– –––––––– –––––––
572+
Base Module
573+
Core Module
574+
Main Module
575+
gvar_self 13 bytes String
575576
```
576577

577578
This does not apply to `function` or `type` declarations. However, anonymous functions bound to global

doc/src/manual/modules.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ end
119119
There are three important standard modules: Main, Core, and Base.
120120

121121
Main is the top-level module, and Julia starts with Main set as the current module. Variables
122-
defined at the prompt go in Main, and `whos()` lists variables in Main.
122+
defined at the prompt go in Main, and `varinfo()` lists variables in Main.
123123

124124
Core contains all identifiers considered "built in" to the language, i.e. part of the core language
125125
and not libraries. Every module implicitly specifies `using Core`, since you can't do anything

doc/src/manual/parallel-computing.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -312,12 +312,13 @@ julia> let B = B
312312
remotecall_fetch(()->B, 2)
313313
end;
314314
315-
julia> @spawnat 2 whos();
316-
317-
julia> From worker 2: A 800 bytes 10×10 Array{Float64,2}
318-
From worker 2: Base Module
319-
From worker 2: Core Module
320-
From worker 2: Main Module
315+
julia> @fetchfrom 2 varinfo()
316+
name size summary
317+
––––––––– ––––––––– ––––––––––––––––––––––
318+
A 800 bytes 10×10 Array{Float64,2}
319+
Base Module
320+
Core Module
321+
Main Module
321322
```
322323

323324
As can be seen, global variable `A` is defined on worker 2, but `B` is captured as a local variable

doc/src/stdlib/base.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Base.quit
2323
Base.atexit
2424
Base.atreplinit
2525
Base.isinteractive
26-
Base.whos
26+
Base.varinfo
2727
Base.summarysize
2828
Base.edit(::AbstractString, ::Integer)
2929
Base.edit(::Any)

test/misc.jl

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -327,13 +327,16 @@ let R = Ref{Any}(nothing), depth = 10^6
327327
@test summarysize(R) == (depth + 4) * sizeof(Ptr)
328328
end
329329

330-
module _test_whos_
330+
module _test_varinfo_
331331
export x
332332
x = 1.0
333333
end
334-
@test sprint(whos, Main, r"^$") == ""
335-
let v = sprint(whos, _test_whos_)
336-
@test contains(v, "x 8 bytes Float64")
334+
@test repr(varinfo(Main, r"^$")) == """
335+
| name | size | summary |
336+
|:---- | ----:|:------- |
337+
"""
338+
let v = repr(varinfo(_test_varinfo_))
339+
@test contains(v, "| x | 8 bytes | Float64 |")
337340
end
338341

339342
# issue #13021
@@ -351,9 +354,9 @@ module Tmp14173
351354
export A
352355
A = randn(2000, 2000)
353356
end
354-
whos(IOBuffer(), Tmp14173) # warm up
357+
varinfo(Tmp14173) # warm up
355358
const MEMDEBUG = ccall(:jl_is_memdebug, Bool, ())
356-
@test @allocated(whos(IOBuffer(), Tmp14173)) < (MEMDEBUG ? 30000 : 10000)
359+
@test @allocated(varinfo(Tmp14173)) < (MEMDEBUG ? 60000 : 20000)
357360

358361
## test conversion from UTF-8 to UTF-16 (for Windows APIs)
359362

0 commit comments

Comments
 (0)