Revision f0271461

b/ncclient/operations/listener.py
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 Lock
16
from weakref import WeakValueDictionary
17

  
18
from . import logger
19
from ncclient.content.parsers import RootParser
20
from ncclient.content.common import qualify as _
21
from ncclient.content.common import unqualify as __
22
from ncclient.content.common import BASE_NS, CISCO_BS
23

  
24
class SessionListener:
25
    
26
    '''This is the glue between received data and the object it should be
27
    forwarded to.
28
    '''
29
    
30
    def __init__(self):
31
        # this dictionary takes care of <rpc-reply> elements received
32
        # { 'message-id': obj } dict
33
        self._id2rpc = WeakValueDictionary()
34
        # this is a more generic dict takes care of other top-level elements
35
        # that may be received, e.g. <notification>'s
36
        # {'tag': obj} dict
37
        self._tag2obj = WeakValueDictionary() 
38
        # if we receive a SessionCloseError it might not be one we want to act on
39
        self._expecting_close = False
40
        self._errback = None # error event callback
41
        self._lock = Lock()
42
    
43
    def __str__(self):
44
        return 'SessionListener'
45
    
46
    def register(self, msgid, rpc):
47
        with self._lock:
48
            self._id2rpc[msgid] = rpc
49
    
50
    def recognize(self, tag, obj):
51
        with self._lock:
52
            self._tag2obj[tag] = obj
53
    
54
    def expect_close(self):
55
        self._expecting_close = True
56
    
57
    @property
58
    def _recognized_elements(self):
59
        elems = [ 'rpc-reply' ] 
60
        with self._lock:
61
            elems.extend(self._tag2obj.keys())
62
        return elems
63
    
64
    def set_errback(self, errback):
65
        self._errback = errback
66
    
67
    def received(self, raw):
68
        res = RootParser.parse(raw, self._recognized_elements)
69
        if res is not None:
70
            (tag, attrs) = res
71
        else:
72
            return
73
        logger.debug('SessionListener.reply: parsed (%r, %r)' % res)
74
        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)
80
                else:
81
                    obj = self._id2rpc.get(id, None)
82
            else:
83
                obj = self._tag2obj.get(tag, None)
84
            if obj is not None:
85
                obj.deliver(raw)
86
        except Exception as e:
87
            logger.warning('SessionListener.reply: %r' % e)
88
    
89
    def error(self, err):
90
        from ncclient.transport.errors import SessionCloseError
91
        act = True
92
        if isinstance(err, SessionCloseError):
93
            logger.debug('session closed, expecting_close=%s' %
94
                         self._expecting_close)
95
            if self._expecting_close:
96
                act = False
97
        if act:
98
            logger.error('SessionListener.error: %r' % err)
99
            if self._errback is not None:
100
                errback(err)
b/ncclient/operations/rpc.py
18 18

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

  
22 23
class RPC:
23 24
    
......
84 85
    def __init__(self, raw):
85 86
        self._raw = raw
86 87
        self._parsed = False
87
        self._ok = None
88 88
        self._errs = []
89 89
    
90 90
    def __str__(self):
91 91
        return self._raw
92 92
    
93 93
    def parse(self):
94
        #errs = RPCParser.parse(self._raw)
95
        #for raw, err_dict in errs:
96
        #    self._errs.append(RPCError(raw, err_dict))
97
        self._parsed = True
94
        if not self._parsed:
95
            errs = RPCReplyParser.parse(self._raw)
96
            for raw, err_dict in errs:
97
                self._errs.append(RPCError(raw, err_dict))
98
            self._parsed = True
98 99
    
99 100
    @property
100 101
    def raw(self):
......
111 112
    @property
112 113
    def errors(self):
113 114
        return self._errs
114
    
115
    @property
116
    def raw(self):
117
        return self._raw
118 115

  
119 116
class RPCError(Exception): # raise it if you like
120 117
    

Also available in: Unified diff