Merge lp:~adeuring/launchpad/bug-438734-parse-kernel-release-nnode into lp:launchpad
- bug-438734-parse-kernel-release-nnode
- Merge into devel
Proposed by
Abel Deuring
Status: | Merged |
---|---|
Approved by: | Brad Crittenden |
Approved revision: | no longer in the source branch. |
Merged at revision: | not available |
Proposed branch: | lp:~adeuring/launchpad/bug-438734-parse-kernel-release-nnode |
Merge into: | lp:launchpad |
Diff against target: |
387 lines 3 files modified
lib/canonical/launchpad/scripts/hwdbsubmissions.py (+78/-0) lib/canonical/launchpad/scripts/tests/hardwaretest-udev.xml (+13/-4) lib/canonical/launchpad/scripts/tests/test_hwdb_submission_parser.py (+216/-2) |
To merge this branch: | bzr merge lp:~adeuring/launchpad/bug-438734-parse-kernel-release-nnode |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Brad Crittenden (community) | code | Approve | |
Review via email: mp+12589@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Abel Deuring (adeuring) wrote : | # |
Revision history for this message
Brad Crittenden (bac) wrote : | # |
Hi Abel,
Thanks for making this change in support of Karmic. I found a few little issues:
typo: s/<smmary>
The pytz package already has an instance of UTC we can use. Please replace utc_tz with just pytz.UTC. It's more readable and less work.
Thanks,
Brad
review:
Approve
(code)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/canonical/launchpad/scripts/hwdbsubmissions.py' | |||
2 | --- lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-09-28 11:33:57 +0000 | |||
3 | +++ lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-09-29 15:36:18 +0000 | |||
4 | @@ -260,6 +260,7 @@ | |||
5 | 260 | 'contactable': _getValueAttributeAsBoolean, | 260 | 'contactable': _getValueAttributeAsBoolean, |
6 | 261 | 'date_created': _getValueAttributeAsDateTime, | 261 | 'date_created': _getValueAttributeAsDateTime, |
7 | 262 | 'client': _getClientData, | 262 | 'client': _getClientData, |
8 | 263 | 'kernel-release': _getValueAttributeAsString, | ||
9 | 263 | } | 264 | } |
10 | 264 | 265 | ||
11 | 265 | def _parseSummary(self, summary_node): | 266 | def _parseSummary(self, summary_node): |
12 | @@ -556,6 +557,82 @@ | |||
13 | 556 | dmi_data[record[0]] = record[1] | 557 | dmi_data[record[0]] = record[1] |
14 | 557 | return dmi_data | 558 | return dmi_data |
15 | 558 | 559 | ||
16 | 560 | def _parseSysfsAttributes(self, sysfs_node): | ||
17 | 561 | """Parse the <sysfs-attributes> node. | ||
18 | 562 | |||
19 | 563 | :return: A dictionary {path: attrs, ...} where path is the | ||
20 | 564 | path is the path of a sysfs directory, and where attrs | ||
21 | 565 | is a dictionary containing attribute names and values. | ||
22 | 566 | |||
23 | 567 | A sample of the input data: | ||
24 | 568 | |||
25 | 569 | P: /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0 | ||
26 | 570 | A: modalias=input:b0019v0000p0001e0000-e0,1,k74,ramlsfw | ||
27 | 571 | A: uniq= | ||
28 | 572 | A: phys=LNXPWRBN/button/input0 | ||
29 | 573 | A: name=Power Button | ||
30 | 574 | |||
31 | 575 | P: /devices/LNXSYSTM:00/device:00/PNP0A08:00/device:03/input/input8 | ||
32 | 576 | A: modalias=input:b0019v0000p0006e0000-e0,1,kE0,E1,E3,F0,F1 | ||
33 | 577 | A: uniq= | ||
34 | 578 | A: phys=/video/input0 | ||
35 | 579 | A: name=Video Bus | ||
36 | 580 | |||
37 | 581 | Data for different devices is separated by empty lines. The data | ||
38 | 582 | for each device starts with a line 'P: /devices/LNXSYSTM...', | ||
39 | 583 | specifying the sysfs path of a device, followed by zero or more | ||
40 | 584 | lines of the form 'A: key=value' | ||
41 | 585 | """ | ||
42 | 586 | sysfs_lines = sysfs_node.text.split('\n') | ||
43 | 587 | sysfs_data = {} | ||
44 | 588 | attributes = None | ||
45 | 589 | |||
46 | 590 | for line_number, line in enumerate(sysfs_lines): | ||
47 | 591 | if len(line) == 0: | ||
48 | 592 | attributes = None | ||
49 | 593 | continue | ||
50 | 594 | record = line.split(': ', 1) | ||
51 | 595 | if len(record) != 2: | ||
52 | 596 | self._logError( | ||
53 | 597 | 'Line %i in <sysfs-attributes>: No valid key:value data: ' | ||
54 | 598 | '%r' % (line_number, line), | ||
55 | 599 | self.submission_key) | ||
56 | 600 | return None | ||
57 | 601 | |||
58 | 602 | key, value = record | ||
59 | 603 | if key == 'P': | ||
60 | 604 | if attributes is not None: | ||
61 | 605 | self._logError( | ||
62 | 606 | "Line %i in <sysfs-attributes>: duplicate 'P' line " | ||
63 | 607 | "found: %r" % (line_number, line), | ||
64 | 608 | self.submission_key) | ||
65 | 609 | return None | ||
66 | 610 | attributes = {} | ||
67 | 611 | sysfs_data[value] = attributes | ||
68 | 612 | elif key == 'A': | ||
69 | 613 | if attributes is None: | ||
70 | 614 | self._logError( | ||
71 | 615 | "Line %i in <sysfs-attributes>: Block for a device " | ||
72 | 616 | "does not start with 'P:': %r" % (line_number, line), | ||
73 | 617 | self.submission_key) | ||
74 | 618 | return None | ||
75 | 619 | attribute_data = value.split('=', 1) | ||
76 | 620 | if len(attribute_data) != 2: | ||
77 | 621 | self._logError( | ||
78 | 622 | 'Line %i in <sysfs-attributes>: Attribute line does ' | ||
79 | 623 | 'not contain key=value data: %r' | ||
80 | 624 | % (line_number, line), | ||
81 | 625 | self.submission_key) | ||
82 | 626 | return None | ||
83 | 627 | attributes[attribute_data[0]] = attribute_data[1] | ||
84 | 628 | else: | ||
85 | 629 | self._logError( | ||
86 | 630 | 'Line %i in <sysfs-attributes>: Unexpected key: %r' | ||
87 | 631 | % (line_number, line), | ||
88 | 632 | self.submission_key) | ||
89 | 633 | return None | ||
90 | 634 | return sysfs_data | ||
91 | 635 | |||
92 | 559 | def _setHardwareSectionParsers(self): | 636 | def _setHardwareSectionParsers(self): |
93 | 560 | self._parse_hardware_section = { | 637 | self._parse_hardware_section = { |
94 | 561 | 'hal': self._parseHAL, | 638 | 'hal': self._parseHAL, |
95 | @@ -563,6 +640,7 @@ | |||
96 | 563 | 'aliases': self._parseAliases, | 640 | 'aliases': self._parseAliases, |
97 | 564 | 'udev': self._parseUdev, | 641 | 'udev': self._parseUdev, |
98 | 565 | 'dmi': self._parseDmi, | 642 | 'dmi': self._parseDmi, |
99 | 643 | 'sysfs-attributes': self._parseSysfsAttributes, | ||
100 | 566 | } | 644 | } |
101 | 567 | 645 | ||
102 | 568 | def _parseHardware(self, hardware_node): | 646 | def _parseHardware(self, hardware_node): |
103 | 569 | 647 | ||
104 | === modified file 'lib/canonical/launchpad/scripts/tests/hardwaretest-udev.xml' | |||
105 | --- lib/canonical/launchpad/scripts/tests/hardwaretest-udev.xml 2009-09-14 09:16:45 +0000 | |||
106 | +++ lib/canonical/launchpad/scripts/tests/hardwaretest-udev.xml 2009-09-29 15:36:18 +0000 | |||
107 | @@ -184,10 +184,19 @@ | |||
108 | 184 | is stored in the same format as the DMI data: | 184 | is stored in the same format as the DMI data: |
109 | 185 | /path/to/file:filecontent | 185 | /path/to/file:filecontent |
110 | 186 | --> | 186 | --> |
115 | 187 | <sysfs-attributes>/sys/devices/pci0000:00/0000:00:1f.1/host3/target3:0:0/3:0:0:0/vendor:HL-DT-ST | 187 | <sysfs-attributes> |
116 | 188 | /sys/devices/pci0000:00/0000:00:1f.1/host3/target3:0:0/3:0:0:0/model:DVDRAM GSA-4083N | 188 | P: /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0 |
117 | 189 | /sys/devices/pci0000:00/0000:00:1f.1/host3/target3:0:0/3:0:0:0/type:5 | 189 | A: modalias=input:b0019v0000p0001e0000-e0,1,k74,ramlsfw |
118 | 190 | </sysfs-attributes> | 190 | A: uniq= |
119 | 191 | A: phys=LNXPWRBN/button/input0 | ||
120 | 192 | A: name=Power Button | ||
121 | 193 | |||
122 | 194 | P: /devices/LNXSYSTM:00/device:00/PNP0A08:00/device:03/input/input8 | ||
123 | 195 | A: modalias=input:b0019v0000p0006e0000-e0,1,kE0,E1,E3,F0,F1,F2,F3,F4,F5,ramlsfw | ||
124 | 196 | A: uniq= | ||
125 | 197 | A: phys=/video/input0 | ||
126 | 198 | A: name=Video Bus | ||
127 | 199 | </sysfs-attributes> | ||
128 | 191 | 200 | ||
129 | 192 | <!-- processors: Data about processors installed in a system. | 201 | <!-- processors: Data about processors installed in a system. |
130 | 193 | The data is retrieved from /proc/cpuinfo. | 202 | The data is retrieved from /proc/cpuinfo. |
131 | 194 | 203 | ||
132 | === modified file 'lib/canonical/launchpad/scripts/tests/test_hwdb_submission_parser.py' | |||
133 | --- lib/canonical/launchpad/scripts/tests/test_hwdb_submission_parser.py 2009-09-28 12:35:40 +0000 | |||
134 | +++ lib/canonical/launchpad/scripts/tests/test_hwdb_submission_parser.py 2009-09-29 15:36:18 +0000 | |||
135 | @@ -11,6 +11,7 @@ | |||
136 | 11 | from datetime import datetime | 11 | from datetime import datetime |
137 | 12 | import logging | 12 | import logging |
138 | 13 | import os | 13 | import os |
139 | 14 | from textwrap import dedent | ||
140 | 14 | from unittest import TestCase, TestLoader | 15 | from unittest import TestCase, TestLoader |
141 | 15 | 16 | ||
142 | 16 | import pytz | 17 | import pytz |
143 | @@ -184,7 +185,6 @@ | |||
144 | 184 | """) | 185 | """) |
145 | 185 | parser = SubmissionParser(self.log) | 186 | parser = SubmissionParser(self.log) |
146 | 186 | summary = parser._parseSummary(node) | 187 | summary = parser._parseSummary(node) |
147 | 187 | utc_tz = pytz.timezone('UTC') | ||
148 | 188 | expected_data = { | 188 | expected_data = { |
149 | 189 | 'live_cd': False, | 189 | 'live_cd': False, |
150 | 190 | 'system_id': 'f982bb1ab536469cebfd6eaadcea0ffc', | 190 | 'system_id': 'f982bb1ab536469cebfd6eaadcea0ffc', |
151 | @@ -194,7 +194,7 @@ | |||
152 | 194 | 'private': False, | 194 | 'private': False, |
153 | 195 | 'contactable': False, | 195 | 'contactable': False, |
154 | 196 | 'date_created': datetime(2007, 9, 28, 16, 9, 20, 126842, | 196 | 'date_created': datetime(2007, 9, 28, 16, 9, 20, 126842, |
156 | 197 | tzinfo=utc_tz), | 197 | tzinfo=pytz.UTC), |
157 | 198 | 'client': { | 198 | 'client': { |
158 | 199 | 'name': 'hwtest', | 199 | 'name': 'hwtest', |
159 | 200 | 'version': '0.9', | 200 | 'version': '0.9', |
160 | @@ -208,6 +208,57 @@ | |||
161 | 208 | summary, expected_data, | 208 | summary, expected_data, |
162 | 209 | 'SubmissionParser.parseSummary returned an unexpected result') | 209 | 'SubmissionParser.parseSummary returned an unexpected result') |
163 | 210 | 210 | ||
164 | 211 | def testSummaryNodeWithKernelRelease(self): | ||
165 | 212 | """The <summary> node may contain the sub-node <kernel-release>.""" | ||
166 | 213 | node = etree.fromstring(""" | ||
167 | 214 | <summary> | ||
168 | 215 | <live_cd value="False"/> | ||
169 | 216 | <system_id value="f982bb1ab536469cebfd6eaadcea0ffc"/> | ||
170 | 217 | <distribution value="Ubuntu"/> | ||
171 | 218 | <distroseries value="7.04"/> | ||
172 | 219 | <architecture value="amd64"/> | ||
173 | 220 | <private value="False"/> | ||
174 | 221 | <contactable value="False"/> | ||
175 | 222 | <date_created value="2007-09-28T16:09:20.126842"/> | ||
176 | 223 | <client name="hwtest" version="0.9"> | ||
177 | 224 | <plugin name="architecture_info" version="1.1"/> | ||
178 | 225 | <plugin name="find_network_controllers" version="2.34"/> | ||
179 | 226 | </client> | ||
180 | 227 | <kernel-release value="2.6.28-15-generic"/> | ||
181 | 228 | </summary> | ||
182 | 229 | """) | ||
183 | 230 | parser = SubmissionParser(self.log) | ||
184 | 231 | summary = parser._parseSummary(node) | ||
185 | 232 | expected_data = { | ||
186 | 233 | 'live_cd': False, | ||
187 | 234 | 'system_id': 'f982bb1ab536469cebfd6eaadcea0ffc', | ||
188 | 235 | 'distribution': 'Ubuntu', | ||
189 | 236 | 'distroseries': '7.04', | ||
190 | 237 | 'architecture': 'amd64', | ||
191 | 238 | 'private': False, | ||
192 | 239 | 'contactable': False, | ||
193 | 240 | 'date_created': datetime(2007, 9, 28, 16, 9, 20, 126842, | ||
194 | 241 | tzinfo=pytz.UTC), | ||
195 | 242 | 'client': { | ||
196 | 243 | 'name': 'hwtest', | ||
197 | 244 | 'version': '0.9', | ||
198 | 245 | 'plugins': [ | ||
199 | 246 | { | ||
200 | 247 | 'name': 'architecture_info', | ||
201 | 248 | 'version': '1.1' | ||
202 | 249 | }, | ||
203 | 250 | { | ||
204 | 251 | 'name': 'find_network_controllers', | ||
205 | 252 | 'version': '2.34' | ||
206 | 253 | } | ||
207 | 254 | ] | ||
208 | 255 | }, | ||
209 | 256 | 'kernel-release': '2.6.28-15-generic', | ||
210 | 257 | } | ||
211 | 258 | self.assertEqual( | ||
212 | 259 | summary, expected_data, | ||
213 | 260 | 'SubmissionParser.parseSummary returned an unexpected result') | ||
214 | 261 | |||
215 | 211 | def _runPropertyTest(self, xml): | 262 | def _runPropertyTest(self, xml): |
216 | 212 | parser = SubmissionParser(self.log) | 263 | parser = SubmissionParser(self.log) |
217 | 213 | node = etree.fromstring(xml) | 264 | node = etree.fromstring(xml) |
218 | @@ -649,6 +700,169 @@ | |||
219 | 649 | parser.submission_key, | 700 | parser.submission_key, |
220 | 650 | "Line 1 in <dmi>: No valid key:value data: 'invalid line'") | 701 | "Line 1 in <dmi>: No valid key:value data: 'invalid line'") |
221 | 651 | 702 | ||
222 | 703 | def testSysfsAttributes(self): | ||
223 | 704 | """Test of SubmissionParser._parseSysfsAttributes(). | ||
224 | 705 | |||
225 | 706 | The content of the <sys-attributes> node is converted into | ||
226 | 707 | a dictionary. | ||
227 | 708 | """ | ||
228 | 709 | parser = SubmissionParser(self.log) | ||
229 | 710 | node = etree.fromstring(dedent(""" | ||
230 | 711 | <sysfs-attributes> | ||
231 | 712 | P: /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0 | ||
232 | 713 | A: modalias=input:b0019v0000p0001e0000-e0,1,k74 | ||
233 | 714 | A: uniq= | ||
234 | 715 | A: phys=LNXPWRBN/button/input0 | ||
235 | 716 | A: name=Power Button | ||
236 | 717 | |||
237 | 718 | P: /devices/LNXSYSTM:00/device:00/PNP0A08:00/device:03 | ||
238 | 719 | A: uniq= | ||
239 | 720 | A: phys=/video/input0 | ||
240 | 721 | A: name=Video Bus | ||
241 | 722 | </sysfs-attributes> | ||
242 | 723 | """)) | ||
243 | 724 | result = parser._parseSysfsAttributes(node) | ||
244 | 725 | self.assertEqual( | ||
245 | 726 | { | ||
246 | 727 | '/devices/LNXSYSTM:00/LNXPWRBN:00/input/input0': { | ||
247 | 728 | 'modalias': 'input:b0019v0000p0001e0000-e0,1,k74', | ||
248 | 729 | 'uniq': '', | ||
249 | 730 | 'phys': 'LNXPWRBN/button/input0', | ||
250 | 731 | 'name': 'Power Button', | ||
251 | 732 | }, | ||
252 | 733 | '/devices/LNXSYSTM:00/device:00/PNP0A08:00/device:03': { | ||
253 | 734 | 'uniq': '', | ||
254 | 735 | 'phys': '/video/input0', | ||
255 | 736 | 'name': 'Video Bus', | ||
256 | 737 | }, | ||
257 | 738 | |||
258 | 739 | }, | ||
259 | 740 | result, | ||
260 | 741 | 'Invalid parsing result of <sysfs-attributes> node.') | ||
261 | 742 | |||
262 | 743 | def testSysfsAttributesLineWithoutKeyValueData(self): | ||
263 | 744 | """Test of SubmissionParser._parseSysfsAttributes(). | ||
264 | 745 | |||
265 | 746 | Lines not in key: value format are rejected. | ||
266 | 747 | """ | ||
267 | 748 | parser = SubmissionParser(self.log) | ||
268 | 749 | parser.submission_key = ( | ||
269 | 750 | 'Detect <sysfs-attributes> lines not in key:value format') | ||
270 | 751 | node = etree.fromstring(dedent(""" | ||
271 | 752 | <sysfs-attributes> | ||
272 | 753 | P: /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0 | ||
273 | 754 | A: modalias=input:b0019v0000p0001e0000-e0,1,k74 | ||
274 | 755 | invalid line | ||
275 | 756 | </sysfs-attributes> | ||
276 | 757 | """)) | ||
277 | 758 | result = parser._parseSysfsAttributes(node) | ||
278 | 759 | self.assertEqual( | ||
279 | 760 | None, result, | ||
280 | 761 | 'Invalid parsing result of a <sysfs-attributes> node containing ' | ||
281 | 762 | 'a line not in key:value format.') | ||
282 | 763 | self.assertErrorMessage( | ||
283 | 764 | parser.submission_key, | ||
284 | 765 | "Line 3 in <sysfs-attributes>: No valid key:value data: " | ||
285 | 766 | "'invalid line'") | ||
286 | 767 | |||
287 | 768 | def testSysfsAttributesDuplicatePLine(self): | ||
288 | 769 | """Test of SubmissionParser._parseSysfsAttributes(). | ||
289 | 770 | |||
290 | 771 | A line starting with "P:" must be the first line of a device block. | ||
291 | 772 | """ | ||
292 | 773 | parser = SubmissionParser(self.log) | ||
293 | 774 | parser.submission_key = ( | ||
294 | 775 | 'Detect <sysfs-attributes> node with duplicate P: line') | ||
295 | 776 | node = etree.fromstring(dedent(""" | ||
296 | 777 | <sysfs-attributes> | ||
297 | 778 | P: /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0 | ||
298 | 779 | A: modalias=input:b0019v0000p0001e0000-e0,1,k74 | ||
299 | 780 | P: /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0 | ||
300 | 781 | </sysfs-attributes> | ||
301 | 782 | """)) | ||
302 | 783 | result = parser._parseSysfsAttributes(node) | ||
303 | 784 | self.assertEqual( | ||
304 | 785 | None, result, | ||
305 | 786 | 'Invalid parsing result of a <sysfs-attributes> node containing ' | ||
306 | 787 | 'a duplicate P: line.') | ||
307 | 788 | self.assertErrorMessage( | ||
308 | 789 | parser.submission_key, | ||
309 | 790 | "Line 3 in <sysfs-attributes>: duplicate 'P' line found: " | ||
310 | 791 | "'P: /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0'") | ||
311 | 792 | |||
312 | 793 | def testSysfsAttributesNoPLineAtDeviceStart(self): | ||
313 | 794 | """Test of SubmissionParser._parseSysfsAttributes(). | ||
314 | 795 | |||
315 | 796 | The data for a device must start with a "P:" line. | ||
316 | 797 | """ | ||
317 | 798 | parser = SubmissionParser(self.log) | ||
318 | 799 | parser.submission_key = ( | ||
319 | 800 | 'Detect <sysfs-attributes> node without leading P: line') | ||
320 | 801 | node = etree.fromstring(dedent(""" | ||
321 | 802 | <sysfs-attributes> | ||
322 | 803 | A: modalias=input:b0019v0000p0001e0000-e0,1,k74 | ||
323 | 804 | </sysfs-attributes> | ||
324 | 805 | """)) | ||
325 | 806 | result = parser._parseSysfsAttributes(node) | ||
326 | 807 | self.assertEqual( | ||
327 | 808 | None, result, | ||
328 | 809 | 'Invalid parsing result of a <sysfs-attributes> node where a ' | ||
329 | 810 | 'device block does not start with a "P": line.') | ||
330 | 811 | self.assertErrorMessage( | ||
331 | 812 | parser.submission_key, | ||
332 | 813 | "Line 1 in <sysfs-attributes>: Block for a device does not " | ||
333 | 814 | "start with 'P:': " | ||
334 | 815 | "'A: modalias=input:b0019v0000p0001e0000-e0,1,k74'") | ||
335 | 816 | |||
336 | 817 | def testSysfsAttributesNoAttributeKeyValue(self): | ||
337 | 818 | """Test of SubmissionParser._parseSysfsAttributes(). | ||
338 | 819 | |||
339 | 820 | A line starting with "A:" must be in key=value format. | ||
340 | 821 | """ | ||
341 | 822 | parser = SubmissionParser(self.log) | ||
342 | 823 | parser.submission_key = ( | ||
343 | 824 | 'Detect <sysfs-attributes> node with A: line not in key=value ' | ||
344 | 825 | 'format') | ||
345 | 826 | node = etree.fromstring(dedent(""" | ||
346 | 827 | <sysfs-attributes> | ||
347 | 828 | P: /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0 | ||
348 | 829 | A: equal sign is missing | ||
349 | 830 | </sysfs-attributes> | ||
350 | 831 | """)) | ||
351 | 832 | result = parser._parseSysfsAttributes(node) | ||
352 | 833 | self.assertEqual( | ||
353 | 834 | None, result, | ||
354 | 835 | 'Invalid parsing result of a <sysfs-attributes> node with A: ' | ||
355 | 836 | 'line not in key=value format.') | ||
356 | 837 | self.assertErrorMessage( | ||
357 | 838 | parser.submission_key, | ||
358 | 839 | "Line 2 in <sysfs-attributes>: Attribute line does not contain " | ||
359 | 840 | "key=value data: 'A: equal sign is missing'") | ||
360 | 841 | |||
361 | 842 | def testSysfsAttributesInvalidMainKey(self): | ||
362 | 843 | """Test of SubmissionParser._parseSysfsAttributes(). | ||
363 | 844 | |||
364 | 845 | All lines must start with "P:" or "A:". | ||
365 | 846 | """ | ||
366 | 847 | parser = SubmissionParser(self.log) | ||
367 | 848 | parser.submission_key = ( | ||
368 | 849 | 'Detect <sysfs-attributes> node with invalid main key.') | ||
369 | 850 | node = etree.fromstring(dedent(""" | ||
370 | 851 | <sysfs-attributes> | ||
371 | 852 | P: /devices/LNXSYSTM:00/LNXPWRBN:00/input/input0 | ||
372 | 853 | X: an invalid line | ||
373 | 854 | </sysfs-attributes> | ||
374 | 855 | """)) | ||
375 | 856 | result = parser._parseSysfsAttributes(node) | ||
376 | 857 | self.assertEqual( | ||
377 | 858 | None, result, | ||
378 | 859 | 'Invalid parsing result of a <sysfs-attributes> node containg ' | ||
379 | 860 | 'a line that does not start with "A:" or "P:".') | ||
380 | 861 | self.assertErrorMessage( | ||
381 | 862 | parser.submission_key, | ||
382 | 863 | "Line 2 in <sysfs-attributes>: Unexpected key: " | ||
383 | 864 | "'X: an invalid line'") | ||
384 | 865 | |||
385 | 652 | def testHardware(self): | 866 | def testHardware(self): |
386 | 653 | """The <hardware> tag is converted into a dictionary.""" | 867 | """The <hardware> tag is converted into a dictionary.""" |
387 | 654 | test = self | 868 | test = self |
This branch makes the method l.c.l.scripts. hwsdbsubmission s.SubmissionPar ser._parseSumma ry() aware of the new optional node <kernel-release> in HWDB submissions. Data submitted by the HWDB client in Karmic will contain this data.
test: ./bin/test-t test_hwdb_ submission_ parser
= Launchpad lint =
Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.
Linting changed files: /launchpad/ scripts/ hwdbsubmissions .py /launchpad/ scripts/ tests/test_ hwdb_submission _parser. py
lib/canonical
lib/canonical
== Pyflakes notices ==
lib/canonical/ launchpad/ scripts/ hwdbsubmissions .py
22: redefinition of unused 'etree' from line 20
lib/canonical/ launchpad/ scripts/ tests/test_ hwdb_submission _parser. py
10: redefinition of unused 'etree' from line 8
== Pylint notices ==
lib/canonical/ launchpad/ scripts/ hwdbsubmissions .py cElementTree' (No module named etree)
20: [F0401] Unable to import 'xml.etree.
This message is not related to my changes.
This branch is based on lp:~adeuring/launchpad/bug-438169-parse-sysfs-attr, reviewed by gmb, but not yet landed. The diff against this branch:
=== modified file 'lib/canonical/ launchpad/ scripts/ hwdbsubmissions .py' launchpad/ scripts/ hwdbsubmissions .py 2009-09-29 10:11:50 +0000 launchpad/ scripts/ hwdbsubmissions .py 2009-09-29 15:02:47 +0000
'contactable' : _getValueAttrib uteAsBoolean,
'date_ created' : _getValueAttrib uteAsDateTime, uteAsString,
--- lib/canonical/
+++ lib/canonical/
@@ -260,6 +260,7 @@
'client': _getClientData,
+ 'kernel-release': _getValueAttrib
}
def _parseSummary(self, summary_node):
=== modified file 'lib/canonical/ launchpad/ scripts/ tests/test_ hwdb_submission _parser. p launchpad/ scripts/ tests/test_ hwdb_submission _parser. py 2009-0 launchpad/ scripts/ tests/test_ hwdb_submission _parser. py 2009-0
summary, expected_data,
' SubmissionParse r.parseSummary returned an unexpected result')
y'
--- lib/canonical/
9-29 11:23:04 +0000
+++ lib/canonical/
9-29 15:03:15 +0000
@@ -209,6 +209,58 @@
+ def testSummaryNode WithKernelRelea se(self) : release> .""" g(""" f982bb1ab536469 cebfd6eaadcea0f fc"/> 2007-09- 28T16:09: 20.126842" /> ure_info" version="1.1"/> network_ controllers" version="2.34"/> 2.6.28- 15-generic" /> r(self. log) _parseSummary( node) 'UTC')
+ """The <smmary> node may contain the sub-node <kernel-
+ node = etree.fromstrin
+ <summary>
+ <live_cd value="False"/>
+ <system_id value="
+ <distribution value="Ubuntu"/>
+ <distroseries value="7.04"/>
+ <architecture value="amd64"/>
+ <private value="False"/>
+ <contactable value="False"/>
+ <date_created value="
+ <client name="hwtest" version="0.9">
+ <plugin name="architect
+ <plugin name="find_
+ </client>
+ <kernel-release value="
+ </summary>
+ """)
+ parser = SubmissionParse
+ summary = parser.
+ utc_tz = pytz.timezone(
+ expected_data...