|
13 | 13 | from ..api import decode_if_bytes, walk |
14 | 14 | from ..compat import IS_PYTHON3, find_module |
15 | 15 | from ..msgpack_rpc import ErrorResponse |
| 16 | +from ..util import format_exc_skip |
16 | 17 |
|
17 | 18 | __all__ = ('Host') |
18 | 19 |
|
@@ -60,6 +61,24 @@ def shutdown(self): |
60 | 61 | self._unload() |
61 | 62 | self.nvim.stop_loop() |
62 | 63 |
|
| 64 | + def _wrap_function(self, fn, sync, decode, nvim_bind, name, *args): |
| 65 | + if decode: |
| 66 | + args = walk(decode_if_bytes, args, decode) |
| 67 | + if nvim_bind is not None: |
| 68 | + args.insert(0, nvim_bind) |
| 69 | + try: |
| 70 | + return fn(*args) |
| 71 | + except Exception: |
| 72 | + if sync: |
| 73 | + msg = ("error caught in request handler '{} {}':\n{}" |
| 74 | + .format(name, args, format_exc_skip(1, 5))) |
| 75 | + raise ErrorResponse(msg) |
| 76 | + else: |
| 77 | + msg = ("error caught in async handler '{} {}'\n{}\n" |
| 78 | + .format(name, args, format_exc_skip(1, 5))) |
| 79 | + self._on_async_err(msg + "\n") |
| 80 | + raise |
| 81 | + |
63 | 82 | def _on_request(self, name, args): |
64 | 83 | """Handle a msgpack-rpc request.""" |
65 | 84 | if IS_PYTHON3: |
@@ -87,13 +106,7 @@ def _on_notification(self, name, args): |
87 | 106 | return |
88 | 107 |
|
89 | 108 | debug('calling notification handler for "%s", args: "%s"', name, args) |
90 | | - try: |
91 | | - handler(*args) |
92 | | - except Exception as err: |
93 | | - msg = ("error caught in async handler '{} {}':\n{!r}\n{}\n" |
94 | | - .format(name, args, err, format_exc(5))) |
95 | | - self._on_async_err(msg + "\n") |
96 | | - raise |
| 109 | + handler(*args) |
97 | 110 |
|
98 | 111 | def _missing_handler_error(self, name, kind): |
99 | 112 | msg = 'no {} handler registered for "{}"'.format(kind, name) |
@@ -156,40 +169,36 @@ def _discover_functions(self, obj, handlers, plugin_path): |
156 | 169 | def predicate(o): |
157 | 170 | return hasattr(o, '_nvim_rpc_method_name') |
158 | 171 |
|
159 | | - def decoder(fn, decode, *args): |
160 | | - return fn(*walk(decode_if_bytes, args, decode)) |
161 | 172 | specs = [] |
162 | 173 | objdecode = getattr(obj, '_nvim_decode', self._decode_default) |
163 | 174 | for _, fn in inspect.getmembers(obj, predicate): |
| 175 | + sync = fn._nvim_rpc_sync |
164 | 176 | decode = getattr(fn, '_nvim_decode', objdecode) |
| 177 | + nvim_bind = None |
165 | 178 | if fn._nvim_bind: |
166 | | - # bind a nvim instance to the handler |
167 | | - fn2 = functools.partial(fn, self._configure_nvim_for(fn)) |
168 | | - # copy _nvim_* attributes from the original function |
169 | | - self._copy_attributes(fn, fn2) |
170 | | - fn = fn2 |
171 | | - if decode: |
172 | | - fn2 = functools.partial(decoder, fn, decode) |
173 | | - self._copy_attributes(fn, fn2) |
174 | | - fn = fn2 |
| 179 | + nvim_bind = self._configure_nvim_for(fn) |
175 | 180 |
|
176 | | - # register in the rpc handler dict |
177 | 181 | method = fn._nvim_rpc_method_name |
178 | 182 | if fn._nvim_prefix_plugin_path: |
179 | 183 | method = '{0}:{1}'.format(plugin_path, method) |
180 | | - if fn._nvim_rpc_sync: |
| 184 | + |
| 185 | + fn_wrapped = functools.partial(self._wrap_function, fn, |
| 186 | + sync, decode, nvim_bind, method) |
| 187 | + self._copy_attributes(fn, fn_wrapped) |
| 188 | + # register in the rpc handler dict |
| 189 | + if sync: |
181 | 190 | if method in self._request_handlers: |
182 | 191 | raise Exception(('Request handler for "{0}" is ' + |
183 | 192 | 'already registered').format(method)) |
184 | | - self._request_handlers[method] = fn |
| 193 | + self._request_handlers[method] = fn_wrapped |
185 | 194 | else: |
186 | 195 | if method in self._notification_handlers: |
187 | 196 | raise Exception(('Notification handler for "{0}" is ' + |
188 | 197 | 'already registered').format(method)) |
189 | | - self._notification_handlers[method] = fn |
| 198 | + self._notification_handlers[method] = fn_wrapped |
190 | 199 | if hasattr(fn, '_nvim_rpc_spec'): |
191 | 200 | specs.append(fn._nvim_rpc_spec) |
192 | | - handlers.append(fn) |
| 201 | + handlers.append(fn_wrapped) |
193 | 202 | if specs: |
194 | 203 | self._specs[plugin_path] = specs |
195 | 204 |
|
|
0 commit comments