Merge lp:~adeuring/launchpad/hwdb-class-udev-device-2 into lp:launchpad
- hwdb-class-udev-device-2
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Barry Warsaw |
Approved revision: | no longer in the source branch. |
Merged at revision: | not available |
Proposed branch: | lp:~adeuring/launchpad/hwdb-class-udev-device-2 |
Merge into: | lp:launchpad |
Diff against target: |
456 lines 3 files modified
lib/canonical/launchpad/scripts/hwdbsubmissions.py (+109/-4) lib/canonical/launchpad/scripts/tests/test_hwdb_submission_parser.py (+150/-7) lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py (+54/-0) |
To merge this branch: | bzr merge lp:~adeuring/launchpad/hwdb-class-udev-device-2 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Barry Warsaw (community) | Approve | ||
Review via email: mp+13118@code.launchpad.net |
Commit message
Description of the change
Abel Deuring (adeuring) wrote : | # |
Barry Warsaw (barry) wrote : | # |
Hi Abel,
A rather terse review from me today, since I'm also the CHR. I have some
comments that should be easy to address. r=me, merge-conditional with their
consideration.
review approve
status approve
-Barry
=== modified file 'lib/canonical/
--- lib/canonical/
+++ lib/canonical/
> @@ -1212,11 +1212,83 @@
> return False
> return True
>
> + USB_DEVICE_
> + usb_product_re = re.compile(
> + '^[0-9a-
> + usb_type_re = re.compile(
Is there a reason these are class attributes? They probably make more sense
being module globals, with all-caps names.
> +
> + def checkUdevUsbPro
> + """Validation of udev USB devices.
> +
> + USB devices must have the properties DEVTYPE (value
> + 'usb_device' or 'usb_interface'), PRODUCT and TYPE. PRODUCT
> + must be a tuple of three integers in hexadecimal
> + representation, separates by '/'. TYPE must be a a tuple of
> + three integers in decimal representation, separated by '/'.
> + usb_interface nodes must additionally have a property
> + INTERFACE, containing three integers in the same format as
> + TYPE.
> + """
> + for device in udev_data:
> + subsystem = device[
> + if subsystem != 'usb':
> + continue
> + properties = device['E']
> + property_names = set(properties.
Since 'properties' is a dictionary, this is more efficient:
> + existing_
> + self.USB_
> + if existing_
> + self._logError(
> + 'USB udev device found without required properties: %r %r'
> + % (self.USB_
> + existing_
> + device['P']),
This is somewhat unreadable. You should move the .difference() calculation to
above the self._logError() call and stash it in a local variable, then use the
local variable in the interpolation.
> + self.submission
> + return False
> + if self.usb_
> + self._logError(
> + 'USB udev device found with invalid product ID: %r %r'
> + % (properties[
> + self.submission
> + return False
> + if self.usb_
> + self._logError(
> + 'USB udev device found with invalid type data: %r %r'
> + % (properties[
> + ...
Preview Diff
1 | === modified file 'lib/canonical/launchpad/scripts/hwdbsubmissions.py' |
2 | --- lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-10-08 13:41:32 +0000 |
3 | +++ lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-10-09 15:45:23 +0000 |
4 | @@ -94,6 +94,11 @@ |
5 | 'scsi': '%-16s', |
6 | } |
7 | |
8 | +UDEV_USB_DEVICE_PROPERTIES = set(('DEVTYPE', 'PRODUCT', 'TYPE')) |
9 | +UDEV_USB_PRODUCT_RE = re.compile( |
10 | + '^[0-9a-f]{1,4}/[0-9a-f]{1,4}/[0-9a-f]{1,4}$', re.I) |
11 | +UDEV_USB_TYPE_RE = re.compile('^[0-9]{1,3}/[0-9]{1,3}/[0-9]{1,3}$') |
12 | + |
13 | class SubmissionParser(object): |
14 | """A Parser for the submissions to the hardware database.""" |
15 | |
16 | @@ -1165,7 +1170,7 @@ |
17 | """ |
18 | for device in udev_data: |
19 | properties = device['E'] |
20 | - property_names = set(properties.keys()) |
21 | + property_names = set(properties) |
22 | existing_pci_properties = property_names.intersection( |
23 | self.PCI_PROPERTIES) |
24 | subsystem = device['E'].get('SUBSYSTEM') |
25 | @@ -1212,11 +1217,78 @@ |
26 | return False |
27 | return True |
28 | |
29 | + def checkUdevUsbProperties(self, udev_data): |
30 | + """Validation of udev USB devices. |
31 | + |
32 | + USB devices must have the properties DEVTYPE (value |
33 | + 'usb_device' or 'usb_interface'), PRODUCT and TYPE. PRODUCT |
34 | + must be a tuple of three integers in hexadecimal |
35 | + representation, separates by '/'. TYPE must be a a tuple of |
36 | + three integers in decimal representation, separated by '/'. |
37 | + usb_interface nodes must additionally have a property |
38 | + INTERFACE, containing three integers in the same format as |
39 | + TYPE. |
40 | + """ |
41 | + for device in udev_data: |
42 | + subsystem = device['E'].get('SUBSYSTEM') |
43 | + if subsystem != 'usb': |
44 | + continue |
45 | + properties = device['E'] |
46 | + property_names = set(properties) |
47 | + existing_usb_properties = property_names.intersection( |
48 | + UDEV_USB_DEVICE_PROPERTIES) |
49 | + if existing_usb_properties != UDEV_USB_DEVICE_PROPERTIES: |
50 | + missing_properties = UDEV_USB_DEVICE_PROPERTIES.difference( |
51 | + existing_usb_properties) |
52 | + self._logError( |
53 | + 'USB udev device found without required properties: %r %r' |
54 | + % (missing_properties, device['P']), |
55 | + self.submission_key) |
56 | + return False |
57 | + if UDEV_USB_PRODUCT_RE.search(properties['PRODUCT']) is None: |
58 | + self._logError( |
59 | + 'USB udev device found with invalid product ID: %r %r' |
60 | + % (properties['PRODUCT'], device['P']), |
61 | + self.submission_key) |
62 | + return False |
63 | + if UDEV_USB_TYPE_RE.search(properties['TYPE']) is None: |
64 | + self._logError( |
65 | + 'USB udev device found with invalid type data: %r %r' |
66 | + % (properties['TYPE'], device['P']), |
67 | + self.submission_key) |
68 | + return False |
69 | + |
70 | + device_type = properties['DEVTYPE'] |
71 | + if device_type not in ('usb_device', 'usb_interface'): |
72 | + self._logError( |
73 | + 'USB udev device found with invalid udev type data: %r %r' |
74 | + % (device_type, device['P']), |
75 | + self.submission_key) |
76 | + return False |
77 | + if device_type == 'usb_interface': |
78 | + interface_type = properties.get('INTERFACE') |
79 | + if interface_type is None: |
80 | + self._logError( |
81 | + 'USB interface udev device found without INTERFACE ' |
82 | + 'property: %r' |
83 | + % device['P'], |
84 | + self.submission_key) |
85 | + return False |
86 | + if UDEV_USB_TYPE_RE.search(interface_type) is None: |
87 | + self._logError( |
88 | + 'USB Interface udev device found with invalid ' |
89 | + 'INTERFACE property: %r %r' |
90 | + % (interface_type, device['P']), |
91 | + self.submission_key) |
92 | + return False |
93 | + return True |
94 | + |
95 | def checkConsistentUdevDeviceData(self, udev_data): |
96 | """Consistency checks for udev data.""" |
97 | - if not self.checkUdevDictsHavePathKey(udev_data): |
98 | - return False |
99 | - return self.checkUdevPciProperties(udev_data) |
100 | + return ( |
101 | + self.checkUdevDictsHavePathKey(udev_data) and |
102 | + self.checkUdevPciProperties(udev_data) and |
103 | + self.checkUdevUsbProperties(udev_data)) |
104 | |
105 | def checkConsistency(self, parsed_data): |
106 | """Run consistency checks on the submitted data. |
107 | @@ -2278,6 +2350,39 @@ |
108 | """See `BaseDevice`.""" |
109 | return self.pci_class_info[1] |
110 | |
111 | + @property |
112 | + def is_usb(self): |
113 | + """True, if this is a USB device, else False.""" |
114 | + return self.udev['E'].get('SUBSYSTEM') == 'usb' |
115 | + |
116 | + @property |
117 | + def usb_ids(self): |
118 | + """The vendor ID, product ID, product version for USB devices. |
119 | + |
120 | + :return: [vendor_id, product_id, version] for USB devices |
121 | + or [None, None, None] for other devices. |
122 | + """ |
123 | + if self.is_usb: |
124 | + # udev represents USB device IDs as strings |
125 | + # vendor_id/prodct_id/version, where each part is |
126 | + # as a hexdecimal number. |
127 | + # SubmissionParser.checkUdevUsbProperties() ensures that |
128 | + # the string PRODUCT is in the format required below. |
129 | + product_info = self.udev['E']['PRODUCT'].split('/') |
130 | + return [int(part, 16) for part in product_info] |
131 | + else: |
132 | + return [None, None, None] |
133 | + |
134 | + @property |
135 | + def usb_vendor_id(self): |
136 | + """See `BaseDevice`.""" |
137 | + return self.usb_ids[0] |
138 | + |
139 | + @property |
140 | + def usb_product_id(self): |
141 | + """See `BaseDevice`.""" |
142 | + return self.usb_ids[1] |
143 | + |
144 | |
145 | class ProcessingLoop(object): |
146 | """An `ITunableLoop` for processing HWDB submissions.""" |
147 | |
148 | === modified file 'lib/canonical/launchpad/scripts/tests/test_hwdb_submission_parser.py' |
149 | --- lib/canonical/launchpad/scripts/tests/test_hwdb_submission_parser.py 2009-10-08 13:41:32 +0000 |
150 | +++ lib/canonical/launchpad/scripts/tests/test_hwdb_submission_parser.py 2009-10-09 15:45:23 +0000 |
151 | @@ -112,6 +112,25 @@ |
152 | 'PCI_SLOT_NAME': '0000:00:1f.2', |
153 | } |
154 | } |
155 | + self.udev_usb_device = { |
156 | + 'P': '/devices/pci0000:00/0000:00:1d.1/usb3/3-2', |
157 | + 'E': { |
158 | + 'SUBSYSTEM': 'usb', |
159 | + 'DEVTYPE': 'usb_device', |
160 | + 'PRODUCT': '46d/a01/1013', |
161 | + 'TYPE': '0/0/0', |
162 | + }, |
163 | + } |
164 | + self.udev_usb_interface = { |
165 | + 'P': '/devices/pci0000:00/0000:00:1d.1/usb3/3-2/3-2:1.1', |
166 | + 'E': { |
167 | + 'SUBSYSTEM': 'usb', |
168 | + 'DEVTYPE': 'usb_interface', |
169 | + 'PRODUCT': '46d/a01/1013', |
170 | + 'TYPE': '0/0/0', |
171 | + 'INTERFACE': '1/2/0', |
172 | + }, |
173 | + } |
174 | |
175 | def getTimestampETreeNode(self, time_string): |
176 | """Return an Elementtree node for an XML tag with a timestamp.""" |
177 | @@ -1788,7 +1807,7 @@ |
178 | parser.submission_key, 'udev node found without a "P" key') |
179 | |
180 | def testCheckUdevPciProperties(self): |
181 | - """Test of SubmmissionParser.checkUdevPciProperties().""" |
182 | + """Test of SubmissionParser.checkUdevPciProperties().""" |
183 | # udev PCI devices must have the properties PCI_CLASS, PCI_ID, |
184 | # PCI_SUBSYS_ID, PCI_SLOT_NAME; other devices must not have |
185 | # these properties. |
186 | @@ -1797,7 +1816,7 @@ |
187 | [self.udev_root_device, self.udev_pci_device])) |
188 | |
189 | def testCheckUdevPciPropertiesNonPciDeviceWithPciProperties(self): |
190 | - """Test of SubmmissionParser.checkUdevPciProperties(). |
191 | + """Test of SubmissionParser.checkUdevPciProperties(). |
192 | |
193 | A non-PCI device having PCI properties makes a submission invalid. |
194 | """ |
195 | @@ -1812,7 +1831,7 @@ |
196 | "'/devices/LNXSYSTM:00'") |
197 | |
198 | def testCheckUdevPciPropertiesPciDeviceWithoutRequiredProperties(self): |
199 | - """Test of SubmmissionParser.checkUdevPciProperties(). |
200 | + """Test of SubmissionParser.checkUdevPciProperties(). |
201 | |
202 | A PCI device not having a required PCI property makes a submission |
203 | invalid. |
204 | @@ -1828,7 +1847,7 @@ |
205 | "set(['PCI_CLASS']) '/devices/pci0000:00/0000:00:1f.2'") |
206 | |
207 | def testCheckUdevPciPropertiesPciDeviceWithNonIntegerPciClass(self): |
208 | - """Test of SubmmissionParser.checkUdevPciProperties(). |
209 | + """Test of SubmissionParser.checkUdevPciProperties(). |
210 | |
211 | A PCI device with a non-integer class value makes a submission |
212 | invalid. |
213 | @@ -1844,7 +1863,7 @@ |
214 | "'/devices/pci0000:00/0000:00:1f.2'") |
215 | |
216 | def testCheckUdevPciPropertiesPciDeviceWithInvalidPciClassValue(self): |
217 | - """Test of SubmmissionParser.checkUdevPciProperties(). |
218 | + """Test of SubmissionParser.checkUdevPciProperties(). |
219 | |
220 | A PCI device with invalid class data makes a submission |
221 | invalid. |
222 | @@ -1860,7 +1879,7 @@ |
223 | "'/devices/pci0000:00/0000:00:1f.2'") |
224 | |
225 | def testCheckUdevPciPropertiesPciDeviceWithInvalidDeviceID(self): |
226 | - """Test of SubmmissionParser.checkUdevPciProperties(). |
227 | + """Test of SubmissionParser.checkUdevPciProperties(). |
228 | |
229 | A PCI device with an invalid device ID makes a submission |
230 | invalid. |
231 | @@ -1876,7 +1895,7 @@ |
232 | "'/devices/pci0000:00/0000:00:1f.2'") |
233 | |
234 | def testCheckUdevPciPropertiesPciDeviceWithInvalidSubsystemID(self): |
235 | - """Test of SubmmissionParser.checkUdevPciProperties(). |
236 | + """Test of SubmissionParser.checkUdevPciProperties(). |
237 | |
238 | A PCI device with an invalid subsystem ID makes a submission |
239 | invalid. |
240 | @@ -1891,6 +1910,110 @@ |
241 | "Invalid udev PCI device ID: 'not-a-subsystem-id' " |
242 | "'/devices/pci0000:00/0000:00:1f.2'") |
243 | |
244 | + def testCheckUdevUsbProperties(self): |
245 | + """Test of SubmissionParser.checkUdevUsbProperties().""" |
246 | + parser = SubmissionParser() |
247 | + self.assertTrue(parser.checkUdevUsbProperties( |
248 | + [self.udev_root_device, self.udev_usb_device, |
249 | + self.udev_usb_interface])) |
250 | + |
251 | + def testCheckUdevUsbProperties_missing_required_property(self): |
252 | + """Test of SubmissionParser.checkUdevUsbProperties(). |
253 | + |
254 | + A USB device that does not have a required property makes a |
255 | + submission invalid. |
256 | + """ |
257 | + del self.udev_usb_device['E']['DEVTYPE'] |
258 | + parser = SubmissionParser(self.log) |
259 | + parser.submission_key = 'USB device without DEVTYPE property' |
260 | + self.assertFalse(parser.checkUdevUsbProperties( |
261 | + [self.udev_root_device, self.udev_usb_device])) |
262 | + self.assertErrorMessage( |
263 | + parser.submission_key, |
264 | + "USB udev device found without required properties: " |
265 | + "set(['DEVTYPE']) '/devices/pci0000:00/0000:00:1d.1/usb3/3-2'") |
266 | + |
267 | + def testCheckUdevUsbProperties_with_invalid_product_id(self): |
268 | + """Test of SubmissionParser.checkUdevUsbProperties(). |
269 | + |
270 | + A USB device with an invalid product ID makes a submission |
271 | + invalid. |
272 | + """ |
273 | + self.udev_usb_device['E']['PRODUCT'] = 'not-a-valid-usb-product-id' |
274 | + parser = SubmissionParser(self.log) |
275 | + parser.submission_key = 'USB device with invalid product ID' |
276 | + self.assertFalse(parser.checkUdevUsbProperties( |
277 | + [self.udev_root_device, self.udev_usb_device])) |
278 | + self.assertErrorMessage( |
279 | + parser.submission_key, |
280 | + "USB udev device found with invalid product ID: " |
281 | + "'not-a-valid-usb-product-id' " |
282 | + "'/devices/pci0000:00/0000:00:1d.1/usb3/3-2'") |
283 | + |
284 | + def testCheckUdevUsbProperties_with_invalid_type_data(self): |
285 | + """Test of SubmmissionParser.checkUdevUsbProperties(). |
286 | + |
287 | + A USB device with invalid type data makes a submission invalid. |
288 | + """ |
289 | + self.udev_usb_device['E']['TYPE'] = 'no-type' |
290 | + parser = SubmissionParser(self.log) |
291 | + parser.submission_key = 'USB device with invalid type data' |
292 | + self.assertFalse(parser.checkUdevUsbProperties( |
293 | + [self.udev_root_device, self.udev_usb_device])) |
294 | + self.assertErrorMessage( |
295 | + parser.submission_key, |
296 | + "USB udev device found with invalid type data: 'no-type' " |
297 | + "'/devices/pci0000:00/0000:00:1d.1/usb3/3-2'") |
298 | + |
299 | + def testCheckUdevUsbProperties_with_invalid_devtype(self): |
300 | + """Test of SubmmissionParser.checkUdevUsbProperties(). |
301 | + |
302 | + A udev USB device must have DEVTYPE set to 'usb_device' or |
303 | + 'usb_interface'. |
304 | + """ |
305 | + self.udev_usb_device['E']['DEVTYPE'] = 'nonsense' |
306 | + parser = SubmissionParser(self.log) |
307 | + parser.submission_key = 'USB device with invalid DEVTYPE' |
308 | + self.assertFalse(parser.checkUdevUsbProperties( |
309 | + [self.udev_root_device, self.udev_usb_device])) |
310 | + self.assertErrorMessage( |
311 | + parser.submission_key, |
312 | + "USB udev device found with invalid udev type data: 'nonsense' " |
313 | + "'/devices/pci0000:00/0000:00:1d.1/usb3/3-2'") |
314 | + |
315 | + def testCheckUdevUsbProperties_interface_without_interface_property(self): |
316 | + """Test of SubmmissionParser.checkUdevUsbProperties(). |
317 | + |
318 | + A udev USB device for a USB interface have the property INTERFACE. |
319 | + """ |
320 | + del self.udev_usb_interface['E']['INTERFACE'] |
321 | + parser = SubmissionParser(self.log) |
322 | + parser.submission_key = 'USB interface without INTERFACE property' |
323 | + self.assertFalse(parser.checkUdevUsbProperties( |
324 | + [self.udev_root_device, self.udev_usb_interface])) |
325 | + self.assertErrorMessage( |
326 | + parser.submission_key, |
327 | + "USB interface udev device found without INTERFACE property: " |
328 | + "'/devices/pci0000:00/0000:00:1d.1/usb3/3-2/3-2:1.1'") |
329 | + |
330 | + def testCheckUdevUsbProperties_interface_invalid_interface_property(self): |
331 | + """Test of SubmmissionParser.checkUdevUsbProperties(). |
332 | + |
333 | + The INTERFACE proeprty of A udev USB device for a USB interface |
334 | + must have value in the format main_class/sub_class/version |
335 | + """ |
336 | + self.udev_usb_interface['E']['INTERFACE'] = 'nonsense' |
337 | + parser = SubmissionParser(self.log) |
338 | + parser.submission_key = 'USB interface with invalid INTERFACE data' |
339 | + self.assertFalse(parser.checkUdevUsbProperties( |
340 | + [self.udev_root_device, self.udev_usb_interface])) |
341 | + self.assertErrorMessage( |
342 | + parser.submission_key, |
343 | + "USB Interface udev device found with invalid INTERFACE " |
344 | + "property: 'nonsense' " |
345 | + "'/devices/pci0000:00/0000:00:1d.1/usb3/3-2/3-2:1.1'") |
346 | + |
347 | + |
348 | class UdevTestSubmissionParser(SubmissionParser): |
349 | """A variant of SubmissionParser that shortcuts udev related tests. |
350 | |
351 | @@ -1904,6 +2027,10 @@ |
352 | """See `SubmissionParser`.""" |
353 | return True |
354 | |
355 | + def checkUdevUsbProperties(self, udev_data): |
356 | + """See `SubmissionParser`.""" |
357 | + return True |
358 | + |
359 | def testCheckConsistentUdevDeviceData(self): |
360 | """Test of SubmissionParser.checkConsistentUdevDeviceData(),""" |
361 | parser = self.UdevTestSubmissionParser() |
362 | @@ -1941,6 +2068,22 @@ |
363 | parser = SubmissionParserUdevPciCheckFails() |
364 | self.assertFalse(parser.checkConsistentUdevDeviceData(None)) |
365 | |
366 | + def testCheckConsistentUdevDeviceData_invalid_usb_data(self): |
367 | + """Test of SubmissionParser.checkConsistentUdevDeviceData(), |
368 | + |
369 | + Detection of invalid PCI data lets the check fail. |
370 | + """ |
371 | + class SubmissionParserUdevUsbCheckFails( |
372 | + self.UdevTestSubmissionParser): |
373 | + """A SubmissionPaser where checkUdevPciProperties() fails.""" |
374 | + |
375 | + def checkUdevUsbProperties(self, udev_data): |
376 | + """See `SubmissionParser`.""" |
377 | + return False |
378 | + |
379 | + parser = SubmissionParserUdevUsbCheckFails() |
380 | + self.assertFalse(parser.checkConsistentUdevDeviceData(None)) |
381 | + |
382 | def _setupConsistencyCheckParser(self): |
383 | """Prepare and return a SubmissionParser instance. |
384 | |
385 | |
386 | === modified file 'lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py' |
387 | --- lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py 2009-10-08 13:41:32 +0000 |
388 | +++ lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py 2009-10-09 15:45:23 +0000 |
389 | @@ -2617,6 +2617,16 @@ |
390 | } |
391 | } |
392 | |
393 | + usb_device_data = { |
394 | + 'P': '/devices/pci0000:00/0000:00:1d.1/usb3/3-2', |
395 | + 'E': { |
396 | + 'SUBSYSTEM': 'usb', |
397 | + 'DEVTYPE': 'usb_device', |
398 | + 'PRODUCT': '46d/a01/1013', |
399 | + 'TYPE': '0/0/0', |
400 | + }, |
401 | + } |
402 | + |
403 | def test_device_id(self): |
404 | """Test of UdevDevice.device_id.""" |
405 | device = UdevDevice(self.pci_device_data, None, None) |
406 | @@ -2668,6 +2678,50 @@ |
407 | None, device.pci_class, |
408 | 'Invalid value of UdevDevice.pci_class for Non-PCI device.') |
409 | |
410 | + def test_is_usb(self): |
411 | + """Test of UdevDevice.is_usb""" |
412 | + device = UdevDevice(self.usb_device_data, None, None) |
413 | + self.assertTrue(device.is_usb) |
414 | + |
415 | + device = UdevDevice(self.pci_device_data, None, None) |
416 | + self.assertFalse(device.is_usb) |
417 | + |
418 | + def test_usb_ids(self): |
419 | + """Test of UdevDevice.usb_ids""" |
420 | + device = UdevDevice(self.usb_device_data, None, None) |
421 | + self.assertEqual( |
422 | + [0x46d, 0xa01, 0x1013], device.usb_ids, |
423 | + 'Invalid value of UdevDevice.usb_ids for USB device.') |
424 | + |
425 | + device = UdevDevice(self.root_device, None, None) |
426 | + self.assertEqual( |
427 | + [None, None, None], device.usb_ids, |
428 | + 'Invalid value of UdevDevice.usb_ids for Non-USB device.') |
429 | + |
430 | + def test_usb_vendor_id(self): |
431 | + """Test of UdevDevice.usb_vendor_id""" |
432 | + device = UdevDevice(self.usb_device_data, None, None) |
433 | + self.assertEqual( |
434 | + 0x46d, device.usb_vendor_id, |
435 | + 'Invalid value of UdevDevice.usb_vendor_id for USB device.') |
436 | + |
437 | + device = UdevDevice(self.root_device, None, None) |
438 | + self.assertEqual( |
439 | + None, device.usb_vendor_id, |
440 | + 'Invalid value of UdevDevice.usb_vendor_id for Non-USB device.') |
441 | + |
442 | + def test_usb_product_id(self): |
443 | + """Test of UdevDevice.usb_product_id""" |
444 | + device = UdevDevice(self.usb_device_data, None, None) |
445 | + self.assertEqual( |
446 | + 0xa01, device.usb_product_id, |
447 | + 'Invalid value of UdevDevice.usb_product_id for USB device.') |
448 | + |
449 | + device = UdevDevice(self.root_device, None, None) |
450 | + self.assertEqual( |
451 | + None, device.usb_product_id, |
452 | + 'Invalid value of UdevDevice.usb_product_id for Non-USB device.') |
453 | + |
454 | |
455 | class TestHWDBSubmissionTablePopulation(TestCaseHWDB): |
456 | """Tests of the HWDB popoluation with submitted data.""" |
This branch adds a few USB-related properties to class UdevDevice, which will be used in the script hwdbsubmisison.py to process HWDB submission coming from the client in Karmic.
The branch also adds some sanity checks for USB-related data, to ensure that required properties exist and that their values have the correct format.
tests:
./bin/test --test= test_hwdb_ submission_ parser/ bin/test --test= test_hwdb_ submission_ processing
= 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 /launchpad/ scripts/ tests/test_ hwdb_submission _processing. py
lib/canonical
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.
lib/canonical/ launchpad/ scripts/ tests/test_ hwdb_submission _parser. py cElementTree' (No module named etree)
8: [F0401] Unable to import 'xml.etree.
These complaints are not not related to my cheanges; the come from a branch which prepares LP for Python 2.5