Skip to content

Commit 0886e84

Browse files
committed
remove decodehook
1 parent 69d6d0f commit 0886e84

File tree

9 files changed

+81
-93
lines changed

9 files changed

+81
-93
lines changed

neovim/__init__.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@
66
import os
77
import sys
88

9-
from .api import DecodeHook, Nvim
9+
from .api import Nvim
1010
from .msgpack_rpc import (ErrorResponse, child_session, socket_session,
1111
stdio_session, tcp_session)
12-
from .plugin import (Host, autocmd, command, encoding, function, plugin,
13-
rpc_export, shutdown_hook)
12+
from .plugin import (Host, autocmd, command, decode, encoding, function,
13+
plugin, rpc_export, shutdown_hook)
1414

1515

1616
__all__ = ('tcp_session', 'socket_session', 'stdio_session', 'child_session',
17-
'start_host', 'autocmd', 'command', 'encoding', 'function',
18-
'plugin', 'rpc_export', 'Host', 'DecodeHook', 'Nvim',
17+
'start_host', 'autocmd', 'command', 'encoding', 'decode',
18+
'function', 'plugin', 'rpc_export', 'Host', 'Nvim',
1919
'shutdown_hook', 'attach', 'setup_logging', 'ErrorResponse')
2020

2121

neovim/api/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
"""
66

77
from .buffer import Buffer
8-
from .common import DecodeHook
8+
from .common import decode_if_bytes, walk
99
from .nvim import Nvim, NvimError
1010
from .tabpage import Tabpage
1111
from .window import Window
1212

1313

1414
__all__ = ('Nvim', 'Buffer', 'Window', 'Tabpage', 'NvimError',
15-
'DecodeHook')
15+
'decode_if_bytes', 'walk')

neovim/api/common.py

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -153,38 +153,20 @@ def _identity(obj, session, method, kind):
153153
return obj
154154

155155

156-
class DecodeHook(object):
157-
158-
"""SessionHook subclass that decodes utf-8 strings coming from Nvim.
159-
160-
This class is useful for python3, where strings are now unicode by
161-
default(byte strings need to be prefixed with "b").
162-
"""
163-
164-
def __init__(self, encoding='utf-8', encoding_errors='strict'):
165-
"""Initialize with encoding and encoding errors policy."""
166-
self.encoding = encoding
167-
self.encoding_errors = encoding_errors
168-
169-
def decode_if_bytes(self, obj):
170-
"""Decode obj if it is bytes."""
171-
if isinstance(obj, bytes):
172-
return obj.decode(self.encoding, errors=self.encoding_errors)
173-
return obj
174-
175-
def walk(self, obj):
176-
"""Decode bytes found in obj (any msgpack object).
177-
178-
Uses encoding and policy specified in constructor.
179-
"""
180-
return walk(self.decode_if_bytes, obj)
156+
def decode_if_bytes(obj, mode=True):
157+
"""Decode obj if it is bytes."""
158+
if mode is True:
159+
mode = "strict"
160+
if isinstance(obj, bytes):
161+
return obj.decode("utf-8", errors=mode)
162+
return obj
181163

182164

183-
def walk(fn, obj, *args):
165+
def walk(fn, obj, *args, **kwargs):
184166
"""Recursively walk an object graph applying `fn`/`args` to objects."""
185167
if type(obj) in [list, tuple]:
186168
return list(walk(fn, o, *args) for o in obj)
187169
if type(obj) is dict:
188170
return dict((walk(fn, k, *args), walk(fn, v, *args)) for k, v in
189171
obj.items())
190-
return fn(obj, *args)
172+
return fn(obj, *args, **kwargs)

neovim/api/nvim.py

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
from msgpack import ExtType
99

1010
from .buffer import Buffer
11-
from .common import (DecodeHook, Remote, RemoteApi,
12-
RemoteMap, RemoteSequence, walk)
11+
from .common import (Remote, RemoteApi, RemoteMap, RemoteSequence,
12+
decode_if_bytes, walk)
1313
from .tabpage import Tabpage
1414
from .window import Window
1515
from ..compat import IS_PYTHON3
@@ -33,7 +33,7 @@ class Nvim(object):
3333
from a raw `Session` instance.
3434
3535
Subsequent instances for the same session can be created by calling the
36-
`with_decodehook` instance method to change the decoding behavior or
36+
`with_decode` instance method to change the decoding behavior or
3737
`SubClass.from_nvim(nvim)` where `SubClass` is a subclass of `Nvim`, which
3838
is useful for having multiple `Nvim` objects that behave differently
3939
without one affecting the other.
@@ -52,7 +52,7 @@ def from_session(cls, session):
5252

5353
if IS_PYTHON3:
5454
# decode all metadata strings for python3
55-
metadata = DecodeHook().walk(metadata)
55+
metadata = walk(decode_if_bytes, metadata)
5656

5757
types = {
5858
metadata['types']['Buffer']['id']: Buffer,
@@ -66,10 +66,10 @@ def from_session(cls, session):
6666
def from_nvim(cls, nvim):
6767
"""Create a new Nvim instance from an existing instance."""
6868
return cls(nvim._session, nvim.channel_id, nvim.metadata,
69-
nvim.types, nvim._decodehook, nvim._err_cb)
69+
nvim.types, nvim._decode, nvim._err_cb)
7070

7171
def __init__(self, session, channel_id, metadata, types,
72-
decodehook=None, err_cb=None):
72+
decode=False, err_cb=None):
7373
"""Initialize a new Nvim instance. This method is module-private."""
7474
self._session = session
7575
self.channel_id = channel_id
@@ -85,15 +85,17 @@ def __init__(self, session, channel_id, metadata, types,
8585
self.current = Current(self)
8686
self.funcs = Funcs(self)
8787
self.error = NvimError
88-
self._decodehook = decodehook
88+
self._decode = decode
8989
self._err_cb = err_cb
9090

91-
def _from_nvim(self, obj):
91+
def _from_nvim(self, obj, decode=None):
92+
if decode is None:
93+
decode = self._decode
9294
if type(obj) is ExtType:
9395
cls = self.types[obj.code]
9496
return cls(self, (obj.code, obj.data))
95-
if self._decodehook is not None:
96-
obj = self._decodehook.decode_if_bytes(obj)
97+
if decode:
98+
obj = decode_if_bytes(obj, decode)
9799
return obj
98100

99101
def _to_nvim(self, obj):
@@ -121,9 +123,10 @@ def request(self, name, *args, **kwargs):
121123
present and True, a asynchronous notification is sent instead. This
122124
will never block, and the return value or error is ignored.
123125
"""
126+
decode = kwargs.pop('decode', self._decode)
124127
args = walk(self._to_nvim, args)
125128
res = self._session.request(name, *args, **kwargs)
126-
return walk(self._from_nvim, res)
129+
return walk(self._from_nvim, res, decode=decode)
127130

128131
def next_message(self):
129132
"""Block until a message(request or notification) is available.
@@ -160,10 +163,10 @@ def stop_loop(self):
160163
"""Stop the event loop being started with `run_loop`."""
161164
self._session.stop()
162165

163-
def with_decodehook(self, hook):
166+
def with_decode(self, decode=True):
164167
"""Initialize a new Nvim instance."""
165168
return Nvim(self._session, self.channel_id,
166-
self.metadata, self.types, hook, self._err_cb)
169+
self.metadata, self.types, decode, self._err_cb)
167170

168171
def ui_attach(self, width, height, rgb):
169172
"""Register as a remote UI.
@@ -192,24 +195,20 @@ def unsubscribe(self, event):
192195
"""Unsubscribe to a Nvim event."""
193196
return self.request('vim_unsubscribe', event)
194197

195-
def command(self, string, async=False):
198+
def command(self, string, **kwargs):
196199
"""Execute a single ex command."""
197-
return self.request('vim_command', string, async=async)
200+
return self.request('vim_command', string, **kwargs)
198201

199202
def command_output(self, string):
200203
"""Execute a single ex command and return the output."""
201204
return self.request('vim_command_output', string)
202205

203-
def eval(self, string, async=False):
206+
def eval(self, string, **kwargs):
204207
"""Evaluate a vimscript expression."""
205-
return self.request('vim_eval', string, async=async)
208+
return self.request('vim_eval', string, **kwargs)
206209

207210
def call(self, name, *args, **kwargs):
208211
"""Call a vimscript function."""
209-
for k in kwargs:
210-
if k != "async":
211-
raise TypeError(
212-
"call() got an unexpected keyword argument '{}'".format(k))
213212
return self.request('vim_call_function', name, args, **kwargs)
214213

215214
def strwidth(self, string):
@@ -285,9 +284,9 @@ def out_write(self, msg):
285284
"""Print `msg` as a normal message."""
286285
return self.request('vim_out_write', msg)
287286

288-
def err_write(self, msg, async=False):
287+
def err_write(self, msg, **kwargs):
289288
"""Print `msg` as an error message."""
290-
return self.request('vim_err_write', msg, async=async)
289+
return self.request('vim_err_write', msg, **kwargs)
291290

292291
def quit(self, quit_command='qa!'):
293292
"""Send a quit command to Nvim.

neovim/msgpack_rpc/session.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,15 @@ def request(self, method, *args, **kwargs):
7676
sent instead. This will never block, and the return value or error is
7777
ignored.
7878
"""
79-
async = kwargs.get('async', False)
79+
async = kwargs.pop('async', False)
8080
if async:
8181
self._async_session.notify(method, args)
8282
return
8383

84+
if kwargs:
85+
raise ValueError("request got unsupported keyword argument(s): {0}"
86+
.format(', '.join(kwargs.keys())))
87+
8488
if self._is_running:
8589
v = self._yielding_request(method, args)
8690
else:

neovim/plugin/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
"""Nvim plugin/host subpackage."""
22

3-
from .decorators import (autocmd, command, encoding, function, plugin,
4-
rpc_export, shutdown_hook)
3+
from .decorators import (autocmd, command, decode, encoding, function,
4+
plugin, rpc_export, shutdown_hook)
55
from .host import Host
66

77

88
__all__ = ('Host', 'plugin', 'rpc_export', 'command', 'autocmd',
9-
'function', 'encoding', 'shutdown_hook')
9+
'function', 'encoding', 'decode', 'shutdown_hook')

neovim/plugin/decorators.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
logger = logging.getLogger(__name__)
99
debug, info, warn = (logger.debug, logger.info, logger.warning,)
1010
__all__ = ('plugin', 'rpc_export', 'command', 'autocmd', 'function',
11-
'encoding', 'shutdown_hook')
11+
'encoding', 'decode', 'shutdown_hook')
1212

1313

1414
def plugin(cls):
@@ -141,9 +141,20 @@ def shutdown_hook(f):
141141
return f
142142

143143

144-
def encoding(encoding=True):
144+
def decode(mode='strict'):
145145
"""Configure automatic encoding/decoding of strings."""
146146
def dec(f):
147-
f._nvim_encoding = encoding
147+
f._nvim_decode = mode
148+
return f
149+
return dec
150+
151+
152+
def encoding(encoding=True):
153+
"""DEPRECATED: use neovim.decode()."""
154+
if isinstance(encoding, str):
155+
encoding = True
156+
157+
def dec(f):
158+
f._nvim_decode = encoding
148159
return f
149160
return dec

neovim/plugin/host.py

Lines changed: 20 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from traceback import format_exc
1111

1212
from . import script_host
13-
from ..api import DecodeHook
13+
from ..api import decode_if_bytes, walk
1414
from ..compat import IS_PYTHON3, find_module
1515
from ..msgpack_rpc import ErrorResponse
1616

@@ -41,9 +41,9 @@ def __init__(self, nvim):
4141
'specs': self._on_specs_request,
4242
'shutdown': self.shutdown
4343
}
44-
self._nvim_encoding = nvim.options['encoding']
45-
if IS_PYTHON3 and isinstance(self._nvim_encoding, bytes):
46-
self._nvim_encoding = self._nvim_encoding.decode('ascii')
44+
45+
# Decode per default for Python3
46+
self._decode_default = IS_PYTHON3
4747

4848
def _on_async_err(self, msg):
4949
self.nvim.err_write(msg, async=True)
@@ -62,8 +62,8 @@ def shutdown(self):
6262

6363
def _on_request(self, name, args):
6464
"""Handle a msgpack-rpc request."""
65-
if IS_PYTHON3 and isinstance(name, bytes):
66-
name = name.decode(self._nvim_encoding)
65+
if IS_PYTHON3:
66+
name = decode_if_bytes(name)
6767
handler = self._request_handlers.get(name, None)
6868
if not handler:
6969
msg = self._missing_handler_error(name, 'request')
@@ -77,8 +77,8 @@ def _on_request(self, name, args):
7777

7878
def _on_notification(self, name, args):
7979
"""Handle a msgpack-rpc notification."""
80-
if IS_PYTHON3 and isinstance(name, bytes):
81-
name = name.decode(self._nvim_encoding)
80+
if IS_PYTHON3:
81+
name = decode_if_bytes(name)
8282
handler = self._notification_handlers.get(name, None)
8383
if not handler:
8484
msg = self._missing_handler_error(name, 'notification')
@@ -155,20 +155,21 @@ def _discover_classes(self, module, handlers, plugin_path):
155155
def _discover_functions(self, obj, handlers, plugin_path):
156156
def predicate(o):
157157
return hasattr(o, '_nvim_rpc_method_name')
158+
159+
def decoder(fn, decode, *args):
160+
return fn(*walk(decode_if_bytes, args, decode))
158161
specs = []
159-
objenc = getattr(obj, '_nvim_encoding', None)
162+
objdecode = getattr(obj, '_nvim_decode', self._decode_default)
160163
for _, fn in inspect.getmembers(obj, predicate):
161-
enc = getattr(fn, '_nvim_encoding', objenc)
164+
decode = getattr(fn, '_nvim_decode', objdecode)
162165
if fn._nvim_bind:
163166
# bind a nvim instance to the handler
164167
fn2 = functools.partial(fn, self._configure_nvim_for(fn))
165168
# copy _nvim_* attributes from the original function
166169
self._copy_attributes(fn, fn2)
167170
fn = fn2
168-
decodehook = self._decodehook_for(enc)
169-
if decodehook is not None:
170-
decoder = lambda fn, hook, *args: fn(*hook.walk(args))
171-
fn2 = functools.partial(decoder, fn, decodehook)
171+
if decode:
172+
fn2 = functools.partial(decoder, fn, decode)
172173
self._copy_attributes(fn, fn2)
173174
fn = fn2
174175

@@ -199,25 +200,16 @@ def _copy_attributes(self, fn, fn2):
199200
setattr(fn2, attr, getattr(fn, attr))
200201

201202
def _on_specs_request(self, path):
202-
if IS_PYTHON3 and isinstance(path, bytes):
203-
path = path.decode(self._nvim_encoding)
203+
if IS_PYTHON3:
204+
path = decode_if_bytes(path)
204205
if path in self._load_errors:
205206
self.nvim.out_write(self._load_errors[path] + '\n')
206207
return self._specs.get(path, 0)
207208

208-
def _decodehook_for(self, encoding):
209-
if IS_PYTHON3 and encoding is None:
210-
encoding = True
211-
if encoding is True:
212-
encoding = self._nvim_encoding
213-
if encoding:
214-
return DecodeHook(encoding)
215-
216209
def _configure_nvim_for(self, obj):
217210
# Configure a nvim instance for obj (checks encoding configuration)
218211
nvim = self.nvim
219-
encoding = getattr(obj, '_nvim_encoding', None)
220-
hook = self._decodehook_for(encoding)
221-
if hook is not None:
222-
nvim = nvim.with_decodehook(hook)
212+
decode = getattr(obj, '_nvim_decode', self._decode_default)
213+
if decode:
214+
nvim = nvim.with_decode(decode)
223215
return nvim

test/test_common.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
if sys.version_info >= (3, 0):
2222
# For Python3 we decode binary strings as Unicode for compatibility
2323
# with Python2
24-
vim = vim.with_decodehook(neovim.DecodeHook())
24+
vim = vim.with_decode()
2525

2626
cleanup_func = ''':function BeforeEachTest()
2727
set all&

0 commit comments

Comments
 (0)