Merge lp:~adeuring/launchpad/hwdb-refactor-haldevice-3 into lp:launchpad
- hwdb-refactor-haldevice-3
- Merge into devel
Proposed by
Abel Deuring
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-refactor-haldevice-3 |
Merge into: | lp:launchpad |
Diff against target: |
604 lines 2 files modified
lib/canonical/launchpad/scripts/hwdbsubmissions.py (+258/-209) lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py (+54/-0) |
To merge this branch: | bzr merge lp:~adeuring/launchpad/hwdb-refactor-haldevice-3 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Barry Warsaw (community) | Approve | ||
Review via email: mp+12733@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
Barry Warsaw (barry) wrote : | # |
<barry> adeuring: when you raise NotImplementedError in your properties, you
don't need to instantiate them if they have no arguments. Python will
DTRT for you here, and it's also somewhat more efficient [11:27]
with that fix, r=me
review:
Approve
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-10-01 11:14:19 +0000 | |||
3 | +++ lib/canonical/launchpad/scripts/hwdbsubmissions.py 2009-10-02 15:43:14 +0000 | |||
4 | @@ -1281,28 +1281,94 @@ | |||
5 | 1281 | @property | 1281 | @property |
6 | 1282 | def device_id(self): | 1282 | def device_id(self): |
7 | 1283 | """A unique ID for this device.""" | 1283 | """A unique ID for this device.""" |
9 | 1284 | raise NotImplementedError() | 1284 | raise NotImplementedError |
10 | 1285 | 1285 | ||
11 | 1286 | @property | 1286 | @property |
12 | 1287 | def pci_class(self): | 1287 | def pci_class(self): |
13 | 1288 | """The PCI device class of the device or None for Non-PCI devices.""" | 1288 | """The PCI device class of the device or None for Non-PCI devices.""" |
15 | 1289 | raise NotImplementedError() | 1289 | raise NotImplementedError |
16 | 1290 | 1290 | ||
17 | 1291 | @property | 1291 | @property |
18 | 1292 | def pci_subclass(self): | 1292 | def pci_subclass(self): |
19 | 1293 | """The PCI device sub-class of the device or None for Non-PCI devices. | 1293 | """The PCI device sub-class of the device or None for Non-PCI devices. |
20 | 1294 | """ | 1294 | """ |
22 | 1295 | raise NotImplementedError() | 1295 | raise NotImplementedError |
23 | 1296 | 1296 | ||
24 | 1297 | @property | 1297 | @property |
25 | 1298 | def usb_vendor_id(self): | 1298 | def usb_vendor_id(self): |
26 | 1299 | """The USB vendor ID of the device or None for Non-USB devices.""" | 1299 | """The USB vendor ID of the device or None for Non-USB devices.""" |
28 | 1300 | raise NotImplementedError() | 1300 | raise NotImplementedError |
29 | 1301 | 1301 | ||
30 | 1302 | @property | 1302 | @property |
31 | 1303 | def usb_product_id(self): | 1303 | def usb_product_id(self): |
32 | 1304 | """The USB product ID of the device or None for Non-USB devices.""" | 1304 | """The USB product ID of the device or None for Non-USB devices.""" |
34 | 1305 | raise NotImplementedError() | 1305 | raise NotImplementedError |
35 | 1306 | |||
36 | 1307 | @property | ||
37 | 1308 | def scsi_vendor(self): | ||
38 | 1309 | """The SCSI vendor name of the device or None for Non-SCSI devices.""" | ||
39 | 1310 | raise NotImplementedError | ||
40 | 1311 | |||
41 | 1312 | @property | ||
42 | 1313 | def scsi_model(self): | ||
43 | 1314 | """The SCSI model name of the device or None for Non-SCSI devices.""" | ||
44 | 1315 | raise NotImplementedError | ||
45 | 1316 | |||
46 | 1317 | @property | ||
47 | 1318 | def vendor(self): | ||
48 | 1319 | """The vendor of this device.""" | ||
49 | 1320 | raise NotImplementedError | ||
50 | 1321 | |||
51 | 1322 | @property | ||
52 | 1323 | def product(self): | ||
53 | 1324 | """The vendor of this device.""" | ||
54 | 1325 | raise NotImplementedError | ||
55 | 1326 | |||
56 | 1327 | @property | ||
57 | 1328 | def vendor_id(self): | ||
58 | 1329 | """The vendor ID of this device.""" | ||
59 | 1330 | raise NotImplementedError | ||
60 | 1331 | |||
61 | 1332 | @property | ||
62 | 1333 | def product_id(self): | ||
63 | 1334 | """The product ID of this device.""" | ||
64 | 1335 | raise NotImplementedError | ||
65 | 1336 | |||
66 | 1337 | @property | ||
67 | 1338 | def vendor_id_for_db(self): | ||
68 | 1339 | """The vendor ID in the representation needed for the HWDB tables. | ||
69 | 1340 | |||
70 | 1341 | USB and PCI IDs are represented in the database in hexadecimal, | ||
71 | 1342 | while the IDs provided by HAL are integers. | ||
72 | 1343 | |||
73 | 1344 | The SCSI vendor name is right-padded with spaces to 8 bytes. | ||
74 | 1345 | """ | ||
75 | 1346 | bus = self.raw_bus | ||
76 | 1347 | format = DB_FORMAT_FOR_VENDOR_ID.get(bus) | ||
77 | 1348 | if format is None: | ||
78 | 1349 | return self.vendor_id | ||
79 | 1350 | else: | ||
80 | 1351 | return format % self.vendor_id | ||
81 | 1352 | |||
82 | 1353 | @property | ||
83 | 1354 | def product_id_for_db(self): | ||
84 | 1355 | """The product ID in the representation needed for the HWDB tables. | ||
85 | 1356 | |||
86 | 1357 | USB and PCI IDs are represented in the database in hexadecimal, | ||
87 | 1358 | while the IDs provided by HAL are integers. | ||
88 | 1359 | |||
89 | 1360 | The SCSI product name is right-padded with spaces to 16 bytes. | ||
90 | 1361 | """ | ||
91 | 1362 | bus = self.raw_bus | ||
92 | 1363 | format = DB_FORMAT_FOR_PRODUCT_ID.get(bus) | ||
93 | 1364 | if format is None: | ||
94 | 1365 | return self.product_id | ||
95 | 1366 | else: | ||
96 | 1367 | return format % self.product_id | ||
97 | 1368 | |||
98 | 1369 | @property | ||
99 | 1370 | def driver_name(self): | ||
100 | 1371 | """The name of the driver contolling this device. May be None.""" | ||
101 | 1306 | 1372 | ||
102 | 1307 | def translateScsiBus(self): | 1373 | def translateScsiBus(self): |
103 | 1308 | """Return the real bus of a device where raw_bus=='scsi'. | 1374 | """Return the real bus of a device where raw_bus=='scsi'. |
104 | @@ -1403,7 +1469,7 @@ | |||
105 | 1403 | @property | 1469 | @property |
106 | 1404 | def raw_bus(self): | 1470 | def raw_bus(self): |
107 | 1405 | """Return the device bus as specified by HAL or udev.""" | 1471 | """Return the device bus as specified by HAL or udev.""" |
109 | 1406 | raise NotImplementedError() | 1472 | raise NotImplementedError |
110 | 1407 | 1473 | ||
111 | 1408 | @property | 1474 | @property |
112 | 1409 | def real_bus(self): | 1475 | def real_bus(self): |
113 | @@ -1734,88 +1800,6 @@ | |||
114 | 1734 | return False | 1800 | return False |
115 | 1735 | return True | 1801 | return True |
116 | 1736 | 1802 | ||
117 | 1737 | |||
118 | 1738 | class HALDevice(BaseDevice): | ||
119 | 1739 | """The representation of a HAL device node.""" | ||
120 | 1740 | |||
121 | 1741 | def __init__(self, id, udi, properties, parser): | ||
122 | 1742 | """HALDevice constructor. | ||
123 | 1743 | |||
124 | 1744 | :param id: The ID of the HAL device in the submission data as | ||
125 | 1745 | specified in <device id=...>. | ||
126 | 1746 | :type id: int | ||
127 | 1747 | :param udi: The UDI of the HAL device. | ||
128 | 1748 | :type udi: string | ||
129 | 1749 | :param properties: The HAL properties of the device. | ||
130 | 1750 | :type properties: dict | ||
131 | 1751 | :param parser: The parser processing a submission. | ||
132 | 1752 | :type parser: SubmissionParser | ||
133 | 1753 | """ | ||
134 | 1754 | super(HALDevice, self).__init__(parser) | ||
135 | 1755 | self.id = id | ||
136 | 1756 | self.udi = udi | ||
137 | 1757 | self.properties = properties | ||
138 | 1758 | |||
139 | 1759 | def getProperty(self, property_name): | ||
140 | 1760 | """Return the HAL property property_name. | ||
141 | 1761 | |||
142 | 1762 | Note that there is no check of the property type. | ||
143 | 1763 | """ | ||
144 | 1764 | if property_name not in self.properties: | ||
145 | 1765 | return None | ||
146 | 1766 | name, type_ = self.properties[property_name] | ||
147 | 1767 | return name | ||
148 | 1768 | |||
149 | 1769 | @property | ||
150 | 1770 | def parent_udi(self): | ||
151 | 1771 | """The UDI of the parent device.""" | ||
152 | 1772 | return self.getProperty('info.parent') | ||
153 | 1773 | |||
154 | 1774 | @property | ||
155 | 1775 | def device_id(self): | ||
156 | 1776 | """See `BaseDevice`.""" | ||
157 | 1777 | return self.udi | ||
158 | 1778 | |||
159 | 1779 | @property | ||
160 | 1780 | def pci_class(self): | ||
161 | 1781 | """See `BaseDevice`.""" | ||
162 | 1782 | return self.getProperty('pci.device_class') | ||
163 | 1783 | |||
164 | 1784 | @property | ||
165 | 1785 | def pci_subclass(self): | ||
166 | 1786 | """The PCI device sub-class of the device or None for Non-PCI devices. | ||
167 | 1787 | """ | ||
168 | 1788 | return self.getProperty('pci.device_subclass') | ||
169 | 1789 | |||
170 | 1790 | @property | ||
171 | 1791 | def usb_vendor_id(self): | ||
172 | 1792 | """See `BaseDevice`.""" | ||
173 | 1793 | return self.getProperty('usb_device.vendor_id') | ||
174 | 1794 | |||
175 | 1795 | @property | ||
176 | 1796 | def usb_product_id(self): | ||
177 | 1797 | """See `BaseDevice`.""" | ||
178 | 1798 | return self.getProperty('usb_device.product_id') | ||
179 | 1799 | |||
180 | 1800 | @property | ||
181 | 1801 | def raw_bus(self): | ||
182 | 1802 | """See `BaseDevice`.""" | ||
183 | 1803 | # Older versions of HAL stored this value in the property | ||
184 | 1804 | # info.bus; newer versions store it in info.subsystem. | ||
185 | 1805 | # | ||
186 | 1806 | # Note that info.bus is gone for all devices except the | ||
187 | 1807 | # USB bus. For USB devices, the property info.bus returns more | ||
188 | 1808 | # detailed data: info.subsystem has the value 'usb' for all | ||
189 | 1809 | # HAL nodes belonging to USB devices, while info.bus has the | ||
190 | 1810 | # value 'usb_device' for the root node of a USB device, and the | ||
191 | 1811 | # value 'usb' for sub-nodes of a USB device. We use these | ||
192 | 1812 | # different value to to find the root USB device node, hence | ||
193 | 1813 | # try to read info.bus first. | ||
194 | 1814 | result = self.getProperty('info.bus') | ||
195 | 1815 | if result is not None: | ||
196 | 1816 | return result | ||
197 | 1817 | return self.getProperty('info.subsystem') | ||
198 | 1818 | |||
199 | 1819 | def getScsiVendorAndModelName(self): | 1803 | def getScsiVendorAndModelName(self): |
200 | 1820 | """Separate vendor and model name of SCSI decvices. | 1804 | """Separate vendor and model name of SCSI decvices. |
201 | 1821 | 1805 | ||
202 | @@ -1839,132 +1823,17 @@ | |||
203 | 1839 | 1823 | ||
204 | 1840 | In all other cases, vendor and model name are returned unmodified. | 1824 | In all other cases, vendor and model name are returned unmodified. |
205 | 1841 | """ | 1825 | """ |
207 | 1842 | vendor = self.getProperty('scsi.vendor') | 1826 | vendor = self.scsi_vendor |
208 | 1843 | if vendor == 'ATA': | 1827 | if vendor == 'ATA': |
209 | 1844 | # The assumption below that the vendor name does not | 1828 | # The assumption below that the vendor name does not |
210 | 1845 | # contain any spaces is not necessarily correct, but | 1829 | # contain any spaces is not necessarily correct, but |
211 | 1846 | # it is hard to find a better heuristic to separate | 1830 | # it is hard to find a better heuristic to separate |
212 | 1847 | # the vendor name from the product name. | 1831 | # the vendor name from the product name. |
214 | 1848 | splitted_name = self.getProperty('scsi.model').split(' ', 1) | 1832 | splitted_name = self.scsi_model.split(' ', 1) |
215 | 1849 | if len(splitted_name) < 2: | 1833 | if len(splitted_name) < 2: |
216 | 1850 | return 'ATA', splitted_name[0] | 1834 | return 'ATA', splitted_name[0] |
217 | 1851 | return splitted_name | 1835 | return splitted_name |
334 | 1852 | return (vendor, self.getProperty('scsi.model')) | 1836 | return (vendor, self.scsi_model) |
219 | 1853 | |||
220 | 1854 | def getVendorOrProduct(self, type_): | ||
221 | 1855 | """Return the vendor or product of this device. | ||
222 | 1856 | |||
223 | 1857 | :return: The vendor or product data for this device. | ||
224 | 1858 | :param type_: 'vendor' or 'product' | ||
225 | 1859 | """ | ||
226 | 1860 | # HAL does not store vendor data very consistently. Try to find | ||
227 | 1861 | # the data in several places. | ||
228 | 1862 | assert type_ in ('vendor', 'product'), ( | ||
229 | 1863 | 'Unexpected value of type_: %r' % type_) | ||
230 | 1864 | |||
231 | 1865 | bus = self.raw_bus | ||
232 | 1866 | if self.udi == ROOT_UDI: | ||
233 | 1867 | # HAL sets info.product to "Computer", provides no property | ||
234 | 1868 | # info.vendor and raw_bus is "unknown", hence the logic | ||
235 | 1869 | # below does not work properly. | ||
236 | 1870 | return self.getProperty('system.hardware.' + type_) | ||
237 | 1871 | elif bus == 'scsi': | ||
238 | 1872 | vendor, product = self.getScsiVendorAndModelName() | ||
239 | 1873 | if type_ == 'vendor': | ||
240 | 1874 | return vendor | ||
241 | 1875 | else: | ||
242 | 1876 | return product | ||
243 | 1877 | else: | ||
244 | 1878 | result = self.getProperty('info.' + type_) | ||
245 | 1879 | if result is None: | ||
246 | 1880 | if bus is None: | ||
247 | 1881 | return None | ||
248 | 1882 | else: | ||
249 | 1883 | return self.getProperty('%s.%s' % (bus, type_)) | ||
250 | 1884 | else: | ||
251 | 1885 | return result | ||
252 | 1886 | |||
253 | 1887 | @property | ||
254 | 1888 | def vendor(self): | ||
255 | 1889 | """The vendor of this device.""" | ||
256 | 1890 | return self.getVendorOrProduct('vendor') | ||
257 | 1891 | |||
258 | 1892 | @property | ||
259 | 1893 | def product(self): | ||
260 | 1894 | """The vendor of this device.""" | ||
261 | 1895 | return self.getVendorOrProduct('product') | ||
262 | 1896 | |||
263 | 1897 | def getVendorOrProductID(self, type_): | ||
264 | 1898 | """Return the vendor or product ID for this device. | ||
265 | 1899 | |||
266 | 1900 | :return: The vendor or product ID for this device. | ||
267 | 1901 | :param type_: 'vendor' or 'product' | ||
268 | 1902 | """ | ||
269 | 1903 | assert type_ in ('vendor', 'product'), ( | ||
270 | 1904 | 'Unexpected value of type_: %r' % type_) | ||
271 | 1905 | bus = self.raw_bus | ||
272 | 1906 | if self.udi == ROOT_UDI: | ||
273 | 1907 | # HAL does not provide IDs for a system itself, we use the | ||
274 | 1908 | # vendor resp. product name instead. | ||
275 | 1909 | return self.getVendorOrProduct(type_) | ||
276 | 1910 | elif bus is None: | ||
277 | 1911 | return None | ||
278 | 1912 | elif bus == 'scsi' or self.udi == ROOT_UDI: | ||
279 | 1913 | # The SCSI specification does not distinguish between a | ||
280 | 1914 | # vendor/model ID and vendor/model name: the SCSI INQUIRY | ||
281 | 1915 | # command returns an 8 byte string as the vendor name and | ||
282 | 1916 | # a 16 byte string as the model name. We use these strings | ||
283 | 1917 | # as the vendor/product name as well as the vendor/product | ||
284 | 1918 | # ID. | ||
285 | 1919 | # | ||
286 | 1920 | # Similary, HAL does not provide a vendor or product ID | ||
287 | 1921 | # for the host system itself, so we use the vendor resp. | ||
288 | 1922 | # product name as the vendor/product ID for systems too. | ||
289 | 1923 | return self.getVendorOrProduct(type_) | ||
290 | 1924 | else: | ||
291 | 1925 | return self.getProperty('%s.%s_id' % (bus, type_)) | ||
292 | 1926 | |||
293 | 1927 | @property | ||
294 | 1928 | def vendor_id(self): | ||
295 | 1929 | """The vendor ID of this device.""" | ||
296 | 1930 | return self.getVendorOrProductID('vendor') | ||
297 | 1931 | |||
298 | 1932 | @property | ||
299 | 1933 | def product_id(self): | ||
300 | 1934 | """The product ID of this device.""" | ||
301 | 1935 | return self.getVendorOrProductID('product') | ||
302 | 1936 | |||
303 | 1937 | @property | ||
304 | 1938 | def vendor_id_for_db(self): | ||
305 | 1939 | """The vendor ID in the representation needed for the HWDB tables. | ||
306 | 1940 | |||
307 | 1941 | USB and PCI IDs are represented in the database in hexadecimal, | ||
308 | 1942 | while the IDs provided by HAL are integers. | ||
309 | 1943 | |||
310 | 1944 | The SCSI vendor name is right-padded with spaces to 8 bytes. | ||
311 | 1945 | """ | ||
312 | 1946 | bus = self.raw_bus | ||
313 | 1947 | format = DB_FORMAT_FOR_VENDOR_ID.get(bus) | ||
314 | 1948 | if format is None: | ||
315 | 1949 | return self.vendor_id | ||
316 | 1950 | else: | ||
317 | 1951 | return format % self.vendor_id | ||
318 | 1952 | |||
319 | 1953 | @property | ||
320 | 1954 | def product_id_for_db(self): | ||
321 | 1955 | """The product ID in the representation needed for the HWDB tables. | ||
322 | 1956 | |||
323 | 1957 | USB and PCI IDs are represented in the database in hexadecimal, | ||
324 | 1958 | while the IDs provided by HAL are integers. | ||
325 | 1959 | |||
326 | 1960 | The SCSI product name is right-padded with spaces to 16 bytes. | ||
327 | 1961 | """ | ||
328 | 1962 | bus = self.raw_bus | ||
329 | 1963 | format = DB_FORMAT_FOR_PRODUCT_ID.get(bus) | ||
330 | 1964 | if format is None: | ||
331 | 1965 | return self.product_id | ||
332 | 1966 | else: | ||
333 | 1967 | return format % self.product_id | ||
335 | 1968 | 1837 | ||
336 | 1969 | def getDriver(self): | 1838 | def getDriver(self): |
337 | 1970 | """Return the HWDriver instance associated with this device. | 1839 | """Return the HWDriver instance associated with this device. |
338 | @@ -1974,11 +1843,11 @@ | |||
339 | 1974 | # HAL and the HWDB client know at present only about kernel | 1843 | # HAL and the HWDB client know at present only about kernel |
340 | 1975 | # drivers, so there is currently no need to search for | 1844 | # drivers, so there is currently no need to search for |
341 | 1976 | # for user space printer drivers, for example. | 1845 | # for user space printer drivers, for example. |
344 | 1977 | driver_name = self.getProperty('info.linux.driver') | 1846 | if self.driver_name is not None: |
343 | 1978 | if driver_name is not None: | ||
345 | 1979 | kernel_package_name = self.parser.getKernelPackageName() | 1847 | kernel_package_name = self.parser.getKernelPackageName() |
346 | 1980 | db_driver_set = getUtility(IHWDriverSet) | 1848 | db_driver_set = getUtility(IHWDriverSet) |
348 | 1981 | return db_driver_set.getOrCreate(kernel_package_name, driver_name) | 1849 | return db_driver_set.getOrCreate( |
349 | 1850 | kernel_package_name, self.driver_name) | ||
350 | 1982 | else: | 1851 | else: |
351 | 1983 | return None | 1852 | return None |
352 | 1984 | 1853 | ||
353 | @@ -2069,6 +1938,186 @@ | |||
354 | 2069 | submission_device) | 1938 | submission_device) |
355 | 2070 | 1939 | ||
356 | 2071 | 1940 | ||
357 | 1941 | class HALDevice(BaseDevice): | ||
358 | 1942 | """The representation of a HAL device node.""" | ||
359 | 1943 | |||
360 | 1944 | def __init__(self, id, udi, properties, parser): | ||
361 | 1945 | """HALDevice constructor. | ||
362 | 1946 | |||
363 | 1947 | :param id: The ID of the HAL device in the submission data as | ||
364 | 1948 | specified in <device id=...>. | ||
365 | 1949 | :type id: int | ||
366 | 1950 | :param udi: The UDI of the HAL device. | ||
367 | 1951 | :type udi: string | ||
368 | 1952 | :param properties: The HAL properties of the device. | ||
369 | 1953 | :type properties: dict | ||
370 | 1954 | :param parser: The parser processing a submission. | ||
371 | 1955 | :type parser: SubmissionParser | ||
372 | 1956 | """ | ||
373 | 1957 | super(HALDevice, self).__init__(parser) | ||
374 | 1958 | self.id = id | ||
375 | 1959 | self.udi = udi | ||
376 | 1960 | self.properties = properties | ||
377 | 1961 | |||
378 | 1962 | def getProperty(self, property_name): | ||
379 | 1963 | """Return the HAL property property_name. | ||
380 | 1964 | |||
381 | 1965 | Note that there is no check of the property type. | ||
382 | 1966 | """ | ||
383 | 1967 | if property_name not in self.properties: | ||
384 | 1968 | return None | ||
385 | 1969 | name, type_ = self.properties[property_name] | ||
386 | 1970 | return name | ||
387 | 1971 | |||
388 | 1972 | @property | ||
389 | 1973 | def parent_udi(self): | ||
390 | 1974 | """The UDI of the parent device.""" | ||
391 | 1975 | return self.getProperty('info.parent') | ||
392 | 1976 | |||
393 | 1977 | @property | ||
394 | 1978 | def device_id(self): | ||
395 | 1979 | """See `BaseDevice`.""" | ||
396 | 1980 | return self.udi | ||
397 | 1981 | |||
398 | 1982 | @property | ||
399 | 1983 | def pci_class(self): | ||
400 | 1984 | """See `BaseDevice`.""" | ||
401 | 1985 | return self.getProperty('pci.device_class') | ||
402 | 1986 | |||
403 | 1987 | @property | ||
404 | 1988 | def pci_subclass(self): | ||
405 | 1989 | """The PCI device sub-class of the device or None for Non-PCI devices. | ||
406 | 1990 | """ | ||
407 | 1991 | return self.getProperty('pci.device_subclass') | ||
408 | 1992 | |||
409 | 1993 | @property | ||
410 | 1994 | def usb_vendor_id(self): | ||
411 | 1995 | """See `BaseDevice`.""" | ||
412 | 1996 | return self.getProperty('usb_device.vendor_id') | ||
413 | 1997 | |||
414 | 1998 | @property | ||
415 | 1999 | def usb_product_id(self): | ||
416 | 2000 | """See `BaseDevice`.""" | ||
417 | 2001 | return self.getProperty('usb_device.product_id') | ||
418 | 2002 | |||
419 | 2003 | @property | ||
420 | 2004 | def scsi_vendor(self): | ||
421 | 2005 | """See `BaseDevice`.""" | ||
422 | 2006 | return self.getProperty('scsi.vendor') | ||
423 | 2007 | |||
424 | 2008 | @property | ||
425 | 2009 | def scsi_model(self): | ||
426 | 2010 | """See `BaseDevice`.""" | ||
427 | 2011 | return self.getProperty('scsi.model') | ||
428 | 2012 | |||
429 | 2013 | @property | ||
430 | 2014 | def driver_name(self): | ||
431 | 2015 | """See `BaseDevice`.""" | ||
432 | 2016 | return self.getProperty('info.linux.driver') | ||
433 | 2017 | |||
434 | 2018 | @property | ||
435 | 2019 | def raw_bus(self): | ||
436 | 2020 | """See `BaseDevice`.""" | ||
437 | 2021 | # Older versions of HAL stored this value in the property | ||
438 | 2022 | # info.bus; newer versions store it in info.subsystem. | ||
439 | 2023 | # | ||
440 | 2024 | # Note that info.bus is gone for all devices except the | ||
441 | 2025 | # USB bus. For USB devices, the property info.bus returns more | ||
442 | 2026 | # detailed data: info.subsystem has the value 'usb' for all | ||
443 | 2027 | # HAL nodes belonging to USB devices, while info.bus has the | ||
444 | 2028 | # value 'usb_device' for the root node of a USB device, and the | ||
445 | 2029 | # value 'usb' for sub-nodes of a USB device. We use these | ||
446 | 2030 | # different value to to find the root USB device node, hence | ||
447 | 2031 | # try to read info.bus first. | ||
448 | 2032 | result = self.getProperty('info.bus') | ||
449 | 2033 | if result is not None: | ||
450 | 2034 | return result | ||
451 | 2035 | return self.getProperty('info.subsystem') | ||
452 | 2036 | |||
453 | 2037 | def getVendorOrProduct(self, type_): | ||
454 | 2038 | """Return the vendor or product of this device. | ||
455 | 2039 | |||
456 | 2040 | :return: The vendor or product data for this device. | ||
457 | 2041 | :param type_: 'vendor' or 'product' | ||
458 | 2042 | """ | ||
459 | 2043 | # HAL does not store vendor data very consistently. Try to find | ||
460 | 2044 | # the data in several places. | ||
461 | 2045 | assert type_ in ('vendor', 'product'), ( | ||
462 | 2046 | 'Unexpected value of type_: %r' % type_) | ||
463 | 2047 | |||
464 | 2048 | bus = self.raw_bus | ||
465 | 2049 | if self.udi == ROOT_UDI: | ||
466 | 2050 | # HAL sets info.product to "Computer", provides no property | ||
467 | 2051 | # info.vendor and raw_bus is "unknown", hence the logic | ||
468 | 2052 | # below does not work properly. | ||
469 | 2053 | return self.getProperty('system.hardware.' + type_) | ||
470 | 2054 | elif bus == 'scsi': | ||
471 | 2055 | vendor, product = self.getScsiVendorAndModelName() | ||
472 | 2056 | if type_ == 'vendor': | ||
473 | 2057 | return vendor | ||
474 | 2058 | else: | ||
475 | 2059 | return product | ||
476 | 2060 | else: | ||
477 | 2061 | result = self.getProperty('info.' + type_) | ||
478 | 2062 | if result is None: | ||
479 | 2063 | if bus is None: | ||
480 | 2064 | return None | ||
481 | 2065 | else: | ||
482 | 2066 | return self.getProperty('%s.%s' % (bus, type_)) | ||
483 | 2067 | else: | ||
484 | 2068 | return result | ||
485 | 2069 | |||
486 | 2070 | @property | ||
487 | 2071 | def vendor(self): | ||
488 | 2072 | """See `BaseDevice`.""" | ||
489 | 2073 | return self.getVendorOrProduct('vendor') | ||
490 | 2074 | |||
491 | 2075 | @property | ||
492 | 2076 | def product(self): | ||
493 | 2077 | """See `BaseDevice`.""" | ||
494 | 2078 | return self.getVendorOrProduct('product') | ||
495 | 2079 | |||
496 | 2080 | def getVendorOrProductID(self, type_): | ||
497 | 2081 | """Return the vendor or product ID for this device. | ||
498 | 2082 | |||
499 | 2083 | :return: The vendor or product ID for this device. | ||
500 | 2084 | :param type_: 'vendor' or 'product' | ||
501 | 2085 | """ | ||
502 | 2086 | assert type_ in ('vendor', 'product'), ( | ||
503 | 2087 | 'Unexpected value of type_: %r' % type_) | ||
504 | 2088 | bus = self.raw_bus | ||
505 | 2089 | if self.udi == ROOT_UDI: | ||
506 | 2090 | # HAL does not provide IDs for a system itself, we use the | ||
507 | 2091 | # vendor resp. product name instead. | ||
508 | 2092 | return self.getVendorOrProduct(type_) | ||
509 | 2093 | elif bus is None: | ||
510 | 2094 | return None | ||
511 | 2095 | elif bus == 'scsi' or self.udi == ROOT_UDI: | ||
512 | 2096 | # The SCSI specification does not distinguish between a | ||
513 | 2097 | # vendor/model ID and vendor/model name: the SCSI INQUIRY | ||
514 | 2098 | # command returns an 8 byte string as the vendor name and | ||
515 | 2099 | # a 16 byte string as the model name. We use these strings | ||
516 | 2100 | # as the vendor/product name as well as the vendor/product | ||
517 | 2101 | # ID. | ||
518 | 2102 | # | ||
519 | 2103 | # Similary, HAL does not provide a vendor or product ID | ||
520 | 2104 | # for the host system itself, so we use the vendor resp. | ||
521 | 2105 | # product name as the vendor/product ID for systems too. | ||
522 | 2106 | return self.getVendorOrProduct(type_) | ||
523 | 2107 | else: | ||
524 | 2108 | return self.getProperty('%s.%s_id' % (bus, type_)) | ||
525 | 2109 | |||
526 | 2110 | @property | ||
527 | 2111 | def vendor_id(self): | ||
528 | 2112 | """See `BaseDevice`.""" | ||
529 | 2113 | return self.getVendorOrProductID('vendor') | ||
530 | 2114 | |||
531 | 2115 | @property | ||
532 | 2116 | def product_id(self): | ||
533 | 2117 | """See `BaseDevice`.""" | ||
534 | 2118 | return self.getVendorOrProductID('product') | ||
535 | 2119 | |||
536 | 2120 | |||
537 | 2072 | class ProcessingLoop(object): | 2121 | class ProcessingLoop(object): |
538 | 2073 | """An `ITunableLoop` for processing HWDB submissions.""" | 2122 | """An `ITunableLoop` for processing HWDB submissions.""" |
539 | 2074 | 2123 | ||
540 | 2075 | 2124 | ||
541 | === modified file 'lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py' | |||
542 | --- lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py 2009-10-01 11:14:19 +0000 | |||
543 | +++ lib/canonical/launchpad/scripts/tests/test_hwdb_submission_processing.py 2009-10-02 15:43:14 +0000 | |||
544 | @@ -462,6 +462,60 @@ | |||
545 | 462 | 'Unexpected value of HALDevice.usb_product_id for Non-USB ' | 462 | 'Unexpected value of HALDevice.usb_product_id for Non-USB ' |
546 | 463 | 'device.') | 463 | 'device.') |
547 | 464 | 464 | ||
548 | 465 | def testHALDeviceScsiVendor(self): | ||
549 | 466 | """Test of HALDevice.scsi_vendor.""" | ||
550 | 467 | properties = { | ||
551 | 468 | 'scsi.vendor': ('SEAGATE', 'string'), | ||
552 | 469 | } | ||
553 | 470 | parser = SubmissionParser(self.log) | ||
554 | 471 | device = HALDevice(1, '/some/udi/path', properties, parser) | ||
555 | 472 | self.assertEqual( | ||
556 | 473 | 'SEAGATE', device.scsi_vendor, | ||
557 | 474 | 'Unexpected value of HALDevice.scsi_vendor.') | ||
558 | 475 | |||
559 | 476 | properties = {} | ||
560 | 477 | parser = SubmissionParser(self.log) | ||
561 | 478 | device = HALDevice(1, '/some/udi/path', properties, parser) | ||
562 | 479 | self.assertEqual( | ||
563 | 480 | None, device.scsi_vendor, | ||
564 | 481 | 'Unexpected value of HALDevice.scsi_vendor for Non-SCSI device.') | ||
565 | 482 | |||
566 | 483 | def testHALDeviceScsiModel(self): | ||
567 | 484 | """Test of HALDevice.scsi_model.""" | ||
568 | 485 | properties = { | ||
569 | 486 | 'scsi.model': ('ST1234567', 'string'), | ||
570 | 487 | } | ||
571 | 488 | parser = SubmissionParser(self.log) | ||
572 | 489 | device = HALDevice(1, '/some/udi/path', properties, parser) | ||
573 | 490 | self.assertEqual( | ||
574 | 491 | 'ST1234567', device.scsi_model, | ||
575 | 492 | 'Unexpected value of HALDevice.scsi_model.') | ||
576 | 493 | |||
577 | 494 | properties = {} | ||
578 | 495 | parser = SubmissionParser(self.log) | ||
579 | 496 | device = HALDevice(1, '/some/udi/path', properties, parser) | ||
580 | 497 | self.assertEqual( | ||
581 | 498 | None, device.scsi_model, | ||
582 | 499 | 'Unexpected value of HALDevice.scsi_model for Non-SCSI device.') | ||
583 | 500 | |||
584 | 501 | def testHALDeviceDriverName(self): | ||
585 | 502 | """Test of HALDevice.driver_name.""" | ||
586 | 503 | properties = { | ||
587 | 504 | 'info.linux.driver': ('ahci', 'string'), | ||
588 | 505 | } | ||
589 | 506 | parser = SubmissionParser(self.log) | ||
590 | 507 | device = HALDevice(1, '/some/udi/path', properties, parser) | ||
591 | 508 | self.assertEqual( | ||
592 | 509 | 'ahci', device.driver_name, | ||
593 | 510 | 'Unexpected value of HALDevice.driver_name.') | ||
594 | 511 | |||
595 | 512 | properties = {} | ||
596 | 513 | parser = SubmissionParser(self.log) | ||
597 | 514 | device = HALDevice(1, '/some/udi/path', properties, parser) | ||
598 | 515 | self.assertEqual( | ||
599 | 516 | None, device.driver_name, | ||
600 | 517 | 'Unexpected value of HALDevice.driver_name for Non-SCSI device.') | ||
601 | 518 | |||
602 | 465 | def testHalDeviceRawBus(self): | 519 | def testHalDeviceRawBus(self): |
603 | 466 | """test of HALDevice.raw_bus.""" | 520 | """test of HALDevice.raw_bus.""" |
604 | 467 | properties = { | 521 | properties = { |
This branch is the third and last part to refactor class hwdbsubmissions .HALDevice. See /code.edge. launchpad. net/~adeuring/ launchpad/ hwdb-refactor- haldevice/ +merge/ 12669
l.c.l.scripts.
https:/
for the reason of the refactoring.
The branch adds new properties scsi_vendor, scsi_model and driver_name
to BaseDevice and HALDevice (including short tests), and it defines some
"dummy properties" in class BaseDevice that correspond to exsting
properties in class HALDevice.
Finally, it moves methods that can be used both for class HALDevice and
the not-yet-existing class UdevDevice into class BaseDevice.
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: /launchpad/ scripts/ hwdbsubmissions .py /launchpad/ scripts/ tests/test_ hwdb_submission _processing. py
lib/canonical
lib/canonical
== Pyflakes notices ==
lib/canonical/ launchpad/ scripts/ hwdbsubmissions .py
22: redefinition of unused 'etree' from line 20
== Pylint notices ==
lib/canonical/ launchpad/ scripts/ hwdbsubmissions .py cElementTree' (No module
20: [F0401] Unable to import 'xml.etree.
named etree)
A complaint caused by an unrelated branch that prepares Launchpad for
Python 2.5