11"""Code shared between the API classes."""
2+ import functools
23
34
45class Remote (object ):
@@ -10,6 +11,20 @@ class Remote(object):
1011 object handle into consideration.
1112 """
1213
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+
1328 def __eq__ (self , other ):
1429 """Return True if `self` and `other` are the same object."""
1530 return (hasattr (other , 'code_data' ) and
@@ -19,6 +34,24 @@ def __hash__(self):
1934 """Return hash based on remote object id."""
2035 return self .code_data .__hash__ ()
2136
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+
2255
2356class RemoteMap (object ):
2457
@@ -31,12 +64,12 @@ class RemoteMap(object):
3164 It is used to provide a dict-like API to vim variables and options.
3265 """
3366
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 ):
3568 """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 )
3770 self ._set = None
3871 if set_method :
39- self ._set = _wrap ( session , set_method , self_obj )
72+ self ._set = functools . partial ( obj . request , set_method )
4073
4174 def __getitem__ (self , key ):
4275 """Return a map value by key."""
@@ -91,9 +124,9 @@ class RemoteSequence(object):
91124 locally(iteration, indexing, counting, etc).
92125 """
93126
94- def __init__ (self , session , method , self_obj = None ):
127+ def __init__ (self , session , method ):
95128 """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 )
97130
98131 def __len__ (self ):
99132 """Return the length of the remote sequence."""
@@ -120,48 +153,7 @@ def _identity(obj, session, method, kind):
120153 return obj
121154
122155
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 ):
165157
166158 """SessionHook subclass that decodes utf-8 strings coming from Nvim.
167159
@@ -173,9 +165,9 @@ def __init__(self, encoding='utf-8', encoding_errors='strict'):
173165 """Initialize with encoding and encoding errors policy."""
174166 self .encoding = encoding
175167 self .encoding_errors = encoding_errors
176- super (DecodeHook , self ).__init__ (from_nvim = self ._decode_if_bytes )
177168
178- def _decode_if_bytes (self , obj , session , method , kind ):
169+ def decode_if_bytes (self , obj ):
170+ """Decode obj if it is bytes."""
179171 if isinstance (obj , bytes ):
180172 return obj .decode (self .encoding , errors = self .encoding_errors )
181173 return obj
@@ -185,67 +177,7 @@ def walk(self, obj):
185177
186178 Uses encoding and policy specified in constructor.
187179 """
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 )
249181
250182
251183def walk (fn , obj , * args ):
@@ -256,10 +188,3 @@ def walk(fn, obj, *args):
256188 return dict ((walk (fn , k , * args ), walk (fn , v , * args )) for k , v in
257189 obj .items ())
258190 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