|
18 | 18 | from IPython.core.interactiveshell import InteractiveShell
|
19 | 19 | from IPython.display import clear_output
|
20 | 20 | from IPython import get_ipython
|
21 |
| - |
| 21 | +import traceback |
22 | 22 |
|
23 | 23 | @register
|
24 | 24 | class Output(DOMWidget):
|
@@ -108,30 +108,48 @@ def __enter__(self):
|
108 | 108 | """Called upon entering output widget context manager."""
|
109 | 109 | self._flush()
|
110 | 110 | ip = get_ipython()
|
| 111 | + kernel = None |
111 | 112 | if ip and getattr(ip, "kernel", None) is not None:
|
112 |
| - if hasattr(ip.kernel, "get_parent"): |
113 |
| - parent = ip.kernel.get_parent() |
114 |
| - elif hasattr(ip.kernel, "_parent_header"): |
| 113 | + kernel = ip.kernel |
| 114 | + elif self.comm is not None and self.comm.kernel is not None: |
| 115 | + kernel = self.comm.kernel |
| 116 | + |
| 117 | + if kernel: |
| 118 | + parent = None |
| 119 | + if hasattr(kernel, "get_parent"): |
| 120 | + parent = kernel.get_parent() |
| 121 | + elif hasattr(kernel, "_parent_header"): |
115 | 122 | # ipykernel < 6: kernel._parent_header is the parent *request*
|
116 |
| - parent = ip.kernel._parent_header |
| 123 | + parent = kernel._parent_header |
117 | 124 |
|
118 | 125 | if parent and parent.get("header"):
|
119 | 126 | self.msg_id = parent["header"]["msg_id"]
|
120 | 127 | self.__counter += 1
|
121 | 128 |
|
122 | 129 | def __exit__(self, etype, evalue, tb):
|
123 | 130 | """Called upon exiting output widget context manager."""
|
124 |
| - ip = get_ipython() |
| 131 | + kernel = None |
125 | 132 | if etype is not None:
|
| 133 | + ip = get_ipython() |
126 | 134 | if ip:
|
| 135 | + kernel = ip |
127 | 136 | ip.showtraceback((etype, evalue, tb), tb_offset=0)
|
| 137 | + elif self.comm is not None and self.comm.kernel is not None: |
| 138 | + kernel = self.comm.kernel |
| 139 | + kernel.send_response(kernel.iopub_socket, |
| 140 | + u'error', |
| 141 | + { |
| 142 | + u'traceback': ["".join(traceback.format_exception(etype, evalue, tb))], |
| 143 | + u'evalue': repr(evalue.args), |
| 144 | + u'ename': etype.__name__ |
| 145 | + }) |
128 | 146 | self._flush()
|
129 | 147 | self.__counter -= 1
|
130 | 148 | if self.__counter == 0:
|
131 | 149 | self.msg_id = ''
|
132 |
| - # suppress exceptions when in a kernel, since they are shown above, |
| 150 | + # suppress exceptions when in IPython, since they are shown above, |
133 | 151 | # otherwise let someone else handle it
|
134 |
| - return True if ip else None |
| 152 | + return True if kernel else None |
135 | 153 |
|
136 | 154 | def _flush(self):
|
137 | 155 | """Flush stdout and stderr buffers."""
|
|
0 commit comments