Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

minor post-execute fixes (#1154) #1155

Merged
merged 3 commits into from

2 participants

@minrk
Owner

Two changes:

  1. Don't unregister failing post-exec callbacks automatically. Instead, print a message regarding the failure, pointing to new disable_failing_post_execute trait for skipping failing callbacks.
    • When this flag is False (the default), failing callbacks will continue to be called.
    • When True, behavior is unchanged from previous, where callbacks are only allowed to fail once.
  2. protect flush_figures() post-exec function from user error. Invalid matplotlib data may raise inside print_figure(). flush_figures() is a post-exec function, so user errors should not raise. Instead, call get_ipython().showtraceback() if called from IPython, raising as before otherwise.

closes #1154

minrk added some commits
@minrk minrk Don't unregister failing post-exec callbacks automatically
Instead, print a message regarding the failure, pointing to new
`disable_failing_post_execute` trait for skipping failing callbacks.

When this flag is False (the default), failing callbacks will continue to be called.
When True, behavior is unchanged from previous, where callbacks are only allowed to fail once.
f972ef8
@minrk minrk protect flush_figures post-exec function from user error
Invalid matplotlib data may raise inside print_figure.  flush_figures()
is a post-exec function, so user errors should not raise.  Instead,
call get_ipython().showtraceback() if called from IPython, raising as before
otherwise.
c98183c
@fperez
Owner

Reviewed together at Berkeley, @minrk is making one tiny fix and then we'll merge.

@fperez fperez merged commit 2c683b7 into from
@fperez fperez referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 14, 2011
  1. @minrk

    Don't unregister failing post-exec callbacks automatically

    minrk authored
    Instead, print a message regarding the failure, pointing to new
    `disable_failing_post_execute` trait for skipping failing callbacks.
    
    When this flag is False (the default), failing callbacks will continue to be called.
    When True, behavior is unchanged from previous, where callbacks are only allowed to fail once.
  2. @minrk

    protect flush_figures post-exec function from user error

    minrk authored
    Invalid matplotlib data may raise inside print_figure.  flush_figures()
    is a post-exec function, so user errors should not raise.  Instead,
    call get_ipython().showtraceback() if called from IPython, raising as before
    otherwise.
Commits on Dec 15, 2011
  1. @minrk
This page is out of date. Refresh to see the latest.
View
18 IPython/core/interactiveshell.py
@@ -261,6 +261,9 @@ class InteractiveShell(SingletonConfigurable, Magic):
deep_reload will still be available as dreload().
"""
)
+ disable_failing_post_execute = CBool(False, config=True,
+ help="Don't call post-execute functions that have failed in the past."""
+ )
display_formatter = Instance(DisplayFormatter)
displayhook_class = Type(DisplayHook)
display_pub_class = Type(DisplayPublisher)
@@ -749,7 +752,7 @@ def register_post_execute(self, func):
if not callable(func):
raise ValueError('argument %s must be callable' % func)
self._post_execute[func] = True
-
+
#-------------------------------------------------------------------------
# Things related to the "main" module
#-------------------------------------------------------------------------
@@ -2426,17 +2429,22 @@ def run_cell(self, raw_cell, store_history=False):
# Execute any registered post-execution functions.
for func, status in self._post_execute.iteritems():
- if not status:
+ if self.disable_failing_post_execute and not status:
continue
try:
func()
except KeyboardInterrupt:
print >> io.stderr, "\nKeyboardInterrupt"
except Exception:
- print >> io.stderr, "Disabling failed post-execution function: %s" % func
- self.showtraceback()
- # Deactivate failing function
+ # register as failing:
self._post_execute[func] = False
+ self.showtraceback()
+ print >> io.stderr, '\n'.join([
+ "post-execution function %r produced an error." % func,
+ "If this problem persists, you can disable failing post-exec functions with:",
+ "",
+ " get_ipython().disable_failing_post_execute = True"
+ ])
if store_history:
# Write output to the database. Does nothing unless
View
37 IPython/zmq/pylab/backend_inline.py
@@ -140,19 +140,43 @@ def flush_figures():
This is meant to be called automatically and will call show() if, during
prior code execution, there had been any calls to draw_if_interactive.
+
+ This function is meant to be used as a post_execute callback in IPython,
+ so user-caused errors are handled with showtraceback() instead of being
+ allowed to raise. If this function is not called from within IPython,
+ then these exceptions will raise.
"""
if not show._draw_called:
return
if InlineBackend.instance().close_figures:
# ignore the tracking, just draw and close all figures
- return show(True)
-
+ try:
+ return show(True)
+ except Exception as e:
+ # safely show traceback if in IPython, else raise
+ try:
+ get_ipython
+ except NameError:
+ raise e
+ else:
+ get_ipython().showtraceback()
+ return
try:
# exclude any figures that were closed:
active = set([fm.canvas.figure for fm in Gcf.get_all_fig_managers()])
for fig in [ fig for fig in show._to_draw if fig in active ]:
- send_figure(fig)
+ try:
+ send_figure(fig)
+ except Exception as e:
+ # safely show traceback if in IPython, else raise
+ try:
+ get_ipython
+ except NameError:
+ raise e
+ else:
+ get_ipython().showtraceback()
+ break
finally:
# clear flags for next round
show._to_draw = []
@@ -162,12 +186,11 @@ def flush_figures():
def send_figure(fig):
"""Draw the current figure and send it as a PNG payload.
"""
- # For an empty figure, don't even bother calling figure_to_svg, to avoid
- # big blank spaces in the qt console
- if not fig.axes:
- return
fmt = InlineBackend.instance().figure_format
data = print_figure(fig, fmt)
+ # print_figure will return None if there's nothing to draw:
+ if data is None:
+ return
mimetypes = { 'png' : 'image/png', 'svg' : 'image/svg+xml' }
mime = mimetypes[fmt]
# flush text streams before sending figures, helps a little with output
Something went wrong with that request. Please try again.