|
1 |
| -py_mime_reprmethod(::MIME) = nothing |
2 |
| -py_mime_reprmethod(::MIME"text/plain") = "__repr__" |
3 |
| -py_mime_reprmethod(::MIME"text/html") = "_repr_html_" |
4 |
| -py_mime_reprmethod(::MIME"text/markdown") = "_repr_markdown_" |
5 |
| -py_mime_reprmethod(::MIME"text/json") = "_repr_json_" |
6 |
| -py_mime_reprmethod(::MIME"text/latex") = "_repr_latex_" |
7 |
| -py_mime_reprmethod(::MIME"application/javascript") = "_repr_javascript_" |
8 |
| -py_mime_reprmethod(::MIME"application/pdf") = "_repr_pdf_" |
9 |
| -py_mime_reprmethod(::MIME"image/jpeg") = "_repr_jpeg_" |
10 |
| -py_mime_reprmethod(::MIME"image/png") = "_repr_png_" |
11 |
| -py_mime_reprmethod(::MIME"image/svg+xml") = "_repr_svg_" |
12 |
| - |
13 |
| -py_mime_data(m::MIME, o) = begin |
14 |
| - o = Py(o) |
15 |
| - r = py_mime_reprmethod(m) |
16 |
| - data = nothing |
17 |
| - meta = nothing |
| 1 | +### Extensible system for multimedia display of Python objects |
| 2 | + |
| 3 | +const PYSHOW_RULES = Function[] |
| 4 | + |
| 5 | +function pyshow_add_rule(rule::Function) |
| 6 | + push!(PYSHOW_RULES, rule) |
| 7 | + return |
| 8 | +end |
| 9 | + |
| 10 | +function pyshow(io::IO, mime::MIME, x) |
| 11 | + x_ = Py(x) |
| 12 | + for rule in PYSHOW_RULES |
| 13 | + rule(io, string(mime), x_) && return |
| 14 | + end |
| 15 | + throw(MethodError(show, (io, mime, x_))) |
| 16 | +end |
| 17 | + |
| 18 | +function pyshowable(mime::MIME, x) |
| 19 | + x_ = Py(x) |
| 20 | + for rule in PYSHOW_RULES |
| 21 | + rule(devnull, string(mime), x_) && return true |
| 22 | + end |
| 23 | + return false |
| 24 | +end |
| 25 | + |
| 26 | +### Particular rules |
| 27 | + |
| 28 | +function pyshow_rule_mimebundle(io::IO, mime::String, x::Py) |
18 | 29 | try
|
19 |
| - x = o.__class__._repr_mimebundle_(o, include=pylist((string(m),))) |
20 |
| - if pyisinstance(x, pybuiltins.tuple) |
21 |
| - data = x[0][string(m)] |
22 |
| - meta = x[1].get(string(m)) |
| 30 | + ans = x._repr_mimebundle_(include=pylist((mime,))) |
| 31 | + if pyisinstance(ans, pybuiltins.tuple) |
| 32 | + data = ans[0][mime] |
| 33 | + meta = ans[1].get(mime) |
23 | 34 | else
|
24 |
| - data = x[m] |
| 35 | + data = ans[mime] |
| 36 | + meta = pybuiltins.None |
25 | 37 | end
|
| 38 | + write(io, pyconvert(Union{String,Vector{UInt8}}, data)) |
| 39 | + return true |
26 | 40 | catch exc
|
27 |
| - exc isa PyException || rethrow() |
| 41 | + if exc isa PyException |
| 42 | + return false |
| 43 | + else |
| 44 | + rethrow() |
| 45 | + end |
28 | 46 | end
|
29 |
| - if data === nothing && r !== nothing |
30 |
| - try |
31 |
| - x = pygetattr(o.__class__, r)(o) |
32 |
| - if pyisinstance(x, pybuiltins.tuple) |
33 |
| - data = x[0] |
34 |
| - meta = x[1] |
35 |
| - else |
36 |
| - data = x |
37 |
| - end |
38 |
| - catch exc |
39 |
| - exc isa PyException || rethrow() |
| 47 | +end |
| 48 | + |
| 49 | +const MIME_TO_REPR_METHOD = Dict( |
| 50 | + "text/plain" => "__repr__", |
| 51 | + "text/html" => "_repr_html_", |
| 52 | + "text/markdown" => "_repr_markdown_", |
| 53 | + "text/json" => "_repr_json_", |
| 54 | + "text/latex" => "_repr_latex_", |
| 55 | + "application/javascript" => "_repr_javascript_", |
| 56 | + "application/pdf" => "_repr_pdf_", |
| 57 | + "image/jpeg" => "_repr_jpeg_", |
| 58 | + "image/png" => "_repr_png_", |
| 59 | + "image/svg+xml" => "_repr_svg_", |
| 60 | +) |
| 61 | + |
| 62 | +function pyshow_rule_repr(io::IO, mime::String, x::Py) |
| 63 | + method = get(MIME_TO_REPR_METHOD, mime, "") |
| 64 | + isempty(method) && return false |
| 65 | + try |
| 66 | + ans = pygetattr(x, method)() |
| 67 | + if pyisinstance(ans, pybuiltins.tuple) |
| 68 | + data = ans[0] |
| 69 | + meta = ans[1] |
| 70 | + else |
| 71 | + data = ans |
| 72 | + meta = pybuiltins.None |
| 73 | + end |
| 74 | + write(io, pyconvert(Union{String,Vector{UInt8}}, data)) |
| 75 | + return true |
| 76 | + catch exc |
| 77 | + if exc isa PyException |
| 78 | + return false |
| 79 | + else |
| 80 | + rethrow() |
40 | 81 | end
|
41 | 82 | end
|
42 |
| - data, meta |
43 | 83 | end
|
44 | 84 |
|
45 |
| -py_mime_showable(m::MIME, o) = begin |
46 |
| - data, meta = py_mime_data(m, o) |
47 |
| - data !== nothing |
| 85 | +const MIME_TO_MATPLOTLIB_FORMAT = Dict( |
| 86 | + "image/png" => "png", |
| 87 | + "image/jpeg" => "jpeg", |
| 88 | + "image/tiff" => "tiff", |
| 89 | + "image/svg+xml" => "svg", |
| 90 | + "application/pdf" => "pdf", |
| 91 | +) |
| 92 | + |
| 93 | +function pyshow_rule_savefig(io::IO, mime::String, x::Py) |
| 94 | + # TODO: restrict to types or modules which are known to have a savefig method like this? |
| 95 | + format = get(MIME_TO_MATPLOTLIB_FORMAT, mime, "") |
| 96 | + isempty(format) && return false |
| 97 | + try |
| 98 | + # buf = pyimport("io").BytesIO() |
| 99 | + # x.savefig(buf, format=format) |
| 100 | + # data = pyconvert(Vector{UInt8}, buf.getvalue()) |
| 101 | + # write(io, data) |
| 102 | + x.savefig(io, format=format) |
| 103 | + return true |
| 104 | + catch exc |
| 105 | + if exc isa PyException |
| 106 | + return false |
| 107 | + else |
| 108 | + rethrow() |
| 109 | + end |
| 110 | + end |
48 | 111 | end
|
49 | 112 |
|
50 |
| -py_mime_show(io::IO, m::MIME, o) = begin |
51 |
| - data, meta = py_mime_data(m, o) |
52 |
| - write(io, istextmime(m) ? pystr(String, data) : pybytes(Vector{UInt8}, data)) |
53 |
| - nothing |
| 113 | +function init_pyshow() |
| 114 | + pyshow_add_rule(pyshow_rule_mimebundle) |
| 115 | + pyshow_add_rule(pyshow_rule_repr) |
| 116 | + pyshow_add_rule(pyshow_rule_savefig) |
54 | 117 | end
|
0 commit comments