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

Do not suppress exceptions in Output widget context #3417

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

wookayin
Copy link

@wookayin wookayin commented Mar 16, 2022

Output widgets, when used as context managers in a with statement and in IPython, were suppressing exceptions (whose stacktrace would be printed to the output widget).

This change makes Output widgets not suppress an exception, which will make the control flow of the code transparent and same as if output widgets were not used.

For compatibility reasons, the previous behavior can be achieved by setting capture_exception attribute to True, in which case the context manager will suppress any exceptions thrown (if any).

Fixes #3208

TODO:

  • Make decisions on the default behavior (see the unit tests) and potential breaking changes
  • Update documentation

@github-actions
Copy link

Binder 👈 Launch a binder notebook on branch wookayin/ipywidgets/output-exception

@wookayin wookayin changed the title Do not suppress exceptions in Output widget context (#3208) Do not suppress exceptions in Output widget context Mar 16, 2022
@wookayin
Copy link
Author

I am open to not changing the default behavior (see #3208) -- by the v8.0 release (#2750), although I think it is more reasonable to not suppress exceptions. Any opinions or feedbacks would be appreciated.

Copy link
Member

@vidartf vidartf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. It mainly looks good, but some tweaks suggested.

@@ -60,6 +67,8 @@ def func():
msg_id = Unicode('', help="Parent message id of messages to capture").tag(sync=True)
outputs = TypedTuple(trait=Dict(), help="The output messages synced from the frontend.").tag(sync=True)

catch_exception = Bool(False, help="Whether to catch and suppress all exceptions.").tag(sync=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably doesn't need to be synced (?). Making it backwards compatible by keeping the current default would also be a clear preference on my end.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this could be an attribute rather than a trait? In such cases should I add a custom __init__ constructor? Or would just sync=False (or not having it) suffice?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just not including the .tag(sync=True) should be sufficient for keeping it as a type-checked trait that is not synced to the front-end.

Comment on lines 163 to 165
if kernel:
if self.catch_exception:
return True
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit-pick :)

Suggested change
if kernel:
if self.catch_exception:
return True
if kernel and self.catch_exception:
return True

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@jasongrout jasongrout added this to the 8.0 milestone Jul 7, 2022
@jasongrout
Copy link
Member

Interestingly, in JupyterLite it seems that an output widget does not capture exceptions, even though it does in ipykernel.

@jasongrout
Copy link
Member

From @vidartf:

Making it backwards compatible by keeping the current default would also be a clear preference on my end.

I agree with Vidar. A very common case for output widgets is to capture output that would not otherwise be visible (like widget callbacks), and capturing and displaying exceptions is very valuable for seeing why callbacks did not work. Also, I think if there is a question, preserving backwards compatibility should have a high priority (there is a lot of widgets code out there that people don't want to change if they can help it)

@vidartf vidartf modified the milestones: 8.0, 8.1 Jul 12, 2022
@wookayin
Copy link
Author

wookayin commented Sep 30, 2022

@vidartf, any possibility this can be merged in 8.0? I can make requested changes quickly. It's kind of a breaking change, so I feel it would be included in the major version.

UPDATE: never mind, I missed that 8.0 has been already out. Looking forward to be merged in the next release. Should we also add warnings for changing default behaviors in future versions, say 9.x?

…3208)

Output widgets, when used as context managers in a with statement
and in IPython, were suppressing exceptions (whose stacktrace would
be printed to the output widget).

This change allows Output widgets to suppress an exception when
`catch_exception` is set to False, which would make the control flow
of the code transparent and same as if output widgets were not used.

For backward compatibility reasons, the default behavior is not yet
changed at the moment of ipywidgets 8.0, i.e., the context manager of
Output widgets will consume and suppress any exceptions thrown.
However, at later versions the default behavior may change.
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

Successfully merging this pull request may close these issues.

ipywidgets.Output() context suppresses exceptions
3 participants