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