Statistics
| Branch: | Tag: | Revision:

root / ncclient / content.py @ cc9af1c3

History | View | Annotate | Download (4.2 kB)

1 94dd4342 Shikhar Bhushan
# Copyright 2009 Shikhar Bhushan
2 94dd4342 Shikhar Bhushan
#
3 94dd4342 Shikhar Bhushan
# Licensed under the Apache License, Version 2.0 (the "License");
4 94dd4342 Shikhar Bhushan
# you may not use this file except in compliance with the License.
5 94dd4342 Shikhar Bhushan
# You may obtain a copy of the License at
6 94dd4342 Shikhar Bhushan
#
7 94dd4342 Shikhar Bhushan
#    http://www.apache.org/licenses/LICENSE-2.0
8 94dd4342 Shikhar Bhushan
#
9 94dd4342 Shikhar Bhushan
# Unless required by applicable law or agreed to in writing, software
10 94dd4342 Shikhar Bhushan
# distributed under the License is distributed on an "AS IS" BASIS,
11 94dd4342 Shikhar Bhushan
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 94dd4342 Shikhar Bhushan
# See the License for the specific language governing permissions and
13 94dd4342 Shikhar Bhushan
# limitations under the License.
14 94dd4342 Shikhar Bhushan
15 94dd4342 Shikhar Bhushan
"TODO: docstring"
16 94dd4342 Shikhar Bhushan
17 94dd4342 Shikhar Bhushan
from xml.etree import cElementTree as ET
18 94dd4342 Shikhar Bhushan
19 bf31e33e Shikhar Bhushan
20 6bd810f9 Shikhar Bhushan
### Namespace-related ###
21 94dd4342 Shikhar Bhushan
22 94dd4342 Shikhar Bhushan
BASE_NS = 'urn:ietf:params:xml:ns:netconf:base:1.0'
23 1fca349b Shikhar Bhushan
# and this is BASE_NS according to cisco devices...
24 94dd4342 Shikhar Bhushan
CISCO_BS = 'urn:ietf:params:netconf:base:1.0'
25 94dd4342 Shikhar Bhushan
26 94dd4342 Shikhar Bhushan
try:
27 94dd4342 Shikhar Bhushan
    register_namespace = ET.register_namespace
28 94dd4342 Shikhar Bhushan
except AttributeError:
29 94dd4342 Shikhar Bhushan
    def register_namespace(prefix, uri):
30 94dd4342 Shikhar Bhushan
        from xml.etree import ElementTree
31 94dd4342 Shikhar Bhushan
        # cElementTree uses ElementTree's _namespace_map, so that's ok
32 94dd4342 Shikhar Bhushan
        ElementTree._namespace_map[uri] = prefix
33 94dd4342 Shikhar Bhushan
34 e91a5349 Shikhar Bhushan
# we'd like BASE_NS to be prefixed as "netconf"
35 94dd4342 Shikhar Bhushan
register_namespace('netconf', BASE_NS)
36 94dd4342 Shikhar Bhushan
37 bf31e33e Shikhar Bhushan
qualify = lambda tag, ns=BASE_NS: '{%s}%s' % (ns, tag)
38 bf31e33e Shikhar Bhushan
39 bf31e33e Shikhar Bhushan
# i would have written a def if lambdas weren't so much fun
40 b4e9d4c2 Shikhar Bhushan
multiqualify = lambda tag, nslist=(BASE_NS, CISCO_BS): [qualify(tag, ns)
41 b4e9d4c2 Shikhar Bhushan
                                                        for ns in nslist]
42 94dd4342 Shikhar Bhushan
43 94dd4342 Shikhar Bhushan
unqualify = lambda tag: tag[tag.rfind('}')+1:]
44 94dd4342 Shikhar Bhushan
45 c2a5b930 Shikhar Bhushan
def namespaced_find(ele, tag, workaround=True):
46 c2a5b930 Shikhar Bhushan
    """`workaround` is for Cisco implementations (at least the one tested), 
47 c2a5b930 Shikhar Bhushan
    which uses an incorrect namespace.
48 c2a5b930 Shikhar Bhushan
    """
49 c2a5b930 Shikhar Bhushan
    found = None
50 c2a5b930 Shikhar Bhushan
    if not workaround:
51 c2a5b930 Shikhar Bhushan
        found = ele.find(tag)
52 c2a5b930 Shikhar Bhushan
    else:
53 c2a5b930 Shikhar Bhushan
        for qname in multiqualify(tag):
54 c2a5b930 Shikhar Bhushan
            found = ele.find(qname)
55 c2a5b930 Shikhar Bhushan
            if found is not None:
56 c2a5b930 Shikhar Bhushan
                break
57 c2a5b930 Shikhar Bhushan
    return found
58 cc9af1c3 Shikhar Bhushan
59 c2a5b930 Shikhar Bhushan
60 ea04739a Shikhar Bhushan
### Build XML using Python data structures ###
61 94dd4342 Shikhar Bhushan
62 94803aaf Shikhar Bhushan
class XMLConverter:
63 94dd4342 Shikhar Bhushan
    """Build an ElementTree.Element instance from an XML tree specification
64 94dd4342 Shikhar Bhushan
    based on nested dictionaries. TODO: describe spec
65 94dd4342 Shikhar Bhushan
    """
66 94dd4342 Shikhar Bhushan
    
67 94dd4342 Shikhar Bhushan
    def __init__(self, spec):
68 94dd4342 Shikhar Bhushan
        "TODO: docstring"
69 94803aaf Shikhar Bhushan
        self._root = XMLConverter.build(spec)
70 cc8de468 Shikhar Bhushan
    
71 cc9af1c3 Shikhar Bhushan
    def tostring(self, encoding='utf-8'):
72 94dd4342 Shikhar Bhushan
        "TODO: docstring"
73 94dd4342 Shikhar Bhushan
        xml = ET.tostring(self._root, encoding)
74 d6688264 Shikhar Bhushan
        # some etree versions don't include xml decl with utf-8
75 94dd4342 Shikhar Bhushan
        # this is a problem with some devices
76 2f8bc438 Shikhar Bhushan
        return (xml if xml.startswith('<?xml')
77 2f8bc438 Shikhar Bhushan
                else '<?xml version="1.0" encoding="%s"?>%s' % (encoding, xml))
78 94dd4342 Shikhar Bhushan
    
79 94dd4342 Shikhar Bhushan
    @property
80 94dd4342 Shikhar Bhushan
    def tree(self):
81 94dd4342 Shikhar Bhushan
        "TODO: docstring"
82 94dd4342 Shikhar Bhushan
        return self._root
83 94dd4342 Shikhar Bhushan
    
84 94dd4342 Shikhar Bhushan
    @staticmethod
85 94dd4342 Shikhar Bhushan
    def build(spec):
86 94dd4342 Shikhar Bhushan
        "TODO: docstring"
87 c2a5b930 Shikhar Bhushan
        if iselement(spec):
88 d6688264 Shikhar Bhushan
            return spec
89 d6688264 Shikhar Bhushan
        elif isinstance(spec, basestring):
90 d6688264 Shikhar Bhushan
            return ET.XML(spec)
91 cc9af1c3 Shikhar Bhushan
        # assume isinstance(spec, dict)
92 2f8bc438 Shikhar Bhushan
        if 'tag' in spec:
93 94dd4342 Shikhar Bhushan
            ele = ET.Element(spec.get('tag'), spec.get('attributes', {}))
94 2f8bc438 Shikhar Bhushan
            ele.text = spec.get('text', '')
95 179b00d4 Shikhar Bhushan
            ele.tail = spec.get('tail', '')
96 179b00d4 Shikhar Bhushan
            subtree = spec.get('subtree', [])
97 179b00d4 Shikhar Bhushan
            # might not be properly specified as list but may be dict
98 179b00d4 Shikhar Bhushan
            if isinstance(subtree, dict):
99 179b00d4 Shikhar Bhushan
                subtree = [subtree]
100 179b00d4 Shikhar Bhushan
            for subele in subtree:
101 179b00d4 Shikhar Bhushan
                ele.append(XMLConverter.build(subele))
102 94dd4342 Shikhar Bhushan
            return ele
103 bf31e33e Shikhar Bhushan
        elif 'comment' in spec:
104 94dd4342 Shikhar Bhushan
            return ET.Comment(spec.get('comment'))
105 cc9af1c3 Shikhar Bhushan
        # TODO elif DOM rep
106 94dd4342 Shikhar Bhushan
        else:
107 179b00d4 Shikhar Bhushan
            raise ContentError('Invalid tree spec')
108 179b00d4 Shikhar Bhushan
    
109 179b00d4 Shikhar Bhushan
    @staticmethod
110 cc9af1c3 Shikhar Bhushan
    def fromstring(xml):
111 179b00d4 Shikhar Bhushan
        return XMLConverter.parse(ET.fromstring(xml))
112 179b00d4 Shikhar Bhushan
    
113 179b00d4 Shikhar Bhushan
    @staticmethod
114 179b00d4 Shikhar Bhushan
    def parse(root):
115 179b00d4 Shikhar Bhushan
        return {
116 179b00d4 Shikhar Bhushan
            'tag': root.tag,
117 179b00d4 Shikhar Bhushan
            'attributes': root.attrib,
118 179b00d4 Shikhar Bhushan
            'text': root.text,
119 179b00d4 Shikhar Bhushan
            'tail': root.tail,
120 179b00d4 Shikhar Bhushan
            'subtree': [ XMLConverter.parse(child) for child in root.getchildren() ]
121 179b00d4 Shikhar Bhushan
        }
122 cc9af1c3 Shikhar Bhushan
123 cc9af1c3 Shikhar Bhushan
## utility functions
124 cc9af1c3 Shikhar Bhushan
125 cc9af1c3 Shikhar Bhushan
iselement = ET.iselement
126 cc9af1c3 Shikhar Bhushan
127 cc9af1c3 Shikhar Bhushan
def isdom(x): return True # TODO
128 cc9af1c3 Shikhar Bhushan
129 cc9af1c3 Shikhar Bhushan
def root_ensured(rep, tag):
130 cc9af1c3 Shikhar Bhushan
    if isinstance(rep, basestring):
131 cc9af1c3 Shikhar Bhushan
        rep = ET.XML(rep)
132 cc9af1c3 Shikhar Bhushan
    err = False
133 cc9af1c3 Shikhar Bhushan
    if ((iselement(rep) and (rep.tag not in (tag, qualify(tag))) or (isdom(x)))): 
134 cc9af1c3 Shikhar Bhushan
        raise ArgumentError("Expected root element [%s] not found" % tag)
135 cc9af1c3 Shikhar Bhushan
    else:
136 cc9af1c3 Shikhar Bhushan
        return rep