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 . - :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 - - @property - def parent_udi(self): - """The UDI of the parent device.""" - return self.getProperty('info.parent') - - @property - def device_id(self): - """See `BaseDevice`.""" - return self.udi - - @property - def pci_class(self): - """See `BaseDevice`.""" - return self.getProperty('pci.device_class') - - @property - def pci_subclass(self): - """The PCI device sub-class of the device or None for Non-PCI devices. - """ - return self.getProperty('pci.device_subclass') - - @property - def raw_bus(self): - """See `BaseDevice`.""" - # Older versions of HAL stored this value in the property - # info.bus; newer versions store it in info.subsystem. - # - # Note that info.bus is gone for all devices except the - # USB bus. For USB devices, the property info.bus returns more - # detailed data: info.subsystem has the value 'usb' for all - # HAL nodes belonging to USB devices, while info.bus has the - # value 'usb_device' for the root node of a USB device, and the - # value 'usb' for sub-nodes of a USB device. We use these - # different value to to find the root USB device node, hence - # try to read info.bus first. - result = self.getProperty('info.bus') - if result is not None: - return result - return self.getProperty('info.subsystem') - @property def real_bus(self): """Return the bus this device connects to on the host side. @@ -1627,7 +1565,7 @@ info.bus == 'usb' is used for end points of USB devices; the root node of a USB device has info.bus == 'usb_device'. - info.bus == 'viedo4linux' is used for the "input aspect" + info.bus == 'video4linux' is used for the "input aspect" of video devices. """ bus = self.raw_bus @@ -1642,8 +1580,8 @@ # info.bus property that we treat as a real device. return self.udi == ROOT_UDI elif bus == 'usb_device': - vendor_id = self.getProperty('usb_device.vendor_id') - product_id = self.getProperty('usb_device.product_id') + vendor_id = self.usb_vendor_id + product_id = self.usb_product_id if vendor_id == 0 and product_id == 0: # double-check: The parent device should be a PCI host # controller, identifiable by its device class and subclass. @@ -1796,6 +1734,88 @@ return False return True + +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 . + :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 + + @property + def parent_udi(self): + """The UDI of the parent device.""" + return self.getProperty('info.parent') + + @property + def device_id(self): + """See `BaseDevice`.""" + return self.udi + + @property + def pci_class(self): + """See `BaseDevice`.""" + return self.getProperty('pci.device_class') + + @property + def pci_subclass(self): + """The PCI device sub-class of the device or None for Non-PCI devices. + """ + return self.getProperty('pci.device_subclass') + + @property + def usb_vendor_id(self): + """See `BaseDevice`.""" + return self.getProperty('usb_device.vendor_id') + + @property + def usb_product_id(self): + """See `BaseDevice`.""" + return self.getProperty('usb_device.product_id') + + @property + def raw_bus(self): + """See `BaseDevice`.""" + # Older versions of HAL stored this value in the property + # info.bus; newer versions store it in info.subsystem. + # + # Note that info.bus is gone for all devices except the + # USB bus. For USB devices, the property info.bus returns more + # detailed data: info.subsystem has the value 'usb' for all + # HAL nodes belonging to USB devices, while info.bus has the + # value 'usb_device' for the root node of a USB device, and the + # value 'usb' for sub-nodes of a USB device. We use these + # different value to to find the root USB device node, hence + # try to read info.bus first. + result = self.getProperty('info.bus') + if result is not None: + return result + return self.getProperty('info.subsystem') + def getScsiVendorAndModelName(self): """Separate vendor and model name of SCSI decvices. @@ -1869,13 +1889,11 @@ """The vendor of this device.""" return self.getVendorOrProduct('vendor') - @property def product(self): """The vendor of this device.""" return self.getVendorOrProduct('product') - def getVendorOrProductID(self, type_): """Return the vendor or product ID for this device. === modified file 'lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py' --- lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py 2009-10-01 09:06:59 +0000 +++ lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py 2009-10-01 11:13:55 +0000 @@ -415,7 +415,7 @@ parser = SubmissionParser(self.log) device = HALDevice(1, '/some/udi/path', properties, parser) self.assertEqual( - device.pci_subclass, 1, + 1, device.pci_subclass, 'Unexpected value of HALDevice.pci_subclass.') properties = {} @@ -425,6 +425,43 @@ None, device.pci_subclass, 'Unexpected value of HALDevice.pci_sub_class for Non-PCI device.') + def testHALDeviceUsbVendorId(self): + """Test of HALDevice.usb_vendor_id.""" + properties = { + 'usb_device.vendor_id': (1, 'int'), + } + parser = SubmissionParser(self.log) + device = HALDevice(1, '/some/udi/path', properties, parser) + self.assertEqual( + 1, device.usb_vendor_id, + 'Unexpected value of HALDevice.usb_vendor_id.') + + properties = {} + parser = SubmissionParser(self.log) + device = HALDevice(1, '/some/udi/path', properties, parser) + self.assertEqual( + None, device.usb_vendor_id, + 'Unexpected value of HALDevice.usb_vendor_id for Non-USB device.') + + def testHALDeviceUsbProductId(self): + """Test of HALDevice.usb_product_id.""" + properties = { + 'usb_device.product_id': (1, 'int'), + } + parser = SubmissionParser(self.log) + device = HALDevice(1, '/some/udi/path', properties, parser) + self.assertEqual( + 1, device.usb_product_id, + 'Unexpected value of HALDevice.usb_product_id.') + + properties = {} + parser = SubmissionParser(self.log) + device = HALDevice(1, '/some/udi/path', properties, parser) + self.assertEqual( + None, device.usb_product_id, + 'Unexpected value of HALDevice.usb_product_id for Non-USB ' + 'device.') + def testHalDeviceRawBus(self): """test of HALDevice.raw_bus.""" properties = {