Statistics
| Branch: | Tag: | Revision:

root / ncclient / glue.py @ 41e2ed46

History | View | Annotate | Download (3.2 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
"TODO: docstring"
16

    
17
from cStringIO import StringIO
18
from threading import Thread
19
from Queue import Queue
20
from threading import Lock
21
from xml.etree import cElementTree as ET
22

    
23
import logging
24
logger = logging.getLogger('ncclient.glue')
25

    
26
def parse_root(raw):
27
    '''Parse the top-level element from a string representing an XML document.
28
    
29
    Returns a `(tag, attributes)` tuple, where `tag` is a string representing
30
    the qualified name of the root element and `attributes` is an
31
    `{attribute: value}` dictionary.
32
    '''
33
    fp = StringIO(raw)
34
    for event, element in ET.iterparse(fp, events=('start',)):
35
        return (element.tag, element.attrib)
36

    
37

    
38
class Subject(Thread):
39
    
40
    'Meant for subclassing by transport.Session'
41

    
42
    def __init__(self):
43
        "TODO: docstring"
44
        Thread.__init__(self)
45
        self._q = Queue()
46
        self._listeners = set() # TODO(?) weakref
47
        self._lock = Lock()
48
    
49
    def _dispatch_message(self, raw):
50
        "TODO: docstring"
51
        root = parse_root(raw)
52
        with self._lock:
53
            listeners = list(self._listeners)
54
        for l in listeners:
55
            logger.debug('dispatching message to %r' % l)
56
            try:
57
                l.callback(root, raw)
58
            except Exception as e:
59
                logger.warning('[error] %r' % e)
60
    
61
    def _dispatch_error(self, err):
62
        "TODO: docstring"
63
        with self._lock:
64
            listeners = list(self._listeners)
65
        for l in listeners:
66
            logger.debug('dispatching error to %r' % l)
67
            try:
68
                l.errback(err)
69
            except Exception as e:
70
                logger.warning('error %r' % e)
71
    
72
    def add_listener(self, listener):
73
        "TODO: docstring"
74
        logger.debug('installing listener %r' % listener)
75
        with self._lock:
76
            self._listeners.add(listener)
77
    
78
    def remove_listener(self, listener):
79
        "TODO: docstring"
80
        logger.debug('discarding listener %r' % listener)
81
        with self._lock:
82
            self._listeners.discard(listener)
83
    
84
    def get_listener_instance(self, cls):
85
        '''This is useful when we want to maintain one listener of a particular
86
        type per subject i.e. a multiton.
87
        '''
88
        with self._lock:
89
            for listener in self._listeners:
90
                if isinstance(listener, cls):
91
                    return listener
92
    
93
    def send(self, message):
94
        "TODO: docstring"
95
        logger.debug('queueing %s' % message)
96
        self._q.put(message)
97

    
98

    
99
class Listener(object):
100
    
101
    "TODO: docstring"
102
    
103
    def callback(self, root, raw):
104
        raise NotImplementedError
105
    
106
    def errback(self, err):
107
        raise NotImplementedError