1
1
"""Code shared between the API classes."""
2
+ import functools
2
3
3
4
4
5
class Remote (object ):
@@ -10,6 +11,20 @@ class Remote(object):
10
11
object handle into consideration.
11
12
"""
12
13
14
+ def __init__ (self , session , code_data ):
15
+ """Initialize from session and code_data immutable object.
16
+
17
+ The `code_data` contains serialization information required for
18
+ msgpack-rpc calls. It must be immutable for Buffer equality to work.
19
+ """
20
+ self ._session = session
21
+ self .code_data = code_data
22
+ self .api = RemoteApi (self , self ._api_prefix )
23
+ self .vars = RemoteMap (self , self ._api_prefix + 'get_var' ,
24
+ self ._api_prefix + 'set_var' )
25
+ self .options = RemoteMap (self , self ._api_prefix + 'get_option' ,
26
+ self ._api_prefix + 'set_option' )
27
+
13
28
def __eq__ (self , other ):
14
29
"""Return True if `self` and `other` are the same object."""
15
30
return (hasattr (other , 'code_data' ) and
@@ -19,6 +34,24 @@ def __hash__(self):
19
34
"""Return hash based on remote object id."""
20
35
return self .code_data .__hash__ ()
21
36
37
+ def request (self , name , * args , ** kwargs ):
38
+ """Wrapper for nvim.request."""
39
+ return self ._session .request (name , self , * args , ** kwargs )
40
+
41
+
42
+ class RemoteApi (object ):
43
+
44
+ """Wrapper to allow api methods to be called like python methods."""
45
+
46
+ def __init__ (self , obj , api_prefix ):
47
+ """Initialize a RemoteApi with object and api prefix."""
48
+ self ._obj = obj
49
+ self ._api_prefix = api_prefix
50
+
51
+ def __getattr__ (self , name ):
52
+ """Return wrapper to named api method."""
53
+ return functools .partial (self ._obj .request , self ._api_prefix + name )
54
+
22
55
23
56
class RemoteMap (object ):
24
57
@@ -31,12 +64,12 @@ class RemoteMap(object):
31
64
It is used to provide a dict-like API to vim variables and options.
32
65
"""
33
66
34
- def __init__ (self , session , get_method , set_method , self_obj = None ):
67
+ def __init__ (self , obj , get_method , set_method = None , self_obj = None ):
35
68
"""Initialize a RemoteMap with session, getter/setter and self_obj."""
36
- self ._get = _wrap ( session , get_method , self_obj )
69
+ self ._get = functools . partial ( obj . request , get_method )
37
70
self ._set = None
38
71
if set_method :
39
- self ._set = _wrap ( session , set_method , self_obj )
72
+ self ._set = functools . partial ( obj . request , set_method )
40
73
41
74
def __getitem__ (self , key ):
42
75
"""Return a map value by key."""
@@ -91,9 +124,9 @@ class RemoteSequence(object):
91
124
locally(iteration, indexing, counting, etc).
92
125
"""
93
126
94
- def __init__ (self , session , method , self_obj = None ):
127
+ def __init__ (self , session , method ):
95
128
"""Initialize a RemoteSequence with session, method and self_obj."""
96
- self ._fetch = _wrap (session , method , self_obj )
129
+ self ._fetch = functools . partial (session . request , method )
97
130
98
131
def __len__ (self ):
99
132
"""Return the length of the remote sequence."""
@@ -120,48 +153,7 @@ def _identity(obj, session, method, kind):
120
153
return obj
121
154
122
155
123
- class SessionHook (object ):
124
-
125
- """Pair of functions to filter objects coming/going from/to Nvim.
126
-
127
- Filter functions receive the following arguments:
128
-
129
- - obj: The object to process
130
- - session: The current session object
131
- - method: The method name
132
- - kind: Kind of filter, can be one of:
133
- - 'request' for requests coming from Nvim
134
- - 'notification' for notifications coming from Nvim
135
- - 'out-request' for requests going to Nvim
136
-
137
- Whatever is returned from the function is used as a replacement for `obj`.
138
-
139
- This class also provides a `compose` method for composing hooks.
140
- """
141
-
142
- def __init__ (self , from_nvim = _identity , to_nvim = _identity ):
143
- """Initialize a SessionHook with from/to filters."""
144
- self .from_nvim = from_nvim
145
- self .to_nvim = to_nvim
146
-
147
- def compose (self , other ):
148
- """Compose two SessionHook instances.
149
-
150
- This works by composing the individual from/to filters and creating
151
- a new SessionHook instance with the composed filters.
152
- """
153
- def comp (f1 , f2 ):
154
- if f1 is _identity :
155
- return f2
156
- if f2 is _identity :
157
- return f1
158
- return lambda o , s , m , k : f1 (f2 (o , s , m , k ), s , m , k )
159
-
160
- return SessionHook (comp (other .from_nvim , self .from_nvim ),
161
- comp (other .to_nvim , self .to_nvim ))
162
-
163
-
164
- class DecodeHook (SessionHook ):
156
+ class DecodeHook (object ):
165
157
166
158
"""SessionHook subclass that decodes utf-8 strings coming from Nvim.
167
159
@@ -173,9 +165,9 @@ def __init__(self, encoding='utf-8', encoding_errors='strict'):
173
165
"""Initialize with encoding and encoding errors policy."""
174
166
self .encoding = encoding
175
167
self .encoding_errors = encoding_errors
176
- super (DecodeHook , self ).__init__ (from_nvim = self ._decode_if_bytes )
177
168
178
- def _decode_if_bytes (self , obj , session , method , kind ):
169
+ def decode_if_bytes (self , obj ):
170
+ """Decode obj if it is bytes."""
179
171
if isinstance (obj , bytes ):
180
172
return obj .decode (self .encoding , errors = self .encoding_errors )
181
173
return obj
@@ -185,67 +177,7 @@ def walk(self, obj):
185
177
186
178
Uses encoding and policy specified in constructor.
187
179
"""
188
- return walk (self ._decode_if_bytes , obj , None , None , None )
189
-
190
-
191
- class SessionFilter (object ):
192
-
193
- """Wraps a session-like object with a SessionHook instance.
194
-
195
- This class can be used as a drop-in replacement for a sessions, the
196
- difference is that a hook is applied to all data passing through a
197
- SessionFilter instance.
198
- """
199
-
200
- def __init__ (self , session , hook ):
201
- """Initialize with a Session(or SessionFilter) and a hook.
202
-
203
- If `session` is already a SessionFilter, it's hook will be extracted
204
- and composed with `hook`.
205
- """
206
- if isinstance (session , SessionFilter ):
207
- self ._hook = session ._hook .compose (hook )
208
- self ._session = session ._session
209
- else :
210
- self ._hook = hook
211
- self ._session = session
212
- # Both filters are applied to `walk` so objects are transformed
213
- # recursively
214
- self ._in = self ._hook .from_nvim
215
- self ._out = self ._hook .to_nvim
216
-
217
- def threadsafe_call (self , fn , * args , ** kwargs ):
218
- """Wrapper for Session.threadsafe_call."""
219
- self ._session .threadsafe_call (fn , * args , ** kwargs )
220
-
221
- def next_message (self ):
222
- """Wrapper for Session.next_message."""
223
- msg = self ._session .next_message ()
224
- if msg :
225
- return walk (self ._in , msg , self , msg [1 ], msg [0 ])
226
-
227
- def request (self , name , * args , ** kwargs ):
228
- """Wrapper for Session.request."""
229
- args = walk (self ._out , args , self , name , 'out-request' )
230
- return walk (self ._in , self ._session .request (name , * args , ** kwargs ),
231
- self , name , 'out-request' )
232
-
233
- def run (self , request_cb , notification_cb , setup_cb = None ):
234
- """Wrapper for Session.run."""
235
- def filter_request_cb (name , args ):
236
- result = request_cb (self ._in (name , self , name , 'request' ),
237
- walk (self ._in , args , self , name , 'request' ))
238
- return walk (self ._out , result , self , name , 'request' )
239
-
240
- def filter_notification_cb (name , args ):
241
- notification_cb (self ._in (name , self , name , 'notification' ),
242
- walk (self ._in , args , self , name , 'notification' ))
243
-
244
- self ._session .run (filter_request_cb , filter_notification_cb , setup_cb )
245
-
246
- def stop (self ):
247
- """Wrapper for Session.stop."""
248
- self ._session .stop ()
180
+ return walk (self .decode_if_bytes , obj )
249
181
250
182
251
183
def walk (fn , obj , * args ):
@@ -256,10 +188,3 @@ def walk(fn, obj, *args):
256
188
return dict ((walk (fn , k , * args ), walk (fn , v , * args )) for k , v in
257
189
obj .items ())
258
190
return fn (obj , * args )
259
-
260
-
261
- def _wrap (session , method , self_obj ):
262
- if self_obj is not None :
263
- return lambda * args : session .request (method , self_obj , * args )
264
- else :
265
- return lambda * args : session .request (method , * args )
0 commit comments