The HTML backend can fail to print to `stdout`
I found that writing a doctest using the HTML backend can fail. It was printing to the terminal, rather than whichever IO that Documenter.jl was redirecting to. I think that the issue is caused by this line. Note that the docstring for display says that "In general, you cannot assume that display output goes to stdout".
In this MWE, the output of pretty_table should get written to the pipe. Instead, it is printed on the terminal.
julia> using PrettyTables
julia> (_read, _write) = pipe = Pipe()
Pipe(RawFD(4294967295) init => RawFD(4294967295) init, 0 bytes waiting)
# note the semicolon, the table is getting printed on the terminal instead of written to `stdout`
julia> redirect_stdout(() -> pretty_table(stdout, [1,2,3,4]; backend = Val(:html)), pipe);
<table>
<thead>
<tr class = "header headerLastRow">
<th style = "text-align: right;">Col. 1</th>
</tr>
</thead>
<tbody>
<tr>
<td style = "text-align: right;">1</td>
</tr>
<tr>
<td style = "text-align: right;">2</td>
</tr>
<tr>
<td style = "text-align: right;">3</td>
</tr>
<tr>
<td style = "text-align: right;">4</td>
</tr>
</tbody>
</table>
julia> close(_write)
julia> read(_read, String)
""
For comparison, here is the redirection working correctly:
julia> using PrettyTables
julia> (_read, _write) = pipe = Pipe()
Pipe(RawFD(4294967295) init => RawFD(4294967295) init, 0 bytes waiting)
julia> redirect_stdout(() -> pretty_table(stdout, [1,2,3,4]), pipe);
julia> close(_write)
julia> read(_read, String)
"┌────────┐\n│ Col. 1 │\n├────────┤\n│ 1 │\n│ 2 │\n│ 3 │\n│ 4 │\n└────────┘\n"
Hi @jakobjpeters !
Yes, I was aware of this problem. The issue is that we need that logic to make environments like Jupyter or Pluto to render the HTML content properly. I have no idea if we can properly fix this issue without compromising how PrettyTables renders in Jupyter, for example.
Besides doctests, are there any scenarios that this issue is causing problems?
Hi, thanks for the reply :)
I'm not aware of any other specific scenarios. It seems like this behavior deviates from the expected behavior of writing to the given IO, but I understand the use-case you point out. Is this documented?
This may or may not be a different issue, but I anticipated (EDIT: based on your rationale for using display when io = stdout) that the 2nd call in the notebook would also render the table as HTML. Am I using it incorrectly here?
I would argue for the idiomatic way to print a table in a notebook would be to explicitly use the HTML as the io argument. However, I am not a notebook user so I don't know about their behaviors and have that bias.
Hum, I have no idea. Everything is working in Jupyter (I really do not use Pluto.jl). Maybe Pluto.jl does not use stdout to render HTML content? Anyway, we can definitely improve our support for Pluto.jl here.
One thing that we should reach is to support the front ends so that pretty_table(...; backend = Val(:html)) renders the HTML when it is supported.
Oh! I think I remember this case! Pluto expects an object, that's why we need to pass HTML to pretty_table. Jupyter, on the other hand, renders the output to stdout.
I setup Jupyter and it works as you described. Currently, pretty_table(HTML, ...) renders in both Pluto and Jupyter while pretty_table(...; backend = Val(:html)) only renders in Jupyter. I support some way to disentangle these behaviors so that the notebook rendering is consistent and printing HTML to stdout works correctly. A couple of methods I can think of that may accomplish this are:
- Only render when using the form
pretty_table(HTML, ...) - A new function for rendering in notebooks
- A keyword argument to specify whether or not to use
display - Wrapping tables in a struct (
PrettyTable) and usingshowmethods (?)
Do you have any other ideas? Do you want the behavior to remain as is or would you prefer to change it (such as implementing one of these methods)?
Only render when using the form pretty_table(HTML, ...)
I think the user would expect that that system renders the HTML table is backend = Val(:html) is selected.
A new function for rendering in notebooks
Wouldn't this be way too confusing?
A keyword argument to specify whether or not to use display
It can be an alternative, do you have a suggestion?
Wrapping tables in a struct (PrettyTable) and using show methods (?)
I think this is not a correct move. PrettyTables is a package to render tables. It should not have a specific type to "describe" a table.
Do you have any other ideas? Do you want the behavior to remain as is or would you prefer to change it (such as implementing one of these methods)?
No, I do not! But I am 100% open to improve the user experience :)
Thanks for the feedback! I have another idea that I think satisfies both desires.
- When the input is
pretty_table(data; backend = Val(:html), ...)andpretty_table(HTML, data; ...), the notebooks are given the capability of rendering. This still requires a fix for Pluto. Since noioargument was provided, it seems reasonable to be flexible there. - When the input is
pretty_table(stdout, ...; backend = Val(:html), ...), the table is written tostdout(not todisplay), since the user specifically wants it to be written there.
What do you think?