|
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