Merge lp:~cr3/checkbox/838123 into lp:checkbox

Proposed by Marc Tardif
Status: Merged
Merged at revision: 1034
Proposed branch: lp:~cr3/checkbox/838123
Merge into: lp:checkbox
Diff against target: 841 lines (+619/-34)
10 files modified
checkbox/report.py (+39/-12)
checkbox/tests/report.py (+1/-1)
data/whitelists/default.whitelist (+1/-0)
debian/changelog (+1/-0)
debian/control (+1/-1)
jobs/info.txt.in (+9/-0)
plugins/launchpad_prompt.py (+2/-2)
plugins/launchpad_report.py (+25/-18)
plugins/report_prompt.py (+7/-0)
report/hardware-1_0.rng (+533/-0)
To merge this branch: bzr merge lp:~cr3/checkbox/838123
Reviewer Review Type Date Requested Status
Daniel Manrique (community) Approve
Marc Tardif (community) Needs Resubmitting
Review via email: mp+74621@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Daniel Manrique (roadmr) wrote :

The bug report has no steps to reproduce so I was unable to check what happens with a borked xml submission file. It looks fine to me, there are no errors in the logs from a normal run.

There's one thing I observed, though: when I try to open the report it looks ugly :( this is because in checkbox.xsl the CHECKBOX_SHARE variable is not substituted and there's stuff like:

href="%(CHECKBOX_SHARE)s/report/styles.css"

if I replace %(CHECKBOX_SHARE)s with the actual path where the files reside, all works well.

This is worth fixing, because there are usually compliments about how nice the report looks, and if this slips by, we won't get those anymore :)

review: Needs Fixing
Revision history for this message
Marc Tardif (cr3) wrote :

Good catch, fixed.

review: Needs Resubmitting
lp:~cr3/checkbox/838123 updated
1035. By Marc Tardif

Replaced environment variables in stylesheet.

Revision history for this message
Daniel Manrique (roadmr) wrote :

Great! tested and it's working fine now, approving and merging. Thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'checkbox/report.py'
2--- checkbox/report.py 2009-07-22 18:02:57 +0000
3+++ checkbox/report.py 2011-09-08 18:23:40 +0000
4@@ -16,6 +16,9 @@
5 # You should have received a copy of the GNU General Public License
6 # along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
7 #
8+import libxml2
9+import posixpath
10+
11 from xml.dom.minidom import Document, Element, parseString
12
13
14@@ -27,13 +30,13 @@
15 handlers to understand the formats for dumping and loading actions.
16 """
17
18- def __init__(self, name, version=None, stylesheet=None):
19+ def __init__(self, name, version=None, stylesheet=None, schema=None):
20 self.name = name
21 self.version = version
22 self.stylesheet = stylesheet
23+ self.schema = schema
24 self.dumps_table = {}
25 self.loads_table = {}
26- self.document = None
27
28 def handle_dumps(self, type, handler):
29 """
30@@ -83,17 +86,17 @@
31 Dump the given object which may be a container of any objects
32 supported by the reports added to the manager.
33 """
34- self.document = Document()
35+ document = Document()
36
37 if self.stylesheet:
38 type = "text/xsl"
39- href = "file://%s" % self.stylesheet
40- style = self.document.createProcessingInstruction("xml-stylesheet",
41+ href = "file://%s" % posixpath.abspath(self.stylesheet)
42+ style = document.createProcessingInstruction("xml-stylesheet",
43 "type=\"%s\" href=\"%s\"" % (type, href))
44- self.document.appendChild(style)
45+ document.appendChild(style)
46
47- node = self.document.createElement(self.name)
48- self.document.appendChild(node)
49+ node = document.createElement(self.name)
50+ document.appendChild(node)
51
52 if self.version:
53 node.setAttribute("version", self.version)
54@@ -103,8 +106,6 @@
55 except KeyError, e:
56 raise ValueError, "Unsupported type: %s" % e
57
58- document = self.document
59- self.document = None
60 return document
61
62 def loads(self, str):
63@@ -123,6 +124,32 @@
64
65 return ret
66
67+ def validate(self, str):
68+ """
69+ Validate the given string
70+ """
71+ if not self.schema:
72+ return False
73+
74+ file = open(self.schema)
75+ try:
76+ schema = file.read()
77+ finally:
78+ file.close()
79+
80+ rngParser = libxml2.relaxNGNewMemParserCtxt(schema, len(schema))
81+ rngSchema = rngParser.relaxNGParse()
82+ ctxt = rngSchema.relaxNGNewValidCtxt()
83+ doc = libxml2.parseDoc(str)
84+ is_valid = doc.relaxNGValidateDoc(ctxt)
85+
86+ # Clean up
87+ doc.freeDoc()
88+ del rngParser, rngSchema, ctxt
89+ libxml2.relaxNGCleanupTypes()
90+ libxml2.cleanupParser()
91+ return is_valid == 0
92+
93
94 class Report(object):
95 """A convenience for writing reports.
96@@ -133,12 +160,12 @@
97 """
98
99 def _create_element(self, name, parent):
100- element = self._manager.document.createElement(name)
101+ element = parent.ownerDocument.createElement(name)
102 parent.appendChild(element)
103 return element
104
105 def _create_text_node(self, text, parent):
106- text_node = self._manager.document.createTextNode(text)
107+ text_node = parent.ownerDocument.createTextNode(text)
108 parent.appendChild(text_node)
109 return text_node
110
111
112=== modified file 'checkbox/tests/report.py'
113--- checkbox/tests/report.py 2009-02-16 15:48:24 +0000
114+++ checkbox/tests/report.py 2011-09-08 18:23:40 +0000
115@@ -33,7 +33,7 @@
116 self._manager.handle_loads("default", self.loads_default)
117
118 def dumps_test(self, obj, parent):
119- text_node = self._manager.document.createTextNode(obj)
120+ text_node = parent.ownerDocument.createTextNode(obj)
121 parent.appendChild(text_node)
122
123 def loads_test(self, node):
124
125=== modified file 'data/whitelists/default.whitelist'
126--- data/whitelists/default.whitelist 2011-09-01 10:55:45 +0000
127+++ data/whitelists/default.whitelist 2011-09-08 18:23:40 +0000
128@@ -61,6 +61,7 @@
129 info/gcov_attachment
130 info/modprobe_attachment
131 info/modules_attachment
132+info/sysfs_attachment
133 info/sysctl_attachment
134 info/udev_attachment
135 __input__
136
137=== modified file 'debian/changelog'
138--- debian/changelog 2011-09-06 21:44:47 +0000
139+++ debian/changelog 2011-09-08 18:23:40 +0000
140@@ -2,6 +2,7 @@
141
142 [Marc Tardif]
143 * Only connecting hyper text widgets once (LP: #827904)
144+ * Validating the submission.xml (LP: #838123)
145
146 -- Daniel Manrique <daniel.manrique@canonical.com> Tue, 06 Sep 2011 17:42:57 -0400
147
148
149=== modified file 'debian/control'
150--- debian/control 2011-08-25 15:05:30 +0000
151+++ debian/control 2011-09-08 18:23:40 +0000
152@@ -13,7 +13,7 @@
153 Architecture: all
154 Replaces: hwtest (<< 0.1-0ubuntu12)
155 Provides: hwtest
156-Depends: ${misc:Depends}, ${python:Depends}, debconf, udev
157+Depends: ${misc:Depends}, ${python:Depends}, debconf, python-libxml2, udev
158 Recommends: dpkg (>= 1.13), lsb-release, pm-utils, python-apport, python-apt, python-dateutil, python-gst0.10
159 Suggests: checkbox-cli | checkbox-gtk, bonnie++, bootchart, bzr, cvs, ethtool, flex, fwts, git-core, hdparm, lshw, make, nmap, obexd-client, python-pexpect, smartmontools, sox, stress, wodim
160 Conflicts: hwtest (<< 0.1-0ubuntu12)
161
162=== modified file 'jobs/info.txt.in'
163--- jobs/info.txt.in 2011-08-24 19:17:05 +0000
164+++ jobs/info.txt.in 2011-09-08 18:23:40 +0000
165@@ -37,6 +37,15 @@
166 plugin: attachment
167 command: find /etc/sysctl.* -name \*.conf | xargs cat
168
169+name: info/sysfs_attachment
170+plugin: attachment
171+command:
172+ for i in `udevadm info --export-db | sed -n 's/^P: //p'`; do
173+ echo "P: $i"
174+ udevadm info --attribute-walk --path=/sys$i 2>/dev/null | sed -n 's/ ATTR{\(.*\)}=="\(.*\)"/A: \1=\2/p'
175+ echo
176+ done
177+
178 name: info/udev_attachment
179 plugin: attachment
180 command: udevadm info --export-db
181
182=== modified file 'plugins/launchpad_prompt.py'
183--- plugins/launchpad_prompt.py 2011-02-02 16:57:29 +0000
184+++ plugins/launchpad_prompt.py 2011-09-08 18:23:40 +0000
185@@ -46,7 +46,7 @@
186 self.persist = persist.root_at("launchpad_prompt")
187
188 def launchpad_report(self, report):
189- self._launchpad_report = report
190+ self.report = report
191
192 def prompt_exchange(self, interface):
193 if self.persist and self.persist.has("email"):
194@@ -66,7 +66,7 @@
195 for error in errors:
196 self._manager.reactor.fire("prompt-error", interface, error)
197
198- url = "file://%s" % posixpath.abspath(self._launchpad_report)
199+ url = "file://%s" % posixpath.abspath(self.report)
200
201 email = interface.show_entry(_("""\
202 The following report has been generated for submission to the Launchpad \
203
204=== modified file 'plugins/launchpad_report.py'
205--- plugins/launchpad_report.py 2011-08-08 13:13:20 +0000
206+++ plugins/launchpad_report.py 2011-09-08 18:23:40 +0000
207@@ -17,7 +17,8 @@
208 # along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
209 #
210 import os
211-import posixpath
212+
213+from gettext import gettext as _
214
215 from checkbox.lib.safe import safe_make_directory
216
217@@ -31,6 +32,9 @@
218 # Filename where submission information is cached.
219 filename = Path(default="%(checkbox_data)s/submission.xml")
220
221+ # XML Schema
222+ schema = Path(default="%(checkbox_share)s/report/hardware-1_0.rng")
223+
224 # XSL Stylesheet
225 stylesheet = Path(default="%(checkbox_share)s/report/checkbox.xsl")
226
227@@ -67,10 +71,13 @@
228 def report_attachments(self, attachments):
229 for attachment in attachments:
230 name = attachment["name"]
231- if "dmi" in name:
232+ if "sysfs_attachment" in name:
233+ self._report["hardware"]["sysfs-attributes"] = attachment["data"]
234+
235+ elif "dmi_attachment" in name:
236 self._report["hardware"]["dmi"] = attachment["data"]
237
238- elif "udev" in name:
239+ elif "udev_attachment" in name:
240 self._report["hardware"]["udev"] = attachment["data"]
241
242 else:
243@@ -123,24 +130,24 @@
244 self._report["questions"].append(question)
245
246 def report(self):
247- # Convert stylesheet to report directory
248+ # Prepare the payload and attach it to the form
249+ stylesheet_path = os.path.join(
250+ os.path.dirname(self.filename),
251+ os.path.basename(self.stylesheet))
252+ report_manager = LaunchpadReportManager(
253+ "system", "1.0", stylesheet_path, self.schema)
254+ payload = report_manager.dumps(self._report).toprettyxml("")
255+ if not report_manager.validate(payload):
256+ self._manager.reactor.fire("report-error", _("""\
257+The generated report seems to have validation errors,
258+so it might not be processed by Launchpad."""))
259+
260+ # Write the report
261 stylesheet_data = open(self.stylesheet).read() % os.environ
262- stylesheet_path = posixpath.join(
263- posixpath.dirname(self.filename),
264- posixpath.basename(self.stylesheet))
265 open(stylesheet_path, "w").write(stylesheet_data)
266-
267- # Prepare the payload and attach it to the form
268- stylesheet_path = posixpath.abspath(stylesheet_path)
269- report_manager = LaunchpadReportManager("system", "1.0", stylesheet_path)
270- payload = report_manager.dumps(self._report).toprettyxml("")
271-
272- directory = posixpath.dirname(self.filename)
273+ directory = os.path.dirname(self.filename)
274 safe_make_directory(directory)
275-
276- file = open(self.filename, "w")
277- file.write(payload)
278- file.close()
279+ open(self.filename, "w").write(payload)
280
281 self._manager.reactor.fire("launchpad-report", self.filename)
282
283
284=== modified file 'plugins/report_prompt.py'
285--- plugins/report_prompt.py 2010-02-22 15:16:05 +0000
286+++ plugins/report_prompt.py 2011-09-08 18:23:40 +0000
287@@ -30,9 +30,16 @@
288 self._manager.reactor.call_on("prompt-report", self.prompt_report)
289
290 def prompt_report(self, interface):
291+ def report_error(e):
292+ self._manager.reactor.fire("prompt-error", interface, e)
293+
294+ event_id = self._manager.reactor.call_on("report-error", report_error)
295+
296 if interface.direction != PREV:
297 interface.show_progress(_("Building report..."),
298 self._manager.reactor.fire, "report")
299
300+ self._manager.reactor.cancel_call(event_id)
301+
302
303 factory = ReportPrompt
304
305=== added file 'report/hardware-1_0.rng'
306--- report/hardware-1_0.rng 1970-01-01 00:00:00 +0000
307+++ report/hardware-1_0.rng 2011-09-08 18:23:40 +0000
308@@ -0,0 +1,533 @@
309+<?xml version="1.0" ?>
310+<grammar xmlns="http://relaxng.org/ns/structure/1.0"
311+ datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
312+ xmlns:a="http://launchpad.net/annotation">
313+ <start>
314+ <element name="system">
315+ <attribute name="version">
316+ <value>1.0</value>
317+ </attribute>
318+ <interleave>
319+ <element name="summary">
320+ <ref name="summarySection"/>
321+ </element>
322+ <element name="hardware">
323+ <ref name="hardwareSection"/>
324+ </element>
325+ <element name="software">
326+ <ref name="softwareSection"/>
327+ </element>
328+ <element name="questions">
329+ <ref name="questionsSection"/>
330+ </element>
331+ <optional>
332+ <element name="context">
333+ <ref name="contextSection"/>
334+ </element>
335+ </optional>
336+ </interleave>
337+ </element>
338+ </start>
339+
340+ <define name="summarySection">
341+ <interleave>
342+ <element name="live_cd">
343+ <attribute name="value">
344+ <ref name="booleanValue"/>
345+ </attribute>
346+ <empty/>
347+ </element>
348+ <element name="system_id">
349+ <attribute name="value">
350+ <text/>
351+ </attribute>
352+ <empty/>
353+ </element>
354+ <element name="distribution">
355+ <attribute name="value">
356+ <text/>
357+ </attribute>
358+ <empty/>
359+ </element>
360+ <element name="distroseries">
361+ <attribute name="value">
362+ <text/>
363+ </attribute>
364+ <empty/>
365+ </element>
366+ <element name="architecture">
367+ <attribute name="value">
368+ <text/>
369+ </attribute>
370+ <empty/>
371+ </element>
372+ <element name="private">
373+ <attribute name="value">
374+ <ref name="booleanValue"/>
375+ </attribute>
376+ <empty/>
377+ </element>
378+ <element name="contactable">
379+ <attribute name="value">
380+ <ref name="booleanValue"/>
381+ </attribute>
382+ <empty/>
383+ </element>
384+ <element name="date_created">
385+ <attribute name="value">
386+ <data type="dateTime"/>
387+ </attribute>
388+ <empty/>
389+ </element>
390+ <element name="client">
391+ <attribute name="name">
392+ <text/>
393+ </attribute>
394+ <attribute name="version">
395+ <text/>
396+ </attribute>
397+ <empty/>
398+ <zeroOrMore>
399+ <element name="plugin">
400+ <attribute name="name">
401+ <text/>
402+ </attribute>
403+ <attribute name="version">
404+ <text/>
405+ </attribute>
406+ </element>
407+ </zeroOrMore>
408+ </element>
409+ <optional>
410+ <element name="kernel-release">
411+ <attribute name="value">
412+ <text/>
413+ </attribute>
414+ </element>
415+ </optional>
416+ </interleave>
417+ </define>
418+
419+ <define name="hardwareSection">
420+ <interleave>
421+ <choice>
422+ <element name="hal">
423+ <attribute name="version">
424+ <text/>
425+ </attribute>
426+ <oneOrMore>
427+ <element name="device">
428+ <attribute name="id">
429+ <data type="integer">
430+ <except>
431+ <value/>
432+ </except>
433+ </data>
434+ </attribute>
435+ <attribute name="udi">
436+ <text/>
437+ </attribute>
438+ <optional>
439+ <attribute name="parent">
440+ <data type="integer"/>
441+ </attribute>
442+ </optional>
443+ <!-- XXX: Abel Deuring 2007-12-07:
444+ specify a set of required properties? -->
445+ <oneOrMore>
446+ <ref name="property"/>
447+ </oneOrMore>
448+ </element>
449+ </oneOrMore>
450+ </element>
451+ <group>
452+ <interleave>
453+ <element name="udev">
454+ <text/>
455+ </element>
456+ <element name="dmi">
457+ <text/>
458+ </element>
459+ <element name="sysfs-attributes">
460+ <zeroOrMore>
461+ <text/>
462+ </zeroOrMore>
463+ </element>
464+ </interleave>
465+ </group>
466+ </choice>
467+ <element name="processors">
468+ <oneOrMore>
469+ <element name="processor">
470+ <attribute name="id">
471+ <data type="integer">
472+ <except>
473+ <value/>
474+ </except>
475+ </data>
476+ </attribute>
477+ <attribute name="name">
478+ <text/>
479+ </attribute>
480+ <oneOrMore>
481+ <ref name="property"/>
482+ </oneOrMore>
483+ </element>
484+ </oneOrMore>
485+ </element>
486+ <optional>
487+ <element name="aliases">
488+ <zeroOrMore>
489+ <element name="alias">
490+ <attribute name="target">
491+ <text/>
492+ </attribute>
493+ <interleave>
494+ <element name="vendor">
495+ <text/>
496+ </element>
497+ <element name="model">
498+ <text/>
499+ </element>
500+ </interleave>
501+ </element>
502+ </zeroOrMore>
503+ </element>
504+ </optional>
505+ </interleave>
506+ </define>
507+
508+ <define name="softwareSection">
509+ <interleave>
510+ <element name="lsbrelease">
511+ <!-- XXX: Abel Deuring 2007-12-07:
512+ specify a more restrictive set of allowed
513+ and/or required properties?
514+ -->
515+ <oneOrMore>
516+ <ref name="property"/>
517+ </oneOrMore>
518+ </element>
519+ <optional>
520+ <element name="packages">
521+ <zeroOrMore>
522+ <element name="package">
523+ <attribute name="name"/>
524+ <attribute name="id">
525+ <data type="integer">
526+ <except>
527+ <value/>
528+ </except>
529+ </data>
530+ </attribute>
531+ <oneOrMore>
532+ <ref name="property"/>
533+ </oneOrMore>
534+ </element>
535+ </zeroOrMore>
536+ </element>
537+ </optional>
538+ <optional>
539+ <element name="xorg">
540+ <attribute name="version">
541+ <text/>
542+ </attribute>
543+ <zeroOrMore>
544+ <element name="driver">
545+ <optional>
546+ <attribute name="device">
547+ <data type="integer"/>
548+ </attribute>
549+ </optional>
550+ <attribute name="name">
551+ <text/>
552+ </attribute>
553+ <optional>
554+ <attribute name="version">
555+ <text/>
556+ </attribute>
557+ </optional>
558+ <attribute name="class">
559+ <text/>
560+ </attribute>
561+ </element>
562+ </zeroOrMore>
563+ </element>
564+ </optional>
565+ </interleave>
566+ </define>
567+
568+ <define name="questionsSection">
569+ <zeroOrMore>
570+ <element name="question">
571+ <attribute name="name">
572+ <text/>
573+ </attribute>
574+ <a:comment>
575+ The attribute "plugin" must be set, if the question
576+ is generated by a plugin.
577+ </a:comment>
578+ <optional>
579+ <attribute name="plugin">
580+ <text/>
581+ </attribute>
582+ </optional>
583+ <interleave>
584+ <optional>
585+ <element name="command">
586+ <text/>
587+ </element>
588+ </optional>
589+ <choice>
590+ <interleave>
591+ <element name="answer">
592+ <attribute name="type">
593+ <value>multiple_choice</value>
594+ </attribute>
595+ <optional>
596+ <attribute name="unit">
597+ <text/>
598+ </attribute>
599+ </optional>
600+ <text/>
601+ </element>
602+ <element name="answer_choices">
603+ <oneOrMore>
604+ <ref name="value"/>
605+ </oneOrMore>
606+ </element>
607+ </interleave>
608+ <element name="answer">
609+ <attribute name="type">
610+ <value>measurement</value>
611+ </attribute>
612+ <optional>
613+ <attribute name="unit">
614+ <text/>
615+ </attribute>
616+ </optional>
617+ <data type="decimal"/>
618+ </element>
619+ </choice>
620+ <zeroOrMore>
621+ <element name="target">
622+ <attribute name="id">
623+ <text/>
624+ </attribute>
625+ <interleave>
626+ <zeroOrMore>
627+ <element name="driver">
628+ <text/>
629+ </element>
630+ </zeroOrMore>
631+ </interleave>
632+ </element>
633+ </zeroOrMore>
634+ <optional>
635+ <element name="comment">
636+ <text/>
637+ </element>
638+ </optional>
639+ </interleave>
640+ </element>
641+ </zeroOrMore>
642+ </define>
643+
644+ <define name="contextSection">
645+ <zeroOrMore>
646+ <element name="info">
647+ <attribute name="command">
648+ <text/>
649+ </attribute>
650+ <text/>
651+ </element>
652+ </zeroOrMore>
653+ </define>
654+
655+ <a:comment>
656+ convenience for Python code: 'True'/'False' for boolean values
657+ instead of 'true'/'false' as defined by
658+ http://www.w3.org/2001/XMLSchema-datatypes .
659+ </a:comment>
660+ <define name="booleanValue">
661+ <choice>
662+ <value>True</value>
663+ <value>False</value>
664+ </choice>
665+ </define>
666+
667+ <define name="propertyAndValueContent">
668+ <a:comment>
669+ Allowed types and values:
670+ The dbus... data types are used for HAL properties; the data
671+ types are specified in
672+ http://dbus.freedesktop.org/doc/dbus-specification.html
673+ The other data types are Python data types, defined in
674+ http://docs.python.org/lib/types.html
675+ </a:comment>
676+ <choice>
677+ <group>
678+ <attribute name="type">
679+ <choice>
680+ <value>dbus.Boolean</value>
681+ <value>bool</value>
682+ </choice>
683+ </attribute>
684+ <ref name="booleanValue"/>
685+ </group>
686+ <group>
687+ <attribute name="type">
688+ <choice>
689+ <value>dbus.String</value>
690+ <value>dbus.UTF8String</value>
691+ <value>str</value>
692+ </choice>
693+ </attribute>
694+ <text/>
695+ </group>
696+ <group>
697+ <attribute name="type">
698+ <value>dbus.Byte</value>
699+ </attribute>
700+ <data type="unsignedByte">
701+ <except>
702+ <value/>
703+ </except>
704+ </data>
705+ </group>
706+ <group>
707+ <attribute name="type">
708+ <value>dbus.Int16</value>
709+ </attribute>
710+ <data type="short">
711+ <except>
712+ <value/>
713+ </except>
714+ </data>
715+ </group>
716+ <group>
717+ <attribute name="type">
718+ <value>dbus.Int32</value>
719+ </attribute>
720+ <data type="int">
721+ <except>
722+ <value/>
723+ </except>
724+ </data>
725+ </group>
726+ <group>
727+ <attribute name="type">
728+ <value>dbus.Int64</value>
729+ </attribute>
730+ <data type="long">
731+ <except>
732+ <value/>
733+ </except>
734+ </data>
735+ </group>
736+ <group>
737+ <attribute name="type">
738+ <value>dbus.UInt16</value>
739+ </attribute>
740+ <data type="unsignedShort">
741+ <except>
742+ <value/>
743+ </except>
744+ </data>
745+ </group>
746+ <group>
747+ <attribute name="type">
748+ <value>dbus.UInt32</value>
749+ </attribute>
750+ <data type="unsignedInt">
751+ <except>
752+ <value/>
753+ </except>
754+ </data>
755+ </group>
756+ <group>
757+ <attribute name="type">
758+ <value>dbus.UInt64</value>
759+ </attribute>
760+ <data type="unsignedLong">
761+ <except>
762+ <value/>
763+ </except>
764+ </data>
765+ </group>
766+ <group>
767+ <attribute name="type">
768+ <value>int</value>
769+ </attribute>
770+ <data type="long">
771+ <except>
772+ <value/>
773+ </except>
774+ </data>
775+ </group>
776+ <group>
777+ <attribute name="type">
778+ <value>long</value>
779+ </attribute>
780+ <data type="integer">
781+ <except>
782+ <value/>
783+ </except>
784+ </data>
785+ </group>
786+ <group>
787+ <attribute name="type">
788+ <choice>
789+ <value>dbus.Double</value>
790+ <value>float</value>
791+ </choice>
792+ </attribute>
793+ <data type="decimal"/>
794+ </group>
795+ <group>
796+ <attribute name="type">
797+ <choice>
798+ <value>dbus.Array</value>
799+ <value>list</value>
800+ </choice>
801+ </attribute>
802+ <zeroOrMore>
803+ <element name="value">
804+ <ref name="propertyAndValueContent"/>
805+ </element>
806+ </zeroOrMore>
807+ </group>
808+ <group>
809+ <attribute name="type">
810+ <choice>
811+ <value>dbus.Dictionary</value>
812+ <value>dict</value>
813+ </choice>
814+ </attribute>
815+ <zeroOrMore>
816+ <element name="value">
817+ <attribute name="name">
818+ <text/>
819+ </attribute>
820+ <ref name="propertyAndValueContent"/>
821+ </element>
822+ </zeroOrMore>
823+ </group>
824+ </choice>
825+ </define>
826+
827+ <define name="property">
828+ <element name="property">
829+ <attribute name="name">
830+ <text/>
831+ </attribute>
832+ <ref name="propertyAndValueContent"/>
833+ </element>
834+ </define>
835+
836+ <define name="value">
837+ <element name="value">
838+ <ref name="propertyAndValueContent"/>
839+ </element>
840+ </define>
841+</grammar>

Subscribers

People subscribed via source and target branches