Revision 0b7d3b31

b/docs/build/latex/ncclient.idx
119 119
\indexentry{DiscardChanges (class in ncclient.operations)|hyperpage}{12}
120 120
\indexentry{request() (ncclient.operations.DiscardChanges method)|hyperpage}{12}
121 121
\indexentry{CloseSession (class in ncclient.operations)|hyperpage}{12}
122
\indexentry{request() (ncclient.operations.CloseSession method)|hyperpage}{12}
122 123
\indexentry{KillSession (class in ncclient.operations)|hyperpage}{12}
124
\indexentry{request() (ncclient.operations.KillSession method)|hyperpage}{12}
123 125
\indexentry{LockContext (class in ncclient.operations)|hyperpage}{13}
124 126
\indexentry{OperationError|hyperpage}{13}
125 127
\indexentry{TimeoutExpiredError|hyperpage}{13}
b/docs/build/latex/ncclient.ilg
1 1
This is makeindex, version 2.15 [20-Nov-2007] (kpathsea + Thai support).
2 2
Scanning style file ./python.ist......done (6 attributes redefined, 0 ignored).
3
Scanning input file ncclient.idx....done (126 entries accepted, 0 rejected).
4
Sorting entries....done (923 comparisons).
5
Generating output file ncclient.ind....done (192 lines written, 0 warnings).
3
Scanning input file ncclient.idx....done (128 entries accepted, 0 rejected).
4
Sorting entries....done (941 comparisons).
5
Generating output file ncclient.ind....done (194 lines written, 0 warnings).
6 6
Output written in ncclient.ind.
7 7
Transcript written in ncclient.ilg.
b/docs/build/latex/ncclient.ind
129 129
  \item remove() (ncclient.capabilities.Capabilities method), \hyperpage{4}
130 130
  \item remove\_listener() (ncclient.transport.Session method), \hyperpage{7}
131 131
  \item reply (ncclient.operations.rpc.RPC attribute), \hyperpage{9}
132
  \item request() (ncclient.operations.CloseSession method), \hyperpage{12}
132 133
  \item request() (ncclient.operations.Commit method), \hyperpage{12}
133 134
  \item request() (ncclient.operations.CopyConfig method), \hyperpage{12}
134 135
  \item request() (ncclient.operations.DeleteConfig method), \hyperpage{12}
......
136 137
  \item request() (ncclient.operations.EditConfig method), \hyperpage{11}
137 138
  \item request() (ncclient.operations.Get method), \hyperpage{10}
138 139
  \item request() (ncclient.operations.GetConfig method), \hyperpage{11}
140
  \item request() (ncclient.operations.KillSession method), \hyperpage{12}
139 141
  \item request() (ncclient.operations.Lock method), \hyperpage{11}
140 142
  \item request() (ncclient.operations.Unlock method), \hyperpage{11}
141 143
  \item request() (ncclient.operations.Validate method), \hyperpage{12}
b/docs/build/latex/ncclient.log
1
This is pdfTeXk, Version 3.1415926-1.40.9 (Web2C 7.5.7) (format=pdflatex 2009.2.28)  17 MAY 2009 04:41
1
This is pdfTeXk, Version 3.1415926-1.40.9 (Web2C 7.5.7) (format=pdflatex 2009.2.28)  17 MAY 2009 04:51
2 2
entering extended mode
3 3
 %&-line parsing enabled.
4 4
**ncclient.tex
......
846 846
Chapter 1.
847 847
LaTeX Font Info:    Font shape `T1/phv/bx/n' in size <14.4> not available
848 848
(Font)              Font shape `T1/phv/b/n' tried instead on input line 92.
849
LaTeX Font Info:    Try loading font information for TS1+ptm on input line 98.
849
LaTeX Font Info:    Try loading font information for TS1+ptm on input line 100.
850

  
850 851
(/usr/share/texmf-dist/tex/latex/psnfss/ts1ptm.fd
851 852
File: ts1ptm.fd 2001/06/04 font definitions for TS1/ptm.
852 853
)
853 854
LaTeX Font Info:    Font shape `T1/pcr/bx/n' in size <9> not available
854
(Font)              Font shape `T1/pcr/b/n' tried instead on input line 118.
855
(Font)              Font shape `T1/pcr/b/n' tried instead on input line 120.
855 856
 [1
856 857

  
857 858

  
......
860 861
]
861 862
Chapter 2.
862 863
LaTeX Font Info:    Font shape `T1/pcr/bx/n' in size <14.4> not available
863
(Font)              Font shape `T1/pcr/b/n' tried instead on input line 137.
864
(Font)              Font shape `T1/pcr/b/n' tried instead on input line 139.
864 865
LaTeX Font Info:    Font shape `T1/phv/bx/n' in size <12> not available
865
(Font)              Font shape `T1/phv/b/n' tried instead on input line 143.
866
(Font)              Font shape `T1/phv/b/n' tried instead on input line 145.
866 867
LaTeX Font Info:    Font shape `T1/pcr/bx/n' in size <10> not available
867
(Font)              Font shape `T1/pcr/b/n' tried instead on input line 148.
868
(Font)              Font shape `T1/pcr/b/n' tried instead on input line 150.
868 869
[3] [4] [5] [6]
869
Underfull \hbox (badness 5985) in paragraph at lines 701--703
870
Underfull \hbox (badness 5985) in paragraph at lines 703--705
870 871
[]\T1/ptm/m/n/10 This de-fault call-back al-ways re-turns [][]\T1/pcr/m/n/10 Fa
871 872
lse[][]\T1/ptm/m/n/10 , which would lead to \T1/pcr/m/n/10 connect() \T1/ptm/m/
872 873
n/10 rais-ing a
......
874 875

  
875 876
[7] [8] [9]
876 877
LaTeX Font Info:    Font shape `T1/ptm/bx/it' in size <10> not available
877
(Font)              Font shape `T1/ptm/b/it' tried instead on input line 992.
878
(Font)              Font shape `T1/ptm/b/it' tried instead on input line 994.
878 879
 [10] [11] [12] [13] [14
879 880

  
880 881
]
......
920 921
[19
921 922

  
922 923
]
923
Underfull \hbox (badness 10000) in paragraph at lines 135--136
924
Underfull \hbox (badness 10000) in paragraph at lines 136--137
924 925
[]\T1/ptm/m/n/10 request() (nc-client.operations.DiscardChanges
925 926
 []
926 927

  
927 928

  
928
Underfull \hbox (badness 10000) in paragraph at lines 151--152
929
Underfull \hbox (badness 10000) in paragraph at lines 153--154
929 930
[]\T1/ptm/m/n/10 server_capabilities (nc-client.manager.Manager at-
930 931
 []
931 932

  
932 933

  
933
Underfull \hbox (badness 10000) in paragraph at lines 152--153
934
Underfull \hbox (badness 10000) in paragraph at lines 154--155
934 935
[]\T1/ptm/m/n/10 server_capabilities (nc-client.transport.Session at-
935 936
 []
936 937

  
937 938

  
938
Underfull \hbox (badness 10000) in paragraph at lines 159--160
939
Underfull \hbox (badness 10000) in paragraph at lines 161--162
939 940
[]\T1/ptm/m/n/10 set_rpc_error_action() (nc-client.manager.Manager
940 941
 []
941 942

  
942 943
[20]) (./ncclient.aux) ) 
943 944
Here is how much of TeX's memory you used:
944
 7953 strings out of 493886
945
 108890 string characters out of 1155675
946
 192632 words of memory out of 3000000
945
 7955 strings out of 493886
946
 108969 string characters out of 1155675
947
 194632 words of memory out of 3000000
947 948
 10851 multiletter control sequences out of 10000+50000
948 949
 58566 words of font info for 62 fonts, out of 3000000 for 5000
949 950
 715 hyphenation exceptions out of 8191
......
956 957
ts/type1/urw/times/utmb8a.pfb></usr/share/texmf-dist/fonts/type1/urw/times/utmb
957 958
i8a.pfb></usr/share/texmf-dist/fonts/type1/urw/times/utmr8a.pfb></usr/share/tex
958 959
mf-dist/fonts/type1/urw/times/utmri8a.pfb>
959
Output written on ncclient.pdf (24 pages, 241640 bytes).
960
Output written on ncclient.pdf (24 pages, 243329 bytes).
960 961
PDF statistics:
961
 684 PDF objects out of 1000 (max. 8388607)
962
 194 named destinations out of 1000 (max. 131072)
962
 694 PDF objects out of 1000 (max. 8388607)
963
 196 named destinations out of 1000 (max. 131072)
963 964
 93 words of extra memory for PDF output out of 10000 (max. 10000000)
964 965

  
b/docs/build/latex/ncclient.tex
91 91

  
92 92
\chapter{Introduction}
93 93

  
94
NCClient is a Python library for NETCONF clients. NETCONF is a network management protocol defined in \index{RFC!RFC 4741}\href{http://tools.ietf.org/html/rfc4741.html}{\textbf{RFC 4741}}. It is meant for Python 2.6+ (not Python 3 yet, though).
94
NCClient is a Python library for NETCONF clients. NETCONF is a network management protocol defined in \index{RFC!RFC 4741}\href{http://tools.ietf.org/html/rfc4741.html}{\textbf{RFC 4741}}.
95

  
96
It is meant for Python 2.6+ (not Python 3 yet, though).
95 97

  
96 98
The features of NCClient include:
97 99
\begin{itemize}
......
275 277

  
276 278
\hypertarget{ncclient.manager.Manager.close_session}{}\begin{methoddesc}{close\_session}{*args, **kwds}~\begin{quote}\begin{description}
277 279
\item[See]
278
\code{CloseSession.request()}
280
\hyperlink{ncclient.operations.CloseSession.request}{\code{CloseSession.request()}}
279 281

  
280 282
\end{description}\end{quote}
281 283
\end{methoddesc}
......
283 285

  
284 286
\hypertarget{ncclient.manager.Manager.kill_session}{}\begin{methoddesc}{kill\_session}{*args, **kwds}~\begin{quote}\begin{description}
285 287
\item[See]
286
\code{KillSession.request()}
288
\hyperlink{ncclient.operations.KillSession.request}{\code{KillSession.request()}}
287 289

  
288 290
\end{description}\end{quote}
289 291
\end{methoddesc}
......
296 298
\emph{target} (\href{http://docs.python.org/library/string.html\#string}{\code{string}}) -- name of the datastore to lock
297 299

  
298 300
\item[Return type]
299
\code{operations.LockContext}
301
\hyperlink{ncclient.operations.LockContext}{\code{LockContext}}
300 302

  
301 303
\end{description}\end{quote}
302 304
\end{methoddesc}
......
1240 1242
\emph{\textless{}discard-changes\textgreater{}} RPC. Depends on the \emph{:candidate} capability.
1241 1243
\index{request() (ncclient.operations.DiscardChanges method)}
1242 1244

  
1243
\hypertarget{ncclient.operations.DiscardChanges.request}{}\begin{methoddesc}{request}{*args, **kwds}
1244
Subclasses implement this method. Here, the operation is constructed
1245
in \hyperlink{dtree}{\emph{DictTree XML representation}}, and the result of \code{\_request()} returned.
1245
\hypertarget{ncclient.operations.DiscardChanges.request}{}\begin{methoddesc}{request}{}~\begin{quote}\begin{description}
1246
\item[Seealso]
1247
\hyperlink{return}{\emph{Return type}}
1248

  
1249
\end{description}\end{quote}
1246 1250
\end{methoddesc}
1247 1251
\end{classdesc}
1248 1252

  
......
1254 1258
Bases: \hyperlink{ncclient.operations.rpc.RPC}{\code{ncclient.operations.rpc.RPC}}
1255 1259

  
1256 1260
\emph{\textless{}close-session\textgreater{}} RPC. The connection to NETCONF server is also closed.
1261
\index{request() (ncclient.operations.CloseSession method)}
1262

  
1263
\hypertarget{ncclient.operations.CloseSession.request}{}\begin{methoddesc}{request}{}~\begin{quote}\begin{description}
1264
\item[Seealso]
1265
\hyperlink{return}{\emph{Return type}}
1266

  
1267
\end{description}\end{quote}
1268
\end{methoddesc}
1257 1269
\end{classdesc}
1258 1270
\index{KillSession (class in ncclient.operations)}
1259 1271

  
......
1261 1273
Bases: \hyperlink{ncclient.operations.rpc.RPC}{\code{ncclient.operations.rpc.RPC}}
1262 1274

  
1263 1275
\emph{\textless{}kill-session\textgreater{}} RPC.
1276
\index{request() (ncclient.operations.KillSession method)}
1277

  
1278
\hypertarget{ncclient.operations.KillSession.request}{}\begin{methoddesc}{request}{session\_id}~\begin{quote}\begin{description}
1279
\item[Parameter]
1280
\emph{session\_id} (\href{http://docs.python.org/library/string.html\#string}{\code{string}}) -- \emph{session-id} of NETCONF session to kill
1281

  
1282
\item[Seealso]
1283
\hyperlink{return}{\emph{Return type}}
1284

  
1285
\end{description}\end{quote}
1286
\end{methoddesc}
1264 1287
\end{classdesc}
1265 1288

  
1266 1289

  
b/docs/source/intro.rst
2 2
Introduction
3 3
*************
4 4

  
5
NCClient is a Python library for NETCONF clients. NETCONF is a network management protocol defined in :rfc:`4741`. It is meant for Python 2.6+ (not Python 3 yet, though).
5
NCClient is a Python library for NETCONF clients. NETCONF is a network management protocol defined in :rfc:`4741`.
6

  
7
It is meant for Python 2.6+ (not Python 3 yet, though).
6 8

  
7 9
The features of NCClient include:
8 10

  
b/ncclient/content.py
74 74
            ele.tail = spec.get('tail', '')
75 75
            subtree = spec.get('subtree', [])
76 76
            # might not be properly specified as list but may be dict
77
            if isinstance(subtree, dict):
77
            if not isinstance(subtree, list):
78 78
                subtree = [subtree]
79 79
            for subele in subtree:
80 80
                ele.append(DictTree.Element(subele))
......
184 184
    for event, element in ET.iterparse(fp, events=('start',)):
185 185
        return (element.tag, element.attrib)
186 186

  
187
def validated_element(rep, tag=None, attrs=None, text=None):
187
def validated_element(rep, tags=None, attrs=None, text=None):
188 188
    """Checks if the root element meets the supplied criteria. Returns a :class:`~xml.etree.ElementTree.Element` instance if so, otherwise raises :exc:`ContentError`.
189 189

  
190
    :arg tag: tag name or a list of allowable tag names
190
    :arg tags: tag name or a list of allowable tag names
191 191
    :arg attrs: list of required attribute names, each item may be a list of allowable alternatives
192 192
    :arg text: textual content to match
193 193
    :type rep: :obj:`dict` or :obj:`string` or :class:`~xml.etree.ElementTree.Element`
194 194
    """
195 195
    ele = dtree2ele(rep)
196 196
    err = False
197
    if tag:
198
        if isinstance(tag, basestring): tag = [tag]
197
    if tags:
198
        if isinstance(tags, basestring):
199
            tags = [tags]
199 200
        if ele.tag not in tags:
200 201
            err = True
201 202
    if attrs:
b/ncclient/manager.py
15 15
"Thin layer of abstraction around NCClient"
16 16

  
17 17
import capabilities
18
from operations import OPERATIONS
18
import operations
19 19
import transport
20 20

  
21 21
def connect_ssh(*args, **kwds):
......
55 55
        """
56 56
        self._raise = action
57 57

  
58
    def __enter__(self):
59
        return self
60

  
61
    def __exit__(self, *args):
62
        self.close()
63
        return False
58
    #def __enter__(self):
59
    #    return self
60
    #
61
    #def __exit__(self, *args):
62
    #    self.close()
63
    #    return False
64 64

  
65 65
    def do(self, op, *args, **kwds):
66
        op = OPERATIONS[op](self._session)
66
        op = operations.OPERATIONS[op](self._session)
67 67
        reply = op.request(*args, **kwds)
68 68
        if not reply.ok:
69 69
            if self._raise == RAISE_ALL:
......
115 115

  
116 116
        :arg target: name of the datastore to lock
117 117
        :type target: `string`
118
        :rtype: :class:`operations.LockContext`
118
        :rtype: :class:`~ncclient.operations.LockContext`
119 119
        """
120 120
        return operations.LockContext(self._session, target)
121 121

  
b/ncclient/operations/edit.py
18 18

  
19 19
import util
20 20

  
21
import logging
22
logger = logging.getLogger('ncclient.operations.edit')
23

  
24

  
25

  
21 26
"Operations related to changing device configuration"
22 27

  
23 28
class EditConfig(RPC):
......
87 92

  
88 93
class CopyConfig(RPC):
89 94

  
95
    # TESTED
96

  
90 97
    "*<copy-config>* RPC"
91 98

  
92 99
    SPEC = {'tag': 'copy-config', 'subtree': []}
......
102 109
        :seealso: :ref:`return`
103 110
        """
104 111
        spec = CopyConfig.SPEC.copy()
105
        spec['subtree'].append(util.store_or_url('source', source, self._assert))
106 112
        spec['subtree'].append(util.store_or_url('target', target, self._assert))
113
        spec['subtree'].append(util.store_or_url('source', source, self._assert))
107 114
        return self._request(spec)
108 115

  
109 116

  
110 117
class Validate(RPC):
111 118

  
119
    # TESTED
120

  
112 121
    "*<validate>* RPC. Depends on the *:validate* capability."
113 122

  
114 123
    DEPENDS = [':validate']
......
124 133
        """
125 134
        spec = Validate.SPEC.copy()
126 135
        try:
127
            spec['subtree'].append({
128
                'tag': 'source',
129
                'subtree':
130
                    content.validated_element(
131
                        config, ('config', content.qualify('config')))
132
                })
133
        except:
134
            spec['subtree'].append(util.store_or_url('source', source, self._assert))
136
            src = content.validated_element(source, ('config', content.qualify('config')))
137
        except Exception as e:
138
            logger.debug(e)
139
            src = util.store_or_url('source', source, self._assert)
140
        spec['subtree'].append({
141
            'tag': 'source',
142
            'subtree': src
143
            })
135 144
        return self._request(spec)
136 145

  
137 146

  
......
178 187
    DEPENDS = [':candidate']
179 188

  
180 189
    SPEC = {'tag': 'discard-changes'}
190

  
191
    def request(self):
192
        ":seealso: :ref:`return`"
193
        return self._request(DiscardChanges.SPEC)
b/ncclient/operations/lock.py
18 18

  
19 19
class Lock(RPC):
20 20

  
21
    # TESTED
22

  
21 23
    "*<lock>* RPC"
22 24

  
23 25
    SPEC = {
......
42 44

  
43 45
class Unlock(RPC):
44 46

  
47
    # TESTED
48

  
45 49
    "*<unlock>* RPC"
46 50

  
47 51
    SPEC = {
......
66 70

  
67 71
class LockContext:
68 72

  
73
    # TESTED
74

  
69 75
    """
70 76
    A context manager for the :class:`Lock` / :class:`Unlock` pair of RPC's.
71 77

  
......
85 91
            return self
86 92

  
87 93
    def __exit__(self, *args):
88
        reply = Unlock(session).request(self.target)
94
        reply = Unlock(self.session).request(self.target)
89 95
        if not reply.ok:
90 96
            raise reply.error
91 97
        return False
b/ncclient/operations/retrieve.py
20 20

  
21 21
class GetReply(RPCReply):
22 22

  
23
    # TESTED
24

  
23 25
    """Adds attributes for the *<data>* element to :class:`RPCReply`, which
24 26
    pertains to the :class:`Get` and :class:`GetConfig` operations."""
25 27

  
......
55 57

  
56 58
class Get(RPC):
57 59

  
60
    # TESTED
61

  
58 62
    "The *<get>* RPC"
59 63

  
60 64
    SPEC = {'tag': 'get', 'subtree': []}
......
75 79

  
76 80
class GetConfig(RPC):
77 81

  
82
    # TESTED
83

  
78 84
    "The *<get-config>* RPC"
79 85

  
80 86
    SPEC = {'tag': 'get-config', 'subtree': []}
b/ncclient/operations/rpc.py
289 289
        :type opspec: :obj:`dict` or :obj:`string` or :class:`~xml.etree.ElementTree.Element`
290 290
        :rtype: :class:`~threading.Event` or :class:`RPCReply`
291 291
        """
292
        logger.debug('request %r with opsepc=%r' % (self, op))
292 293
        req = self._build(op)
293
        self._session.send(req)
294
        if self._async:
295
            return self._event
294
        self.session.send(req)
295
        if self.async:
296
            logger.debug('async, returning event')
297
            return self.event
296 298
        else:
297
            self._event.wait(self._timeout)
298
            if self._event.isSet():
299
                if self._error:
299
            logger.debug('sync, will wait for timeout=%r' % self.timeout)
300
            self.event.wait(self.timeout)
301
            if self.event.isSet():
302
                if self.error:
300 303
                    raise self._error
301
                self._reply.parse()
302
                return self._reply
304
                self.reply.parse()
305
                return self.reply
303 306
            else:
304 307
                raise TimeoutExpiredError
305 308

  
b/ncclient/operations/session.py
18 18

  
19 19
class CloseSession(RPC):
20 20

  
21
    # TESTED
22

  
21 23
    "*<close-session>* RPC. The connection to NETCONF server is also closed."
22 24

  
23 25
    SPEC = { 'tag': 'close-session' }
......
26 28
        self.session.close()
27 29

  
28 30
    def request(self):
31
        ":seealso: :ref:`return`"
29 32
        return self._request(CloseSession.SPEC)
30 33

  
31 34

  
......
39 42
    }
40 43

  
41 44
    def request(self, session_id):
45
        """
46
        :arg session_id: *session-id* of NETCONF session to kill
47
        :type session_id: `string`
48

  
49
        :seealso: :ref:`return`
50
        """
42 51
        spec = KillSession.SPEC.copy()
43
        if not isinstance(session_id, basestring): # just making sure...
52
        if not isinstance(session_id, basestring): # make sure
44 53
            session_id = str(session_id)
45 54
        spec['subtree'].append({
46 55
            'tag': 'session-id',
b/ncclient/transport/session.py
62 62
            try:
63 63
                l.errback(err)
64 64
            except Exception as e:
65
                logger.warning('error %r' % e)
65
                logger.warning('error dispatching to %r: %r' % (l, e))
66 66

  
67 67
    def _post_connect(self):
68 68
        "Greeting stuff"
b/ncclient/transport/ssh.py
321 321
                        data = data[n:]
322 322
        except Exception as e:
323 323
            logger.debug('broke out of main loop')
324
            expecting = self._expecting_close
324 325
            self.close()
325
            if not (isinstance(e, SessionCloseError) and self._expecting_close):
326
            logger.debug('error=%r' % e)
327
            logger.debug('expecting_close=%r' % expecting)
328
            if not (isinstance(e, SessionCloseError) and expecting):
326 329
                self._dispatch_error(e)
327 330

  
328 331
    @property

Also available in: Unified diff