Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The HTML backend can fail to print to stdout #235

Open
jakobjpeters opened this issue Dec 15, 2023 · 8 comments
Open

The HTML backend can fail to print to stdout #235

jakobjpeters opened this issue Dec 15, 2023 · 8 comments

Comments

@jakobjpeters
Copy link
Contributor

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"
@ronisbr
Copy link
Owner

ronisbr commented Dec 16, 2023

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?

@jakobjpeters
Copy link
Contributor Author

jakobjpeters commented Dec 16, 2023

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?
pluto_pretty_table

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.

@ronisbr
Copy link
Owner

ronisbr commented Dec 16, 2023

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.

@ronisbr
Copy link
Owner

ronisbr commented Dec 16, 2023

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.

@jakobjpeters
Copy link
Contributor Author

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 using show methods (?)

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)?

@ronisbr
Copy link
Owner

ronisbr commented Dec 16, 2023

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 :)

@jakobjpeters
Copy link
Contributor Author

jakobjpeters commented Dec 16, 2023

Thanks for the feedback! I have another idea that I think satisfies both desires.

  • When the input is pretty_table(data; backend = Val(:html), ...) and pretty_table(HTML, data; ...), the notebooks are given the capability of rendering. This still requires a fix for Pluto. Since no io argument was provided, it seems reasonable to be flexible there.
  • When the input is pretty_table(stdout, ...; backend = Val(:html), ...), the table is written to stdout (not to display), since the user specifically wants it to be written there.

What do you think?

@jakobjpeters
Copy link
Contributor Author

Another option: check to see if the current environment is IJulia or is Pluto and respond accordingly. This can also be used to enable rendering for the case that Pluto is missing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants