~neovim-ppa/neovim-ppa/python-neovim

« back to all changes in this revision

Viewing changes to neovim/rpc_stream.py

  • Committer: Thiago de Arruda
  • Date: 2014-05-13 23:01:56 UTC
  • Revision ID: git-v1:cd7ef838ce097f060607a6d35ae6209615e175fd
Add license and update readme

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
from collections import deque
2
 
import logging
3
 
 
4
 
logger = logging.getLogger(__name__)
5
 
debug, info, warn = (logger.debug, logger.info, logger.warn,)
6
 
 
7
 
class RPCStream(object):
8
 
    def __init__(self, stream):
9
 
        self.stream = stream
10
 
        self.pending_requests = {}
11
 
        self.next_request_id = 1
12
 
        self.interrupted = False
13
 
        self.posted_notifications = deque()
14
 
 
15
 
 
16
 
    def post(self, name, args):
17
 
        self.posted_notifications.append((name, args,))
18
 
        self.stream.interrupt()
19
 
 
20
 
 
21
 
    def send(self, method, args, response_cb):
22
 
        request_id = self.next_request_id
23
 
        # Update request id
24
 
        self.next_request_id = request_id + 1
25
 
        # Send the request
26
 
        self.stream.send([0, request_id, method, args])
27
 
        # set the callback
28
 
        self.pending_requests[request_id] = response_cb
29
 
 
30
 
 
31
 
    def loop_start(self, request_cb, notification_cb, error_cb):
32
 
        def msg_cb(msg):
33
 
            msg_type = msg[0]
34
 
            if msg_type == 0:
35
 
                # request
36
 
                #   - msg[1]: id
37
 
                #   - msg[2]: method name
38
 
                #   - msg[3]: arguments
39
 
                debug('received request: %s, %s', msg[2], msg[3])
40
 
                request_cb(msg[2], msg[3], reply_fn(self.stream, msg[1]))
41
 
            elif msg_type == 1:
42
 
                # response to a previous request:
43
 
                #   - msg[1]: the id
44
 
                #   - msg[2]: error(if any)
45
 
                #   - msg[3]: result(if not errored)
46
 
                debug('received response: %s, %s', msg[2], msg[3])
47
 
                self.pending_requests.pop(msg[1])(msg[2], msg[3])
48
 
            elif msg_type == 2:
49
 
                # notification/event
50
 
                #   - msg[1]: event name
51
 
                #   - msg[2]: arguments
52
 
                debug('received notification: %s, %s', msg[1], msg[2])
53
 
                notification_cb(msg[1], msg[2])
54
 
            else:
55
 
                error = 'Received invalid message %s' % msg
56
 
                warn(error)
57
 
                raise Exception(error)
58
 
 
59
 
        self.stream.loop_start(msg_cb, error_cb)
60
 
 
61
 
        while self.posted_notifications:
62
 
            notification_cb(*self.posted_notifications.popleft())
63
 
            self.stream.loop_start(msg_cb, error_cb)
64
 
 
65
 
 
66
 
    def loop_stop(self):
67
 
        self.stream.loop_stop()
68
 
 
69
 
 
70
 
def reply_fn(stream, request_id):
71
 
    def reply(value, error=False):
72
 
        if error:
73
 
            resp = [1, request_id, value, None]
74
 
        else:
75
 
            resp = [1, request_id, None, value]
76
 
        stream.send(resp)
77
 
 
78
 
    return reply