Skip to content

Commit 984741b

Browse files
committed
Merge pull request #189 from bfredl/decode
remove decodehook
2 parents 69d6d0f + 02e28e7 commit 984741b

File tree

9 files changed

+87
-99
lines changed

9 files changed

+87
-99
lines changed

neovim/__init__.py

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

9-
from .api import DecodeHook, Nvim
9+
from .api import Nvim
10+
from .compat import IS_PYTHON3
1011
from .msgpack_rpc import (ErrorResponse, child_session, socket_session,
1112
stdio_session, tcp_session)
12-
from .plugin import (Host, autocmd, command, encoding, function, plugin,
13-
rpc_export, shutdown_hook)
13+
from .plugin import (Host, autocmd, command, decode, encoding, function,
14+
plugin, rpc_export, shutdown_hook)
1415

1516

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

2122

@@ -63,7 +64,8 @@ def start_host(session=None):
6364
host.start(plugins)
6465

6566

66-
def attach(session_type, address=None, port=None, path=None, argv=None):
67+
def attach(session_type, address=None, port=None,
68+
path=None, argv=None, decode=None):
6769
"""Provide a nicer interface to create python api sessions.
6870
6971
Previous machinery to create python api sessions is still there. This only
@@ -89,7 +91,10 @@ def attach(session_type, address=None, port=None, path=None, argv=None):
8991
if not session:
9092
raise Exception('Unknown session type "%s"' % session_type)
9193

92-
return Nvim.from_session(session)
94+
if decode is None:
95+
decode = IS_PYTHON3
96+
97+
return Nvim.from_session(session).with_decode(decode)
9398

9499

95100
def setup_logging():

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

0 commit comments

Comments
 (0)