|
2 | 2 | """Some generic utilities for dealing with classes, urls, and serialization.""" |
3 | 3 | # Copyright (c) IPython Development Team. |
4 | 4 | # Distributed under the terms of the Modified BSD License. |
| 5 | +import asyncio |
| 6 | +import functools |
| 7 | +import inspect |
5 | 8 | import logging |
6 | 9 | import os |
7 | 10 | import re |
|
23 | 26 | import zmq |
24 | 27 | from dateutil.parser import parse as dateutil_parse |
25 | 28 | from dateutil.tz import tzlocal |
26 | | -from decorator import decorator |
27 | 29 | from IPython import get_ipython |
28 | 30 | from IPython.core.profiledir import ProfileDir |
29 | 31 | from IPython.core.profiledir import ProfileDirError |
@@ -101,17 +103,32 @@ def get(self, key, default=None): |
101 | 103 | # ----------------------------------------------------------------------------- |
102 | 104 |
|
103 | 105 |
|
104 | | -@decorator |
105 | | -def log_errors(f, self, *args, **kwargs): |
| 106 | +def log_errors(f): |
106 | 107 | """decorator to log unhandled exceptions raised in a method. |
107 | 108 |
|
108 | 109 | For use wrapping on_recv callbacks, so that exceptions |
109 | 110 | do not cause the stream to be closed. |
110 | 111 | """ |
111 | | - try: |
112 | | - return f(self, *args, **kwargs) |
113 | | - except Exception as e: |
114 | | - self.log.error("Uncaught exception in %r" % f, exc_info=True) |
| 112 | + |
| 113 | + @functools.wraps(f) |
| 114 | + def logs_errors(self, *args, **kwargs): |
| 115 | + try: |
| 116 | + result = f(self, *args, **kwargs) |
| 117 | + except Exception: |
| 118 | + self.log.error("Uncaught exception in {f}: {future.exception()}") |
| 119 | + return |
| 120 | + |
| 121 | + if inspect.isawaitable(result): |
| 122 | + # if it's async, schedule logging for when the future resolves |
| 123 | + future = asyncio.ensure_future(result) |
| 124 | + |
| 125 | + def _log_error(future): |
| 126 | + if future.exception(): |
| 127 | + self.log.error("Uncaught exception in {f}: {future.exception()}") |
| 128 | + |
| 129 | + future.add_done_callback(_log_error) |
| 130 | + |
| 131 | + return logs_errors |
115 | 132 |
|
116 | 133 |
|
117 | 134 | def is_url(url): |
|
0 commit comments