Statistics
| Branch: | Tag: | Revision:

root / ncclient / operations / rpc.py @ 11d9e642

History | View | Annotate | Download (2.9 kB)

1
# Copyright 2009 Shikhar Bhushan
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
6
#
7
#    http://www.apache.org/licenses/LICENSE-2.0
8
#
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
14

    
15
from threading import Event, Lock
16
from uuid import uuid1
17

    
18
from . import logger
19

    
20
class RPC:
21
        
22
    def __init__(self, session, async=False):
23
        self._session = session
24
        self._id = uuid1().urn
25
        self._reply = RPCReply()
26
        self._reply_event = Event()
27
    
28
    def _build(self, op, encoding='utf-8'):
29
        if isinstance(op, basestring):
30
            return RPCBuilder.build_from_string(self._id, op, encoding)
31
        else:
32
            return RPCBuilder.build_from_spec(self._id, op, encoding)
33
    
34
    def _request(self, op):
35
        self._reply = RPCReply()
36
        # get the listener instance for this session
37
        # <rpc-reply> with message id will reach response_cb
38
        self._listener.register(self._id, self)
39
        # only effective the first time, transport.session.Subject internally
40
        # uses a set type for listeners
41
        self._session.add_listener(self._listener)
42
        req = RPCBuilder.build(self._id, op)
43
        self._session.send(req)
44
        if reply_event is not None: # if we were provided an Event to use
45
            self._reply_event = reply_event
46
        else: # otherwise, block till response received and return it
47
            self._reply_event = Event()
48
            self._reply_event.wait()
49
            self._reply.parse()
50
        return self._reply
51
    
52
    def request(self, *args, **kwds):
53
        raise NotImplementedError
54
    
55
    @property
56
    def has_reply(self):
57
        try:
58
            return self._reply_event.isSet()
59
        except TypeError: # reply_event is None
60
            return False
61
    
62
    @property
63
    def reply(self):
64
        return self._reply
65
    
66
    @property
67
    def id(self):
68
        return self._id
69
    
70
    @property
71
    def session(self):
72
        return self._session
73
    
74
    @staticmethod
75
    def build_from_spec(msgid, opspec, encoding='utf-8'):
76
        "TODO: docstring"
77
        spec = {
78
            'tag': _('rpc', BASE_NS),
79
            'attributes': {'message-id': msgid},
80
            'children': opspec
81
            }
82
        return TreeBuilder(spec).to_string(encoding)
83
    
84
    @staticmethod
85
    def build_from_string(msgid, opstr, encoding='utf-8'):
86
        "TODO: docstring"
87
        decl = '<?xml version="1.0" encoding="%s"?>' % encoding
88
        doc = (u'''<rpc message-id="%s" xmlns="%s">%s</rpc>''' %
89
               (msgid, BASE_NS, opstr)).encode(encoding)
90
        return (decl + doc)