• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37527

pending completion
#37527

push

local

web-flow
make `IRShow.method_name` inferrable (#49607)

18 of 18 new or added lines in 3 files covered. (100.0%)

68710 of 81829 relevant lines covered (83.97%)

33068903.12 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

43.01
/base/multimedia.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
module Multimedia
4

5
import .Base: show, print, convert, repr
6

7
export AbstractDisplay, display, pushdisplay, popdisplay, displayable, redisplay,
8
    MIME, @MIME_str, istextmime,
9
    showable, TextDisplay
10

11
###########################################################################
12
# We define a singleton type MIME{mime symbol} for each MIME type, so
13
# that Julia's dispatch and overloading mechanisms can be used to
14
# dispatch show and to add conversions for new types.
15

16
"""
17
    MIME
18

19
A type representing a standard internet data format. "MIME" stands for
20
"Multipurpose Internet Mail Extensions", since the standard was originally
21
used to describe multimedia attachments to email messages.
22

23
A `MIME` object can be passed as the second argument to [`show`](@ref) to
24
request output in that format.
25

26
# Examples
27
```jldoctest
28
julia> show(stdout, MIME("text/plain"), "hi")
29
"hi"
30
```
31
"""
32
struct MIME{mime} end
114,739✔
33

34
"""
35
    @MIME_str
36

37
A convenience macro for writing [`MIME`](@ref) types, typically used when
38
adding methods to [`show`](@ref).
39
For example the syntax `show(io::IO, ::MIME"text/html", x::MyType) = ...`
40
could be used to define how to write an HTML representation of `MyType`.
41
"""
42
macro MIME_str(s)
65✔
43
    :(MIME{$(Expr(:quote, Symbol(s)))})
65✔
44
end
45

46
# fallback text/plain representation of any type:
47
show(io::IO, ::MIME"text/plain", x) = show(io, x)
113,336✔
48

49
MIME(s) = MIME{Symbol(s)}()
114,854✔
50
show(io::IO, ::MIME{mime}) where {mime} = print(io, "MIME type ", string(mime))
1✔
51
print(io::IO, ::MIME{mime}) where {mime} = print(io, mime)
71✔
52

53
###########################################################################
54
# For any type T one can define show(io, ::MIME"type", x::T) = ...
55
# in order to provide a way to export T as a given mime type.
56

57
"""
58
    showable(mime, x)
59

60
Return a boolean value indicating whether or not the object `x` can be written
61
as the given `mime` type.
62

63
(By default, this is determined automatically by the existence of the
64
corresponding [`show`](@ref) method for `typeof(x)`.  Some types provide custom `showable`
65
methods; for example, if the available MIME formats depend on the *value* of `x`.)
66

67
# Examples
68
```jldoctest
69
julia> showable(MIME("text/plain"), rand(5))
70
true
71

72
julia> showable("image/png", rand(5))
73
false
74
```
75
"""
76
showable(::MIME{mime}, @nospecialize x) where {mime} = hasmethod(show, Tuple{IO, MIME{mime}, typeof(x)})
117✔
77
showable(m::AbstractString, @nospecialize x) = showable(MIME(m), x)
117✔
78

79
"""
80
    show(io::IO, mime, x)
81

82
The [`display`](@ref) functions ultimately call `show` in order to write an object `x` as a
83
given `mime` type to a given I/O stream `io` (usually a memory buffer), if possible. In order
84
to provide a rich multimedia representation of a user-defined type `T`, it is only necessary
85
to define a new `show` method for `T`, via: `show(io, ::MIME"mime", x::T) = ...`,
86
where `mime` is a MIME-type string and the function body calls [`write`](@ref) (or similar) to write
87
that representation of `x` to `io`. (Note that the `MIME""` notation only supports
88
literal strings; to construct `MIME` types in a more flexible manner use
89
`MIME{Symbol("")}`.)
90

91
For example, if you define a `MyImage` type and know how to write it to a PNG file, you
92
could define a function `show(io, ::MIME"image/png", x::MyImage) = ...` to allow
93
your images to be displayed on any PNG-capable `AbstractDisplay` (such as IJulia). As usual, be sure
94
to `import Base.show` in order to add new methods to the built-in Julia function
95
`show`.
96

97
Technically, the `MIME"mime"` macro defines a singleton type for the given `mime` string,
98
which allows us to exploit Julia's dispatch mechanisms in determining how to display objects
99
of any given type.
100

101
The default MIME type is `MIME"text/plain"`. There is a fallback definition for `text/plain`
102
output that calls `show` with 2 arguments, so it is not always necessary to add a method
103
for that case. If a type benefits from custom human-readable output though,
104
`show(::IO, ::MIME"text/plain", ::T)` should be defined. For example, the `Day` type uses
105
`1 day` as the output for the `text/plain` MIME type, and `Day(1)` as the output of 2-argument `show`.
106

107
# Examples
108
```jldoctest
109
julia> struct Day
110
           n::Int
111
       end
112

113
julia> Base.show(io::IO, ::MIME"text/plain", d::Day) = print(io, d.n, " day")
114

115
julia> Day(1)
116
1 day
117
```
118

119
Container types generally implement 3-argument `show` by calling `show(io, MIME"text/plain"(), x)`
120
for elements `x`, with `:compact => true` set in an [`IOContext`](@ref) passed as the first argument.
121
"""
122
show(stream::IO, mime, x)
123
show(io::IO, m::AbstractString, x) = show(io, MIME(m), x)
114,350✔
124

125
"""
126
    repr(mime, x; context=nothing)
127

128
Return an `AbstractString` or `Vector{UInt8}` containing the representation of
129
`x` in the requested `mime` type, as written by [`show(io, mime, x)`](@ref) (throwing a
130
[`MethodError`](@ref) if no appropriate `show` is available). An `AbstractString` is
131
returned for MIME types with textual representations (such as `"text/html"` or
132
`"application/postscript"`), whereas binary data is returned as
133
`Vector{UInt8}`. (The function `istextmime(mime)` returns whether or not Julia
134
treats a given `mime` type as text.)
135

136
The optional keyword argument `context` can be set to `:key=>value` pair
137
or an `IO` or [`IOContext`](@ref) object whose attributes are used for the I/O
138
stream passed to `show`.
139

140
As a special case, if `x` is an `AbstractString` (for textual MIME types) or a
141
`Vector{UInt8}` (for binary MIME types), the `repr` function assumes that
142
`x` is already in the requested `mime` format and simply returns `x`. This
143
special case does not apply to the `"text/plain"` MIME type. This is useful so
144
that raw data can be passed to `display(m::MIME, x)`.
145

146
In particular, `repr("text/plain", x)` is typically a "pretty-printed" version
147
of `x` designed for human consumption.  See also [`repr(x)`](@ref) to instead
148
return a string corresponding to [`show(x)`](@ref) that may be closer to how
149
the value of `x` would be entered in Julia.
150

151
# Examples
152
```jldoctest
153
julia> A = [1 2; 3 4];
154

155
julia> repr("text/plain", A)
156
"2×2 Matrix{Int64}:\\n 1  2\\n 3  4"
157
```
158
"""
159
repr(m::MIME, x; context=nothing) = istextmime(m) ? _textrepr(m, x, context) : _binrepr(m, x, context)
94✔
160
repr(m::AbstractString, x; context=nothing) = repr(MIME(m), x; context=context)
82✔
161

162
# strings are shown escaped for text/plain
163
_textrepr(m::MIME, x, context) = String(__binrepr(m, x, context))
46✔
164
_textrepr(::MIME, x::AbstractString, context) = x
2✔
165
_textrepr(m::MIME"text/plain", x::AbstractString, context) = String(__binrepr(m, x, context))
3✔
166

167

168
function __binrepr(m::MIME, x, context)
49✔
169
    s = IOBuffer()
49✔
170
    if context === nothing
49✔
171
        show(s, m, x)
44✔
172
    else
173
        show(IOContext(s, context), m, x)
7✔
174
    end
175
    take!(s)
49✔
176
end
177
_binrepr(m::MIME, x, context) = __binrepr(m, x, context)
×
178
_binrepr(m::MIME, x::Vector{UInt8}, context) = x
1✔
179

180
"""
181
    istextmime(m::MIME)
182

183
Determine whether a MIME type is text data. MIME types are assumed to be binary
184
data except for a set of types known to be text data (possibly Unicode).
185

186
# Examples
187
```jldoctest
188
julia> istextmime(MIME("text/plain"))
189
true
190

191
julia> istextmime(MIME("image/png"))
192
false
193
```
194
"""
195
istextmime(m::MIME) = startswith(string(m), "text/")
57✔
196
istextmime(m::AbstractString) = istextmime(MIME(m))
×
197

198
for mime in ["application/atom+xml", "application/ecmascript",
199
             "application/javascript", "application/julia",
200
             "application/json", "application/postscript",
201
             "application/rdf+xml", "application/rss+xml",
202
             "application/x-latex", "application/xhtml+xml", "application/xml",
203
             "application/xml-dtd", "image/svg+xml", "model/vrml",
204
             "model/x3d+vrml", "model/x3d+xml"]
205
    global istextmime(::MIME{Symbol(mime)}) = true
×
206
end
207

208
###########################################################################
209
# We have an abstract AbstractDisplay class that can be subclassed in order to
210
# define new rich-display output devices.  A typical subclass should
211
# overload display(d::AbstractDisplay, m::MIME, x) for supported MIME types m,
212
# (typically using show, repr, ..., to get the MIME
213
# representation of x) and should also overload display(d::AbstractDisplay, x)
214
# to display x in whatever MIME type is preferred by the AbstractDisplay and
215
# is writable by x.  display(..., x) should throw a MethodError if x
216
# cannot be displayed.  The return value of display(...) is up to the
217
# AbstractDisplay type.
218

219
"""
220
    AbstractDisplay
221

222
Abstract supertype for rich display output devices. [`TextDisplay`](@ref) is a subtype
223
of this.
224
"""
225
abstract type AbstractDisplay end
226

227
# it is convenient to accept strings instead of ::MIME
228
display(d::AbstractDisplay, mime::AbstractString, @nospecialize x) = display(d, MIME(mime), x)
2✔
229
display(mime::AbstractString, @nospecialize x) = display(MIME(mime), x)
×
230

231
"""
232
    displayable(mime) -> Bool
233
    displayable(d::AbstractDisplay, mime) -> Bool
234

235
Return a boolean value indicating whether the given `mime` type (string) is displayable by
236
any of the displays in the current display stack, or specifically by the display `d` in the
237
second variant.
238
"""
239
displayable(d::AbstractDisplay, mime::AbstractString) = displayable(d, MIME(mime))
×
240
displayable(mime::AbstractString) = displayable(MIME(mime))
×
241

242
# simplest display, which only knows how to display text/plain
243

244
"""
245
    TextDisplay(io::IO)
246

247
Return a `TextDisplay <: AbstractDisplay`, which displays any object as the text/plain MIME type
248
(by default), writing the text representation to the given I/O stream. (This is how
249
objects are printed in the Julia REPL.)
250
"""
251
struct TextDisplay <: AbstractDisplay
252
    io::IO
899✔
253
end
254
display(d::TextDisplay, M::MIME"text/plain", @nospecialize x) = (show(d.io, M, x); println(d.io))
16✔
255
display(d::TextDisplay, @nospecialize x) = display(d, MIME"text/plain"(), x)
8✔
256

257
# if you explicitly call display("text/foo", x), it should work on a TextDisplay:
258
displayable(d::TextDisplay, M::MIME) = istextmime(M)
2✔
259
function display(d::TextDisplay, M::MIME, @nospecialize x)
2✔
260
    displayable(d, M) || throw(MethodError(display, (d, M, x)))
2✔
261
    show(d.io, M, x); println(d.io)
2✔
262
end
263

264
import Base: close, flush
265
flush(d::TextDisplay) = flush(d.io)
×
266
close(d::TextDisplay) = close(d.io)
×
267

268
###########################################################################
269
# We keep a stack of Displays, and calling display(x) uses the topmost
270
# AbstractDisplay that is capable of displaying x (doesn't throw an error)
271

272
const displays = AbstractDisplay[]
273

274
"""
275
    pushdisplay(d::AbstractDisplay)
276

277
Pushes a new display `d` on top of the global display-backend stack. Calling `display(x)` or
278
`display(mime, x)` will display `x` on the topmost compatible backend in the stack (i.e.,
279
the topmost backend that does not throw a [`MethodError`](@ref)).
280
"""
281
function pushdisplay(d::AbstractDisplay)
×
282
    global displays
×
283
    push!(displays, d)
449✔
284
end
285

286
"""
287
    popdisplay()
288
    popdisplay(d::AbstractDisplay)
289

290
Pop the topmost backend off of the display-backend stack, or the topmost copy of `d` in the
291
second variant.
292
"""
293
popdisplay() = pop!(displays)
×
294
function popdisplay(d::AbstractDisplay)
×
295
    for i = length(displays):-1:1
×
296
        if d == displays[i]
×
297
            return splice!(displays, i)
×
298
        end
299
    end
×
300
    throw(KeyError(d))
×
301
end
302
function reinit_displays()
×
303
    empty!(displays)
449✔
304
    pushdisplay(TextDisplay(stdout))
449✔
305
end
306

307
xdisplayable(D::AbstractDisplay, @nospecialize args...) = applicable(display, D, args...)
3✔
308

309
"""
310
    display(x)
311
    display(d::AbstractDisplay, x)
312
    display(mime, x)
313
    display(d::AbstractDisplay, mime, x)
314

315
Display `x` using the topmost applicable display in the display stack, typically using the
316
richest supported multimedia output for `x`, with plain-text [`stdout`](@ref) output as a fallback.
317
The `display(d, x)` variant attempts to display `x` on the given display `d` only, throwing
318
a [`MethodError`](@ref) if `d` cannot display objects of this type.
319

320
In general, you cannot assume that `display` output goes to `stdout` (unlike [`print(x)`](@ref) or
321
[`show(x)`](@ref)).  For example, `display(x)` may open up a separate window with an image.
322
`display(x)` means "show `x` in the best way you can for the current output device(s)."
323
If you want REPL-like text output that is guaranteed to go to `stdout`, use
324
[`show(stdout, "text/plain", x)`](@ref) instead.
325

326
There are also two variants with a `mime` argument (a MIME type string, such as
327
`"image/png"`), which attempt to display `x` using the requested MIME type *only*, throwing
328
a `MethodError` if this type is not supported by either the display(s) or by `x`. With these
329
variants, one can also supply the "raw" data in the requested MIME type by passing
330
`x::AbstractString` (for MIME types with text-based storage, such as text/html or
331
application/postscript) or `x::Vector{UInt8}` (for binary MIME types).
332

333
To customize how instances of a type are displayed, overload [`show`](@ref) rather than `display`,
334
as explained in the manual section on [custom pretty-printing](@ref man-custom-pretty-printing).
335
"""
336
function display(@nospecialize x)
3✔
337
    for i = length(displays):-1:1
6✔
338
        if xdisplayable(displays[i], x)
3✔
339
            try
3✔
340
                return display(displays[i], x)
3✔
341
            catch e
342
                isa(e, MethodError) && (e.f === display || e.f === show) ||
×
343
                    rethrow()
344
            end
345
        end
346
    end
×
347
    throw(MethodError(display, (x,)))
×
348
end
349

350
function display(m::MIME, @nospecialize x)
×
351
    for i = length(displays):-1:1
×
352
        if xdisplayable(displays[i], m, x)
×
353
            try
×
354
                return display(displays[i], m, x)
×
355
            catch e
356
                isa(e, MethodError) && e.f == display ||
×
357
                    rethrow()
358
            end
359
        end
360
    end
×
361
    throw(MethodError(display, (m, x)))
×
362
end
363

364
displayable(d::D, ::MIME{mime}) where {D<:AbstractDisplay,mime} =
×
365
    hasmethod(display, Tuple{D,MIME{mime},Any})
366

367
function displayable(m::MIME)
×
368
    for d in displays
×
369
        displayable(d, m) && return true
×
370
    end
×
371
    return false
×
372
end
373

374
###########################################################################
375
# The redisplay method can be overridden by a AbstractDisplay in order to
376
# update an existing display (instead of, for example, opening a new
377
# window), and is used by the IJulia interface to defer display
378
# until the next interactive prompt.  This is especially useful
379
# for Matlab/Pylab-like stateful plotting interfaces, where
380
# a plot is created and then modified many times (xlabel, title, etc.).
381

382
"""
383
    redisplay(x)
384
    redisplay(d::AbstractDisplay, x)
385
    redisplay(mime, x)
386
    redisplay(d::AbstractDisplay, mime, x)
387

388
By default, the `redisplay` functions simply call [`display`](@ref).
389
However, some display backends may override `redisplay` to modify an existing
390
display of `x` (if any).
391
Using `redisplay` is also a hint to the backend that `x` may be redisplayed
392
several times, and the backend may choose to defer the display until
393
(for example) the next interactive prompt.
394
"""
395
function redisplay(@nospecialize x)
×
396
    for i = length(displays):-1:1
×
397
        if xdisplayable(displays[i], x)
×
398
            try
×
399
                return redisplay(displays[i], x)
×
400
            catch e
401
                isa(e, MethodError) && e.f in (redisplay, display, show) ||
×
402
                    rethrow()
403
            end
404
        end
405
    end
×
406
    throw(MethodError(redisplay, (x,)))
×
407
end
408

409
function redisplay(m::Union{MIME,AbstractString}, @nospecialize x)
×
410
    for i = length(displays):-1:1
×
411
        if xdisplayable(displays[i], m, x)
×
412
            try
×
413
                return redisplay(displays[i], m, x)
×
414
            catch e
415
                isa(e, MethodError) && e.f in (redisplay, display) ||
×
416
                    rethrow()
417
            end
418
        end
419
    end
×
420
    throw(MethodError(redisplay, (m, x)))
×
421
end
422

423
# default redisplay is simply to call display
424
redisplay(d::AbstractDisplay, @nospecialize x) = display(d, x)
×
425
redisplay(d::AbstractDisplay, m::Union{MIME,AbstractString}, @nospecialize x) = display(d, m, x)
×
426

427
###########################################################################
428

429
end # module
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc