sessionlistener
authorShikhar Bhushan <shikhar@schmizz.net>
Sun, 26 Apr 2009 07:02:37 +0000 (07:02 +0000)
committerShikhar Bhushan <shikhar@schmizz.net>
Sun, 26 Apr 2009 07:02:37 +0000 (07:02 +0000)
git-svn-id: http://ncclient.googlecode.com/svn/trunk@68 6dbcf712-26ac-11de-a2f3-1373824ab735

ncclient/operations/listener.py [new file with mode: 0644]
ncclient/operations/rpc.py

diff --git a/ncclient/operations/listener.py b/ncclient/operations/listener.py
new file mode 100644 (file)
index 0000000..7fe761c
--- /dev/null
@@ -0,0 +1,100 @@
+# Copyright 2009 Shikhar Bhushan
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from threading import Lock
+from weakref import WeakValueDictionary
+
+from . import logger
+from ncclient.content.parsers import RootParser
+from ncclient.content.common import qualify as _
+from ncclient.content.common import unqualify as __
+from ncclient.content.common import BASE_NS, CISCO_BS
+
+class SessionListener:
+    
+    '''This is the glue between received data and the object it should be
+    forwarded to.
+    '''
+    
+    def __init__(self):
+        # this dictionary takes care of <rpc-reply> elements received
+        # { 'message-id': obj } dict
+        self._id2rpc = WeakValueDictionary()
+        # this is a more generic dict takes care of other top-level elements
+        # that may be received, e.g. <notification>'s
+        # {'tag': obj} dict
+        self._tag2obj = WeakValueDictionary() 
+        # if we receive a SessionCloseError it might not be one we want to act on
+        self._expecting_close = False
+        self._errback = None # error event callback
+        self._lock = Lock()
+    
+    def __str__(self):
+        return 'SessionListener'
+    
+    def register(self, msgid, rpc):
+        with self._lock:
+            self._id2rpc[msgid] = rpc
+    
+    def recognize(self, tag, obj):
+        with self._lock:
+            self._tag2obj[tag] = obj
+    
+    def expect_close(self):
+        self._expecting_close = True
+    
+    @property
+    def _recognized_elements(self):
+        elems = [ 'rpc-reply' ] 
+        with self._lock:
+            elems.extend(self._tag2obj.keys())
+        return elems
+    
+    def set_errback(self, errback):
+        self._errback = errback
+    
+    def received(self, raw):
+        res = RootParser.parse(raw, self._recognized_elements)
+        if res is not None:
+            (tag, attrs) = res
+        else:
+            return
+        logger.debug('SessionListener.reply: parsed (%r, %r)' % res)
+        try:
+            cb = None
+            if tag == 'rpc-reply':
+                id = attrs.get('message-id', None)
+                if id is None:
+                    logger.warning('<rpc-reply> w/o message-id attr received: %s' % raw)
+                else:
+                    obj = self._id2rpc.get(id, None)
+            else:
+                obj = self._tag2obj.get(tag, None)
+            if obj is not None:
+                obj.deliver(raw)
+        except Exception as e:
+            logger.warning('SessionListener.reply: %r' % e)
+    
+    def error(self, err):
+        from ncclient.transport.errors import SessionCloseError
+        act = True
+        if isinstance(err, SessionCloseError):
+            logger.debug('session closed, expecting_close=%s' %
+                         self._expecting_close)
+            if self._expecting_close:
+                act = False
+        if act:
+            logger.error('SessionListener.error: %r' % err)
+            if self._errback is not None:
+                errback(err)
index 8cd1a93..7af4fdc 100644 (file)
@@ -18,6 +18,7 @@ from weakref import WeakKeyDictionary
 
 from listener import SessionListener
 from ncclient.content.builders import RPCBuilder
+from ncclient.content.parsers import RPCReplyParser
 
 class RPC:
     
@@ -84,17 +85,17 @@ class RPCReply:
     def __init__(self, raw):
         self._raw = raw
         self._parsed = False
-        self._ok = None
         self._errs = []
     
     def __str__(self):
         return self._raw
     
     def parse(self):
-        #errs = RPCParser.parse(self._raw)
-        #for raw, err_dict in errs:
-        #    self._errs.append(RPCError(raw, err_dict))
-        self._parsed = True
+        if not self._parsed:
+            errs = RPCReplyParser.parse(self._raw)
+            for raw, err_dict in errs:
+                self._errs.append(RPCError(raw, err_dict))
+            self._parsed = True
     
     @property
     def raw(self):
@@ -111,10 +112,6 @@ class RPCReply:
     @property
     def errors(self):
         return self._errs
-    
-    @property
-    def raw(self):
-        return self._raw
 
 class RPCError(Exception): # raise it if you like