2
# This file is part of Checkbox.
4
# Copyright 2008 Canonical Ltd.
6
# Checkbox is free software: you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation, either version 3 of the License, or
9
# (at your option) any later version.
11
# Checkbox is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License
17
# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
21
from lxml import etree
22
from xml.dom.minidom import Document, Element, parseString
26
"""The central point for dumping and loading information.
28
This keeps references to all reports which have been added to the
29
instance of this manager. These reports will be able to register
30
handlers to understand the formats for dumping and loading actions.
33
def __init__(self, name, version=None, stylesheet=None, schema=None):
35
self.version = version
36
self.stylesheet = stylesheet
41
def handle_dumps(self, type, handler):
43
Call back method for reports to register dump handlers.
45
if type in self.dumps_table:
46
raise Exception("Dumps type already handled: %s" % type)
47
self.dumps_table[type] = handler
49
def handle_loads(self, type, handler):
51
Call back method for reports to register load handlers.
53
if type in self.loads_table:
54
raise Exception("Loads type already handled: %s" % type)
55
self.loads_table[type] = handler
57
def call_dumps(self, obj, node):
59
Convenience method for reports to call the dump handler
60
corresponding to the type of the given object.
62
return self.dumps_table[type(obj)](obj, node)
64
def call_loads(self, node):
66
Convenience method for reports to call the load handler
67
corresponding to the content of the given node.
69
if node.localName in self.loads_table:
70
ret = self.loads_table[node.localName](node)
71
elif isinstance(node, Element) and node.hasAttribute("type"):
72
type = node.getAttribute("type")
73
ret = self.loads_table[type](node)
75
ret = self.loads_table["default"](node)
78
def add(self, report):
80
Add a new report to the manager.
86
Dump the given object which may be a container of any objects
87
supported by the reports added to the manager.
93
href = "file://%s" % posixpath.abspath(self.stylesheet)
94
style = document.createProcessingInstruction("xml-stylesheet",
95
"type=\"%s\" href=\"%s\"" % (type, href))
96
document.appendChild(style)
98
node = document.createElement(self.name)
99
document.appendChild(node)
102
node.setAttribute("version", self.version)
105
self.call_dumps(obj, node)
106
except KeyError as e:
107
raise ValueError("Unsupported type: %s" % e)
111
def loads(self, string):
113
Load the given string which may be a container of any nodes
114
supported by the reports added to the manager.
116
document = parseString(string)
117
node = document.childNodes[0]
118
assert(node.localName == self.name)
121
ret = self.call_loads(document)
122
except KeyError as e:
123
raise ValueError("Unsupported type: %s" % e)
127
def validate(self, string):
129
Validate the given string
134
file = open(self.schema)
140
relaxng_doc = etree.fromstring(schema)
141
relaxng = etree.RelaxNG(relaxng_doc)
143
doc = etree.fromstring(string)
144
return relaxng.validate(doc)
148
"""A convenience for writing reports.
150
This provides a register method which will set the manager attribute
151
and optionally call the C{register_dumps} and C{register_loads}
155
def _create_element(self, name, parent):
156
element = parent.ownerDocument.createElement(name)
157
parent.appendChild(element)
160
def _create_text_node(self, text, parent):
161
text_node = parent.ownerDocument.createTextNode(text)
162
parent.appendChild(text_node)
165
def register(self, manager):
166
self._manager = manager
167
if hasattr(self, "register_dumps"):
168
self.register_dumps()
169
if hasattr(self, "register_loads"):
170
self.register_loads()