Merge lp:~adeuring/launchpad/hwdb-refactor-haldevice-2 into lp:launchpad

Proposed by Abel Deuring
Status: Merged
Merged at revision: not available
Proposed branch: lp:~adeuring/launchpad/hwdb-refactor-haldevice-2
Merge into: lp:launchpad
Diff against target: 435 lines
2 files modified
lib/canonical/launchpad/scripts/hwdbsubmissions.py (+140/-83)
lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py (+82/-0)
To merge this branch: bzr merge lp:~adeuring/launchpad/hwdb-refactor-haldevice-2
Reviewer Review Type Date Requested Status
Michael Nelson (community) code Approve
Review via email: mp+12713@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Abel Deuring (adeuring) wrote :
Download full text (11.1 KiB)

This branch continues the refactoring of class HALDevice in l/c/l/scrpits/hwdbsubmissons.py

(see https://code.edge.launchpad.net/~adeuring/launchpad/hwdb-refactor-haldevice/+merge/12669)

It moves the properties real_bus and is_real_device into the new base class BaseDevice. The latter property needs access to the USB vendor/product IDs, which were retrieved by the HAL-specific mmethod getProperty(). These calls are replaced by the new properties usb_vendor_id and usb_product_id.

test: ./bin/test -t 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:
  lib/canonical/launchpad/scripts/hwdbsubmissions.py
  lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py

== Pyflakes notices ==

lib/canonical/launchpad/scripts/hwdbsubmissions.py
    22: redefinition of unused 'etree' from line 20

== Pylint notices ==

lib/canonical/launchpad/scripts/hwdbsubmissions.py
    20: [F0401] Unable to import 'xml.etree.cElementTree' (No module named etree)

These complaints are caused by another, unrelated, branch that prepares the transition to Python 2.5

diff against the base branch (still in ec2test):

=== modified file 'lib/canonical/launchpad/scripts/hwdbsubmissions.py'
--- lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-10-01 09:06:59 +0000
+++ lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-10-01 11:13:38 +0000
@@ -1294,6 +1294,16 @@
         """
         raise NotImplementedError()

+ @property
+ def usb_vendor_id(self):
+ """The USB vendor ID of the device or None for Non-USB devices."""
+ raise NotImplementedError()
+
+ @property
+ def usb_product_id(self):
+ """The USB product ID of the device or None for Non-USB devices."""
+ raise NotImplementedError()
+
     def translateScsiBus(self):
         """Return the real bus of a device where raw_bus=='scsi'.

@@ -1395,78 +1405,6 @@
         """Return the device bus as specified by HAL or udev."""
         raise NotImplementedError()

-
-class HALDevice(BaseDevice):
- """The representation of a HAL device node."""
-
- def __init__(self, id, udi, properties, parser):
- """HALDevice constructor.
-
- :param id: The ID of the HAL device in the submission data as
- specified in <device id=...>.
- :type id: int
- :param udi: The UDI of the HAL device.
- :type udi: string
- :param properties: The HAL properties of the device.
- :type properties: dict
- :param parser: The parser processing a submission.
- :type parser: SubmissionParser
- """
- super(HALDevice, self).__init__(parser)
- self.id = id
- self.udi = udi
- self.properties = properties
-
- def getProperty(self, property_name):
- """Return the HAL property property_name.
-
- Note that there is no check of the property type.
- """
- if property_name not in self.properties:
- return None
- name, type_ = self.properties[property_name]
- return name
-
- @p...

Revision history for this message
Michael Nelson (michael.nelson) wrote :

<noodles775> adeuring: gee, that's an unfortunate diff...
<adeuring> noodles775: why?
<noodles775> adeuring: Nothing wrong with your code, I jut meant the huge segment of HALDevice that diff has assumed has been deleted and added.
<adeuring> noodles775: Ah, OK.
<noodles775> adeuring: r=me
<adeuring> noodles775: thanks!
<noodles775> adeuring: did you try using the revision spec '-r x..y' with bzr send so that the colour-coded diff on the mp is just the revisions you want? If not, might be good for the third installment :)

review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/canonical/launchpad/scripts/hwdbsubmissions.py'
--- lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-09-29 15:05:09 +0000
+++ lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-10-01 11:20:32 +0000
@@ -7,7 +7,7 @@
7data and for the community test submissions.7data and for the community test submissions.
8"""8"""
99
1010__metaclass__ = type
11__all__ = [11__all__ = [
12 'SubmissionParser',12 'SubmissionParser',
13 'process_pending_submissions',13 'process_pending_submissions',
@@ -1235,59 +1235,30 @@
1235 root_device.createDBData(submission, None)1235 root_device.createDBData(submission, None)
1236 return True1236 return True
12371237
1238class HALDevice:1238
1239 """The representation of a HAL device node."""1239class BaseDevice:
12401240 """A base class to represent device data from HAL and udev."""
1241 def __init__(self, id, udi, properties, parser):1241
1242 """HALDevice constructor.1242 def __init__(self, parser):
1243
1244 :param id: The ID of the HAL device in the submission data as
1245 specified in <device id=...>.
1246 :type id: int
1247 :param udi: The UDI of the HAL device.
1248 :type udi: string
1249 :param properties: The HAL properties of the device.
1250 :type properties: dict
1251 :param parser: The parser processing a submission.
1252 :type parser: SubmissionParser
1253 """
1254 self.id = id
1255 self.udi = udi
1256 self.properties = properties
1257 self.children = []1243 self.children = []
1258 self.parser = parser1244 self.parser = parser
1259 self.parent = None1245 self.parent = None
12601246
1247 # Translation of the HAL info.bus/info.subsystem property and the
1248 # udev property SUBSYSTEM to HWBus enumerated buses.
1249 subsystem_hwbus = {
1250 'pcmcia': HWBus.PCMCIA,
1251 'usb_device': HWBus.USB,
1252 'ide': HWBus.IDE,
1253 'serio': HWBus.SERIAL,
1254 }
1255
1261 def addChild(self, child):1256 def addChild(self, child):
1262 """Add a child device and set the child's parent."""1257 """Add a child device and set the child's parent."""
1263 assert type(child) == type(self)1258 assert type(child) == type(self)
1264 self.children.append(child)1259 self.children.append(child)
1265 child.parent = self1260 child.parent = self
12661261
1267 def getProperty(self, property_name):
1268 """Return the property property_name.
1269
1270 Note that there is no check of the property type.
1271 """
1272 if property_name not in self.properties:
1273 return None
1274 name, type_ = self.properties[property_name]
1275 return name
1276
1277 @property
1278 def parent_udi(self):
1279 """The UDI of the parent device."""
1280 return self.getProperty('info.parent')
1281
1282 # Translation of the HAL info.bus/info.subsystem property to HWBus
1283 # enumerated buses.
1284 hal_bus_hwbus = {
1285 'pcmcia': HWBus.PCMCIA,
1286 'usb_device': HWBus.USB,
1287 'ide': HWBus.IDE,
1288 'serio': HWBus.SERIAL,
1289 }
1290
1291 # Translation of subclasses of the PCI class storage to HWBus1262 # Translation of subclasses of the PCI class storage to HWBus
1292 # enumerated buses. The Linux kernel accesses IDE and SATA disks1263 # enumerated buses. The Linux kernel accesses IDE and SATA disks
1293 # and CDROM drives via the SCSI system; we want to know the real bus1264 # and CDROM drives via the SCSI system; we want to know the real bus
@@ -1307,6 +1278,32 @@
1307 7: HWBus.SAS,1278 7: HWBus.SAS,
1308 }1279 }
13091280
1281 @property
1282 def device_id(self):
1283 """A unique ID for this device."""
1284 raise NotImplementedError()
1285
1286 @property
1287 def pci_class(self):
1288 """The PCI device class of the device or None for Non-PCI devices."""
1289 raise NotImplementedError()
1290
1291 @property
1292 def pci_subclass(self):
1293 """The PCI device sub-class of the device or None for Non-PCI devices.
1294 """
1295 raise NotImplementedError()
1296
1297 @property
1298 def usb_vendor_id(self):
1299 """The USB vendor ID of the device or None for Non-USB devices."""
1300 raise NotImplementedError()
1301
1302 @property
1303 def usb_product_id(self):
1304 """The USB product ID of the device or None for Non-USB devices."""
1305 raise NotImplementedError()
1306
1310 def translateScsiBus(self):1307 def translateScsiBus(self):
1311 """Return the real bus of a device where raw_bus=='scsi'.1308 """Return the real bus of a device where raw_bus=='scsi'.
13121309
@@ -1321,29 +1318,29 @@
1321 parent = self.parent1318 parent = self.parent
1322 if parent is None:1319 if parent is None:
1323 self.parser._logWarning(1320 self.parser._logWarning(
1324 'Found SCSI device without a parent: %s.' % self.udi)1321 'Found SCSI device without a parent: %s.' % self.device_id)
1325 return None1322 return None
1326 grandparent = parent.parent1323 grandparent = parent.parent
1327 if grandparent is None:1324 if grandparent is None:
1328 self.parser._logWarning(1325 self.parser._logWarning(
1329 'Found SCSI device without a grandparent: %s.' % self.udi)1326 'Found SCSI device without a grandparent: %s.'
1327 % self.device_id)
1330 return None1328 return None
13311329
1332 grandparent_bus = grandparent.raw_bus1330 grandparent_bus = grandparent.raw_bus
1333 if grandparent_bus == 'pci':1331 if grandparent_bus == 'pci':
1334 if (grandparent.getProperty('pci.device_class')1332 if (grandparent.pci_class != PCI_CLASS_STORAGE):
1335 != PCI_CLASS_STORAGE):
1336 # This is not a storage class PCI device? This1333 # This is not a storage class PCI device? This
1337 # indicates a bug somewhere in HAL or in the hwdb1334 # indicates a bug somewhere in HAL or in the hwdb
1338 # client, or a fake submission.1335 # client, or a fake submission.
1339 device_class = grandparent.getProperty('pci.device_class')1336 device_class = grandparent.pci_class
1340 self.parser._logWarning(1337 self.parser._logWarning(
1341 'A (possibly fake) SCSI device %s is connected to '1338 'A (possibly fake) SCSI device %s is connected to '
1342 'PCI device %s that has the PCI device class %s; '1339 'PCI device %s that has the PCI device class %s; '
1343 'expected class 1 (storage).'1340 'expected class 1 (storage).'
1344 % (self.udi, grandparent.udi, device_class))1341 % (self.device_id, grandparent.device_id, device_class))
1345 return None1342 return None
1346 pci_subclass = grandparent.getProperty('pci.device_subclass')1343 pci_subclass = grandparent.pci_subclass
1347 return self.pci_storage_subclass_hwbus.get(pci_subclass)1344 return self.pci_storage_subclass_hwbus.get(pci_subclass)
1348 elif grandparent_bus == 'usb':1345 elif grandparent_bus == 'usb':
1349 # USB storage devices have the following HAL device hierarchy:1346 # USB storage devices have the following HAL device hierarchy:
@@ -1395,38 +1392,18 @@
1395 # subclass 7).1392 # subclass 7).
1396 # XXX Abel Deuring 2005-05-14 How can we detect ExpressCards?1393 # XXX Abel Deuring 2005-05-14 How can we detect ExpressCards?
1397 # I do not have any such card at present...1394 # I do not have any such card at present...
1398 parent_class = self.parent.getProperty('pci.device_class')1395 parent_class = self.parent.pci_class
1399 parent_subclass = self.parent.getProperty('pci.device_subclass')1396 parent_subclass = self.parent.pci_subclass
1400 if (parent_class == PCI_CLASS_BRIDGE1397 if (parent_class == PCI_CLASS_BRIDGE
1401 and parent_subclass == PCI_SUBCLASS_BRIDGE_CARDBUS):1398 and parent_subclass == PCI_SUBCLASS_BRIDGE_CARDBUS):
1402 return HWBus.PCCARD1399 return HWBus.PCCARD
1403 else:1400 else:
1404 return HWBus.PCI1401 return HWBus.PCI
14051402
1406 translate_bus_name = {
1407 'pci': translatePciBus,
1408 'scsi': translateScsiBus,
1409 }
1410
1411 @property1403 @property
1412 def raw_bus(self):1404 def raw_bus(self):
1413 """Return the device bus as specified by HAL.1405 """Return the device bus as specified by HAL or udev."""
14141406 raise NotImplementedError()
1415 Older versions of HAL stored this value in the property
1416 info.bus; newer versions store it in info.subsystem.
1417 """
1418 # Note that info.bus is gone for all devices except the
1419 # USB bus. For USB devices, the property info.bus returns more
1420 # detailed data: info.subsystem has the value 'usb' for all
1421 # HAL nodes belonging to USB devices, while info.bus has the
1422 # value 'usb_device' for the root node of a USB device, and the
1423 # value 'usb' for sub-nodes of a USB device. We use these
1424 # different value to to find the root USB device node, hence
1425 # try to read info.bus first.
1426 result = self.getProperty('info.bus')
1427 if result is not None:
1428 return result
1429 return self.getProperty('info.subsystem')
14301407
1431 @property1408 @property
1432 def real_bus(self):1409 def real_bus(self):
@@ -1436,7 +1413,7 @@
1436 cannot be determined.1413 cannot be determined.
1437 """1414 """
1438 device_bus = self.raw_bus1415 device_bus = self.raw_bus
1439 result = self.hal_bus_hwbus.get(device_bus)1416 result = self.subsystem_hwbus.get(device_bus)
1440 if result is not None:1417 if result is not None:
1441 return result1418 return result
14421419
@@ -1588,7 +1565,7 @@
1588 info.bus == 'usb' is used for end points of USB devices;1565 info.bus == 'usb' is used for end points of USB devices;
1589 the root node of a USB device has info.bus == 'usb_device'.1566 the root node of a USB device has info.bus == 'usb_device'.
15901567
1591 info.bus == 'viedo4linux' is used for the "input aspect"1568 info.bus == 'video4linux' is used for the "input aspect"
1592 of video devices.1569 of video devices.
1593 """1570 """
1594 bus = self.raw_bus1571 bus = self.raw_bus
@@ -1603,8 +1580,8 @@
1603 # info.bus property that we treat as a real device.1580 # info.bus property that we treat as a real device.
1604 return self.udi == ROOT_UDI1581 return self.udi == ROOT_UDI
1605 elif bus == 'usb_device':1582 elif bus == 'usb_device':
1606 vendor_id = self.getProperty('usb_device.vendor_id')1583 vendor_id = self.usb_vendor_id
1607 product_id = self.getProperty('usb_device.product_id')1584 product_id = self.usb_product_id
1608 if vendor_id == 0 and product_id == 0:1585 if vendor_id == 0 and product_id == 0:
1609 # double-check: The parent device should be a PCI host1586 # double-check: The parent device should be a PCI host
1610 # controller, identifiable by its device class and subclass.1587 # controller, identifiable by its device class and subclass.
@@ -1612,8 +1589,8 @@
1612 # possible bridges, like ISA->USB..1589 # possible bridges, like ISA->USB..
1613 parent = self.parent1590 parent = self.parent
1614 parent_bus = parent.raw_bus1591 parent_bus = parent.raw_bus
1615 parent_class = parent.getProperty('pci.device_class')1592 parent_class = parent.pci_class
1616 parent_subclass = parent.getProperty('pci.device_subclass')1593 parent_subclass = parent.pci_subclass
1617 if (parent_bus == 'pci'1594 if (parent_bus == 'pci'
1618 and parent_class == PCI_CLASS_SERIALBUS_CONTROLLER1595 and parent_class == PCI_CLASS_SERIALBUS_CONTROLLER
1619 and parent_subclass == PCI_SUBCLASS_SERIALBUS_USB):1596 and parent_subclass == PCI_SUBCLASS_SERIALBUS_USB):
@@ -1757,6 +1734,88 @@
1757 return False1734 return False
1758 return True1735 return True
17591736
1737
1738class HALDevice(BaseDevice):
1739 """The representation of a HAL device node."""
1740
1741 def __init__(self, id, udi, properties, parser):
1742 """HALDevice constructor.
1743
1744 :param id: The ID of the HAL device in the submission data as
1745 specified in <device id=...>.
1746 :type id: int
1747 :param udi: The UDI of the HAL device.
1748 :type udi: string
1749 :param properties: The HAL properties of the device.
1750 :type properties: dict
1751 :param parser: The parser processing a submission.
1752 :type parser: SubmissionParser
1753 """
1754 super(HALDevice, self).__init__(parser)
1755 self.id = id
1756 self.udi = udi
1757 self.properties = properties
1758
1759 def getProperty(self, property_name):
1760 """Return the HAL property property_name.
1761
1762 Note that there is no check of the property type.
1763 """
1764 if property_name not in self.properties:
1765 return None
1766 name, type_ = self.properties[property_name]
1767 return name
1768
1769 @property
1770 def parent_udi(self):
1771 """The UDI of the parent device."""
1772 return self.getProperty('info.parent')
1773
1774 @property
1775 def device_id(self):
1776 """See `BaseDevice`."""
1777 return self.udi
1778
1779 @property
1780 def pci_class(self):
1781 """See `BaseDevice`."""
1782 return self.getProperty('pci.device_class')
1783
1784 @property
1785 def pci_subclass(self):
1786 """The PCI device sub-class of the device or None for Non-PCI devices.
1787 """
1788 return self.getProperty('pci.device_subclass')
1789
1790 @property
1791 def usb_vendor_id(self):
1792 """See `BaseDevice`."""
1793 return self.getProperty('usb_device.vendor_id')
1794
1795 @property
1796 def usb_product_id(self):
1797 """See `BaseDevice`."""
1798 return self.getProperty('usb_device.product_id')
1799
1800 @property
1801 def raw_bus(self):
1802 """See `BaseDevice`."""
1803 # Older versions of HAL stored this value in the property
1804 # info.bus; newer versions store it in info.subsystem.
1805 #
1806 # Note that info.bus is gone for all devices except the
1807 # USB bus. For USB devices, the property info.bus returns more
1808 # detailed data: info.subsystem has the value 'usb' for all
1809 # HAL nodes belonging to USB devices, while info.bus has the
1810 # value 'usb_device' for the root node of a USB device, and the
1811 # value 'usb' for sub-nodes of a USB device. We use these
1812 # different value to to find the root USB device node, hence
1813 # try to read info.bus first.
1814 result = self.getProperty('info.bus')
1815 if result is not None:
1816 return result
1817 return self.getProperty('info.subsystem')
1818
1760 def getScsiVendorAndModelName(self):1819 def getScsiVendorAndModelName(self):
1761 """Separate vendor and model name of SCSI decvices.1820 """Separate vendor and model name of SCSI decvices.
17621821
@@ -1830,13 +1889,11 @@
1830 """The vendor of this device."""1889 """The vendor of this device."""
1831 return self.getVendorOrProduct('vendor')1890 return self.getVendorOrProduct('vendor')
18321891
1833
1834 @property1892 @property
1835 def product(self):1893 def product(self):
1836 """The vendor of this device."""1894 """The vendor of this device."""
1837 return self.getVendorOrProduct('product')1895 return self.getVendorOrProduct('product')
18381896
1839
1840 def getVendorOrProductID(self, type_):1897 def getVendorOrProductID(self, type_):
1841 """Return the vendor or product ID for this device.1898 """Return the vendor or product ID for this device.
18421899
18431900
=== modified file 'lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py'
--- lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py 2009-06-25 05:30:52 +0000
+++ lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py 2009-10-01 11:20:32 +0000
@@ -380,6 +380,88 @@
380 'Unexpected value of HALDevice.parent_udi, '380 'Unexpected value of HALDevice.parent_udi, '
381 'when no parent information available.')381 'when no parent information available.')
382382
383 def testHALDeviceDeviceId(self):
384 """Test of HALDevice.device_id."""
385 properties = {}
386 parser = SubmissionParser(self.log)
387 device = HALDevice(1, '/some/udi/path', properties, parser)
388 self.assertEqual(
389 '/some/udi/path', device.device_id,
390 'Unexpected value of HALDevice.device_id')
391
392 def testHALDevicePciClass(self):
393 """Test of HALDevice.pci_class."""
394 properties = {
395 'pci.device_class': (1, 'int'),
396 }
397 parser = SubmissionParser(self.log)
398 device = HALDevice(1, '/some/udi/path', properties, parser)
399 self.assertEqual(
400 1, device.pci_class,
401 'Unexpected value of HALDevice.pci_class.')
402
403 properties = {}
404 parser = SubmissionParser(self.log)
405 device = HALDevice(1, '/some/udi/path', properties, parser)
406 self.assertEqual(
407 None, device.pci_class,
408 'Unexpected value of HALDevice.pci_class for Non-PCI device.')
409
410 def testHALDevicePciSubClass(self):
411 """Test of HALDevice.pci_subclass."""
412 properties = {
413 'pci.device_subclass': (1, 'int'),
414 }
415 parser = SubmissionParser(self.log)
416 device = HALDevice(1, '/some/udi/path', properties, parser)
417 self.assertEqual(
418 1, device.pci_subclass,
419 'Unexpected value of HALDevice.pci_subclass.')
420
421 properties = {}
422 parser = SubmissionParser(self.log)
423 device = HALDevice(1, '/some/udi/path', properties, parser)
424 self.assertEqual(
425 None, device.pci_subclass,
426 'Unexpected value of HALDevice.pci_sub_class for Non-PCI device.')
427
428 def testHALDeviceUsbVendorId(self):
429 """Test of HALDevice.usb_vendor_id."""
430 properties = {
431 'usb_device.vendor_id': (1, 'int'),
432 }
433 parser = SubmissionParser(self.log)
434 device = HALDevice(1, '/some/udi/path', properties, parser)
435 self.assertEqual(
436 1, device.usb_vendor_id,
437 'Unexpected value of HALDevice.usb_vendor_id.')
438
439 properties = {}
440 parser = SubmissionParser(self.log)
441 device = HALDevice(1, '/some/udi/path', properties, parser)
442 self.assertEqual(
443 None, device.usb_vendor_id,
444 'Unexpected value of HALDevice.usb_vendor_id for Non-USB device.')
445
446 def testHALDeviceUsbProductId(self):
447 """Test of HALDevice.usb_product_id."""
448 properties = {
449 'usb_device.product_id': (1, 'int'),
450 }
451 parser = SubmissionParser(self.log)
452 device = HALDevice(1, '/some/udi/path', properties, parser)
453 self.assertEqual(
454 1, device.usb_product_id,
455 'Unexpected value of HALDevice.usb_product_id.')
456
457 properties = {}
458 parser = SubmissionParser(self.log)
459 device = HALDevice(1, '/some/udi/path', properties, parser)
460 self.assertEqual(
461 None, device.usb_product_id,
462 'Unexpected value of HALDevice.usb_product_id for Non-USB '
463 'device.')
464
383 def testHalDeviceRawBus(self):465 def testHalDeviceRawBus(self):
384 """test of HALDevice.raw_bus."""466 """test of HALDevice.raw_bus."""
385 properties = {467 properties = {