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

issue with display hook in base python repl #4504

Closed
tacaswell opened this issue Jun 8, 2015 · 4 comments · Fixed by #4506
Closed

issue with display hook in base python repl #4504

tacaswell opened this issue Jun 8, 2015 · 4 comments · Fixed by #4506
Assignees
Labels
API: changes Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions.
Milestone

Comments

@tacaswell
Copy link
Member

This only applies to the base python repl, everything works in IPython repls.

In discussion on b2fbae7 discovered that sys.displayhook only gets evaluated for expressions, not statements.

This means that things like

import numpy
pass
a = b

will not trigger the auto-redrawing. This is particularly troubling because this mean

ln, = ax.plot(...)

will not trigger a re-draw, but

ax.plot(...)

will.

Due to b2fbae7, where we rely on the auto-redrawing to trigger the pyplot redrawing this means that many pyplot workflows in the normal repl are broken (as in things that used to auto-redraw no longer do).

The options I think are:

  1. figure out how to trigger a call back on statements (if this is possible, it is well hidden. There may be a reason IPython completely re-wrote the execution handling)
  2. say we only support interactive plotting with the IPython repl (which is a major regression)
  3. revert the removal of draw_if_interactive which maintains some functions as 'special'

I suspect that the answer is going to be both 2 and 3. normal python shell keeps current functionality and gains some new functionality, IPython picks up lots of new functionality, and the code base keeps this particular wart.

@tacaswell tacaswell modified the milestones: next major release, next point release Jun 8, 2015
@tacaswell tacaswell added Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions. API: changes labels Jun 8, 2015
tacaswell referenced this issue Jun 8, 2015
With the repl callback the pyplot function do not need to
call `draw_if_interactive`.
@tacaswell
Copy link
Member Author

Another option may be to hook draw_if_interactive into the callback stack on Figure objects to queue up a draw when the figure becomes stale.

@tacaswell
Copy link
Member Author

copied from commit thread:

If we tie this to the state change of stale on the Figure, it will only get flipped to True once so there should only be one call to draw_if_interactive/draw_idle anyway.

My current inclination is to change the repl registration to use the IPython hooks if they are available and the Figure-based callback otherwise.

I will take a crack at this tomorrow morning.

tacaswell added a commit to tacaswell/matplotlib that referenced this issue Jun 8, 2015
If we do not have IPython, then the only hook I know of in the repl is
the display hook which is called when ever something is going to be
displayed, not after the execution of the last command has finished (the
reason it exists is to give users a chance to intercept and change the
display of the output, not as a generic call back as we were trying to
use it).  In this case register a callback on the `Figure` artist at
creation time to call `draw_idle` on the canvas if the Figure is stale.

We are guaranteed to see this at least once when stale is flipped to
True, but may see it more than once if other paths call `pchanged()`.
Fortunately, `pchanged` is not widely used in the internal code base and
even if `draw_idle` is called multiple times, we should be able to count
on the backends handling multiple draw_idle commands correctly.

Closes matplotlib#4504
@tacaswell tacaswell self-assigned this Jun 8, 2015
@WeatherGod
Copy link
Member

Something I just noticed when playing around with the interactive mode in python REPL. If I create a figure and then call plt.ion(), the subsequent plotting call (which happens to be an expression) does not trigger a show(). Nothing shows until I do plt.show().

>>> import matplotlib.pyplot as plt
>>> fig, ax = plt.subplots()
>>> ax.plot([1, 2, 3])
[<matplotlib.lines.Line2D object at 0x7fc82dbd9c90>]
>>> plt.ion()    # I now decide I want to see what I am doing
>>> ax.plot([3, 2, 1])  # No figure window!
[<matplotlib.lines.Line2D object at 0x7fc82d4a0f90>]
>>> ax.set_xlabel('x data')  # Still no figure window!
<matplotlib.text.Text object at 0x7fc83f0c15d0>
>>> plt.show()  # Figure window appears
>>> fig, ax = plt.subplots()  # New figure window appears right away and subsequent plotting calls work immediately

@OceanWolf
Copy link
Contributor

Sure, but that's expected behaviour right? The same happens with python -i not switching to interactive mode until the script has finished executing...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API: changes Release critical For bugs that make the library unusable (segfaults, incorrect plots, etc) and major regressions.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants