Revision 11bab021

b/ncclient/operations/rpc.py
105 105

  
106 106
    """Represents an *<rpc-error>*. It is a type of :exc:`OperationError`
107 107
    and can be raised like any other exception."""
108

  
108
    
109
    tag_to_attr = {
110
        qualify("error-type"): "_type",
111
        qualify("error-tag"): "_tag",
112
        qualify("error-severity"): "_severity",
113
        qualify("error-info"): "_info",
114
        qualify("error-path"): "_path",
115
        qualify("error-message"): "_message"
116
    }
117
    
109 118
    def __init__(self, err):
110
        self._type = None
111
        self._tag = None
112
        self._severity = None
113
        self._info = None
114
        self._path = None
115
        self._message = None
119
        for attr in tag_to_attr.values():
120
            setattr(self, attr, None)
116 121
        for subele in err:
117
            if subele.tag == qualify("error-type"):
118
                self._type = subele.text
119
            elif subele.tag == qualify("error-tag"):
120
                self._tag = subele.text
121
            elif subele.tag == qualify("error-severity"):
122
                self._severity = subele.text
123
            elif subele.tag == qualify("error-info"):
124
                self._info = subele.text
125
            elif subele.tag == qualify("error-path"):
126
                self._path = subele.text
127
            elif subele.tag == qualify("error-message"):
128
                self._message = subele.text
122
            attr = tag_to_attr.get(subele.tag, None)
123
            if attr is not None:
124
                setattr(self, attr, subele.text)
129 125
        if self.message is not None:
130 126
            OperationError.__init__(self, self.message)
131 127
        else:
132 128
            OperationError.__init__(self, self.to_dict())
133 129
    
134 130
    def to_dict(self):
135
        return {
136
            'type': self.type,
137
            'tag': self.tag,
138
            'severity': self.severity,
139
            'path': self.path,
140
            'message': self.message,
141
            'info': self.info
142
        }
131
        return dict([ (attr[1:], gettattr(self, attr)) for attr in tag_to_attr.values() ])
143 132
    
144 133
    @property
145 134
    def type(self):
......
160 149
    def path(self):
161 150
        "`string` or :const:`None`; representing text of *error-path* element"
162 151
        return self._path
163

  
152
    
164 153
    @property
165 154
    def message(self):
166 155
        "`string` or :const:`None`; representing text of *error-message* element"
167 156
        return self._message
168

  
157
    
169 158
    @property
170 159
    def info(self):
171 160
        "`string` (XML) or :const:`None`, representing *error-info* element"
172 161
        return self._info
173 162

  
174 163

  
175
class RPCReplyListener(SessionListener):
176

  
177
    # internal use
178

  
164
class RPCReplyListener(SessionListener): # internal use
165
    
166
    creation_lock = Lock()
167
    
179 168
    # one instance per session -- maybe there is a better way??
180 169
    def __new__(cls, session):
181
        instance = session.get_listener_instance(cls)
182
        if instance is None:
183
            instance = object.__new__(cls)
184
            instance._lock = Lock()
185
            instance._id2rpc = {}
186
            #instance._pipelined = session.can_pipeline
187
            session.add_listener(instance)
188
        return instance
170
        with creation_lock:
171
            instance = session.get_listener_instance(cls)
172
            if instance is None:
173
                instance = object.__new__(cls)
174
                instance._lock = Lock()
175
                instance._id2rpc = {}
176
                #instance._pipelined = session.can_pipeline
177
                session.add_listener(instance)
178
            return instance
189 179

  
190 180
    def register(self, id, rpc):
191 181
        with self._lock:
......
199 189
            if key == "message-id": # if we found msgid attr
200 190
                id = attrs[key] # get the msgid
201 191
                with self._lock:
202
                    try:                    
192
                    try:
203 193
                        rpc = self._id2rpc[id] # the corresponding rpc
204 194
                        logger.debug("Delivering to %r" % rpc)
205 195
                        rpc.deliver_reply(raw)
206 196
                    except KeyError:
207
                        raise OperationError("Unknown message-id: %s", id)
197
                        raise OperationError("Unknown 'message-id': %s", id)
208 198
                    # no catching other exceptions, fail loudly if must
209 199
                    else:
210 200
                        # if no error delivering, can del the reference to the RPC

Also available in: Unified diff