Revision 7fe0bf33
b/ncclient/content/parsers.py | ||
---|---|---|
38 | 38 |
capabilities.append(cap.text) |
39 | 39 |
return sid, capabilities |
40 | 40 |
|
41 |
|
|
41 | 42 |
class RootParser: |
42 | 43 |
'''Parser for the top-level element of an XML document. Does not look at any |
43 |
sub-elements. It is useful for efficiently determining the type of received |
|
44 |
messages.
|
|
44 |
sub-elements. It is useful for efficiently determining the type of a received
|
|
45 |
message. |
|
45 | 46 |
''' |
46 | 47 |
|
47 | 48 |
@staticmethod |
... | ... | |
49 | 50 |
'''Parse the top-level element from a string representing an XML document. |
50 | 51 |
|
51 | 52 |
recognized is a list of tag names that will be successfully parsed. |
52 |
The tag names should not be qualified. This is for simplicity of parsing |
|
53 |
where the NETCONF implementation is non-compliant (e.g. cisco's which |
|
54 |
uses an incorrect namespace) |
|
53 |
The tag names should be qualified with namespace. |
|
55 | 54 |
|
56 | 55 |
Returns a `(tag, attributes)` tuple, where `tag` is a string representing |
57 | 56 |
the qualified name of the recognized element and `attributes` is an |
... | ... | |
60 | 59 |
fp = StringIO(raw) |
61 | 60 |
for event, element in ET.iterparse(fp, events=('start',)): |
62 | 61 |
for ele in recognized: |
63 |
if __(element.tag) == ele: |
|
64 |
attrs = {} |
|
65 |
for attr in element.attrib: |
|
66 |
attrs[__(attr)] = element.attrib[attr] |
|
67 |
return (ele, attrs) |
|
62 |
if element.tag == ele: |
|
63 |
return (element.tag, element.attrib) |
|
68 | 64 |
break |
69 | 65 |
|
70 | 66 |
|
71 | 67 |
class RPCReplyParser: |
72 | 68 |
|
73 | 69 |
@staticmethod |
70 |
def parse_rpc_error(root, ns): |
|
71 |
err_dict = {} |
|
72 |
for tag in ('error-type', 'error-tag', 'error-severity', 'error-app-tag', |
|
73 |
'error-path', 'error-message', 'error-info'): |
|
74 |
ele = root.find(_(tag, ns)) |
|
75 |
if ele is not None: |
|
76 |
err_dict[tag] = ele.text |
|
77 |
|
|
78 |
@staticmethod |
|
74 | 79 |
def parse(raw): |
75 |
pass |
|
80 |
oktags = (_('ok', BASE_NS), _('ok', CISCO_NS)) |
|
81 |
root = ET.fromstring(raw) |
|
82 |
ok = root.find(_('ok', BASE_NS)) |
|
83 |
if ok is None: |
|
84 |
ok = root.find(_('ok', CISCO_BS)) |
|
85 |
ns = BASE_NS |
|
86 |
errs = root.findall(_('rpc-error', BASE_NS)) |
|
87 |
if not errs: |
|
88 |
errs = root.findall(_('rpc-error', CISCO_BS)) |
|
89 |
ns = CISCO_NS |
|
90 |
ret = [ (err, RPCReplyParser.parse_rpc_error(err, ns)) for err in errs ] |
|
91 |
return ok, ret |
b/ncclient/operations/listener.py | ||
---|---|---|
21 | 21 |
from ncclient.content.common import unqualify as __ |
22 | 22 |
from ncclient.content.common import BASE_NS, CISCO_BS |
23 | 23 |
|
24 |
q_rpcreply = [_('rpc-reply', BASE_NS), _('rpc-reply', CISCO_BS)] |
|
25 |
|
|
24 | 26 |
class SessionListener: |
25 | 27 |
|
26 | 28 |
'''This is the glue between received data and the object it should be |
... | ... | |
56 | 58 |
|
57 | 59 |
@property |
58 | 60 |
def _recognized_elements(self): |
59 |
elems = [ 'rpc-reply' ]
|
|
61 |
elems = q_rpcreply
|
|
60 | 62 |
with self._lock: |
61 | 63 |
elems.extend(self._tag2obj.keys()) |
62 | 64 |
return elems |
... | ... | |
67 | 69 |
def received(self, raw): |
68 | 70 |
res = RootParser.parse(raw, self._recognized_elements) |
69 | 71 |
if res is not None: |
70 |
(tag, attrs) = res
|
|
72 |
tag, attrs = res # unpack
|
|
71 | 73 |
else: |
72 | 74 |
return |
73 | 75 |
logger.debug('SessionListener.reply: parsed (%r, %r)' % res) |
74 | 76 |
try: |
75 |
cb = None |
|
76 |
if tag == 'rpc-reply': |
|
77 |
id = attrs.get('message-id', None) |
|
78 |
if id is None: |
|
79 |
logger.warning('<rpc-reply> w/o message-id attr received: %s' % raw) |
|
77 |
obj = None |
|
78 |
if tag in q_rpcreply: |
|
79 |
for key in attrs: |
|
80 |
if __(key) == 'message-id': |
|
81 |
id = attrs[key] |
|
82 |
break |
|
80 | 83 |
else: |
81 |
obj = self._id2rpc.get(id, None) |
|
84 |
logger.warning('<rpc-reply> without message-id received: %s' |
|
85 |
% raw) |
|
86 |
obj = self._id2rpc.get(id, None) |
|
82 | 87 |
else: |
83 | 88 |
obj = self._tag2obj.get(tag, None) |
84 | 89 |
if obj is not None: |
b/ncclient/operations/session.py | ||
---|---|---|
25 | 25 |
|
26 | 26 |
def deliver(self, reply): |
27 | 27 |
RPC.deliver(self, reply) |
28 |
# can't be too huge a reply, should be ok to parse in callback |
|
28 | 29 |
self._reply.parse() |
29 | 30 |
if self._reply.ok: |
30 | 31 |
self._listener.expect_close() |
Also available in: Unified diff