Revision 11d9e642 ncclient/operations/rpc.py

b/ncclient/operations/rpc.py
14 14

  
15 15
from threading import Event, Lock
16 16
from uuid import uuid1
17
from weakref import WeakKeyDictionary
18 17

  
19 18
from . import logger
20
from listener import SessionListener
21
from ncclient.content.builders import RPCBuilder
22
from ncclient.content.parsers import RPCReplyParser
23

  
24
_listeners = WeakKeyDictionary()
25
_lock = Lock()
26

  
27
def get_listener(session):
28
    with self._lock:
29
        return _listeners.setdefault(session, ReplyListener())
30 19

  
31 20
class RPC:
32 21
        
33
    def __init__(self, session):
22
    def __init__(self, session, async=False):
34 23
        self._session = session
35
        self._id = None
36
        self._reply = None # RPCReply
37
        self._reply_event = None
24
        self._id = uuid1().urn
25
        self._reply = RPCReply()
26
        self._reply_event = Event()
38 27
    
39
    @property
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)
40 33
    
41 34
    def _request(self, op):
42
        self._id = uuid1().urn
43 35
        self._reply = RPCReply()
44 36
        # get the listener instance for this session
45 37
        # <rpc-reply> with message id will reach response_cb
......
78 70
    @property
79 71
    def session(self):
80 72
        return self._session
81

  
82
class RPCReply:
83
    
84
    def __init__(self, event):
85
        self._delivery_event = event
86
        self._raw = None
87
        self._errs = None
88
    
89
    def __str__(self):
90
        return self._raw
91
    
92
    def parse(self):
93
        if not self._parsed:
94
            errs = RPCReplyParser.parse(self._raw)
95
            for raw, err_dict in errs:
96
                self._errs.append(RPCError(raw, err_dict))
97
            self._parsed = True
98
    
99
    def deliver(self, raw):
100
        self._raw = raw
101
        self._delivery_event.set()
102
    
103
    def received(self, timeout=None):
104
        self._delivery_event.wait(timeout)
105
        return True
106
    
107
    @property
108
    def raw(self):
109
        return self._raw
110
    
111
    @property
112
    def parsed(self):
113
        return self._parsed
114
    
115
    @property
116
    def ok(self):
117
        return True if self._parsed and not self._errs else False
118
    
119
    @property
120
    def errors(self):
121
        return self._errs
122

  
123
class RPCError(Exception): # raise it if you like
124
    
125
    def __init__(self, raw, err_dict):
126
        self._raw = raw
127
        self._dict = err_dict
128

  
129
    def __str__(self):
130
        # TODO
131
        return self._raw
132
    
133
    def __dict__(self):
134
        return self._dict
135
    
136
    @property
137
    def raw(self):
138
        return self._raw
139 73
    
140
    @property
141
    def type(self):
142
        return self._dict.get('type', None)
143
    
144
    @property
145
    def severity(self):
146
        return self._dict.get('severity', None)
147
    
148
    @property
149
    def tag(self):
150
        return self._dict.get('tag', None)
151
    
152
    @property
153
    def path(self):
154
        return self._dict.get('path', None)
155
    
156
    @property
157
    def message(self):
158
        return self._dict.get('message', None)
159
    
160
    @property
161
    def info(self):
162
        return self._dict.get('info', None)
163

  
164
class Notification:
165
    
166
    pass
167

  
168

  
169

  
170
from builder import TreeBuilder
171
from common import BASE_NS
172
from common import qualify as _
173

  
174
################################################################################
175

  
176
_ = qualify
177

  
178
def build(msgid, op, encoding='utf-8'):
179
    "TODO: docstring"
180
    if isinstance(op, basestring):
181
        return RPCBuilder.build_from_string(msgid, op, encoding)
182
    else:
183
        return RPCBuilder.build_from_spec(msgid, op, encoding)
184

  
185
def build_from_spec(msgid, opspec, encoding='utf-8'):
186
    "TODO: docstring"
187
    spec = {
188
        'tag': _('rpc', BASE_NS),
189
        'attributes': {'message-id': msgid},
190
        'children': opspec
191
        }
192
    return TreeBuilder(spec).to_string(encoding)
193

  
194
def build_from_string(msgid, opstr, encoding='utf-8'):
195
    "TODO: docstring"
196
    decl = '<?xml version="1.0" encoding="%s"?>' % encoding
197
    doc = (u'''<rpc message-id="%s" xmlns="%s">%s</rpc>''' %
198
           (msgid, BASE_NS, opstr)).encode(encoding)
199
    return (decl + doc)
200

  
201
################################################################################
202

  
203
# parsing stuff TODO
204

  
205

  
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)

Also available in: Unified diff