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)
|