Revision e3b66e4b

b/docs/source/index.rst
1 1
Welcome
2 2
=======
3 3

  
4
``ncclient`` is a Python library for NETCONF clients. It aims to offer an intuitive API that sensibly maps the XML-encoded nature of NETCONF to Python constructs and idioms, and make writing network-management scripts easier. Other key features are:
4
``ncclient`` is a Python library for NETCONF clients. It aims to offer an intuitive API that
5
sensibly maps the XML-encoded nature of NETCONF to Python constructs and idioms, and make writing
6
network-management scripts easier. Other key features are:
5 7

  
6 8
* Supports all operations and capabilities defined in :rfc:`4741`.
7 9
* Request pipelining.
......
9 11
* Keeping XML out of the way unless really needed.
10 12
* Extensible. New transport mappings and capabilities/operations can be easily added.
11 13

  
12
It is suitable for Python 2.6+ (not Python 3 yet, though), and depends on `paramiko <http://www.lag.net/paramiko/>`_, an SSH library.
14
It is suitable for Python 2.6+ (not Python 3 yet, though), and depends on `paramiko
15
<http://www.lag.net/paramiko/>`_, an SSH library.
13 16

  
14 17
The best way to introduce is of course, through a simple code example::
15 18

  
b/docs/source/manager.rst
10 10
These attributes control what capabilties are exchanged with the NETCONF server and what operations
11 11
are available through the `Manager` API.
12 12

  
13
.. autodata:: CAPABILITIES
14

  
15 13
.. autodata:: OPERATIONS
16 14

  
15
.. autodata:: CAPABILITIES
16

  
17 17
Factory functions
18 18
-----------------
19 19

  
b/docs/source/operations.rst
20 20
Operations
21 21
----------
22 22

  
23
*TODO* The operation classes are currently undocumented. See documentation of
24
`~ncclient.manager.Manager` for methods that utilize the operation classes. The parameters accepted
25
by :meth:`~RPC.request` for these classes are the same.
23
*TODO*
24

  
25
The operation classes are currently undocumented. See documentation of `~ncclient.manager.Manager`
26
for methods that utilize the operation classes. The parameters accepted by :meth:`~RPC.request` for
27
these classes are the same.
26 28

  
27 29
Replies with data
28 30
-----------------
b/docs/source/xml_.rst
1
:mod:`~ncclient.xml_` -- XML Handling
1
:mod:`~ncclient.xml_` -- XML handling
2 2
=====================================
3 3

  
4
*TODO*
4
.. module:: ncclient.xml_
5
    :synopsis: XML handling
6

  
7
.. autoexception:: XMLError
8
    :show-inheritance:
9

  
10
Namespaces
11
-----------
12

  
13
.. autodata:: BASE_NS_1_0
14

  
15
.. autodata:: TAILF_AAA_1_1
16

  
17
.. autodata:: TAILF_EXECD_1_1
18

  
19
.. autodata:: CISCO_CPI_1_0
20

  
21
.. autodata:: FLOWMON_1_0
22

  
23
.. function:: register_namespace(prefix, uri)
24
    
25
    ElementTree's namespace map determines the prefixes for namespace URI's when serializing to XML.
26
    This method allows modifying this map to specify a prefix for a namespace URI.
27

  
28
.. autofunction:: qualify
29

  
30
Conversion
31
-----------
32

  
33
.. autofunction:: to_xml
34

  
35
.. autofunction:: to_ele
36

  
37
.. autofunction:: parse_root
38

  
39
.. autofunction:: validated_element
40

  
41
.. 
b/ncclient/manager.py
21 21
import logging
22 22
logger = logging.getLogger('ncclient.manager')
23 23

  
24

  
25
CAPABILITIES = capabilities.Capabilities([
24
CAPABILITIES = [
26 25
    "urn:ietf:params:netconf:base:1.0",
27 26
    "urn:ietf:params:netconf:capability:writable-running:1.0",
28 27
    "urn:ietf:params:netconf:capability:candidate:1.0",
......
35 34
    "urn:liberouter:params:netconf:capability:power-control:1.0"
36 35
    "urn:ietf:params:netconf:capability:interleave:1.0"
37 36
    #'urn:ietf:params:netconf:capability:notification:1.0', # TODO    
38
])
39
"""`~ncclient.capabilities.Capabilities` object representing the client's capabilities. This is used
40
during the initial capability exchange. Modify this if you need to announce some capability not
41
already included.
37
]
38
"""A list of URI's representing the client's capabilities. This is used during the initial
39
capability exchange. Modify this if you need to announce some capability not already included.
42 40
"""
43 41

  
44 42
OPERATIONS = {
......
57 55
    "poweroff_machine": operations.PoweroffMachine,
58 56
    "reboot_machine": operations.RebootMachine
59 57
}
60
"""Dictionary of method names and corresponding `~ncclient.operations.RPC` subclasses. `Manager`
61
uses this to lookup operations, e.g. "get_config" is mapped to `~ncclient.operations.GetConfig`. It
62
is thus possible to add additional operations to the `Manager` API.
63
"""
58
"""Dictionary of method names and corresponding `~ncclient.operations.RPC` subclasses. It is used to
59
lookup operations, e.g. "get_config" is mapped to `~ncclient.operations.GetConfig`. It is thus
60
possible to add additional operations to the `Manager` API."""
64 61

  
65 62
def connect_ssh(*args, **kwds):
66 63
    """Initializes a NETCONF session over SSH, and creates a connected `Manager` instance. *host*
......
114 111
    
115 112
    :rtype: `Manager`
116 113
    """    
117
    session = transport.SSHSession(CAPABILITIES)
114
    session = transport.SSHSession(capabilities.Capabilities(CAPABILITIES))
118 115
    session.load_known_hosts()
119 116
    session.connect(*args, **kwds)
120 117
    return Manager(session)
b/ncclient/xml_.py
12 12
# See the License for the specific language governing permissions and
13 13
# limitations under the License.
14 14

  
15

  
16 15
"Methods for creating, parsing, and dealing with XML and ElementTree objects."
17 16

  
18 17
from cStringIO import StringIO
......
25 24
### Namespace-related
26 25

  
27 26
#: Base NETCONF namespace
28
BASE_NS_1_0 = 'urn:ietf:params:xml:ns:netconf:base:1.0'
27
BASE_NS_1_0 = "urn:ietf:params:xml:ns:netconf:base:1.0"
29 28
#: Namespace for Tail-f core data model
30
TAILF_AAA_1_1 = 'http://tail-f.com/ns/aaa/1.1'
29
TAILF_AAA_1_1 = "http://tail-f.com/ns/aaa/1.1"
31 30
#: Namespace for Tail-f execd data model
32
TAILF_EXECD_1_1 = 'http://tail-f.com/ns/execd/1.1'
31
TAILF_EXECD_1_1 = "http://tail-f.com/ns/execd/1.1"
33 32
#: Namespace for Cisco data model
34
CISCO_CPI_1_0 = 'http://www.cisco.com/cpi_10/schema'
33
CISCO_CPI_1_0 = "http://www.cisco.com/cpi_10/schema"
35 34
#: Namespace for Flowmon data model
36
FLOWMON_1_0 = 'http://www.liberouter.org/ns/netopeer/flowmon/1.0'
35
FLOWMON_1_0 = "http://www.liberouter.org/ns/netopeer/flowmon/1.0"
37 36

  
38 37
try:
39 38
    register_namespace = ET.register_namespace
......
43 42
        # cElementTree uses ElementTree's _namespace_map, so that's ok
44 43
        ElementTree._namespace_map[uri] = prefix
45 44

  
46
prefix_map = {
45
for (ns, pre) in {
47 46
    BASE_NS_1_0: 'nc',
48 47
    TAILF_AAA_1_1: 'aaa',
49 48
    TAILF_EXECD_1_1: 'execd',
50 49
    CISCO_CPI_1_0: 'cpi',
51 50
    FLOWMON_1_0: 'fm',
52
}
51
}.items(): register_namespace(pre, ns)
53 52

  
54
for (ns, pre) in prefix_map.items():
55
    register_namespace(pre, ns)
53
qualify = lambda tag, ns=BASE_NS_1_0: tag if ns is None else "{%s}%s" % (ns, tag)
54
"""Qualify a tag name with a namespace, in :mod:`~xml.etree.ElementTree` fashion i.e. *{namespace}tagname*.
56 55

  
57
qualify = lambda tag, ns=BASE_NS_1_0: tag if ns is None else '{%s}%s' % (ns, tag)
56
:arg tag: name of the tag
57
:type arg: `string`
58 58

  
59
#unqualify = lambda tag: tag[tag.rfind('}')+1:]
59
:arg ns: namespace to qualify with
60
:type ns: `string`
61
"""
60 62

  
61 63
def to_xml(ele, encoding="UTF-8"):
62
    """Convert an :class:`~xml.etree.ElementTree.Element` to XML.
64
    """Convert an `~xml.etree.ElementTree.Element` to XML.
63 65
    
64
    :arg ele: the :class:`~xml.etree.ElementTree.Element`
66
    :arg ele: the `~xml.etree.ElementTree.Element`
65 67
    :arg encoding: character encoding
66
    :rtype: :obj:`string`
68
    :rtype: `string`
67 69
    """
68 70
    xml = ET.tostring(ele, encoding)
69 71
    return xml if xml.startswith('<?xml') else '<?xml version="1.0" encoding="%s"?>%s' % (encoding, xml)
70 72

  
71 73
def to_ele(x):
72
    """Convert XML to :class:`~xml.etree.ElementTree.Element`.
74
    """Convert XML to `~xml.etree.ElementTree.Element`. If passed an
75
    `~xml.etree.ElementTree.Element` simply returns that.
73 76
    
74
    :type xml: :obj:`string`
75
    :rtype: :class:`~xml.etree.ElementTree.Element`
77
    :arg x: the XML document or element
78
    :type x: `string` or `~xml.etree.ElementTree.Element`
79
    :rtype: `~xml.etree.ElementTree.Element`
76 80
    """
77
    return x if iselement(x) else ET.fromstring(x)
78

  
79
iselement = ET.iselement
81
    return x if ET.iselement(x) else ET.fromstring(x)
80 82

  
81 83
def parse_root(raw):
82 84
    """Efficiently parses the root element of an XML document.
83 85

  
84 86
    :arg raw: XML document
85
    :returns: a tuple of `(tag, attrib)`, where *tag* is the (qualified)
86
    name of the element and *attrib* is a dictionary of its attributes.
87
    :returns: a tuple of ``(tag, attrib)``, where *tag* is the (qualified) name of the element and *attrib* is a dictionary of its attributes.
87 88
    :rtype: `tuple`
88 89
    """
89 90
    fp = StringIO(raw)
......
91 92
        return (element.tag, element.attrib)
92 93

  
93 94
def validated_element(x, tags=None, attrs=None):
94
    "Checks if the root element of an XML document or Element meets the supplied criteria."
95
    """Checks if the root element of an XML document or Element meets the supplied criteria.
96
    
97
    :arg tags: allowable tag name or sequence of allowable alternatives
98
    :type tags: `string` or sequence of strings
99
    
100
    :arg attrs: list of required attributes, each of which may be a sequence of several allowable alternatives
101
    :type attrs: sequence of strings or sequence of sequences of strings
102
    
103
    :raises: `XMLError` if the requirements are not met
104
    """
95 105
    ele = to_ele(x)
96 106
    if tags:
97 107
        if isinstance(tags, basestring):
......
108 118
                raise XMLError("Element [%s] does not have required attributes" % ele.tag)
109 119
    return ele
110 120

  
111

  
112 121
new_ele = lambda tag, attrs={}, **extra: ET.Element(tag, attrs, **extra)
113 122

  
114 123
sub_ele = lambda parent, tag, attrs={}, **extra: ET.SubElement(parent, tag, attrs, **extra)

Also available in: Unified diff