Merge ~cjwatson/launchpad:remove-hwdb into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: 01689d471afabeb72e5c1cad0a4df5214a378351
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:remove-hwdb
Merge into: launchpad:master
Diff against target: 9844 lines (+5/-497)
14 files modified
dev/null (+0/-47)
lib/lp/_schema_circular_imports.py (+0/-49)
lib/lp/app/browser/launchpad.py (+0/-2)
lib/lp/app/interfaces/launchpad.py (+0/-1)
lib/lp/app/utilities/celebrities.py (+0/-1)
lib/lp/configure.zcml (+0/-1)
lib/lp/registry/interfaces/role.py (+0/-3)
lib/lp/scripts/garbo.py (+0/-63)
lib/lp/scripts/tests/test_garbo.py (+0/-31)
lib/lp/security.py (+0/-82)
lib/lp/services/webservice/wadl-to-refhtml.xsl (+5/-44)
lib/lp/systemhomes.py (+0/-123)
lib/lp/testing/factory.py (+0/-49)
utilities/snakefood/lp-sfood-packages (+0/-1)
Reviewer Review Type Date Requested Status
Ioana Lasc (community) Approve
Review via email: mp+390183@code.launchpad.net

Commit message

Remove the hardware database

Description of the change

Since Ubuntu xenial, checkbox no longer uses Launchpad's hardware database, and the only new submissions are coming from older systems; the certification teams no longer pay attention to it. We've been refusing new submissions since 2020-05-13 and have had no comments.

The actual data remains in the Launchpad production database and we can extract it manually if need be, but there's no longer any need to keep the application code around.

To post a comment you must log in.
Revision history for this message
Ioana Lasc (ilasc) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/lib/lp/_schema_circular_imports.py b/lib/lp/_schema_circular_imports.py
2index 19bae81..6e2cbfc 100644
3--- a/lib/lp/_schema_circular_imports.py
4+++ b/lib/lp/_schema_circular_imports.py
5@@ -84,17 +84,6 @@ from lp.code.interfaces.sourcepackagerecipe import ISourcePackageRecipe
6 from lp.code.interfaces.sourcepackagerecipebuild import (
7 ISourcePackageRecipeBuild,
8 )
9-from lp.hardwaredb.interfaces.hwdb import (
10- IHWDBApplication,
11- IHWDevice,
12- IHWDeviceClass,
13- IHWDriver,
14- IHWDriverName,
15- IHWDriverPackageName,
16- IHWSubmission,
17- IHWSubmissionDevice,
18- IHWVendorID,
19- )
20 from lp.registry.interfaces.commercialsubscription import (
21 ICommercialSubscription,
22 )
23@@ -897,44 +886,6 @@ patch_entry_explicit_version(IDistroSeriesDifferenceComment, 'beta')
24 # IGPGKey
25 patch_entry_explicit_version(IGPGKey, 'beta')
26
27-# IHWDBApplication
28-patch_entry_explicit_version(IHWDBApplication, 'beta')
29-patch_operations_explicit_version(
30- IHWDBApplication, 'beta', "deviceDriverOwnersAffectedByBugs", "devices",
31- "drivers", "hwInfoByBugRelatedUsers", "numDevicesInSubmissions",
32- "numOwnersOfDevice", "numSubmissionsWithDevice", "search", "vendorIDs")
33-
34-# IHWDevice
35-patch_entry_explicit_version(IHWDevice, 'beta')
36-patch_operations_explicit_version(
37- IHWDevice, 'beta', "getOrCreateDeviceClass", "getSubmissions",
38- "removeDeviceClass")
39-
40-# IHWDeviceClass
41-patch_entry_explicit_version(IHWDeviceClass, 'beta')
42-patch_operations_explicit_version(
43- IHWDeviceClass, 'beta', "delete")
44-
45-# IHWDriver
46-patch_entry_explicit_version(IHWDriver, 'beta')
47-patch_operations_explicit_version(
48- IHWDriver, 'beta', "getSubmissions")
49-
50-# IHWDriverName
51-patch_entry_explicit_version(IHWDriverName, 'beta')
52-
53-# IHWDriverPackageName
54-patch_entry_explicit_version(IHWDriverPackageName, 'beta')
55-
56-# IHWSubmission
57-patch_entry_explicit_version(IHWSubmission, 'beta')
58-
59-# IHWSubmissionDevice
60-patch_entry_explicit_version(IHWSubmissionDevice, 'beta')
61-
62-# IHWVendorID
63-patch_entry_explicit_version(IHWVendorID, 'beta')
64-
65 # IHasBugs
66 patch_entry_explicit_version(IHasBugs, 'beta')
67
68diff --git a/lib/lp/app/browser/launchpad.py b/lib/lp/app/browser/launchpad.py
69index e1a5c71..d31df20 100644
70--- a/lib/lp/app/browser/launchpad.py
71+++ b/lib/lp/app/browser/launchpad.py
72@@ -105,7 +105,6 @@ from lp.code.interfaces.codehosting import IBazaarApplication
73 from lp.code.interfaces.codeimport import ICodeImportSet
74 from lp.code.interfaces.gitlookup import IGitLookup
75 from lp.code.interfaces.gitrepository import IGitRepositorySet
76-from lp.hardwaredb.interfaces.hwdb import IHWDBApplication
77 from lp.layers import WebServiceLayer
78 from lp.registry.enums import VCSType
79 from lp.registry.interfaces.announcement import IAnnouncementSet
80@@ -856,7 +855,6 @@ class LaunchpadRootNavigation(Navigation):
81 '+countries': ICountrySet,
82 'distros': IDistributionSet,
83 '+git': IGitRepositorySet,
84- '+hwdb': IHWDBApplication,
85 'karmaaction': IKarmaActionSet,
86 '+imports': ITranslationImportQueue,
87 '+languages': ILanguageSet,
88diff --git a/lib/lp/app/interfaces/launchpad.py b/lib/lp/app/interfaces/launchpad.py
89index 96a2f95..2ab8033 100644
90--- a/lib/lp/app/interfaces/launchpad.py
91+++ b/lib/lp/app/interfaces/launchpad.py
92@@ -48,7 +48,6 @@ class ILaunchpadCelebrities(Interface):
93 debian = Attribute("The Debian Distribution.")
94 english = Attribute("The English language.")
95 gnome_bugzilla = Attribute("The Gnome Bugzilla.")
96- hwdb_team = Attribute("The HWDB team.")
97 janitor = Attribute("The Launchpad Janitor.")
98 katie = Attribute("The Debian Auto-sync user.")
99 launchpad = Attribute("The Launchpad project.")
100diff --git a/lib/lp/app/utilities/celebrities.py b/lib/lp/app/utilities/celebrities.py
101index cb1de65..35e6d8a 100644
102--- a/lib/lp/app/utilities/celebrities.py
103+++ b/lib/lp/app/utilities/celebrities.py
104@@ -138,7 +138,6 @@ class LaunchpadCelebrities:
105 debian = CelebrityDescriptor(IDistributionSet, 'debian')
106 english = LanguageCelebrityDescriptor(ILanguageSet, 'en')
107 gnome_bugzilla = CelebrityDescriptor(IBugTrackerSet, 'gnome-bugs')
108- hwdb_team = PersonCelebrityDescriptor('hwdb-team')
109 janitor = PersonCelebrityDescriptor('janitor')
110 katie = PersonCelebrityDescriptor('katie')
111 launchpad = CelebrityDescriptor(IProductSet, 'launchpad')
112diff --git a/lib/lp/configure.zcml b/lib/lp/configure.zcml
113index a3e7c08..b77284d 100644
114--- a/lib/lp/configure.zcml
115+++ b/lib/lp/configure.zcml
116@@ -29,7 +29,6 @@
117 <include package="lp.buildmaster" />
118 <include package="lp.code" />
119 <include package="lp.coop.answersbugs" />
120- <include package="lp.hardwaredb" />
121 <include package="lp.oci" />
122 <include package="lp.snappy" />
123 <include package="lp.soyuz" />
124diff --git a/lib/lp/hardwaredb/__init__.py b/lib/lp/hardwaredb/__init__.py
125deleted file mode 100644
126index e69de29..0000000
127--- a/lib/lp/hardwaredb/__init__.py
128+++ /dev/null
129diff --git a/lib/lp/hardwaredb/browser/__init__.py b/lib/lp/hardwaredb/browser/__init__.py
130deleted file mode 100644
131index e69de29..0000000
132--- a/lib/lp/hardwaredb/browser/__init__.py
133+++ /dev/null
134diff --git a/lib/lp/hardwaredb/browser/configure.zcml b/lib/lp/hardwaredb/browser/configure.zcml
135deleted file mode 100644
136index ed130e5..0000000
137--- a/lib/lp/hardwaredb/browser/configure.zcml
138+++ /dev/null
139@@ -1,65 +0,0 @@
140-<configure
141- xmlns="http://namespaces.zope.org/zope"
142- xmlns:browser="http://namespaces.zope.org/browser"
143- xmlns:i18n="http://namespaces.zope.org/i18n"
144- xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
145- i18n_domain="launchpad">
146- <browser:navigation
147- module="lp.hardwaredb.browser.hwdb"
148- classes="
149- HWDBApplicationNavigation"/>
150- <browser:url
151- for="lp.hardwaredb.interfaces.hwdb.IHWDBApplication"
152- path_expression="string:+hwdb"
153- parent_utility="lp.services.webapp.interfaces.ILaunchpadRoot"/>
154- <browser:url
155- for="lp.hardwaredb.interfaces.hwdb.IHWSystemFingerprint"
156- path_expression="string:+fingerprint/${fingerprint}"
157- parent_utility="lp.hardwaredb.interfaces.hwdb.IHWDBApplication"/>
158- <browser:url
159- for="lp.hardwaredb.interfaces.hwdb.IHWSubmission"
160- path_expression="string:+submission/${submission_key}"
161- parent_utility="lp.hardwaredb.interfaces.hwdb.IHWDBApplication"/>
162- <browser:defaultView
163- for="lp.hardwaredb.interfaces.hwdb.IHWSubmission"
164- name="+text"/>
165- <browser:page
166- for="lp.hardwaredb.interfaces.hwdb.IHWSubmission"
167- class="lp.hardwaredb.browser.hwdb.HWDBSubmissionTextView"
168- permission="zope.Public"
169- name="+text"/>
170- <browser:page
171- for="lp.registry.interfaces.person.IPerson"
172- permission="zope.Public"
173- class="lp.hardwaredb.browser.hwdb.HWDBPersonSubmissionsView"
174- template="../templates/person-hwdb-submissions.pt"
175- name="+hwdb-submissions"/>
176- <browser:url
177- for="lp.hardwaredb.interfaces.hwdb.IHWVendorID"
178- path_expression="string:+hwvendorid/${id}"
179- parent_utility="lp.hardwaredb.interfaces.hwdb.IHWDBApplication"/>
180- <browser:url
181- for="lp.hardwaredb.interfaces.hwdb.IHWDevice"
182- path_expression="string:+device/${id}"
183- parent_utility="lp.hardwaredb.interfaces.hwdb.IHWDBApplication"/>
184- <browser:url
185- for="lp.hardwaredb.interfaces.hwdb.IHWDriver"
186- path_expression="string:+driver/${id}"
187- parent_utility="lp.hardwaredb.interfaces.hwdb.IHWDBApplication"/>
188- <browser:url
189- for="lp.hardwaredb.interfaces.hwdb.IHWDriverName"
190- path_expression="string:+drivername/${name}"
191- parent_utility="lp.hardwaredb.interfaces.hwdb.IHWDBApplication"/>
192- <browser:url
193- for="lp.hardwaredb.interfaces.hwdb.IHWDriverPackageName"
194- path_expression="string:+driverpackagename/${package_name}"
195- parent_utility="lp.hardwaredb.interfaces.hwdb.IHWDBApplication"/>
196- <browser:url
197- for="lp.hardwaredb.interfaces.hwdb.IHWDeviceClass"
198- path_expression="string:+deviceclass/${id}"
199- parent_utility="lp.hardwaredb.interfaces.hwdb.IHWDBApplication"/>
200- <browser:url
201- for="lp.hardwaredb.interfaces.hwdb.IHWSubmissionDevice"
202- path_expression="string:+submissiondevice/${id}"
203- parent_utility="lp.hardwaredb.interfaces.hwdb.IHWDBApplication"/>
204-</configure>
205diff --git a/lib/lp/hardwaredb/browser/hwdb.py b/lib/lp/hardwaredb/browser/hwdb.py
206deleted file mode 100644
207index 03bf04c..0000000
208--- a/lib/lp/hardwaredb/browser/hwdb.py
209+++ /dev/null
210@@ -1,178 +0,0 @@
211-# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
212-# GNU Affero General Public License version 3 (see the file LICENSE).
213-
214-__metaclass__ = type
215-
216-__all__ = [
217- 'HWDBApplicationNavigation',
218- 'HWDBFingerprintSetView',
219- 'HWDBPersonSubmissionsView',
220- 'HWDBSubmissionTextView',
221- ]
222-
223-from textwrap import dedent
224-
225-from zope.browserpage import ViewPageTemplateFile
226-from zope.component import getUtility
227-from zope.interface import implementer
228-from zope.publisher.interfaces.browser import IBrowserPublisher
229-
230-from lp.app.errors import NotFoundError
231-from lp.hardwaredb.interfaces.hwdb import (
232- IHWDBApplication,
233- IHWDeviceClassSet,
234- IHWDeviceSet,
235- IHWDriverSet,
236- IHWSubmissionDeviceSet,
237- IHWSubmissionSet,
238- IHWVendorIDSet,
239- )
240-from lp.services.webapp import (
241- LaunchpadView,
242- Navigation,
243- stepthrough,
244- )
245-from lp.services.webapp.batching import BatchNavigator
246-from lp.services.webapp.interfaces import ILaunchBag
247-
248-
249-class HWDBPersonSubmissionsView(LaunchpadView):
250- """View class for preseting HWDB submissions by a person."""
251-
252- @property
253- def label(self):
254- return 'Hardware submissions for %s' % (self.context.title,)
255-
256- @property
257- def page_title(self):
258- return "Hardware Database submissions by %s" % (self.context.title,)
259-
260- def getAllBatched(self):
261- """Return the list of HWDB submissions made by this person."""
262- hw_submissionset = getUtility(IHWSubmissionSet)
263- submissions = hw_submissionset.getByOwner(self.context, self.user)
264- return BatchNavigator(submissions, self.request)
265-
266- def userIsOwner(self):
267- """Return true, if self.context == self.user"""
268- return self.context == self.user
269-
270-
271-class HWDBSubmissionTextView(LaunchpadView):
272- """Renders a HWDBSubmission in parseable text."""
273- def render(self):
274- data = {}
275- data["date_created"] = self.context.date_created
276- data["date_submitted"] = self.context.date_submitted
277- data["format"] = self.context.format.name
278-
279- dar = self.context.distroarchseries
280- if dar:
281- data["distribution"] = dar.distroseries.distribution.name
282- data["distribution_series"] = dar.distroseries.version
283- data["architecture"] = dar.architecturetag
284- else:
285- data["distribution"] = "(unknown)"
286- data["distribution_series"] = "(unknown)"
287- data["architecture"] = "(unknown)"
288-
289- data["system_fingerprint"] = (
290- self.context.system_fingerprint.fingerprint)
291- data["url"] = self.context.raw_submission.http_url
292-
293- return dedent("""
294- Date-Created: %(date_created)s
295- Date-Submitted: %(date_submitted)s
296- Format: %(format)s
297- Distribution: %(distribution)s
298- Distribution-Series: %(distribution_series)s
299- Architecture: %(architecture)s
300- System: %(system_fingerprint)s
301- Submission URL: %(url)s""" % data)
302-
303-
304-class HWDBApplicationNavigation(Navigation):
305- """Navigation class for HWDBSubmissionSet."""
306-
307- usedfor = IHWDBApplication
308-
309- @stepthrough('+submission')
310- def traverse_submission(self, name):
311- user = getUtility(ILaunchBag).user
312- submission = getUtility(IHWSubmissionSet).getBySubmissionKey(
313- name, user=user)
314- return submission
315-
316- @stepthrough('+fingerprint')
317- def traverse_hwdb_fingerprint(self, name):
318- return HWDBFingerprintSetView(self.context, self.request, name)
319-
320- @stepthrough('+device')
321- def traverse_device(self, id):
322- try:
323- id = int(id)
324- except ValueError:
325- raise NotFoundError('invalid value for ID: %r' % id)
326- return getUtility(IHWDeviceSet).getByID(id)
327-
328- @stepthrough('+deviceclass')
329- def traverse_device_class(self, id):
330- try:
331- id = int(id)
332- except ValueError:
333- raise NotFoundError('invalid value for ID: %r' % id)
334- return getUtility(IHWDeviceClassSet).get(id)
335-
336- @stepthrough('+driver')
337- def traverse_driver(self, id):
338- try:
339- id = int(id)
340- except ValueError:
341- raise NotFoundError('invalid value for ID: %r' % id)
342- return getUtility(IHWDriverSet).getByID(id)
343-
344- @stepthrough('+submissiondevice')
345- def traverse_submissiondevice(self, id):
346- try:
347- id = int(id)
348- except ValueError:
349- raise NotFoundError('invalid value for ID: %r' % id)
350- return getUtility(IHWSubmissionDeviceSet).get(id)
351-
352- @stepthrough('+hwvendorid')
353- def traverse_hw_vendor_id(self, id):
354- try:
355- id = int(id)
356- except ValueError:
357- raise NotFoundError('invalid value for ID: %r' % id)
358- return getUtility(IHWVendorIDSet).get(id)
359-
360-
361-@implementer(IBrowserPublisher)
362-class HWDBFingerprintSetView(LaunchpadView):
363- """View class for lists of HWDB submissions for a system fingerprint."""
364- label = page_title = "Hardware Database submissions for a fingerprint"
365-
366- template = ViewPageTemplateFile(
367- '../templates/hwdb-fingerprint-submissions.pt')
368-
369- def __init__(self, context, request, system_name):
370- LaunchpadView.__init__(self, context, request)
371- self.system_name = system_name
372-
373- def getAllBatched(self):
374- """A BatchNavigator instance with the submissions."""
375- submissions = getUtility(IHWSubmissionSet).getByFingerprintName(
376- self.system_name, self.user)
377- return BatchNavigator(submissions, self.request)
378-
379- def browserDefault(self, request):
380- """See `IBrowserPublisher`."""
381- return self, ()
382-
383- def showOwner(self, submission):
384- """Check if the owner can be shown in the list.
385- """
386- return (submission.owner is not None
387- and (submission.contactable
388- or (submission.owner == self.user)))
389diff --git a/lib/lp/hardwaredb/browser/tests/__init__.py b/lib/lp/hardwaredb/browser/tests/__init__.py
390deleted file mode 100644
391index e69de29..0000000
392--- a/lib/lp/hardwaredb/browser/tests/__init__.py
393+++ /dev/null
394diff --git a/lib/lp/hardwaredb/browser/tests/test_views.py b/lib/lp/hardwaredb/browser/tests/test_views.py
395deleted file mode 100644
396index 5bc7dfa..0000000
397--- a/lib/lp/hardwaredb/browser/tests/test_views.py
398+++ /dev/null
399@@ -1,45 +0,0 @@
400-# Copyright 2010 Canonical Ltd. This software is licensed under the
401-# GNU Affero General Public License version 3 (see the file LICENSE).
402-
403-"""
404-Run the view tests.
405-"""
406-
407-from __future__ import absolute_import, print_function, unicode_literals
408-
409-import logging
410-import os
411-import unittest
412-
413-from lp.testing.layers import LaunchpadFunctionalLayer
414-from lp.testing.systemdocs import (
415- LayeredDocFileSuite,
416- setUp,
417- tearDown,
418- )
419-
420-
421-here = os.path.dirname(os.path.realpath(__file__))
422-
423-
424-def test_suite():
425- suite = unittest.TestSuite()
426- testsdir = os.path.abspath(here)
427-
428- # Add tests using default setup/teardown
429- filenames = [filename
430- for filename in os.listdir(testsdir)
431- if filename.endswith('.txt')]
432- # Sort the list to give a predictable order.
433- filenames.sort()
434- for filename in filenames:
435- path = filename
436- one_test = LayeredDocFileSuite(
437- path,
438- setUp=lambda test: setUp(test, future=True), tearDown=tearDown,
439- layer=LaunchpadFunctionalLayer,
440- stdout_logging_level=logging.WARNING
441- )
442- suite.addTest(one_test)
443-
444- return suite
445diff --git a/lib/lp/hardwaredb/configure.zcml b/lib/lp/hardwaredb/configure.zcml
446deleted file mode 100644
447index ffefc0c..0000000
448--- a/lib/lp/hardwaredb/configure.zcml
449+++ /dev/null
450@@ -1,193 +0,0 @@
451-<configure
452- xmlns="http://namespaces.zope.org/zope"
453- xmlns:browser="http://namespaces.zope.org/browser"
454- xmlns:i18n="http://namespaces.zope.org/i18n"
455- xmlns:webservice="http://namespaces.canonical.com/webservice"
456- xmlns:xmlrpc="http://namespaces.zope.org/xmlrpc"
457- i18n_domain="launchpad">
458- <include
459- package=".browser"/>
460-
461- <!-- HWDBApplication -->
462-
463- <class
464- class="lp.systemhomes.HWDBApplication">
465- <allow
466- interface="lazr.restful.interfaces.ITopLevelEntryLink"/>
467- <require
468- permission="launchpad.View"
469- interface="lp.hardwaredb.interfaces.hwdb.IHWDBApplication"/>
470- </class>
471- <securedutility
472- class="lp.systemhomes.HWDBApplication"
473- provides="lp.hardwaredb.interfaces.hwdb.IHWDBApplication">
474- <allow
475- interface="lazr.restful.interfaces.ITopLevelEntryLink"/>
476- <require
477- permission="launchpad.View"
478- interface="lp.hardwaredb.interfaces.hwdb.IHWDBApplication"/>
479- </securedutility>
480- <class
481- class="lp.hardwaredb.model.hwdb.HWSubmission">
482- <require
483- permission="launchpad.View"
484- interface="lp.hardwaredb.interfaces.hwdb.IHWSubmission"
485- attributes="
486- id"/>
487- <require
488- permission="launchpad.Edit"
489- set_attributes="status"/>
490- </class>
491- <securedutility
492- class="lp.hardwaredb.model.hwdb.HWSubmissionSet"
493- provides="lp.hardwaredb.interfaces.hwdb.IHWSubmissionSet">
494- <allow
495- interface="lp.hardwaredb.interfaces.hwdb.IHWSubmissionSet"/>
496- </securedutility>
497- <class
498- class="lp.hardwaredb.model.hwdb.HWSystemFingerprint">
499- <allow
500- interface="lp.hardwaredb.interfaces.hwdb.IHWSystemFingerprint"/>
501- </class>
502- <securedutility
503- class="lp.hardwaredb.model.hwdb.HWSystemFingerprintSet"
504- provides="lp.hardwaredb.interfaces.hwdb.IHWSystemFingerprintSet">
505- <allow
506- interface="lp.hardwaredb.interfaces.hwdb.IHWSystemFingerprintSet"/>
507- </securedutility>
508- <class
509- class="lp.hardwaredb.browser.hwdb.HWDBFingerprintSetView">
510- <allow
511- interface="zope.publisher.interfaces.browser.IBrowserPublisher"/>
512- <allow
513- attributes="
514- __call__"/>
515- </class>
516- <class
517- class="lp.hardwaredb.model.hwdb.HWVendorName">
518- <allow
519- interface="lp.hardwaredb.interfaces.hwdb.IHWVendorName"/>
520- <allow
521- attributes="
522- id"/>
523- </class>
524- <securedutility
525- class="lp.hardwaredb.model.hwdb.HWVendorNameSet"
526- provides="lp.hardwaredb.interfaces.hwdb.IHWVendorNameSet">
527- <allow
528- interface="lp.hardwaredb.interfaces.hwdb.IHWVendorNameSet"/>
529- </securedutility>
530- <class
531- class="lp.hardwaredb.model.hwdb.HWVendorID">
532- <require
533- permission="launchpad.View"
534- interface="lp.hardwaredb.interfaces.hwdb.IHWVendorID"/>
535- </class>
536- <securedutility
537- class="lp.hardwaredb.model.hwdb.HWVendorIDSet"
538- provides="lp.hardwaredb.interfaces.hwdb.IHWVendorIDSet">
539- <allow
540- interface="lp.hardwaredb.interfaces.hwdb.IHWVendorIDSet"/>
541- </securedutility>
542- <class
543- class="lp.hardwaredb.model.hwdb.HWDevice">
544- <require
545- permission="launchpad.View"
546- interface="lp.hardwaredb.interfaces.hwdb.IHWDevice"/>
547- </class>
548- <securedutility
549- class="lp.hardwaredb.model.hwdb.HWDeviceSet"
550- provides="lp.hardwaredb.interfaces.hwdb.IHWDeviceSet">
551- <allow
552- interface="lp.hardwaredb.interfaces.hwdb.IHWDeviceSet"/>
553- </securedutility>
554- <class
555- class="lp.hardwaredb.model.hwdb.HWDeviceNameVariant">
556- <allow
557- interface="lp.hardwaredb.interfaces.hwdb.IHWDeviceNameVariant"/>
558- </class>
559- <securedutility
560- class="lp.hardwaredb.model.hwdb.HWDeviceNameVariantSet"
561- provides="lp.hardwaredb.interfaces.hwdb.IHWDeviceNameVariantSet">
562- <allow
563- interface="lp.hardwaredb.interfaces.hwdb.IHWDeviceNameVariantSet"/>
564- </securedutility>
565- <class
566- class="lp.hardwaredb.model.hwdb.HWDriver">
567- <require
568- permission="launchpad.View"
569- interface="lp.hardwaredb.interfaces.hwdb.IHWDriver"/>
570- </class>
571- <securedutility
572- class="lp.hardwaredb.model.hwdb.HWDriverSet"
573- provides="lp.hardwaredb.interfaces.hwdb.IHWDriverSet">
574- <allow
575- interface="lp.hardwaredb.interfaces.hwdb.IHWDriverSet"/>
576- </securedutility>
577- <class
578- class="lp.hardwaredb.model.hwdb.HWDriverName">
579- <require
580- permission="launchpad.View"
581- interface="lp.hardwaredb.interfaces.hwdb.IHWDriverName"/>
582- </class>
583- <class
584- class="lp.hardwaredb.model.hwdb.HWDriverPackageName">
585- <require
586- permission="launchpad.View"
587- interface="lp.hardwaredb.interfaces.hwdb.IHWDriverPackageName"/>
588- </class>
589- <class
590- class="lp.hardwaredb.model.hwdb.HWDeviceDriverLink">
591- <allow
592- interface="lp.hardwaredb.interfaces.hwdb.IHWDeviceDriverLink"/>
593- <allow
594- attributes="
595- id"/>
596- </class>
597- <securedutility
598- class="lp.hardwaredb.model.hwdb.HWDeviceDriverLinkSet"
599- provides="lp.hardwaredb.interfaces.hwdb.IHWDeviceDriverLinkSet">
600- <allow
601- interface="lp.hardwaredb.interfaces.hwdb.IHWDeviceDriverLinkSet"/>
602- </securedutility>
603- <class
604- class="lp.hardwaredb.model.hwdb.HWDeviceClass">
605- <require
606- permission="launchpad.View"
607- interface="lp.hardwaredb.interfaces.hwdb.IHWDeviceClass"/>
608- </class>
609- <securedutility
610- class="lp.hardwaredb.model.hwdb.HWDeviceClassSet"
611- provides="lp.hardwaredb.interfaces.hwdb.IHWDeviceClassSet">
612- <allow
613- interface="lp.hardwaredb.interfaces.hwdb.IHWDeviceClassSet"/>
614- </securedutility>
615- <class
616- class="lp.hardwaredb.model.hwdb.HWSubmissionDevice">
617- <require
618- permission="launchpad.View"
619- interface="lp.hardwaredb.interfaces.hwdb.IHWSubmissionDevice"/>
620- </class>
621- <securedutility
622- class="lp.hardwaredb.model.hwdb.HWSubmissionDeviceSet"
623- provides="lp.hardwaredb.interfaces.hwdb.IHWSubmissionDeviceSet">
624- <allow
625- interface="lp.hardwaredb.interfaces.hwdb.IHWSubmissionDeviceSet"/>
626- </securedutility>
627- <class
628- class="lp.hardwaredb.model.hwdb.HWSubmissionBug">
629- <allow
630- interface="lp.hardwaredb.interfaces.hwdb.IHWSubmissionBug"/>
631- <allow
632- attributes="
633- id"/>
634- </class>
635- <securedutility
636- class="lp.hardwaredb.model.hwdb.HWSubmissionBugSet"
637- provides="lp.hardwaredb.interfaces.hwdb.IHWSubmissionBugSet">
638- <allow
639- interface="lp.hardwaredb.interfaces.hwdb.IHWSubmissionBugSet"/>
640- </securedutility>
641-
642- <webservice:register module="lp.hardwaredb.interfaces.webservice" />
643-</configure>
644diff --git a/lib/lp/hardwaredb/doc/__init__.py b/lib/lp/hardwaredb/doc/__init__.py
645deleted file mode 100644
646index e69de29..0000000
647--- a/lib/lp/hardwaredb/doc/__init__.py
648+++ /dev/null
649diff --git a/lib/lp/hardwaredb/doc/hwdb-access.txt b/lib/lp/hardwaredb/doc/hwdb-access.txt
650deleted file mode 100644
651index 47c17f9..0000000
652--- a/lib/lp/hardwaredb/doc/hwdb-access.txt
653+++ /dev/null
654@@ -1,131 +0,0 @@
655-Access to HWDB tables
656-=====================
657-
658-The access to most HWDB tables is restricted to members of the team
659-"canonical".
660-
661- >>> from lp.registry.interfaces.person import IPersonSet
662- >>> hwdb_team = getUtility(IPersonSet).getByName('hwdb-team')
663- >>> no_priv = getUtility(IPersonSet).getByName('no-priv')
664- >>> no_priv.inTeam(hwdb_team)
665- False
666- >>> sample_person = getUtility(IPersonSet).getByName('name12')
667- >>> sample_person.inTeam(hwdb_team)
668- True
669-
670- >>> from zope.security.interfaces import Unauthorized
671- >>> def check_authorized_for(obj, attribute, person_name_or_address):
672- ... login(person_name_or_address)
673- ... has_access = True
674- ... try:
675- ... getattr(obj, attribute)
676- ... except Unauthorized:
677- ... has_access = False
678- ... print("Access for %s denied" % person_name_or_address)
679- ... if has_access:
680- ... print("Access for %s allowed" % person_name_or_address)
681- ... logout()
682-
683- >>> def check_authorized_only_for_hwdb_team(obj, attribute):
684- ... check_authorized_for(obj, attribute, ANONYMOUS)
685- ... check_authorized_for(obj, attribute, 'no-priv@canonical.com')
686- ... check_authorized_for(obj, attribute, 'test@canonical.com')
687-
688-HWDriver
689---------
690-
691- >>> from lp.hardwaredb.interfaces.hwdb import IHWDriverSet
692- >>> login('test@canonical.com')
693- >>> driver = getUtility(IHWDriverSet).search(name='sd')[0]
694- >>> check_authorized_only_for_hwdb_team(driver, 'name')
695- Access for launchpad.anonymous denied
696- Access for no-priv@canonical.com denied
697- Access for test@canonical.com allowed
698-
699-
700-HWDriverName
701-------------
702-
703- >>> login('test@canonical.com')
704- >>> driver_name = getUtility(IHWDriverSet).all_driver_names()[0]
705- >>> check_authorized_only_for_hwdb_team(driver_name, 'name')
706- Access for launchpad.anonymous denied
707- Access for no-priv@canonical.com denied
708- Access for test@canonical.com allowed
709-
710-
711-HWDriverPackageName
712--------------------
713-
714- >>> login('test@canonical.com')
715- >>> package_name = getUtility(IHWDriverSet).all_package_names()[0]
716- >>> logout()
717- >>> check_authorized_only_for_hwdb_team(package_name, 'package_name')
718- Access for launchpad.anonymous denied
719- Access for no-priv@canonical.com denied
720- Access for test@canonical.com allowed
721-
722-
723-HWVendorID
724-----------
725-
726- >>> from lp.hardwaredb.interfaces.hwdb import HWBus, IHWVendorIDSet
727- >>> login('test@canonical.com')
728- >>> vendor_id = getUtility(IHWVendorIDSet).getByBusAndVendorID(
729- ... HWBus.PCI, '0x10de')
730- >>> check_authorized_only_for_hwdb_team(vendor_id, 'bus')
731- Access for launchpad.anonymous denied
732- Access for no-priv@canonical.com denied
733- Access for test@canonical.com allowed
734-
735-
736-HWDevice
737---------
738-
739- >>> from lp.hardwaredb.interfaces.hwdb import IHWDeviceSet
740- >>> login('test@canonical.com')
741- >>> device = getUtility(IHWDeviceSet).getByDeviceID(
742- ... HWBus.PCI, '0x10de', '0x0455')
743- >>> check_authorized_only_for_hwdb_team(device, 'name')
744- Access for launchpad.anonymous denied
745- Access for no-priv@canonical.com denied
746- Access for test@canonical.com allowed
747-
748-
749-HWDeviceClass
750--------------
751-
752-The access to most HWDB tables is restricted to members of the team
753-"canonical". the current user, Sample Person, is a member of this team,
754-No-Priv is not (see above).
755-
756- >>> login('test@canonical.com')
757- >>> device_class = device.getOrCreateDeviceClass(12, 3)
758- >>> check_authorized_only_for_hwdb_team(device_class, 'main_class')
759- Access for launchpad.anonymous denied
760- Access for no-priv@canonical.com denied
761- Access for test@canonical.com allowed
762-
763-
764-HWSubmissionDevice
765-------------------
766-
767- >>> from lp.hardwaredb.interfaces.hwdb import IHWSubmissionDeviceSet
768- >>> login('test@canonical.com')
769- >>> submission_device = getUtility(IHWSubmissionDeviceSet).get(1)
770- >>> check_authorized_only_for_hwdb_team(
771- ... submission_device, 'hal_device_id')
772- Access for launchpad.anonymous denied
773- Access for no-priv@canonical.com denied
774- Access for test@canonical.com allowed
775-
776-
777-Methods of IHWDBApplication
778----------------------------
779-
780- >>> from lp.hardwaredb.interfaces.hwdb import IHWDBApplication
781- >>> app = getUtility(IHWDBApplication)
782- >>> check_authorized_only_for_hwdb_team(app, 'numOwnersOfDevice')
783- Access for launchpad.anonymous denied
784- Access for no-priv@canonical.com denied
785- Access for test@canonical.com allowed
786diff --git a/lib/lp/hardwaredb/doc/hwdb-device-tables.txt b/lib/lp/hardwaredb/doc/hwdb-device-tables.txt
787deleted file mode 100644
788index 7b5cb68..0000000
789--- a/lib/lp/hardwaredb/doc/hwdb-device-tables.txt
790+++ /dev/null
791@@ -1,2756 +0,0 @@
792-Hardware Database Device Tables
793-===============================
794-
795-These tables represent devices and complete systems in the database. They
796-allow look up of devices by their bus IDs and by their human readable
797-vendor and product names. They also link devices to drivers.
798-
799-HWVendorName
800-------------
801-
802-HWVendorName is a simple list of vendor names. A new entry is created by
803-IHWVendorNameSet.create().
804-
805- >>> from lp.hardwaredb.interfaces.hwdb import IHWVendorNameSet
806- >>> vendor_name_set = getUtility(IHWVendorNameSet)
807- >>> intel_name = vendor_name_set.create(name='Intel')
808- >>> print(intel_name.name)
809- Intel
810-
811-Each name in the table must be unique. The attempt to create a second
812-row with the same name raises an IntegrityError error.
813-
814- >>> from storm.store import Store
815- >>> store = Store.of(intel_name)
816- >>> from lp.testing.layers import LaunchpadZopelessLayer
817- >>> LaunchpadZopelessLayer.txn.commit()
818- >>> vendor_name_set.create('Intel')
819- <HWVendorName ...
820- >>> store.flush()
821- Traceback (most recent call last):
822- ...
823- IntegrityError: ...
824- <BLANKLINE>
825- >>> LaunchpadZopelessLayer.txn.abort()
826-
827-The database checks the uniqueness of the lower-case name, hence we
828-cannot insert another name like "INTEL" or "intel".
829-
830- >>> vendor_name_set.create('INTEL')
831- <HWVendorName ...
832- >>> store.flush()
833- Traceback (most recent call last):
834- ...
835- IntegrityError: ...
836- <BLANKLINE>
837- >>> LaunchpadZopelessLayer.txn.abort()
838-
839- >>> vendor_name_set.create('intel')
840- <HWVendorName ...
841- >>> store.flush()
842- Traceback (most recent call last):
843- ...
844- IntegrityError: ...
845- <BLANKLINE>
846- >>> LaunchpadZopelessLayer.txn.abort()
847-
848-The lower-case uniqueness constraint works for latin characters with
849-diacritical marks too...
850-
851- >>> a_umlaut_upper = u'\N{LATIN CAPITAL LETTER A WITH DIAERESIS}'
852- >>> a_umlaut_lower = u'\N{LATIN SMALL LETTER A WITH DIAERESIS}'
853- >>> a_umlaut_name = vendor_name_set.create(name=a_umlaut_upper)
854- >>> LaunchpadZopelessLayer.txn.commit()
855- >>> print(repr(a_umlaut_name.name))
856- u'\xc4'
857-
858- >>> vendor_name_set.create(name=a_umlaut_lower)
859- <HWVendorName ...
860- >>> store.flush()
861- Traceback (most recent call last):
862- ...
863- IntegrityError: ...
864- <BLANKLINE>
865- >>> LaunchpadZopelessLayer.txn.abort()
866-
867-...as well as for Cyrillic characters...
868-
869- >>> cyrillic_de_upper = u'\N{CYRILLIC CAPITAL LETTER DE}'
870- >>> cyrillic_de_lower = u'\N{CYRILLIC SMALL LETTER DE}'
871- >>> cyrillic_de_name = vendor_name_set.create(name=cyrillic_de_upper)
872- >>> print(repr(cyrillic_de_name.name))
873- u'\u0414'
874-
875- >>> vendor_name_set.create(name=cyrillic_de_lower)
876- <HWVendorName ...
877- >>> store.flush()
878- Traceback (most recent call last):
879- ...
880- IntegrityError: ...
881- <BLANKLINE>
882- >>> LaunchpadZopelessLayer.txn.abort()
883-
884-...and Greek characters.
885-
886- >>> alpha_upper = u'\N{GREEK CAPITAL LETTER ALPHA}'
887- >>> alpha_lower = u'\N{GREEK SMALL LETTER ALPHA}'
888- >>> cyrillic_de_name = vendor_name_set.create(name=alpha_upper)
889- >>> print(repr(cyrillic_de_name.name))
890- u'\u0391'
891-
892- >>> vendor_name_set.create(name=alpha_lower)
893- <HWVendorName ...
894- >>> store.flush()
895- Traceback (most recent call last):
896- ...
897- IntegrityError: ...
898- <BLANKLINE>
899- >>> LaunchpadZopelessLayer.txn.abort()
900-
901-Existing IHWVendorName records are retrieved by IHWVendorName.getByName().
902-
903- >>> intel_name = vendor_name_set.getByName('Intel')
904- >>> print(intel_name.name)
905- Intel
906-
907-The capitalization of the name does not metter.
908-
909- >>> intel_name = vendor_name_set.getByName('INTEL')
910- >>> print(intel_name.name)
911- Intel
912-
913- >>> intel_name = vendor_name_set.getByName('intel')
914- >>> print(intel_name.name)
915- Intel
916-
917- >>> umlaut_name = vendor_name_set.getByName(
918- ... u'\N{LATIN CAPITAL LETTER A WITH DIAERESIS}')
919- >>> print(repr(umlaut_name.name))
920- u'\xc4'
921-
922- >>> umlaut_name = vendor_name_set.getByName(
923- ... u'\N{LATIN SMALL LETTER A WITH DIAERESIS}')
924- >>> print(repr(umlaut_name.name))
925- u'\xc4'
926-
927-If no record matching the given name exists, IHWVendorName.getByName()
928-returns None.
929-
930- >>> print(vendor_name_set.getByName('Babbage Computers'))
931- None
932-
933-
934-HWVendorID
935-----------
936-
937-HWVendorID associates a bus, as enumerated by HWBus, with a bus-specific
938-vendor ID and a vendor name. We store the IDs as a string, because not all
939-all busses use numeric IDs. Numbers are represented as strings with
940-hexadecimal digits, prepended by '0x'.
941-
942- >>> from lp.hardwaredb.interfaces.hwdb import HWBus, IHWVendorIDSet
943- >>> vendor_id_set = getUtility(IHWVendorIDSet)
944- >>> intel_pci_id = vendor_id_set.create(bus=HWBus.PCI,
945- ... vendor_id='0x8086',
946- ... vendor_name=intel_name)
947- >>> print(intel_pci_id.bus.title, intel_pci_id.vendor_id_for_bus)
948- PCI 0x8086
949- >>> print(intel_pci_id.vendor_name.name)
950- Intel
951-
952-The tuple (bus, vendor id, vendor name) must be unique.
953-
954- >>> LaunchpadZopelessLayer.txn.commit()
955- >>> vendor_id_set.create(bus=HWBus.PCI,
956- ... vendor_id='0x8086',
957- ... vendor_name=intel_name)
958- <HWVendorID ...
959- >>> store.flush()
960- Traceback (most recent call last):
961- ...
962- IntegrityError: ...
963- <BLANKLINE>
964- >>> LaunchpadZopelessLayer.txn.abort()
965-
966-We store the (bus specific) vendor ID as a string, but several busses
967-have stricter constraints for their vendor ID. The PCI and USB busses use
968-16 bit integers, the IEEE1394 bus uses 24 bit integers, the SCSI bus
969-uses ASCII strings with exactly 8 characters. The constructor of
970-HWVendorID ensures that the vendor IDs match the bus-specific format.
971-
972-USB, PCI and PCCard IDs are represented as strings with a four-digit
973-hexadecimal number, prefixed by '0x'; the digits a..f must be lower
974-cases characters. Other ID values raise a ParameterError.
975-
976-The characters a..f are accepted as digits.
977-
978- >>> another_pci_vendor_id = vendor_id_set.create(bus=HWBus.PCI,
979- ... vendor_id='0x10ae',
980- ... vendor_name=intel_name)
981- >>> print(another_pci_vendor_id.bus.title)
982- PCI
983- >>> print(another_pci_vendor_id.vendor_id_for_bus)
984- 0x10ae
985- >>> print(another_pci_vendor_id.vendor_name.name)
986- Intel
987-
988- >>> another_pci_vendor_id = vendor_id_set.create(bus=HWBus.PCCARD,
989- ... vendor_id='0x10ae',
990- ... vendor_name=intel_name)
991- >>> print(another_pci_vendor_id.bus.title)
992- PC Card (32 bit)
993- >>> print(another_pci_vendor_id.vendor_id_for_bus)
994- 0x10ae
995- >>> print(another_pci_vendor_id.vendor_name.name)
996- Intel
997-
998- >>> another_usb_vendor_id = vendor_id_set.create(bus=HWBus.USB,
999- ... vendor_id='0x10ae',
1000- ... vendor_name=intel_name)
1001- >>> print(another_usb_vendor_id.bus.title)
1002- USB
1003- >>> print(another_usb_vendor_id.vendor_id_for_bus)
1004- 0x10ae
1005- >>> print(another_usb_vendor_id.vendor_name.name)
1006- Intel
1007-
1008-A..F is rejected.
1009-
1010- >>> vendor_id_set.create(bus=HWBus.PCI,
1011- ... vendor_id='0x10AE',
1012- ... vendor_name=intel_name)
1013- Traceback (most recent call last):
1014- ...
1015- ParameterError: u'0x10AE' is not a valid vendor ID for PCI
1016- >>> from storm.tracer import debug; debug(True)
1017- >>> store.flush()
1018- >>> debug(False)
1019-
1020- >>> vendor_id_set.create(bus=HWBus.PCCARD,
1021- ... vendor_id='0x10AE',
1022- ... vendor_name=intel_name)
1023- Traceback (most recent call last):
1024- ...
1025- ParameterError: u'0x10AE' is not a valid vendor ID for PC Card (32 bit)
1026-
1027- >>> vendor_id_set.create(bus=HWBus.USB,
1028- ... vendor_id='0x10AE',
1029- ... vendor_name=intel_name)
1030- Traceback (most recent call last):
1031- ...
1032- ParameterError: u'0x10AE' is not a valid vendor ID for USB
1033-
1034-The ID must have the prefix "0x".
1035-
1036- >>> vendor_id_set.create(bus=HWBus.PCI,
1037- ... vendor_id='8086',
1038- ... vendor_name=intel_name)
1039- Traceback (most recent call last):
1040- ...
1041- ParameterError: u'8086' is not a valid vendor ID for PCI
1042-
1043- >>> vendor_id_set.create(bus=HWBus.PCCARD,
1044- ... vendor_id='8086',
1045- ... vendor_name=intel_name)
1046- Traceback (most recent call last):
1047- ...
1048- ParameterError: u'8086' is not a valid vendor ID for PC Card (32 bit)
1049-
1050- >>> vendor_id_set.create(bus=HWBus.USB,
1051- ... vendor_id='8086',
1052- ... vendor_name=intel_name)
1053- Traceback (most recent call last):
1054- ...
1055- ParameterError: u'8086' is not a valid vendor ID for USB
1056-
1057-The number must have four digits.
1058-
1059- >>> vendor_id_set.create(bus=HWBus.PCI,
1060- ... vendor_id='0x123',
1061- ... vendor_name=intel_name)
1062- Traceback (most recent call last):
1063- ...
1064- ParameterError: u'0x123' is not a valid vendor ID for PCI
1065-
1066- >>> vendor_id_set.create(bus=HWBus.PCCARD,
1067- ... vendor_id='0x123',
1068- ... vendor_name=intel_name)
1069- Traceback (most recent call last):
1070- ...
1071- ParameterError: u'0x123' is not a valid vendor ID for PC Card (32 bit)
1072-
1073- >>> vendor_id_set.create(bus=HWBus.USB,
1074- ... vendor_id='0x123',
1075- ... vendor_name=intel_name)
1076- Traceback (most recent call last):
1077- ...
1078- ParameterError: u'0x123' is not a valid vendor ID for USB
1079-
1080- >>> vendor_id_set.create(bus=HWBus.PCI,
1081- ... vendor_id='0x12345',
1082- ... vendor_name=intel_name)
1083- Traceback (most recent call last):
1084- ...
1085- ParameterError: u'0x12345' is not a valid vendor ID for PCI
1086-
1087- >>> vendor_id_set.create(bus=HWBus.PCCARD,
1088- ... vendor_id='0x12345',
1089- ... vendor_name=intel_name)
1090- Traceback (most recent call last):
1091- ...
1092- ParameterError: u'0x12345' is not a valid vendor ID for PC Card (32 bit)
1093-
1094- >>> vendor_id_set.create(bus=HWBus.USB,
1095- ... vendor_id='0x12345',
1096- ... vendor_name=intel_name)
1097- Traceback (most recent call last):
1098- ...
1099- ParameterError: u'0x12345' is not a valid vendor ID for USB
1100-
1101-Only hex digits are allowed.
1102-
1103- >>> vendor_id_set.create(bus=HWBus.PCI,
1104- ... vendor_id='0xblah',
1105- ... vendor_name=intel_name)
1106- Traceback (most recent call last):
1107- ...
1108- ParameterError: u'0xblah' is not a valid vendor ID for PCI
1109-
1110- >>> vendor_id_set.create(bus=HWBus.PCCARD,
1111- ... vendor_id='0xblah',
1112- ... vendor_name=intel_name)
1113- Traceback (most recent call last):
1114- ...
1115- ParameterError: u'0xblah' is not a valid vendor ID for PC Card (32 bit)
1116-
1117- >>> vendor_id_set.create(bus=HWBus.USB,
1118- ... vendor_id='0xblah',
1119- ... vendor_name=intel_name)
1120- Traceback (most recent call last):
1121- ...
1122- ParameterError: u'0xblah' is not a valid vendor ID for USB
1123-
1124-IEEE1394 IDs are represented as strings with a six-digit hexadecimal
1125-number, prefixed by '0x'; the digits a..f must be lower cases characters.
1126-Other ID values raise a value error.
1127-
1128- >>> vendor_id_1394 = vendor_id_set.create(bus=HWBus.IEEE1394,
1129- ... vendor_id='0x0010e0',
1130- ... vendor_name=intel_name)
1131- >>> print(vendor_id_1394.bus.title)
1132- IEEE1394
1133- >>> print(vendor_id_1394.vendor_id_for_bus)
1134- 0x0010e0
1135- >>> print(vendor_id_1394.vendor_name.name)
1136- Intel
1137-
1138-A..F is rejected.
1139-
1140- >>> vendor_id_set.create(bus=HWBus.IEEE1394,
1141- ... vendor_id='0x0010E0',
1142- ... vendor_name=intel_name)
1143- Traceback (most recent call last):
1144- ...
1145- ParameterError: u'0x0010E0' is not a valid vendor ID for IEEE1394
1146-
1147-The ID must have the prefix "0x".
1148-
1149- >>> vendor_id_set.create(bus=HWBus.IEEE1394,
1150- ... vendor_id='0010E0',
1151- ... vendor_name=intel_name)
1152- Traceback (most recent call last):
1153- ...
1154- ParameterError: u'0010E0' is not a valid vendor ID for IEEE1394
1155-
1156-The number must have six digits.
1157-
1158- >>> vendor_id_set.create(bus=HWBus.IEEE1394,
1159- ... vendor_id='0x12345',
1160- ... vendor_name=intel_name)
1161- Traceback (most recent call last):
1162- ...
1163- ParameterError: u'0x12345' is not a valid vendor ID for IEEE1394
1164-
1165- >>> vendor_id_set.create(bus=HWBus.IEEE1394,
1166- ... vendor_id='0x1234567',
1167- ... vendor_name=intel_name)
1168- Traceback (most recent call last):
1169- ...
1170- ParameterError: u'0x1234567' is not a valid vendor ID for IEEE1394
1171-
1172-Only hex digits are allowed.
1173-
1174- >>> vendor_id_set.create(bus=HWBus.IEEE1394,
1175- ... vendor_id='0xfoobar',
1176- ... vendor_name=intel_name)
1177- Traceback (most recent call last):
1178- ...
1179- ParameterError: u'0xfoobar' is not a valid vendor ID for IEEE1394
1180-
1181-SCSI vendor IDs are ASCII strings with exactly eight characters.
1182-
1183- >>> intel_scsi_id = vendor_id_set.create(bus=HWBus.SCSI,
1184- ... vendor_id='INTEL ',
1185- ... vendor_name=intel_name)
1186- >>> print(intel_scsi_id.bus.title)
1187- SCSI
1188- >>> intel_scsi_id.vendor_id_for_bus
1189- u'INTEL '
1190- >>> print(intel_scsi_id.vendor_name.name)
1191- Intel
1192-
1193-Strings with less than eight characters are not allowed as SCSI vendor IDs...
1194-
1195- >>> vendor_id_set.create(bus=HWBus.SCSI,
1196- ... vendor_id='1234567',
1197- ... vendor_name=intel_name)
1198- Traceback (most recent call last):
1199- ...
1200- ParameterError: u'1234567' is not a valid vendor ID for SCSI
1201-
1202-...as well as strings with more than eight characters.
1203-
1204- >>> vendor_id_set.create(bus=HWBus.SCSI,
1205- ... vendor_id='123456789',
1206- ... vendor_name=intel_name)
1207- Traceback (most recent call last):
1208- ...
1209- ParameterError: u'123456789' is not a valid vendor ID for SCSI
1210-
1211-HWVendorIDSet.getByBusAndVendorID() is used to look up a HWVendorID record.
1212-
1213- >>> vendor_id = vendor_id_set.getByBusAndVendorID(bus=HWBus.PCI,
1214- ... vendor_id='0x8086')
1215- >>> print(vendor_id.bus.title)
1216- PCI
1217- >>> print(vendor_id.vendor_name.name)
1218- Intel
1219-
1220-If no record exists for the given bus and vendor ID,
1221-HWVendorIDSet.getByBusAndVendorID() returns None.
1222-
1223- >>> vendor_id = vendor_id_set.getByBusAndVendorID(bus=HWBus.PCI,
1224- ... vendor_id='0xffff')
1225- >>> print(vendor_id)
1226- None
1227-
1228-HWVendorIDSet.getByBusAndVendorID() performs the same validity tests of
1229-the vendor ID as HWVendorSet.create(): The vendor ID passed to
1230-HWVendorIDSet.getByBusAndVendorID() must be a valid ID for the given bus.
1231-
1232- >>> vendor_id_set.getByBusAndVendorID(bus=HWBus.PCI, vendor_id='8086')
1233- Traceback (most recent call last):
1234- ...
1235- ParameterError: u'8086' is not a valid vendor ID for PCI
1236-
1237-HWVendorIDSet.get() returns the HWVendorID record with the given ID...
1238-
1239- >>> vendor_id = vendor_id_set.get(1)
1240- >>> print(vendor_id.bus.name, vendor_id.vendor_id_for_bus)
1241- SYSTEM MSI
1242-
1243-...or None, if no such record exists.
1244-
1245- >>> print(vendor_id_set.get(1000000))
1246- None
1247-
1248-HWVendorIDSet.idsForBus() returns all known HWVendorIDs for a given bus.
1249-
1250- >>> for vendor_id in vendor_id_set.idsForBus(HWBus.PCI):
1251- ... print(vendor_id.bus.name, vendor_id.vendor_id_for_bus)
1252- PCI 0x10ae
1253- PCI 0x10de
1254- PCI 0x8086
1255-
1256-
1257-HWDevice
1258---------
1259-
1260-A HWDevice instance stores core data about a hardware device: The bus
1261-it can connect to, the vendor ID, the product ID, the human readable
1262-product name, variant (see below), and the number of submissions with
1263-a device.
1264-
1265-Aside from "real" devices like keyboards, mice, hard disks, PCI cards,
1266-i.e., "thingies" one can connect to and remove from a computer, we also
1267-store data about "systems" (computers) and "components" in the HWDevice
1268-table. A component is a part that is "permanently built" into a system,
1269-like a hard disk controller that is soldered onto the main board.
1270-
1271-A new device record is created by IHWDeviceSet.create.
1272-
1273- >>> from lp.hardwaredb.interfaces.hwdb import IHWDeviceSet
1274- >>> device_set = getUtility(IHWDeviceSet)
1275- >>> product_name='82801GBM/GHM (ICH7 Family) USB2 EHCI Controller'
1276- >>> usb_controller = device_set.create(bus=HWBus.PCI,
1277- ... vendor_id='0x8086',
1278- ... product_id='0x27cc',
1279- ... product_name=product_name)
1280-
1281-Bus and vendor ID are not directly stored as HWDevice attributes; we can
1282-access them, as well as the vendor name, either via the attribute
1283-bus_vendor, which references HWVendorID...
1284-
1285- >>> print(usb_controller.bus_vendor.bus.title)
1286- PCI
1287- >>> print(usb_controller.bus_vendor.vendor_id_for_bus)
1288- 0x8086
1289- >>> print(usb_controller.bus_vendor.vendor_name.name)
1290- Intel
1291-
1292-...or via the (read-only) HWDevice properties bus, vendor_id, vendor_name.
1293-
1294- >>> print(usb_controller.bus.title)
1295- PCI
1296- >>> print(usb_controller.vendor_id)
1297- 0x8086
1298- >>> print(usb_controller.vendor_name)
1299- Intel
1300-
1301-Other attributes stored in HWDevice are the product ID, the product name,
1302-the product variant and submissions. submissions is a counter of the
1303-number of submissions with this device.
1304-
1305- >>> print(usb_controller.bus_product_id)
1306- 0x27cc
1307- >>> print(usb_controller.name)
1308- 82801GBM/GHM (ICH7 Family) USB2 EHCI Controller
1309- >>> print(usb_controller.variant)
1310- None
1311- >>> print(usb_controller.submissions)
1312- 0
1313-
1314-Like vendor IDs, product IDs of some busses have certain constraints.
1315-USB and PCI product IDs are 16 bit integers; SCSI IDs are strings
1316-with 16 characters. (Note that the IEEE1394 does _not_ define a product
1317-ID.)
1318-
1319-USB, PCI and PCCard IDs are represented as strings with a four-digit
1320-hexadecimal number, prefixed by '0x'; the digits a..f must be lower
1321-cases characters. Other ID values raise a ParameterError.
1322-
1323- >>> another_pci_product = device_set.create(bus=HWBus.PCI,
1324- ... vendor_id='0x8086',
1325- ... product_id='0xabcd',
1326- ... product_name='A PCI card')
1327- >>> print(another_pci_product.bus_product_id)
1328- 0xabcd
1329-
1330- >>> another_pci_product = device_set.create(bus=HWBus.PCCARD,
1331- ... vendor_id='0x8086',
1332- ... product_id='0xabcd',
1333- ... product_name='A PC Card')
1334- >>> print(another_pci_product.bus_product_id)
1335- 0xabcd
1336-
1337- >>> another_usb_product = device_set.create(bus=HWBus.USB,
1338- ... vendor_id='0x8086',
1339- ... product_id='0xabcd',
1340- ... product_name='A USB device')
1341- >>> print(another_usb_product.bus_product_id)
1342- 0xabcd
1343-
1344-A..F is rejected.
1345-
1346- >>> device_set.create(bus=HWBus.PCI,
1347- ... vendor_id='0x8086',
1348- ... product_id='0xABCD',
1349- ... product_name='A PCI card')
1350- Traceback (most recent call last):
1351- ...
1352- ParameterError: u'0xABCD' is not a valid product ID for PCI
1353-
1354- >>> device_set.create(bus=HWBus.PCCARD,
1355- ... vendor_id='0x8086',
1356- ... product_id='0xABCD',
1357- ... product_name='A PC Card')
1358- Traceback (most recent call last):
1359- ...
1360- ParameterError: u'0xABCD' is not a valid product ID for PC Card (32 bit)
1361-
1362- >>> device_set.create(bus=HWBus.USB,
1363- ... vendor_id='0x8086',
1364- ... product_id='0xABCD',
1365- ... product_name='A USB device')
1366- Traceback (most recent call last):
1367- ...
1368- ParameterError: u'0xABCD' is not a valid product ID for USB
1369-
1370-The ID must have the prefix "0x".
1371-
1372- >>> device_set.create(bus=HWBus.PCI,
1373- ... vendor_id='0x8086',
1374- ... product_id='1234',
1375- ... product_name='A PCI card')
1376- Traceback (most recent call last):
1377- ...
1378- ParameterError: u'1234' is not a valid product ID for PCI
1379-
1380- >>> device_set.create(bus=HWBus.PCCARD,
1381- ... vendor_id='0x8086',
1382- ... product_id='1234',
1383- ... product_name='A PC Card')
1384- Traceback (most recent call last):
1385- ...
1386- ParameterError: u'1234' is not a valid product ID for PC Card (32 bit)
1387-
1388- >>> device_set.create(bus=HWBus.USB,
1389- ... vendor_id='0x8086',
1390- ... product_id='1234',
1391- ... product_name='A USB device')
1392- Traceback (most recent call last):
1393- ...
1394- ParameterError: u'1234' is not a valid product ID for USB
1395-
1396-The number must have four digits.
1397-
1398- >>> device_set.create(bus=HWBus.PCI,
1399- ... vendor_id='0x8086',
1400- ... product_id='0x123',
1401- ... product_name='A PCI card')
1402- Traceback (most recent call last):
1403- ...
1404- ParameterError: u'0x123' is not a valid product ID for PCI
1405-
1406- >>> device_set.create(bus=HWBus.PCCARD,
1407- ... vendor_id='0x8086',
1408- ... product_id='0x123',
1409- ... product_name='A PC Card')
1410- Traceback (most recent call last):
1411- ...
1412- ParameterError: u'0x123' is not a valid product ID for PC Card (32 bit)
1413-
1414- >>> device_set.create(bus=HWBus.USB,
1415- ... vendor_id='0x8086',
1416- ... product_id='0x123',
1417- ... product_name='A USB device')
1418- Traceback (most recent call last):
1419- ...
1420- ParameterError: u'0x123' is not a valid product ID for USB
1421-
1422- >>> device_set.create(bus=HWBus.PCI,
1423- ... vendor_id='0x8086',
1424- ... product_id='0x12345',
1425- ... product_name='A PCI card')
1426- Traceback (most recent call last):
1427- ...
1428- ParameterError: u'0x12345' is not a valid product ID for PCI
1429-
1430- >>> device_set.create(bus=HWBus.PCCARD,
1431- ... vendor_id='0x8086',
1432- ... product_id='0x12345',
1433- ... product_name='A PC Card')
1434- Traceback (most recent call last):
1435- ...
1436- ParameterError: u'0x12345' is not a valid product ID for PC Card (32 bit)
1437-
1438- >>> device_set.create(bus=HWBus.USB,
1439- ... vendor_id='0x8086',
1440- ... product_id='0x12345',
1441- ... product_name='A USB device')
1442- Traceback (most recent call last):
1443- ...
1444- ParameterError: u'0x12345' is not a valid product ID for USB
1445-
1446-Only hex digits are allowed.
1447-
1448- >>> device_set.create(bus=HWBus.PCI,
1449- ... vendor_id='0x8086',
1450- ... product_id='0xblah',
1451- ... product_name='A PCI card')
1452- Traceback (most recent call last):
1453- ...
1454- ParameterError: u'0xblah' is not a valid product ID for PCI
1455-
1456- >>> device_set.create(bus=HWBus.PCCARD,
1457- ... vendor_id='0x8086',
1458- ... product_id='0xblah',
1459- ... product_name='A PC Card')
1460- Traceback (most recent call last):
1461- ...
1462- ParameterError: u'0xblah' is not a valid product ID for PC Card (32 bit)
1463-
1464- >>> device_set.create(bus=HWBus.USB,
1465- ... vendor_id='0x8086',
1466- ... product_id='0xblah',
1467- ... product_name='A USB device')
1468- Traceback (most recent call last):
1469- ...
1470- ParameterError: u'0xblah' is not a valid product ID for USB
1471-
1472-SCSI product IDs are ASCII strings with 16 characters.
1473-
1474- >>> scsi_device = device_set.create(bus=HWBus.SCSI,
1475- ... vendor_id='INTEL ',
1476- ... product_id='12345678901234 ',
1477- ... product_name='A SCSI device')
1478- >>> scsi_device.bus_product_id
1479- u'12345678901234 '
1480-
1481-Strings with less than 16 characters are not allowed as SCSI product IDs...
1482-
1483- >>> device_set.create(bus=HWBus.SCSI,
1484- ... vendor_id='INTEL ',
1485- ... product_id='123456789012345',
1486- ... product_name='A SCSI device')
1487- Traceback (most recent call last):
1488- ...
1489- ParameterError: u'123456789012345' is not a valid product ID for SCSI
1490-
1491-...as well as strings with more than 16 characters.
1492-
1493- >>> device_set.create(bus=HWBus.SCSI,
1494- ... vendor_id='INTEL ',
1495- ... product_id='12345678901234567',
1496- ... product_name='A SCSI device')
1497- Traceback (most recent call last):
1498- ...
1499- ParameterError: u'12345678901234567' is not a valid product ID for SCSI
1500-
1501-
1502-Unknown Vendor IDs
1503-..................
1504-
1505-If IHWDevice.create is called with a vendor ID that for which there
1506-is no IHWVendorID record, the latter is automatically created. Since
1507-we do not pass the vendor name to IHWDevice.create, this method
1508-cannot set the real vendor name for the new IHWVendorID record.
1509-Instead, the vendor name is set to "Unknown".
1510-
1511-Reason: IHWDevice will be populated with data collected by the
1512-HWDB client, which gets most of the device data from HAL, and HAL
1513-quite often does not know the vendor name. Hence we will populate
1514-and update IHWVendorID from sources like
1515-
1516-http://www.linux-usb.org/usb.ids
1517-http://www.pcidatabase.com/reports.php?type=csv
1518-http://standards.ieee.org/regauth/oui/oui.txt
1519-
1520- >>> new_vendor_device = device_set.create(bus=HWBus.PCI,
1521- ... vendor_id='0x4321',
1522- ... product_id='0x8765',
1523- ... product_name='mind sensor')
1524- >>> print(new_vendor_device.bus_vendor.vendor_name.name)
1525- Unknown
1526-
1527-
1528-Device Variants
1529-...............
1530-
1531-While most devices can be uniquely identified by their vendor and product
1532-IDs, there are some cases, where different devices have identical IDs:
1533-
1534-(a) The IDs are assigned to a USB chipset that is used in different
1535- devices.
1536-(b) A vendor may inadvertently "recycle" a product ID
1537-(c) A chip manufacturer who does not have its own vendor ID may "forge"
1538- the vendor ID.
1539-
1540-A real world example of the first case is the scanner chipset from
1541-Plustek with the USB ID 0x07b3/0x0017. This chipset is used in devices
1542-that differ for example in the maximum scan window size.
1543-
1544-We do not necessarily know in advance that there are different devices
1545-with identical IDs, so we may have a HWDevice record without the variant
1546-attribute set.
1547-
1548- >>> plustek_name = vendor_name_set.create('Plustek')
1549- >>> plustek_usb_id = vendor_id_set.create(bus=HWBus.USB,
1550- ... vendor_id='0x07b3',
1551- ... vendor_name=plustek_name)
1552- >>> some_plustek_scanner = device_set.create(bus=HWBus.USB,
1553- ... vendor_id='0x07b3',
1554- ... product_id='0x0017',
1555- ... product_name='some scanner')
1556- >>> print(some_plustek_scanner.bus_vendor.vendor_id_for_bus)
1557- 0x07b3
1558- >>> print(some_plustek_scanner.bus_vendor.vendor_name.name)
1559- Plustek
1560- >>> print(some_plustek_scanner.name)
1561- some scanner
1562- >>> print(some_plustek_scanner.variant)
1563- None
1564-
1565-Once we know that (bus, vendor ID, product ID) does not uniquely
1566-identify a device, we can disambiguate these devices by creating
1567-IHWDevice records, where the attribute variant is, for example, set
1568-to the product name.
1569-
1570- >>> optic_pro_ut12 = device_set.create(bus=HWBus.USB,
1571- ... vendor_id='0x07b3',
1572- ... product_id='0x0017',
1573- ... variant='OpticPro UT12',
1574- ... product_name='OpticPro UT12')
1575- >>> optic_pro_ut16 = device_set.create(bus=HWBus.USB,
1576- ... vendor_id='0x07b3',
1577- ... product_id='0x0017',
1578- ... variant='OpticPro UT16',
1579- ... product_name='OpticPro UT16')
1580-
1581-For systems, we use HWBus.SYSTEM as the "bus name"; the HAL property
1582-system.vendor is stored as the vendor ID and vendor name, and the HAL
1583-property system.product is stored as the product ID and the product
1584-name.
1585-
1586- >>> hal_vendor_name = 'Tonka'
1587- >>> hal_product_name = 'Tuffbook 2600'
1588- >>> tonka_name = vendor_name_set.create(name=hal_vendor_name)
1589- >>> tonka_system_id = vendor_id_set.create(bus=HWBus.SYSTEM,
1590- ... vendor_id=hal_vendor_name,
1591- ... vendor_name=tonka_name)
1592- >>> tuffbook_2600 = device_set.create(bus=HWBus.SYSTEM,
1593- ... vendor_id=hal_vendor_name,
1594- ... product_id=hal_product_name,
1595- ... product_name=hal_product_name)
1596- >>> print(tuffbook_2600.bus_vendor.bus.title)
1597- System
1598- >>> print(tuffbook_2600.bus_vendor.vendor_id_for_bus)
1599- Tonka
1600- >>> print(tuffbook_2600.bus_vendor.vendor_name.name)
1601- Tonka
1602- >>> print(tuffbook_2600.bus_product_id)
1603- Tuffbook 2600
1604- >>> print(tuffbook_2600.name)
1605- Tuffbook 2600
1606-
1607-The tuple (bus_vendor, bus_product_id, variant) must be unique.
1608-The attempt to create two rows with the same data raises a
1609-IntegrityError error.
1610-
1611- >>> LaunchpadZopelessLayer.txn.commit()
1612- >>> another_scanner = device_set.create(bus=HWBus.USB,
1613- ... vendor_id='0x07b3',
1614- ... product_id='0x0017',
1615- ... product_name='some scanner')
1616- >>> store.flush()
1617- Traceback (most recent call last):
1618- ...
1619- IntegrityError: ...
1620- <BLANKLINE>
1621- >>> LaunchpadZopelessLayer.txn.abort()
1622-
1623- >>> another_scanner = device_set.create(bus=HWBus.USB,
1624- ... vendor_id='0x07b3',
1625- ... product_id='0x0017',
1626- ... variant='OpticPro UT16',
1627- ... product_name='OpticPro UT16')
1628- >>> store.flush()
1629- Traceback (most recent call last):
1630- ...
1631- IntegrityError: ...
1632- <BLANKLINE>
1633- >>> LaunchpadZopelessLayer.txn.abort()
1634-
1635-Retrieving HWDevice records
1636-...........................
1637-
1638-Existing HWDevice records can be retrieved by calling
1639-HWDeviceSet.getByDeviceID()
1640-
1641- >>> device = device_set.getByDeviceID(HWBus.USB, '0x07b3', '0x0017')
1642- >>> print(device.bus_vendor.bus.title)
1643- USB
1644- >>> print(device.bus_vendor.vendor_id_for_bus)
1645- 0x07b3
1646- >>> print(device.bus_product_id)
1647- 0x0017
1648- >>> print(device.name)
1649- some scanner
1650-
1651-The call to HWDeviceSet.getByDeviceID() above did not specify a product
1652-variant. In such a case, the record having variant==None is returned
1653-
1654- >>> print(device.variant)
1655- None
1656-
1657-If a variant name is given, we get the HWDevice record of that variant.
1658-
1659- >>> device = device_set.getByDeviceID(HWBus.USB, '0x07b3', '0x0017',
1660- ... 'OpticPro UT16')
1661- >>> print(device.bus_vendor.bus.title)
1662- USB
1663- >>> print(device.bus_vendor.vendor_id_for_bus)
1664- 0x07b3
1665- >>> print(device.bus_product_id)
1666- 0x0017
1667- >>> print(device.name)
1668- OpticPro UT16
1669- >>> print(device.variant)
1670- OpticPro UT16
1671-
1672-If the given parameters do not match any existing record, None is
1673-returned.
1674-
1675- >>> print(device_set.getByDeviceID(HWBus.PCI, '0x07b3', '0x0017',
1676- ... 'OpticPro UT16'))
1677- None
1678- >>> print(device_set.getByDeviceID(HWBus.USB, '0xffff', '0x0017',
1679- ... 'OpticPro UT16'))
1680- None
1681- >>> print(device_set.getByDeviceID(HWBus.PCI, '0x07b3', '0xffff',
1682- ... 'OpticPro UT16'))
1683- None
1684- >>> print(device_set.getByDeviceID(HWBus.PCI, '0x07b3', '0x0017',
1685- ... 'nonsense'))
1686- None
1687-
1688-The parameters vendor_id and product_id must be valid IDs for the
1689-given bus.
1690-
1691- >>> device_set.getByDeviceID(HWBus.USB, '07b3', '0x0017')
1692- Traceback (most recent call last):
1693- ...
1694- ParameterError: u'07b3' is not a valid vendor ID for USB
1695-
1696- >>> device_set.getByDeviceID(HWBus.USB, '0x07b3', '0017')
1697- Traceback (most recent call last):
1698- ...
1699- ParameterError: u'0017' is not a valid product ID for USB
1700-
1701-HWDeviceSet.getOrCreate() returns an existing record matching the given
1702-parameters or creates a new one, if no existing record matches.
1703-
1704- >>> device2 = device_set.getOrCreate(bus=HWBus.USB,
1705- ... vendor_id='0x07b3',
1706- ... product_id='0x0017',
1707- ... product_name='OpticPro UT16',
1708- ... variant='OpticPro UT16')
1709- >>> print(device2.bus_vendor.bus.title)
1710- USB
1711- >>> print(device2.bus_vendor.vendor_id_for_bus)
1712- 0x07b3
1713- >>> print(device2.bus_product_id)
1714- 0x0017
1715- >>> print(device2.name)
1716- OpticPro UT16
1717- >>> print(device2.variant)
1718- OpticPro UT16
1719- >>> print(device2.id == device.id)
1720- True
1721-
1722- >>> device3 = device_set.getByDeviceID(bus=HWBus.USB,
1723- ... vendor_id='0x07b3',
1724- ... product_id='0x0017',
1725- ... variant='Some other scanner')
1726- >>> print(device3)
1727- None
1728- >>> device3 = device_set.getOrCreate(bus=HWBus.USB,
1729- ... vendor_id='0x07b3',
1730- ... product_id='0x0017',
1731- ... product_name='Some other scanner',
1732- ... variant='Some other scanner')
1733- >>> print(device3.bus_vendor.bus.title)
1734- USB
1735- >>> print(device3.bus_vendor.vendor_id_for_bus)
1736- 0x07b3
1737- >>> print(device3.bus_product_id)
1738- 0x0017
1739- >>> print(device3.name)
1740- Some other scanner
1741- >>> print(device3.variant)
1742- Some other scanner
1743-
1744- >>> device4 = device_set.getOrCreate(bus=HWBus.USB,
1745- ... vendor_id='0x07b3',
1746- ... product_id='0x0015',
1747- ... product_name='OpticPro U24')
1748- >>> print(device4.bus_vendor.bus.title)
1749- USB
1750- >>> print(device4.bus_vendor.vendor_id_for_bus)
1751- 0x07b3
1752- >>> print(device4.bus_product_id)
1753- 0x0015
1754- >>> print(device4.name)
1755- OpticPro U24
1756- >>> print(device4.variant)
1757- None
1758-
1759-
1760-HWDeviceSet.getByID() returns a HWDevice record with the given database ID.
1761-
1762- >>> device = device_set.getByID(1)
1763- >>> print(device.id)
1764- 1
1765- >>> print(device.vendor_id)
1766- MSI
1767- >>> print(device.bus_product_id)
1768- MS-7369
1769-
1770-HWDeviceSet.getByID() returns None if no record with the passed ID exists.
1771-
1772- >>> device = device_set.getByID(1000000)
1773- >>> print(device)
1774- None
1775-
1776-HWDeviceSet.search() returns all devices with a given bus and vendor ID.
1777-
1778- >>> devices = device_set.search(bus=HWBus.USB, vendor_id='0x07b3')
1779- >>> for device in devices:
1780- ... print(device.bus.title, device.vendor_id, device.bus_product_id,
1781- ... device.variant)
1782- USB 0x07b3 0x0017 None
1783- USB 0x07b3 0x0017 OpticPro UT12
1784- USB 0x07b3 0x0017 OpticPro UT16
1785- USB 0x07b3 0x0017 Some other scanner
1786- USB 0x07b3 0x0015 None
1787-
1788-Searching can be limited to a single product ID.
1789-
1790- >>> devices = device_set.search(
1791- ... bus=HWBus.USB, vendor_id='0x07b3', product_id='0x0017')
1792- >>> for device in devices:
1793- ... print(device.bus.title, device.vendor_id, device.bus_product_id,
1794- ... device.variant)
1795- USB 0x07b3 0x0017 None
1796- USB 0x07b3 0x0017 OpticPro UT12
1797- USB 0x07b3 0x0017 OpticPro UT16
1798- USB 0x07b3 0x0017 Some other scanner
1799-
1800-HWDeviceSet.search() raises a ParameterError for vendor or product IDs
1801-that are not valid for the given bus.
1802-
1803- >>> devices = device_set.search(
1804- ... bus=HWBus.USB, vendor_id='invalid', product_id='0x0017')
1805- Traceback (most recent call last):
1806- ...
1807- ParameterError: u'invalid' is not a valid vendor ID for USB
1808-
1809- >>> devices = device_set.search(
1810- ... bus=HWBus.USB, vendor_id='0x07b3', product_id='nonsense')
1811- Traceback (most recent call last):
1812- ...
1813- ParameterError: u'nonsense' is not a valid product ID for USB
1814-
1815-HWDevice.getSubmissions() returns submissions which contain this device.
1816-
1817-We'll switch the DB user from hwdb-submission-processor to the ordinary
1818-Launchpad user, because the former has no access to the table
1819-distribution, which we want to access in this test.
1820-
1821- >>> from lp.testing.dbuser import (
1822- ... lp_dbuser,
1823- ... switch_dbuser,
1824- ... )
1825-
1826- >>> switch_dbuser('launchpad')
1827- >>> sata_controller = device_set.getByDeviceID(
1828- ... bus=HWBus.PCI, vendor_id='0x10de', product_id='0x045d')
1829- >>> for submission in sata_controller.getSubmissions():
1830- ... print(submission.submission_key)
1831- sample-submission
1832-
1833-We can limit the results to a specific driver. (See below for details about
1834-HWDriver.)
1835-
1836- >>> from lp.hardwaredb.interfaces.hwdb import IHWDriverSet
1837- >>> ahci_driver = getUtility(IHWDriverSet).getByPackageAndName(
1838- ... 'linux-image-2.6.24-19-generic', 'ahci')
1839- >>> for submission in sata_controller.getSubmissions(
1840- ... driver=ahci_driver):
1841- ... print(submission.submission_key)
1842- sample-submission
1843-
1844- >>> usb_storage_driver = getUtility(IHWDriverSet).getByPackageAndName(
1845- ... 'linux-image-2.6.24-19-generic', 'usb-storage')
1846- >>> print(list(sata_controller.getSubmissions(
1847- ... driver=usb_storage_driver)))
1848- []
1849-
1850-We can limit the results to a specific distribution.
1851-
1852- >>> from lp.registry.interfaces.distribution import (
1853- ... IDistributionSet)
1854- >>> distribution_set = getUtility(IDistributionSet)
1855- >>> ubuntu = distribution_set.getByName('ubuntu')
1856- >>> for submission in sata_controller.getSubmissions(
1857- ... distribution=ubuntu):
1858- ... print(submission.submission_key)
1859- sample-submission
1860-
1861- >>> debian = distribution_set.getByName('debian')
1862- >>> sata_controller.getSubmissions(distribution=debian).count()
1863- 0
1864-
1865-We can limit the results to a specific architecture.
1866-
1867- >>> for submission in sata_controller.getSubmissions(
1868- ... architecture='i386'):
1869- ... print(submission.submission_key)
1870- sample-submission
1871-
1872- >>> sata_controller.getSubmissions(architecture='amd64').count()
1873- 0
1874-
1875-We can limit the results to a specific distro series.
1876-
1877- >>> for submission in sata_controller.getSubmissions(
1878- ... distroseries=ubuntu['hoary']):
1879- ... print(submission.submission_key)
1880- sample-submission
1881-
1882- >>> sata_controller.getSubmissions(distroseries=ubuntu['warty']).count()
1883- 0
1884-
1885-We can even limit the results to a specific distro series and architecture.
1886-
1887- >>> for submission in sata_controller.getSubmissions(
1888- ... distroseries=ubuntu['hoary'], architecture='i386'):
1889- ... print(submission.submission_key)
1890- sample-submission
1891-
1892- >>> sata_controller.getSubmissions(
1893- ... distroseries=ubuntu['hoary'], architecture='powerpc').count()
1894- 0
1895-
1896-We can also search for submissions from a particular user.
1897-
1898- >>> from lp.registry.interfaces.person import IPersonSet
1899- >>> owner = getUtility(IPersonSet).getByName('name12')
1900- >>> for submission in sata_controller.getSubmissions(owner=owner):
1901- ... print(submission.submission_key)
1902- sample-submission
1903-
1904- >>> not_owner = getUtility(IPersonSet).getByName('name20')
1905- >>> sata_controller.getSubmissions(owner=not_owner).count()
1906- 0
1907-
1908- >>> import transaction
1909- >>> transaction.abort()
1910- >>> switch_dbuser('hwdb-submission-processor')
1911-
1912-HWDevice.drivers is the set of drivers that are associated via
1913-HWDeviceDriverLink (see below) with this device.
1914-
1915- >>> for driver in sata_controller.drivers:
1916- ... print(driver.package_name, driver.name)
1917- linux-image-2.6.24-19-generic ahci
1918-
1919-
1920-HWDeviceNameVariant
1921--------------------
1922-
1923-Many OEM products are sold by more than one vendor under different
1924-product names; some manufacturers sell the same device under
1925-different names in different parts of the world. The support status
1926-of such devices does not depend on the "publicly visible" vendor and
1927-product name, so we consider these devices to be identical. Users will
1928-nevertheless want to look up devices by the vendor and product name
1929-they see in a store. HWDeviceNameVariant allows us to assign alternative
1930-vendor and product names to a device.
1931-
1932- >>> from lp.hardwaredb.interfaces.hwdb import IHWDeviceNameVariantSet
1933- >>> device_name_variant_set = getUtility(IHWDeviceNameVariantSet)
1934- >>> variant = device_name_variant_set.create(device=optic_pro_ut16,
1935- ... vendor_name='Medion',
1936- ... product_name='MD 1234')
1937- >>> print(variant.device.bus_vendor.vendor_name.name)
1938- Plustek
1939- >>> print(variant.vendor_name.name)
1940- Medion
1941- >>> print(variant.product_name)
1942- MD 1234
1943-
1944-We count the number of submissions which told us an alternative device
1945-name.
1946-
1947- >>> print(variant.submissions)
1948- 0
1949-
1950-The tuple (device, vendor_name, product_name) must be unique.
1951-The attempt to create two rows with the same data raises an
1952-IntegrityError error.
1953-
1954- >>> LaunchpadZopelessLayer.txn.commit()
1955- >>> same_variant = device_name_variant_set.create(device=optic_pro_ut16,
1956- ... vendor_name='Medion',
1957- ... product_name='MD 1234')
1958- >>> store.flush()
1959- Traceback (most recent call last):
1960- ...
1961- IntegrityError: ...
1962- <BLANKLINE>
1963- >>> LaunchpadZopelessLayer.txn.abort()
1964-
1965-
1966-HWDriver
1967---------
1968-
1969-If a device is reported as having problems, then we are more
1970-interested in which drivers are involved rather than the fact that
1971-there are problems. The table HWDriver stores minimal data about
1972-drivers: its package name, the driver name itself and the driver's
1973-license. This data is linked to HWDevice records via the table
1974-HWDeviceDriverLink (see below).
1975-
1976-The driver is not in every case a kernel driver, it may also be for
1977-example a Ghostscript driver of a printer or a Sane scanner backend.
1978-
1979- >>> from lp.hardwaredb.interfaces.hwdb import IHWDriverSet
1980- >>> from lp.registry.interfaces.product import License
1981- >>> driver_set = getUtility(IHWDriverSet)
1982- >>> usb_driver = driver_set.create(package_name='linux-image-generic',
1983- ... name='usb',
1984- ... license=License.GNU_GPL_V2)
1985- >>> print(usb_driver.name)
1986- usb
1987- >>> print(usb_driver.package_name)
1988- linux-image-generic
1989- >>> print(usb_driver.license.title)
1990- GNU GPL v2
1991-
1992-The submitted data does not need to contain package information for all
1993-drivers, hence the field package_name may be None or the empty string
1994-(see below). In both cases, a HWDriver record is created where
1995-package_name is the empty string.
1996-
1997- >>> driver2 = driver_set.create(package_name=None,
1998- ... name='whatever',
1999- ... license=License.GNU_GPL_V2)
2000- >>> print(driver2.name)
2001- whatever
2002- >>> print(repr(driver2.package_name))
2003- u''
2004- >>> print(driver2.license.title)
2005- GNU GPL v2
2006-
2007- >>> driver_blank_package_name = driver_set.create(package_name='',
2008- ... name='bar',
2009- ... license=License.GNU_GPL_V3)
2010- >>> print(driver_blank_package_name.name)
2011- bar
2012- >>> print(repr(driver_blank_package_name.package_name))
2013- u''
2014- >>> print(driver_blank_package_name.license.title)
2015- GNU GPL v3
2016-
2017-Since we also do not always know the license of a driver, the license
2018-may too be None.
2019-
2020- >>> driver3 = driver_set.create(package_name='',
2021- ... name='something_else',
2022- ... license=None)
2023- >>> print(driver3.name)
2024- something_else
2025- >>> print(repr(driver3.package_name))
2026- u''
2027- >>> print(driver3.license)
2028- None
2029-
2030-The tuple (driver name, package name) must be unique.
2031-
2032- >>> LaunchpadZopelessLayer.txn.commit()
2033- >>> driver = driver_set.create(package_name='linux-image-generic',
2034- ... name='usb',
2035- ... license=License.GNU_GPL_V2)
2036- >>> store.flush()
2037- Traceback (most recent call last):
2038- ...
2039- IntegrityError: ...
2040- <BLANKLINE>
2041- >>> LaunchpadZopelessLayer.txn.abort()
2042-
2043- >>> driver = driver_set.create(package_name=None,
2044- ... name='whatever',
2045- ... license=License.GNU_GPL_V2)
2046- >>> store.flush()
2047- Traceback (most recent call last):
2048- ...
2049- IntegrityError: ...
2050- <BLANKLINE>
2051- >>> LaunchpadZopelessLayer.txn.abort()
2052-
2053-An IHWDriver record is retrieved by calling
2054-IHWDriverSet.getByPackageAndName().
2055-
2056- >>> driver = driver_set.getByPackageAndName('linux-image-generic', 'usb')
2057- >>> print(driver.package_name)
2058- linux-image-generic
2059- >>> print(driver.name)
2060- usb
2061-
2062-If we want to search for a driver without a known package, we can
2063-pass None as well as the empty string.
2064-
2065- >>> driver = driver_set.getByPackageAndName('', 'whatever')
2066- >>> print(repr(driver.package_name))
2067- u''
2068- >>> print(driver.name)
2069- whatever
2070-
2071- >>> driver2 = driver_set.getByPackageAndName(None, 'whatever')
2072- >>> driver2.id == driver.id
2073- True
2074-
2075-If no existing record matches the parameters of the
2076-IHWDriverSet.getByPackageAndName() call, None is returned.
2077-
2078- >>> driver = driver_set.getByPackageAndName('nonsense', 'more nonsense')
2079- >>> print(driver)
2080- None
2081-
2082-IHWDriverSet.getOrCreate() returns an existing record matching
2083-the given parameters or creates a new one, if no existing record matches.
2084-
2085- >>> driver = driver_set.getOrCreate('linux-image-generic', 'usb')
2086- >>> print(driver.package_name)
2087- linux-image-generic
2088- >>> print(driver.name)
2089- usb
2090-
2091- >>> driver = driver_set.getByPackageAndName('linux-image-generic', 'foo')
2092- >>> print(driver)
2093- None
2094- >>> driver = driver_set.getOrCreate('linux-image-generic', 'foo')
2095- >>> print(driver.name)
2096- foo
2097- >>> print(driver.package_name)
2098- linux-image-generic
2099-
2100-If we pass None as the value for package_name, we get records where
2101-package_name is None or the empty string.
2102-
2103- >>> driver = driver_set.getOrCreate(None, 'whatever')
2104- >>> print(repr(driver.package_name))
2105- u''
2106- >>> print(driver.name)
2107- whatever
2108-
2109-Older HWDriver records may store None as the package name. We can
2110-retrieve these records by passing None for package_name...
2111-
2112- >>> from lp.hardwaredb.model.hwdb import HWDriver
2113- >>> old_driver = HWDriver(package_name=None, name=u'foo', license=None)
2114- >>> print(old_driver.name)
2115- foo
2116- >>> print(old_driver.package_name)
2117- None
2118-
2119- >>> driver = driver_set.getOrCreate(None, 'foo')
2120- >>> driver.id == old_driver.id
2121- True
2122-
2123-...as well as the empty string.
2124-
2125- >>> driver = driver_set.getOrCreate('', 'foo')
2126- >>> driver.id == old_driver.id
2127- True
2128-
2129-IHWDriverSet.search() returns a sequence of driver records matching the
2130-given parameters.
2131-
2132- >>> drivers = driver_set.search(package_name='linux-image-generic')
2133- >>> for driver in drivers:
2134- ... print(driver.package_name, driver.name)
2135- linux-image-generic usb
2136- linux-image-generic foo
2137-
2138- >>> drivers = driver_set.search(name='usb')
2139- >>> for driver in drivers:
2140- ... print(driver.package_name, driver.name)
2141- linux-image-2.6.24-19-generic usb
2142- linux-image-generic usb
2143-
2144- >>> drivers = driver_set.search(
2145- ... package_name='linux-image-2.6.24-19-generic', name='ahci')
2146- >>> for driver in drivers:
2147- ... print(driver.package_name, driver.name)
2148- linux-image-2.6.24-19-generic ahci
2149-
2150-If package_name is an empty string, driver records are returned where
2151-the package name is not recorded (which is denoted by None or the
2152-empty string. See also bug 306265: Disallow the column value
2153-HWDriver.package_name=null).
2154-
2155- >>> drivers = driver_set.search(package_name='')
2156- >>> for driver in drivers:
2157- ... print(repr(driver.package_name), driver.name)
2158- u'' whatever
2159- u'' bar
2160- u'' something_else
2161- None foo
2162-
2163- >>> drivers = driver_set.search(package_name='', name='whatever')
2164- >>> for driver in drivers:
2165- ... print(repr(driver.package_name), driver.name)
2166- u'' whatever
2167-
2168- >>> drivers = driver_set.search(package_name='', name='foo')
2169- >>> for driver in drivers:
2170- ... print(repr(driver.package_name), driver.name)
2171- None foo
2172-
2173-If no parameters are specified, IHWDriverSet.search() returns all driver
2174-records.
2175-
2176- >>> drivers = driver_set.search()
2177- >>> for driver in drivers:
2178- ... print(repr(driver.package_name), driver.name)
2179- u'linux-image-2.6.24-19-generic' ehci_hcd
2180- u'linux-image-2.6.24-19-generic' usb
2181- u'linux-image-2.6.24-19-generic' usb-storage
2182- u'linux-image-2.6.24-19-generic' sd
2183- u'linux-image-2.6.24-19-generic' hub
2184- u'linux-image-2.6.24-19-generic' ahci
2185- u'linux-image-2.6.24-19-generic' sr
2186- u'linux-image-generic' usb
2187- u'' whatever
2188- u'' bar
2189- u'' something_else
2190- u'linux-image-generic' foo
2191- None foo
2192-
2193-HWDriverSet.getByID() returns a HWDriver record with the given database ID.
2194-
2195- >>> driver = driver_set.getByID(1)
2196- >>> print(driver.id)
2197- 1
2198- >>> print(driver.package_name)
2199- linux-image-2.6.24-19-generic
2200- >>> print(driver.name)
2201- ehci_hcd
2202-
2203-HWDriverSet.getByID() returns None if no record with the passed ID exists.
2204-
2205- >>> driver = driver_set.getByID(1000000)
2206- >>> print(driver)
2207- None
2208-
2209- >>> transaction.abort()
2210- >>> switch_dbuser('launchpad')
2211-
2212-We can search all the submissions related to a driver.
2213-
2214- >>> driver = driver_set.getByID(1)
2215- >>> for submission in driver.getSubmissions():
2216- ... print(submission.submission_key)
2217- sample-submission
2218-
2219-We can limit our search to submissions for a particular distribution.
2220-
2221- >>> for submission in driver.getSubmissions(distribution=ubuntu):
2222- ... print(submission.submission_key)
2223- sample-submission
2224-
2225- >>> print(driver.getSubmissions(distribution=debian).count())
2226- 0
2227-
2228-We can limit the results to a specific distro series.
2229-
2230- >>> for submission in driver.getSubmissions(
2231- ... distroseries=ubuntu['hoary']):
2232- ... print(submission.submission_key)
2233- sample-submission
2234-
2235- >>> driver.getSubmissions(distroseries=ubuntu['warty']).count()
2236- 0
2237-
2238-We can also limit the results to a specific distro series and architecture.
2239-
2240- >>> for submission in driver.getSubmissions(
2241- ... distroseries=ubuntu['hoary'], architecture='i386'):
2242- ... print(submission.submission_key)
2243- sample-submission
2244-
2245- >>> driver.getSubmissions(
2246- ... distroseries=ubuntu['hoary'], architecture='powerpc').count()
2247- 0
2248-
2249-And We can search for submissions from a particular user.
2250-
2251- >>> for submission in driver.getSubmissions(owner=owner):
2252- ... print(submission.submission_key)
2253- sample-submission
2254-
2255- >>> driver.getSubmissions(owner=not_owner).count()
2256- 0
2257-
2258- >>> transaction.abort()
2259- >>> switch_dbuser('hwdb-submission-processor')
2260-
2261-
2262-Driver names and package names
2263-------------------------------
2264-
2265-The same driver names can appear multiple times in HWDriver.
2266-HWDriverSet.all_driver_names() returns a list of distinct driver
2267-names used in the table HWDriver.
2268-
2269- >>> switch_dbuser('launchpad')
2270- >>> for driver_name in driver_set.all_driver_names():
2271- ... print(driver_name.name)
2272- ahci
2273- bar
2274- ehci_hcd
2275- hub
2276- sd
2277- something_else
2278- sr
2279- usb
2280- usb-storage
2281- whatever
2282-
2283-Similary, the same package names appear more than once in HWDriver.
2284-HWDriverSet.all_package_names() returns a list of distinct package
2285-names. Note that the package name value None (used in older submissions)
2286-is not included.
2287-
2288- >>> from lp.hardwaredb.model.hwdb import HWDriver
2289- >>> store.add(HWDriver(name='foo', package_name=None))
2290- <HWDriver at...
2291- >>> for package_name in driver_set.all_package_names():
2292- ... print(package_name.package_name)
2293- <BLANKLINE>
2294- linux-image-2.6.24-19-generic
2295- linux-image-generic
2296-
2297- >>> switch_dbuser('hwdb-submission-processor')
2298-
2299-
2300-HWDeviceDriverLink
2301-------------------
2302-
2303-This table links devices and drivers.
2304-
2305- >>> from lp.hardwaredb.interfaces.hwdb import IHWDeviceDriverLinkSet
2306- >>> device_driver_link_set = getUtility(IHWDeviceDriverLinkSet)
2307- >>> usb_controller_usb_link = device_driver_link_set.create(
2308- ... device=usb_controller, driver=usb_driver)
2309- >>> print(usb_controller_usb_link.device.name)
2310- 82801GBM/GHM (ICH7 Family) USB2 EHCI Controller
2311- >>> print(usb_controller_usb_link.driver.name)
2312- usb
2313-
2314-A device may be linked to more than one driver. A USB2 host controller
2315-for example has two drivers, the "generic" USB driver and the ehci-hcd
2316-driver.
2317-
2318- >>> ehci_hcd_driver = driver_set.create(
2319- ... package_name='linux-image-generic', name='ehci_hcd',
2320- ... license=License.GNU_GPL_V2)
2321- >>> usb_controller_ehci_hcd_link = device_driver_link_set.create(
2322- ... device=usb_controller, driver=ehci_hcd_driver)
2323- >>> print(usb_controller_ehci_hcd_link.device.name)
2324- 82801GBM/GHM (ICH7 Family) USB2 EHCI Controller
2325- >>> print(usb_controller_ehci_hcd_link.driver.name)
2326- ehci_hcd
2327-
2328-A scanner can be linked to the kernel driver for the physical interface
2329-and to its Sane backend.
2330-
2331- >>> scanner_usb_driver_link = device_driver_link_set.create(
2332- ... device=optic_pro_ut12, driver=usb_driver)
2333- >>> print(scanner_usb_driver_link.device.name)
2334- OpticPro UT12
2335- >>> print(scanner_usb_driver_link.driver.name)
2336- usb
2337-
2338- >>> sane_plustek_driver = driver_set.create(package_name='libsane',
2339- ... name='plustek',
2340- ... license=License.GNU_GPL_V2)
2341- >>> scanner_sane_plustek_link = device_driver_link_set.create(
2342- ... device=optic_pro_ut12, driver=sane_plustek_driver)
2343- >>> print(scanner_sane_plustek_link.device.name)
2344- OpticPro UT12
2345- >>> print(scanner_sane_plustek_link.driver.name)
2346- plustek
2347-
2348-Devices can have alternative drivers. Let's assume that Plustek
2349-provides a closed-source driver for its scanners.
2350-
2351- >>> closed_driver = driver_set.create(package_name='plustek-scanner',
2352- ... name='ut12',
2353- ... license=License.OTHER_PROPRIETARY)
2354-
2355-Now we can link the OpticPro UT12 to the closed-source driver too.
2356-
2357- >>> link3 = device_driver_link_set.create(device=optic_pro_ut12,
2358- ... driver=closed_driver)
2359- >>> print(link3.device.name)
2360- OpticPro UT12
2361- >>> print(link3.driver.name)
2362- ut12
2363-
2364-We have two cases, where we do not (or can not) store driver information
2365-for a HWDevice record:
2366- - it does not make much sense to assign drivers to an entire system;
2367- - HAL can list a device without providing driver information. This is
2368- for example the case for an unsupported device.
2369-
2370-Since the tables HWSubmissionDevice, HWTestAnswer and HWTestAnswerCount
2371-(see below) link to HWDeviceDriverLink, we need a record in the latter
2372-table, even when we do not know about a driver of a device or system.
2373-Thus we can create a HWDeviceDriverLink record, where driver is None.
2374-
2375- >>> tuffbook_2600_device_driver_link = device_driver_link_set.create(
2376- ... device=tuffbook_2600, driver=None)
2377-
2378-The tuple (device, driver) must be unique.
2379-
2380- >>> LaunchpadZopelessLayer.txn.commit()
2381- >>> device_driver_link_set.create(device=optic_pro_ut12,
2382- ... driver=closed_driver)
2383- <HWDeviceDriverLink...
2384- >>> store.flush()
2385- Traceback (most recent call last):
2386- ...
2387- IntegrityError: ...
2388- <BLANKLINE>
2389- >>> LaunchpadZopelessLayer.txn.abort()
2390-
2391- >>> device_driver_link_set.create(device=tuffbook_2600, driver=None)
2392- <HWDeviceDriverLink...
2393- >>> store.flush()
2394- Traceback (most recent call last):
2395- ...
2396- IntegrityError: ...
2397- <BLANKLINE>
2398- >>> LaunchpadZopelessLayer.txn.abort()
2399-
2400-An IHWDeviceDriverLink record is retrieved by
2401-IHWDeviceDriverSet.getByDeviceAndDriver().
2402-
2403- >>> link = device_driver_link_set.getByDeviceAndDriver(optic_pro_ut12,
2404- ... closed_driver)
2405- >>> print(link.device.name)
2406- OpticPro UT12
2407- >>> print(link.driver.name)
2408- ut12
2409-
2410-If no record exists for the given tuple (device, driver),
2411-IHWDeviceDriverSet.getByDeviceAndDriver() returns None.
2412-
2413- >>> link = device_driver_link_set.getByDeviceAndDriver(optic_pro_ut12,
2414- ... ehci_hcd_driver)
2415- >>> print(link)
2416- None
2417-
2418-HWDeviceDriverLinkSet.getOrCreate() returns an existing record matching
2419-the given parameters or creates a new one, if no existing record matches.
2420-
2421- >>> link = device_driver_link_set.getOrCreate(optic_pro_ut12,
2422- ... closed_driver)
2423- >>> print(link.device.name)
2424- OpticPro UT12
2425- >>> print(link.driver.name)
2426- ut12
2427- >>> print(link.id == link3.id)
2428- True
2429- >>> link = device_driver_link_set.getByDeviceAndDriver(optic_pro_ut12,
2430- ... None)
2431- >>> print(link)
2432- None
2433- >>> link = device_driver_link_set.getOrCreate(optic_pro_ut12, None)
2434- >>> print(link.device.name)
2435- OpticPro UT12
2436- >>> print(link.driver)
2437- None
2438-
2439-
2440-HWDeviceClass
2441--------------
2442-
2443-This table specifies the class or classes of a device. A device class
2444-describes the capabilities of a device, i.e, if it is a printer,
2445-input device, sound device etc. HWDeviceClass stores the main class of
2446-a device, enumerated by HWMainClass, as well as a sub-class, enumerated
2447-by HWSubClass. The required main class specifies the generic type of
2448-a device, the optional sub-class a more detailed type.
2449-
2450-Note that this information is not very reliable for some devices.
2451-For example, the USB bus has no specification at all for scanners;
2452-many vendors use the "generic" class/sub-class 0/0 for their scanners,
2453-while other vendors use 0x10/0, at least for some of their scanners.
2454-
2455-We have also hardware reports with obviously broken devices. For example
2456-some USB/WLAN adapters with vendor/product IDs 0x050d/0x705a and
2457-0x050d/0x905b claim that they implement the USB class 6, imaging.
2458-Similary, a number of PCI devices return clearly invalid class/subclass
2459-data.
2460-
2461-Let's pretend that Plustek uses the inofficial class/subclass 0x10/0
2462-for their Optic Pro 12 scanner.
2463-
2464- >>> device_class_optic_pro_ut12 = optic_pro_ut12.getOrCreateDeviceClass(
2465- ... main_class=0x10, sub_class=0)
2466- >>> device_class_optic_pro_ut12.main_class
2467- 16
2468- >>> device_class_optic_pro_ut12.sub_class
2469- 0
2470-
2471-We can assign more than one class to devices. This should only be
2472-done for USB devices, which may have different classes for each
2473-of their interfaces. Let's add a second device class, "USB printer",
2474-for the scanner.
2475-
2476- >>> device_class_printer = optic_pro_ut12.getOrCreateDeviceClass(
2477- ... main_class=0x07, sub_class=0x01)
2478- >>> print(device_class_printer.device.name)
2479- OpticPro UT12
2480- >>> print(device_class_printer.main_class)
2481- 7
2482- >>> print(device_class_printer.sub_class)
2483- 1
2484-
2485-IHWDdevice.classes contains the set of classes defined for this device.
2486-
2487- >>> for device_class in optic_pro_ut12.classes:
2488- ... print(device_class.main_class, device_class.sub_class)
2489- 7 1
2490- 16 0
2491-
2492-We get the device class data from HWDB submissiions. Some submissions
2493-contain devices with obviously broken device class information, like
2494-a PCI SCSI controller claiming to be a graphics card, or a USB WLAN
2495-adapter claiming to be an imaging device. If we notice such kind of
2496-broken device class data, we can remove it by calling
2497-IHWDevice.removeDeviceClass().
2498-
2499- >>> LaunchpadZopelessLayer.txn.commit()
2500- >>> switch_dbuser('launchpad')
2501- >>> optic_pro_ut12.removeDeviceClass(main_class=0x07, sub_class=0x01)
2502- >>> for device_class in optic_pro_ut12.classes:
2503- ... print(device_class.main_class, device_class.sub_class)
2504- 16 0
2505-
2506- >>> switch_dbuser('hwdb-submission-processor')
2507-
2508-
2509-HWSubmissionDevice
2510-------------------
2511-
2512-This table links devices listed in a submission to the
2513-HWDeviceDriverLink table. Additionally it links a device of a
2514-submission to its parent device, as modeled by HAL. A submission
2515-may contain two or more identical devices. In order to unambiugously
2516-relate HWSubmissionDevice records to devices as represented in the
2517-submitted data, we store the attribute "id" of the HAL device node
2518-too.
2519-
2520-We need a submission to which we can link HWSubmissionDevice entries.
2521-
2522- >>> from lp.hardwaredb.interfaces.hwdb import IHWSubmissionSet
2523- >>> sample_submission = getUtility(IHWSubmissionSet).getBySubmissionKey(
2524- ... 'test_submission_id_1')
2525-
2526-A HWSubmissionDevice record for a system does not have any parent...
2527-
2528- >>> from lp.hardwaredb.interfaces.hwdb import IHWSubmissionDeviceSet
2529- >>> submission_device_set = getUtility(IHWSubmissionDeviceSet)
2530- >>> submitted_tuffbook_2600 = submission_device_set.create(
2531- ... device_driver_link=tuffbook_2600_device_driver_link,
2532- ... submission=sample_submission, parent=None, hal_device_id=1)
2533- >>> print(submitted_tuffbook_2600.device_driver_link.device.name)
2534- Tuffbook 2600
2535- >>> print(submitted_tuffbook_2600.device.name)
2536- Tuffbook 2600
2537- >>> print(submitted_tuffbook_2600.driver)
2538- None
2539- >>> print(submitted_tuffbook_2600.submission.submission_key)
2540- test_submission_id_1
2541- >>> print(submitted_tuffbook_2600.parent)
2542- None
2543- >>> print(submitted_tuffbook_2600.hal_device_id)
2544- 1
2545-
2546-...while ordinary device entries have the attribute parent set. The
2547-parent/child relationship may extend to several "generations". For
2548-example, our Inspiron 1234 has a USB host controller; its parent
2549-is the system itself.
2550-
2551- >>> submitted_usb_ehci_hcd_controller = submission_device_set.create(
2552- ... device_driver_link=usb_controller_ehci_hcd_link,
2553- ... submission=sample_submission,
2554- ... parent=submitted_tuffbook_2600,
2555- ... hal_device_id=2)
2556-
2557-For the "output aspect" of the USB controller, we have
2558-usb_controller_usb_link; its parent is submitted_usb_ehci_hcd_controller
2559-that we just have created.
2560-
2561- >>> submitted_usb_controller = submission_device_set.create(
2562- ... device_driver_link=usb_controller_usb_link,
2563- ... submission=sample_submission,
2564- ... parent=submitted_usb_ehci_hcd_controller,
2565- ... hal_device_id=3)
2566- >>> print(submitted_usb_controller.device_driver_link.device.name)
2567- 82801GBM/GHM (ICH7 Family) USB2 EHCI Controller
2568- >>> print(submitted_usb_controller.device_driver_link.driver.name)
2569- usb
2570- >>> print(submitted_usb_controller.device.name)
2571- 82801GBM/GHM (ICH7 Family) USB2 EHCI Controller
2572- >>> print(submitted_usb_controller.driver.name)
2573- usb
2574- >>> print(submitted_usb_controller.hal_device_id)
2575- 3
2576-
2577-The USB controller is connected to an (often internal) USB hub. We don't
2578-yet have HWDevice and HWDeviceDriverLink records for this hub, so we must
2579-create them first.
2580-
2581- >>> usb_hub = device_set.create(bus=HWBus.USB,
2582- ... vendor_id='0x8086',
2583- ... product_id='0x1234',
2584- ... product_name='Intel USB hub')
2585- >>> usb_hub_driver_link = device_driver_link_set.create(
2586- ... device=usb_hub, driver=usb_driver)
2587- >>> submitted_usb_hub = submission_device_set.create(
2588- ... device_driver_link=usb_hub_driver_link,
2589- ... submission=sample_submission,
2590- ... parent=submitted_usb_controller,
2591- ... hal_device_id=4)
2592-
2593-Finally, a scanner may be connected to the USB hub.
2594-
2595- >>> submitted_scanner_usb = submission_device_set.create(
2596- ... device_driver_link=scanner_usb_driver_link,
2597- ... submission=sample_submission,
2598- ... parent=submitted_usb_hub,
2599- ... hal_device_id=5)
2600-
2601- >>> submitted_scanner_sane = submission_device_set.create(
2602- ... device_driver_link=scanner_sane_plustek_link,
2603- ... submission=sample_submission,
2604- ... parent=submitted_scanner_usb,
2605- ... hal_device_id=6)
2606-
2607-IHWSubmissionDevice records belonging to a submission are retrieved by
2608-IHWSubmissionDeviceSet.getDevices().
2609-
2610- >>> submitted_devices = submission_device_set.getDevices(
2611- ... submission=sample_submission)
2612- >>> def print_device(submission_device, indent=0):
2613- ... if indent > 0:
2614- ... print('-' * indent + '>', end=' ')
2615- ... device = submission_device.device_driver_link.device
2616- ... driver = submission_device.device_driver_link.driver
2617- ... print(device.bus_vendor.vendor_name.name, device.name, end=' ')
2618- ... if driver is not None:
2619- ... print(driver.name)
2620- ... else:
2621- ... print('(no driver)')
2622- ... for sub_device in submitted_devices:
2623- ... if sub_device.parent == submission_device:
2624- ... print_device(sub_device, indent+1)
2625- >>> devices_without_parent = [
2626- ... device for device in submitted_devices if device.parent is None]
2627- >>> root_device, = devices_without_parent
2628- >>> print_device(root_device)
2629- Tonka Tuffbook 2600 (no driver)
2630- -> Intel 82801GBM/GHM (ICH7 Family) USB2 EHCI Controller ehci_hcd
2631- --> Intel 82801GBM/GHM (ICH7 Family) USB2 EHCI Controller usb
2632- ---> Unknown Intel USB hub usb
2633- ----> Plustek OpticPro UT12 usb
2634- -----> Plustek OpticPro UT12 plustek
2635-
2636-A single IHWSubmissionDevice record is retrieved by
2637-IHWSubmissionDeviceSet.get().
2638-
2639- >>> submitted_device = submission_device_set.get(1)
2640- >>> print_device(submitted_device)
2641- MSI MS-7369 (no driver)
2642-
2643-This method returns None if a nonexistent ID is passed.
2644-
2645- >>> print(submission_device_set.get(1000000))
2646- None
2647-
2648-
2649-Statistical functions
2650----------------------
2651-
2652-HWSubmissionDeviceSet.numDevicesInSubmissions() returns how often a
2653-device appears in HWDB submissions.
2654-
2655- >>> print(submission_device_set.numDevicesInSubmissions(
2656- ... bus=HWBus.IDE, vendor_id='SEAGATE',
2657- ... product_id='ST3250820NS '))
2658- 1
2659-
2660-If a device appears more than once in a submission, it is counted as often
2661-as it appears in the submission. We have currently only unique devices
2662-in the existing data, so let's add another IDE disk to submission 2.
2663-
2664- >>> ide_disk = device_set.getByDeviceID(
2665- ... HWBus.IDE, 'SEAGATE', 'ST3250820NS ')
2666- >>> # We'll use the same parent as that of the existing IDE disk.
2667- >>> parent = getUtility(IHWSubmissionDeviceSet).get(17)
2668- >>> submission = getUtility(IHWSubmissionSet).getBySubmissionKey(
2669- ... 'sample-submission')
2670- >>> # The value of hal_device_id is arbitrary: It is intended for
2671- >>> # for consistency checks and debugging.
2672- >>> factory.makeHWSubmissionDevice(submission, ide_disk, None, parent, 1)
2673- <HWSubmissionDevice at...
2674-
2675-The number returned for the query "count the number of Seagate
2676-ST3250820NS" disks increased.
2677-
2678- >>> print(submission_device_set.numDevicesInSubmissions(
2679- ... bus=HWBus.IDE, vendor_id='SEAGATE',
2680- ... product_id='ST3250820NS '))
2681- 2
2682-
2683-Note that we did _not_ add a HWSubmissionDevice entry for the device
2684-driven by the kernel's sd driver. So, when we query the number of
2685-disks driven by the sd driver, we'll get 1 as without the recently
2686-added device.
2687-
2688- >>> print(submission_device_set.numDevicesInSubmissions(
2689- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2690- ... driver_name='sd'))
2691- 1
2692-
2693-Let's now create another HWDB submission, and let's add
2694-HWSubmissionDevice entries for the disk and the new submission, both
2695-for the "plain" disk and for the disk driven by the sd driver.
2696-
2697- >>> with lp_dbuser():
2698- ... # Set the emailaddress and hence the owner to a non-default
2699- ... # value so that we have submissions with different owners.
2700- ... submission = factory.makeHWSubmission(
2701- ... emailaddress='foo.bar@canonical.com')
2702- >>> first_device = factory.makeHWSubmissionDevice(
2703- ... submission, ide_disk, None, None, 1)
2704- >>> driver = getUtility(IHWDriverSet).getOrCreate(
2705- ... 'linux-image-generic', 'sd')
2706- >>> factory.makeHWSubmissionDevice(
2707- ... submission, ide_disk, driver, first_device, 2)
2708- <HWSubmissionDevice at...
2709- >>> from lp.hardwaredb.interfaces.hwdb import (
2710- ... HWSubmissionProcessingStatus)
2711- >>> # We consider only submissions in the status PROCESSED for
2712- >>> # statistics.
2713- >>> submission.status = HWSubmissionProcessingStatus.PROCESSED
2714- >>> LaunchpadZopelessLayer.txn.commit()
2715-
2716-The number of all ST3250820NS disks and of those disks driven by
2717-the sd driver has now increased by 1.
2718-
2719- >>> print(submission_device_set.numDevicesInSubmissions(
2720- ... bus=HWBus.IDE, vendor_id='SEAGATE',
2721- ... product_id='ST3250820NS '))
2722- 3
2723- >>> print(submission_device_set.numDevicesInSubmissions(
2724- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2725- ... driver_name='sd'))
2726- 2
2727-
2728-We can optionally specify a driver's package name too.
2729-
2730- >>> print(submission_device_set.numDevicesInSubmissions(
2731- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2732- ... driver_name='sd', package_name='linux-image-2.6.24-19-generic'))
2733- 1
2734- >>> print(submission_device_set.numDevicesInSubmissions(
2735- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2736- ... driver_name='sd', package_name='nonsense'))
2737- 0
2738-
2739-And we can query for devices having any driver from a given package too.
2740-
2741- >>> print(submission_device_set.numDevicesInSubmissions(
2742- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2743- ... package_name='linux-image-2.6.24-19-generic'))
2744- 1
2745- >>> print(submission_device_set.numDevicesInSubmissions(
2746- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2747- ... package_name='nonsense'))
2748- 0
2749-
2750-We can also get the number of all devices controlled by a given driver.
2751-
2752- >>> print(submission_device_set.numDevicesInSubmissions(
2753- ... driver_name='sd'))
2754- 6
2755-
2756-We can limit this count to a given package.
2757-
2758- >>> print(submission_device_set.numDevicesInSubmissions(
2759- ... driver_name='sd', package_name='linux-image-2.6.24-19-generic'))
2760- 5
2761-
2762-While the parameters for a device or a driver are optional, specifying
2763-neither of them leads to an error.
2764-
2765- >>> submission_device_set.numDevicesInSubmissions()
2766- Traceback (most recent call last):
2767- ...
2768- ParameterError: Specify (bus, vendor_id, product_id) or driver_name.
2769-
2770-We can additionally query for devices in submissions made for a given
2771-distribution. The device from the new submission we just created is
2772-not counted here, because we created the new submission for a new
2773-distribution.
2774-
2775- >>> switch_dbuser('launchpad')
2776- >>> print(submission_device_set.numDevicesInSubmissions(
2777- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2778- ... distro_target=ubuntu))
2779- 2
2780- >>> print(submission_device_set.numDevicesInSubmissions(
2781- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2782- ... distro_target=debian))
2783- 0
2784-
2785-Similary, we can limit the count to devices mentioned in submissions
2786-made for a given distroseries.
2787-
2788- >>> print(submission_device_set.numDevicesInSubmissions(
2789- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2790- ... distro_target=ubuntu['hoary']))
2791- 2
2792- >>> print(submission_device_set.numDevicesInSubmissions(
2793- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2794- ... distro_target=ubuntu['warty']))
2795- 0
2796-
2797-And we can also search for devices mentioned in submissions made on a
2798-given processor architecture.
2799-
2800- >>> print(submission_device_set.numDevicesInSubmissions(
2801- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2802- ... distro_target=ubuntu['hoary']['i386']))
2803- 2
2804- >>> print(submission_device_set.numDevicesInSubmissions(
2805- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2806- ... distro_target=ubuntu['hoary']['hppa']))
2807- 0
2808-
2809-We can also query the number of devices controlled by a given driver
2810-for a distrotarget.
2811-
2812- >>> print(submission_device_set.numDevicesInSubmissions(
2813- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2814- ... driver_name='sd', distro_target=ubuntu['hoary']['i386']))
2815- 1
2816- >>> print(submission_device_set.numDevicesInSubmissions(
2817- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2818- ... driver_name='nonsense', distro_target=ubuntu['hoary']['i386']))
2819- 0
2820-
2821-And we can additionally specify a package name.
2822-
2823- >>> print(submission_device_set.numDevicesInSubmissions(
2824- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2825- ... driver_name='sd', package_name='linux-image-2.6.24-19-generic',
2826- ... distro_target=ubuntu['hoary']['i386']))
2827- 1
2828- >>> print(submission_device_set.numDevicesInSubmissions(
2829- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2830- ... driver_name='sd', package_name='nonsense',
2831- ... distro_target=ubuntu['hoary']['i386']))
2832- 0
2833-
2834-HWSubmissionSet.numSubmissionsWithDevice() returns all submissions
2835-mentioning a given device and all processed submissions.
2836-
2837-We have currently two processed submissions, both containing the
2838-Seagate ST3250820NS disk. Let's add another submission for hoary/i386
2839-and mark it as "processed" so that we have one processed submission
2840-that does not contain this disk.
2841-
2842- >>> submission = factory.makeHWSubmission(
2843- ... distroarchseries=ubuntu['hoary']['i386'])
2844- >>> submission.status = HWSubmissionProcessingStatus.PROCESSED
2845-
2846- >>> submission_set = getUtility(IHWSubmissionSet)
2847- >>> print(submission_set.numSubmissionsWithDevice(
2848- ... bus=HWBus.IDE, vendor_id='SEAGATE',
2849- ... product_id='ST3250820NS '))
2850- (2L, 3L)
2851-
2852-We can limit the results to a given driver...
2853-
2854- >>> print(submission_set.numSubmissionsWithDevice(
2855- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2856- ... driver_name='sd'))
2857- (2L, 3L)
2858- >>> print(submission_set.numSubmissionsWithDevice(
2859- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2860- ... driver_name='usb'))
2861- (0L, 3L)
2862-
2863-...or we can ask for all submissions containing any device controlled
2864-by a given driver.
2865-
2866- >>> print(submission_set.numSubmissionsWithDevice(
2867- ... driver_name='sd'))
2868- (2L, 3L)
2869-
2870-While the parameters for a device or a driver are optional, specifying
2871-neither of them leads to an error.
2872-
2873- >>> print(submission_set.numSubmissionsWithDevice())
2874- Traceback (most recent call last):
2875- ...
2876- ParameterError: Specify (bus, vendor_id, product_id) or driver_name.
2877-
2878-This count can be limited to a given package.
2879-
2880- >>> print(submission_set.numSubmissionsWithDevice(
2881- ... driver_name='sd', package_name='linux-image-2.6.24-19-generic'))
2882- (1L, 3L)
2883-
2884-We can also limit the count to a distibution...
2885-
2886- >>> print(submission_set.numSubmissionsWithDevice(
2887- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2888- ... distro_target=ubuntu))
2889- (1L, 2L)
2890- >>> print(submission_set.numSubmissionsWithDevice(
2891- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2892- ... distro_target=debian))
2893- (0L, 0L)
2894-
2895-...to a distroseries...
2896-
2897- >>> print(submission_set.numSubmissionsWithDevice(
2898- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2899- ... distro_target=ubuntu['hoary']))
2900- (1L, 2L)
2901- >>> print(submission_set.numSubmissionsWithDevice(
2902- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2903- ... distro_target=ubuntu['warty']))
2904- (0L, 0L)
2905-
2906-...or to a distroarchseries.
2907-
2908- >>> print(submission_set.numSubmissionsWithDevice(
2909- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2910- ... distro_target=ubuntu['hoary']['i386']))
2911- (1L, 2L)
2912- >>> print(submission_set.numSubmissionsWithDevice(
2913- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2914- ... distro_target=ubuntu['hoary']['hppa']))
2915- (0L, 0L)
2916-
2917-We can specify a distro target as well as a driver or package name.
2918-
2919- >>> print(submission_set.numSubmissionsWithDevice(
2920- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2921- ... driver_name='sd', distro_target=ubuntu['hoary']['i386']))
2922- (1L, 2L)
2923- >>> print(submission_set.numSubmissionsWithDevice(
2924- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2925- ... driver_name='nosense', distro_target=ubuntu['hoary']['i386']))
2926- (0L, 2L)
2927-
2928- >>> print(submission_set.numSubmissionsWithDevice(
2929- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2930- ... package_name='linux-image-2.6.24-19-generic',
2931- ... distro_target=ubuntu['hoary']['i386']))
2932- (1L, 2L)
2933- >>> print(submission_set.numSubmissionsWithDevice(
2934- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2935- ... package_name='nonsense', distro_target=ubuntu['hoary']['i386']))
2936- (0L, 2L)
2937-
2938- >>> print(submission_set.numSubmissionsWithDevice(
2939- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2940- ... driver_name='sd', package_name='linux-image-2.6.24-19-generic',
2941- ... distro_target=ubuntu['hoary']['i386']))
2942- (1L, 2L)
2943- >>> print(submission_set.numSubmissionsWithDevice(
2944- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2945- ... driver_name='nonsense',
2946- ... package_name='linux-image-2.6.24-19-generic',
2947- ... distro_target=ubuntu['hoary']['i386']))
2948- (0L, 2L)
2949-
2950-HWSubmission.numDeviceOwners() returns the number of device owners.
2951-Note that we identify owners by the email address as queried by the
2952-HWDB client, not by HWSubmission.owner.
2953-
2954-We have currently three submissions from two submitters, and submissions
2955-from both submitters mention the Seagate ST3250820NS disk. Let's add
2956-another, empty, submission for hoary/i386 from another submitter.
2957-
2958- >>> submission = factory.makeHWSubmission(
2959- ... emailaddress='charles@babbage.com',
2960- ... distroarchseries=ubuntu['hoary']['i386'])
2961- >>> submission.status = HWSubmissionProcessingStatus.PROCESSED
2962-
2963-Now we have three submitters, two of them own our Seagate disk.
2964-
2965- >>> submission_set.numOwnersOfDevice(
2966- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ')
2967- (2L, 3L)
2968-
2969-We can limit the results to a given driver.
2970-
2971- >>> print(submission_set.numOwnersOfDevice(
2972- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2973- ... driver_name='sd'))
2974- (2L, 3L)
2975- >>> print(submission_set.numOwnersOfDevice(
2976- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
2977- ... driver_name='usb'))
2978- (0L, 3L)
2979-
2980-We can also ask for submitters who use a given driver with any device.
2981-
2982- >>> print(submission_set.numOwnersOfDevice(
2983- ... driver_name='sd'))
2984- (2L, 3L)
2985-
2986-This count can be limited to a given package.
2987-
2988- >>> print(submission_set.numOwnersOfDevice(
2989- ... driver_name='sd', package_name='linux-image-2.6.24-19-generic'))
2990- (1L, 3L)
2991-
2992-While the parameters for a device or a driver are optional, specifying
2993-neither of them leads to an error.
2994-
2995- >>> print(submission_set.numOwnersOfDevice())
2996- Traceback (most recent call last):
2997- ...
2998- ParameterError: Specify (bus, vendor_id, product_id) or driver_name.
2999-
3000-We can limit the count to a distibution...
3001-
3002- >>> print(submission_set.numOwnersOfDevice(
3003- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3004- ... distro_target=ubuntu))
3005- (1L, 2L)
3006- >>> print(submission_set.numOwnersOfDevice(
3007- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3008- ... distro_target=debian))
3009- (0L, 0L)
3010-
3011-...to a distroseries...
3012-
3013- >>> print(submission_set.numOwnersOfDevice(
3014- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3015- ... distro_target=ubuntu['hoary']))
3016- (1L, 2L)
3017- >>> print(submission_set.numOwnersOfDevice(
3018- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3019- ... distro_target=ubuntu['warty']))
3020- (0L, 0L)
3021-
3022-...or to a distroarchseries.
3023-
3024- >>> print(submission_set.numOwnersOfDevice(
3025- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3026- ... distro_target=ubuntu['hoary']['i386']))
3027- (1L, 2L)
3028- >>> print(submission_set.numOwnersOfDevice(
3029- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3030- ... distro_target=ubuntu['hoary']['hppa']))
3031- (0L, 0L)
3032-
3033-We can specify a distro target as well as a driver or package name.
3034-
3035- >>> print(submission_set.numOwnersOfDevice(
3036- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3037- ... driver_name='sd', distro_target=ubuntu['hoary']['i386']))
3038- (1L, 2L)
3039- >>> print(submission_set.numOwnersOfDevice(
3040- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3041- ... driver_name='nosense', distro_target=ubuntu['hoary']['i386']))
3042- (0L, 2L)
3043-
3044- >>> print(submission_set.numOwnersOfDevice(
3045- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3046- ... package_name='linux-image-2.6.24-19-generic',
3047- ... distro_target=ubuntu['hoary']['i386']))
3048- (1L, 2L)
3049- >>> print(submission_set.numOwnersOfDevice(
3050- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3051- ... package_name='nonsense', distro_target=ubuntu['hoary']['i386']))
3052- (0L, 2L)
3053-
3054- >>> print(submission_set.numOwnersOfDevice(
3055- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3056- ... driver_name='sd', package_name='linux-image-2.6.24-19-generic',
3057- ... distro_target=ubuntu['hoary']['i386']))
3058- (1L, 2L)
3059- >>> print(submission_set.numOwnersOfDevice(
3060- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3061- ... driver_name='nonsense',
3062- ... package_name='linux-image-2.6.24-19-generic',
3063- ... distro_target=ubuntu['hoary']['i386']))
3064- (0L, 2L)
3065-
3066-
3067-Relations between bugs and HWDB submissions
3068--------------------------------------------
3069-
3070-We can query which owners of a device, or which people owning a device
3071-controlled by a given driver, are related to a set of bugs. We must
3072-specify a device's bus, vendor ID and product ID and one or more bugs.
3073-
3074-By default, only bug reporters are looked up. Sample Person has made
3075-a hardware report containing the IDE disk Seagate ST3250820NS, and
3076-they have filed bug 1.
3077-
3078- >>> from lp.bugs.interfaces.bug import IBugSet
3079- >>> bug_set = getUtility(IBugSet)
3080- >>> bug_one = bug_set.get(1)
3081- >>> print(bug_one.owner.displayname)
3082- Sample Person
3083- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3084- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3085- ... bug_ids=[1]):
3086- ... print(person.displayname)
3087- Sample Person
3088-
3089-If Foo Bar says that they are affected by this bug, they will be listed
3090-too, since they too own the Seagate disk.
3091-
3092- >>> foo_bar = getUtility(IPersonSet).getByEmail('foo.bar@canonical.com')
3093- >>> bug_one = bug_set.get(1)
3094- >>> bug_one.markUserAffected(foo_bar)
3095- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3096- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3097- ... bug_ids=[1], affected_by_bug=True):
3098- ... print(person.displayname)
3099- Foo Bar
3100- Sample Person
3101-
3102-When they say that they are not affected by the bug, they will no longer
3103-be listed.
3104-
3105- >>> bug_one.markUserAffected(foo_bar, False)
3106- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3107- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3108- ... bug_ids=[1], affected_by_bug=True):
3109- ... print(person.displayname)
3110- Sample Person
3111-
3112-By setting the parameter subscribed_to_bug to True, we can also look
3113-for bug subscribers who own a given device.
3114-
3115- >>> bug_one.subscribe(foo_bar, subscribed_by=foo_bar)
3116- <lp.bugs.model.bugsubscription.BugSubscription ...>
3117- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3118- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3119- ... bug_ids=[1], subscribed_to_bug=True):
3120- ... print(person.displayname)
3121- Foo Bar
3122- Sample Person
3123-
3124- >>> bug_one.unsubscribe(foo_bar, unsubscribed_by=foo_bar)
3125- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3126- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3127- ... bug_ids=[1], subscribed_to_bug=True):
3128- ... print(person.displayname)
3129- Sample Person
3130-
3131-We can specify more than one bug ID. If we specify bugs 1 and 3,
3132-deviceDriverOwnersAffectedByBugs() returns again Sample Person and
3133-Foo Bar.
3134-
3135- >>> bug_three = bug_set.get(3)
3136- >>> print(bug_three.owner.displayname)
3137- Foo Bar
3138- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3139- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3140- ... bug_ids=[1, 3]):
3141- ... print(person.displayname)
3142- Foo Bar
3143- Sample Person
3144-
3145-Instead of passing a seqence of bug IDs, we can also specify one or
3146-more bug tags.
3147-
3148- >>> from lp.services.searchbuilder import any
3149- >>> from lp.bugs.interfaces.bugtask import IBugTaskSet
3150- >>> from lp.bugs.interfaces.bugtasksearch import BugTaskSearchParams
3151-
3152- >>> bugtask_set = getUtility(IBugTaskSet)
3153- >>> bugtasks = bugtask_set.search(
3154- ... BugTaskSearchParams(user=foo_bar, tag=any('pebcak')))
3155- >>> owners = set(bugtask.bug.owner for bugtask in bugtasks)
3156- >>> for owner in owners:
3157- ... print(owner.displayname)
3158- Sample Person
3159- >>> bugtasks = bugtask_set.search(
3160- ... BugTaskSearchParams(user=foo_bar, tag=any('crash')))
3161- >>> owners = set(bugtask.bug.owner for bugtask in bugtasks)
3162- >>> for owner in owners:
3163- ... print(owner.displayname)
3164- Foo Bar
3165-
3166- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3167- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3168- ... bug_tags=['pebcak']):
3169- ... print(person.displayname)
3170- Sample Person
3171-
3172- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3173- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3174- ... bug_tags=['pebcak', 'crash']):
3175- ... print(person.displayname)
3176- Foo Bar
3177- Sample Person
3178-
3179- >>> submission_set.deviceDriverOwnersAffectedByBugs(
3180- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3181- ... bug_tags=['lunch-money']).count()
3182- 0
3183-
3184-We can limit the result to owners who use a device with a given driver
3185-by providing a driver_name parameter...
3186-
3187- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3188- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3189- ... driver_name='sd', bug_tags=['pebcak', 'crash']):
3190- ... print(person.displayname)
3191- Foo Bar
3192- Sample Person
3193-
3194- >>> print(submission_set.deviceDriverOwnersAffectedByBugs(
3195- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3196- ... driver_name='nonsense', bug_tags=['pebcak', 'crash']).count())
3197- 0
3198-
3199-...or a given package name by providing a package_name parameter.
3200-
3201- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3202- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3203- ... package_name='linux-image-2.6.24-19-generic',
3204- ... bug_tags=['pebcak', 'crash']):
3205- ... print(person.displayname)
3206- Sample Person
3207-
3208- >>> print(submission_set.deviceDriverOwnersAffectedByBugs(
3209- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3210- ... package_name='nonsense', bug_tags=['pebcak', 'crash']).count())
3211- 0
3212-
3213-Owners of private submissions are only included if the optional parameter
3214-`user` is the owner or an admin.
3215-
3216- >>> private_submission = factory.makeHWSubmission(
3217- ... emailaddress='no-priv@canonical.com', private=True)
3218- >>> switch_dbuser('hwdb-submission-processor')
3219- >>> first_device = factory.makeHWSubmissionDevice(
3220- ... private_submission, ide_disk, None, None, 1)
3221- >>> switch_dbuser('launchpad')
3222- >>> no_priv = getUtility(IPersonSet).getByEmail('no-priv@canonical.com')
3223- >>> bug_one.subscribe(no_priv, subscribed_by=no_priv)
3224- <lp.bugs.model.bugsubscription.BugSubscription ...>
3225- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3226- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3227- ... bug_ids=[1], subscribed_to_bug=True, user=no_priv):
3228- ... print(person.displayname)
3229- No Privileges Person
3230- Sample Person
3231-
3232- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3233- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3234- ... bug_ids=[1], subscribed_to_bug=True, user=foo_bar):
3235- ... print(person.displayname)
3236- No Privileges Person
3237- Sample Person
3238-
3239- >>> sample_person = getUtility(IPersonSet).getByEmail(
3240- ... 'test@canonical.com')
3241- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3242- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3243- ... bug_ids=[1], subscribed_to_bug=True, user=sample_person):
3244- ... print(person.displayname)
3245- Sample Person
3246-
3247- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3248- ... bus=HWBus.IDE, vendor_id='SEAGATE', product_id='ST3250820NS ',
3249- ... bug_ids=[1], subscribed_to_bug=True):
3250- ... print(person.displayname)
3251- Sample Person
3252-
3253-
3254-Searching for drivers instead of devices
3255-........................................
3256-
3257-We can also look for people using a given driver and being affected by a
3258-bug.
3259-
3260- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3261- ... driver_name='sd', bug_ids=[1]):
3262- ... print(person.displayname)
3263- Sample Person
3264-
3265-If Foo Bar says that they are affected by this bug, they will be listed
3266-too, since their machine too uses the sd driver.
3267-
3268- >>> bug_one.markUserAffected(foo_bar)
3269- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3270- ... driver_name='sd', bug_ids=[1], affected_by_bug=True):
3271- ... print(person.displayname)
3272- Foo Bar
3273- Sample Person
3274-
3275-They are also listed if they subscribe to bug 1.
3276-
3277- >>> bug_one.markUserAffected(foo_bar, False)
3278- >>> bug_one.subscribe(foo_bar, subscribed_by=foo_bar)
3279- <lp.bugs.model.bugsubscription.BugSubscription ...>
3280- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3281- ... driver_name='sd', bug_ids=[1], subscribed_to_bug=True):
3282- ... print(person.displayname)
3283- Foo Bar
3284- Sample Person
3285-
3286-We can specify more than one bug ID. If we specify bugs 1 and 3,
3287-deviceDriverOwnersAffectedByBugs() returns again Sample Person and
3288-Foo Bar.
3289-
3290- >>> bug_one.unsubscribe(foo_bar, unsubscribed_by=foo_bar)
3291- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3292- ... driver_name='sd', bug_ids=[1, 3]):
3293- ... print(person.displayname)
3294- Foo Bar
3295- Sample Person
3296-
3297-Instead of passing a sequence of bug IDs, we can also specify one or
3298-more bug tags.
3299-
3300- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3301- ... driver_name='sd', bug_tags=['pebcak']):
3302- ... print(person.displayname)
3303- Sample Person
3304-
3305- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3306- ... driver_name='sd', bug_tags=['pebcak', 'crash']):
3307- ... print(person.displayname)
3308- Foo Bar
3309- Sample Person
3310-
3311- >>> submission_set.deviceDriverOwnersAffectedByBugs(
3312- ... driver_name='sd', bug_tags=['lunch-money']).count()
3313- 0
3314-
3315-We can also query for both bug ids and bug tags together.
3316-
3317- >>> for person in submission_set.deviceDriverOwnersAffectedByBugs(
3318- ... driver_name='sd', bug_ids=[2], bug_tags=['pebcak']):
3319- ... print(person.displayname)
3320- Sample Person
3321-
3322-Also, confirm that nothing is returned where there is no matching
3323-tag on a given bug id.
3324-
3325- >>> print(len(list(submission_set.deviceDriverOwnersAffectedByBugs(
3326- ... driver_name='sd', bug_ids=[3], bug_tags=['pebcak']))))
3327- 0
3328-
3329-If neither a device nor a driver name is specified,
3330-deviceDriverOwnersAffectedByBugs() raises an error.
3331-
3332- >>> submission_set.deviceDriverOwnersAffectedByBugs(
3333- ... bug_tags=['lunch-money'])
3334- Traceback (most recent call last):
3335- ...
3336- ParameterError: Specify (bus, vendor_id, product_id) or driver_name.
3337-
3338-If one of the parameters bus, vendor_id, product_id is supplied, the
3339-others must be supplied too.
3340-
3341- >>> submission_set.deviceDriverOwnersAffectedByBugs(
3342- ... bus=HWBus.IDE, bug_ids=[1], subscribed_to_bug=True)
3343- Traceback (most recent call last):
3344- ...
3345- ParameterError: Either specify bus, vendor_id and product_id or none
3346- of them.
3347-
3348-For a given bug, we can get a list of devices by device owner.
3349-The result is a tuple of (owner_id, bus_number, vender_id, product_id).
3350-
3351- >>> sample_person = getUtility(IPersonSet).getByName('name12')
3352-
3353- >>> for entry in submission_set.hwInfoByBugRelatedUsers(
3354- ... bug_ids=[1]):
3355- ... print(entry)
3356- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
3357- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
3358- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
3359- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x045d')
3360- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x8086', u'0x27cc')
3361- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x04b4', u'0x6560')
3362- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x07b3', u'0x0017')
3363- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x0dda', u'0x2026')
3364- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x8086', u'0x1234')
3365- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'Optiarc', u'DVD RW AD-7170S ')
3366- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'SEAGATE', u'ST3250820NS ')
3367-
3368-This method can also take a list of bugs.
3369-
3370- >>> for entry in submission_set.hwInfoByBugRelatedUsers(
3371- ... bug_ids=[1, 3]):
3372- ... print(entry)
3373- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
3374- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
3375- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
3376- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x045d')
3377- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x8086', u'0x27cc')
3378- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x04b4', u'0x6560')
3379- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x07b3', u'0x0017')
3380- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x0dda', u'0x2026')
3381- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x8086', u'0x1234')
3382- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'Optiarc', u'DVD RW AD-7170S ')
3383- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'SEAGATE', u'ST3250820NS ')
3384- (u'name16', <DBItem HWBus.IDE, (7) IDE>, u'SEAGATE', u'ST3250820NS ')
3385-
3386-We can also query for bug tags instead of bug numbers.
3387-
3388- >>> for entry in submission_set.hwInfoByBugRelatedUsers(
3389- ... bug_tags=['pebcak']):
3390- ... print(entry)
3391- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
3392- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
3393- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
3394- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x045d')
3395- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x8086', u'0x27cc')
3396- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x04b4', u'0x6560')
3397- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x07b3', u'0x0017')
3398- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x0dda', u'0x2026')
3399- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x8086', u'0x1234')
3400- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'Optiarc', u'DVD RW AD-7170S ')
3401- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'SEAGATE', u'ST3250820NS ')
3402-
3403- >>> for entry in submission_set.hwInfoByBugRelatedUsers(
3404- ... bug_tags=['pebcak', 'crash']):
3405- ... print(entry)
3406- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
3407- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
3408- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
3409- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x045d')
3410- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x8086', u'0x27cc')
3411- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x04b4', u'0x6560')
3412- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x07b3', u'0x0017')
3413- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x0dda', u'0x2026')
3414- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x8086', u'0x1234')
3415- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'Optiarc', u'DVD RW AD-7170S ')
3416- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'SEAGATE', u'ST3250820NS ')
3417- (u'name16', <DBItem HWBus.IDE, (7) IDE>, u'SEAGATE', u'ST3250820NS ')
3418-
3419-We can also query for both bug ids and bug tags together.
3420-
3421- >>> for entry in submission_set.hwInfoByBugRelatedUsers(
3422- ... bug_ids=[2], bug_tags=['pebcak']):
3423- ... print(entry)
3424- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
3425- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
3426- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
3427- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x045d')
3428- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x8086', u'0x27cc')
3429- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x04b4', u'0x6560')
3430- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x07b3', u'0x0017')
3431- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x0dda', u'0x2026')
3432- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x8086', u'0x1234')
3433- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'Optiarc', u'DVD RW AD-7170S ')
3434- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'SEAGATE', u'ST3250820NS ')
3435-
3436-Also, confirm that nothing is returned where there is no matching
3437-tag on a given bug id.
3438-
3439- >>> print(len(submission_set.hwInfoByBugRelatedUsers(
3440- ... bug_ids=[3], bug_tags=['pebcak'])))
3441- 0
3442-
3443-This method can also be used to list devices where the
3444-device owner is affected by the bug.
3445-
3446- >>> bug_one.markUserAffected(foo_bar)
3447-
3448- >>> for entry in submission_set.hwInfoByBugRelatedUsers(
3449- ... bug_ids=[1], affected_by_bug=True):
3450- ... print(entry)
3451- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
3452- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
3453- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
3454- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x045d')
3455- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x8086', u'0x27cc')
3456- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x04b4', u'0x6560')
3457- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x07b3', u'0x0017')
3458- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x0dda', u'0x2026')
3459- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x8086', u'0x1234')
3460- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'Optiarc', u'DVD RW AD-7170S ')
3461- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'SEAGATE', u'ST3250820NS ')
3462- (u'name16', <DBItem HWBus.IDE, (7) IDE>, u'SEAGATE', u'ST3250820NS ')
3463-
3464- >>> bug_one.markUserAffected(foo_bar, False)
3465-
3466-We can also check for when the user is subscribed to the bug.
3467-
3468- >>> bug_one.subscribe(foo_bar, subscribed_by=foo_bar)
3469- <lp.bugs.model.bugsubscription.BugSubscription ...>
3470-
3471- >>> for entry in submission_set.hwInfoByBugRelatedUsers(
3472- ... bug_ids=[1], subscribed_to_bug=True):
3473- ... print(entry)
3474- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
3475- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
3476- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
3477- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x045d')
3478- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x8086', u'0x27cc')
3479- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x04b4', u'0x6560')
3480- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x07b3', u'0x0017')
3481- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x0dda', u'0x2026')
3482- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x8086', u'0x1234')
3483- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'Optiarc', u'DVD RW AD-7170S ')
3484- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'SEAGATE', u'ST3250820NS ')
3485- (u'name16', <DBItem HWBus.IDE, (7) IDE>, u'SEAGATE', u'ST3250820NS ')
3486-
3487- >>> bug_one.unsubscribe(foo_bar, unsubscribed_by=foo_bar)
3488-
3489-Data from private submissions is not included by default.
3490-The owner of a private submission can see their submission.
3491-
3492- >>> bug_one.subscribe(no_priv, subscribed_by=no_priv)
3493- <lp.bugs.model.bugsubscription.BugSubscription ...>
3494-
3495- >>> for entry in submission_set.hwInfoByBugRelatedUsers(
3496- ... bug_ids=[1], subscribed_to_bug=True, user=no_priv):
3497- ... print(entry)
3498- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
3499- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
3500- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
3501- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x045d')
3502- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x8086', u'0x27cc')
3503- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x04b4', u'0x6560')
3504- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x07b3', u'0x0017')
3505- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x0dda', u'0x2026')
3506- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x8086', u'0x1234')
3507- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'Optiarc', u'DVD RW AD-7170S ')
3508- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'SEAGATE', u'ST3250820NS ')
3509- (u'no-priv', <DBItem HWBus.IDE, (7) IDE>, u'SEAGATE', u'ST3250820NS ')
3510-
3511-An admin can also see no_priv's private entry.
3512-
3513- >>> for entry in submission_set.hwInfoByBugRelatedUsers(
3514- ... bug_ids=[1], subscribed_to_bug=True, user=foo_bar):
3515- ... print(entry)
3516- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
3517- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
3518- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
3519- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x045d')
3520- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x8086', u'0x27cc')
3521- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x04b4', u'0x6560')
3522- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x07b3', u'0x0017')
3523- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x0dda', u'0x2026')
3524- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x8086', u'0x1234')
3525- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'Optiarc', u'DVD RW AD-7170S ')
3526- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'SEAGATE', u'ST3250820NS ')
3527- (u'no-priv', <DBItem HWBus.IDE, (7) IDE>, u'SEAGATE', u'ST3250820NS ')
3528-
3529-But sample_person cannot see the private entry because they
3530-are not the owner or an admin.
3531-
3532- >>> for entry in submission_set.hwInfoByBugRelatedUsers(
3533- ... bug_ids=[1], subscribed_to_bug=True, user=sample_person):
3534- ... print(entry)
3535- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'MSI', u'MS-7369')
3536- (u'name12', <DBItem HWBus.SYSTEM, (0) System>, u'Tonka', u'Tuffbook 2600')
3537- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x0455')
3538- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x10de', u'0x045d')
3539- (u'name12', <DBItem HWBus.PCI, (1) PCI>, u'0x8086', u'0x27cc')
3540- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x04b4', u'0x6560')
3541- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x07b3', u'0x0017')
3542- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x0dda', u'0x2026')
3543- (u'name12', <DBItem HWBus.USB, (2) USB>, u'0x8086', u'0x1234')
3544- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'Optiarc', u'DVD RW AD-7170S ')
3545- (u'name12', <DBItem HWBus.IDE, (7) IDE>, u'SEAGATE', u'ST3250820NS ')
3546-
3547- >>> bug_one.unsubscribe(no_priv, unsubscribed_by=no_priv)
3548diff --git a/lib/lp/hardwaredb/doc/hwdb.txt b/lib/lp/hardwaredb/doc/hwdb.txt
3549deleted file mode 100644
3550index a29c585..0000000
3551--- a/lib/lp/hardwaredb/doc/hwdb.txt
3552+++ /dev/null
3553@@ -1,739 +0,0 @@
3554-= Hardware database =
3555-
3556-== Storage of raw submissions for the hardware database ==
3557-
3558-The hardware database clients submits an XML file with collected hardware
3559-information and other data. This file is stored without any parsing in a
3560-librarian file. A reference to this file is stored in the table HWSubmission,
3561-together with the following data:
3562-
3563-
3564- >>> from lp.hardwaredb.interfaces.hwdb import IHWSubmissionSet
3565- >>> sample_submission = getUtility(IHWSubmissionSet).getBySubmissionKey(
3566- ... 'sample-submission')
3567-
3568- * reference to the librarian file.
3569-
3570- >>> print(sample_submission.raw_submission)
3571- <...LibraryFileAlias instance at ...>
3572-
3573- * date_created: Date and time of the submission (generated by the client).
3574-
3575- This value is not very reliable:
3576- * Some users do not care to set the correct time, date and time zone.
3577- * Some machines have a broken CMOS battery and the user does not set
3578- date and time after every boot.
3579-
3580- >>> print(sample_submission.date_created)
3581- 2008-09-26 17:19:18+00:00
3582-
3583- * date_submitted: Date and time of the submission (generated by the server).
3584-
3585- >>> print(sample_submission.date_submitted)
3586- 2008-09-30 08:19:00.222131+00:00
3587-
3588- * format: The format version of the submitted data, as given by the HWDB
3589- client. See HWSubmissionFormat for valid values.
3590-
3591- >>> print(sample_submission.format.name)
3592- VERSION_1
3593-
3594- * status: The status of the submission. See HWSubmissionProcessingStatus for
3595- valid values.
3596-
3597- >>> print(sample_submission.status.name)
3598- PROCESSED
3599-
3600- * private: If True, the submitter allows public access to the data. If
3601- false, the data may be used only for statistical purposes.
3602-
3603- >>> print(sample_submission.private)
3604- False
3605-
3606- * contactable: If True, the submitter agrees to be contacted by upstream
3607- developers and package maintainers for tests etc.
3608-
3609- >>> print(sample_submission.contactable)
3610- False
3611-
3612- * submission_key: A unique submission ID.
3613-
3614- >>> print(sample_submission.submission_key)
3615- sample-submission
3616-
3617- * raw_emailaddress: The email address of the submitter.
3618-
3619- >>> print(sample_submission.raw_emailaddress)
3620- test@canonical.com
3621-
3622- * owner: A reference to the Person table. This value is null, if the email
3623- address does not belong (yet) to an entry in Person table.
3624-
3625- >>> print(sample_submission.owner.displayname)
3626- Sample Person
3627-
3628- * distroarchseries: A reference to the distroarchseries of the submission.
3629- This value is null, if the submitted values for distribution,
3630- distroseries and architecture do not match an existing entry in the
3631- Distroarchrelease table.
3632-
3633- >>> print(sample_submission.distroarchseries.architecturetag)
3634- i386
3635-
3636- >>> print(sample_submission.distroarchseries.distroseries.name)
3637- hoary
3638-
3639- >>> print(
3640- ... sample_submission.distroarchseries.distroseries.distribution.name)
3641- ubuntu
3642-
3643- * system_fingerprint: A reference to an entry of the HWSystemFingerprint
3644- table. This table stores the system name as returned by HAL
3645- (system.vendor, system.product).
3646-
3647- >>> print(sample_submission.system_fingerprint.fingerprint)
3648- MSI MS-7369
3649-
3650- * devices: The set set of HWSubmissionDevice records which belong to
3651- this submission.
3652-
3653- Access to all data except submissions is restricted to members of
3654- the Canonical team.
3655-
3656- >>> login('foo.bar@canonical.com')
3657- >>> for submission_device in sample_submission.devices[:2]:
3658- ... print(submission_device.device.name)
3659- MCP65 USB Controller
3660- MCP65 SATA Controller
3661- >>> login(ANONYMOUS)
3662-
3663-Limitations:
3664- * "No name" products like mainboards from companies like ASRock
3665- or Asus that are directly sold to end users have fingerprints like
3666- "American Megatrends Inc. Unknown 1.0".
3667- * A manufacturer may erroneously assign identical DMI values for product
3668- and vendor to different systems.
3669- * submissions for "counterfeit systems".
3670- * users submitting bogus values using a patched HWDB client.
3671-
3672-The system fingerprint is stored in a separate table, HWSystemFingerprint.
3673-IHWSystemFingerPrintSet.createFingerprint creates a new row in this table.
3674-
3675- >>> from lp.hardwaredb.interfaces.hwdb import IHWSystemFingerprintSet
3676- >>> from storm.store import Store
3677- >>> hw_fingerprint_set = getUtility(IHWSystemFingerprintSet)
3678- >>> fp = hw_fingerprint_set.createFingerprint(u'IBM T41')
3679- >>> fp.fingerprint
3680- u'IBM T41'
3681-
3682-Each fingerprint string in HWSystemFingerprint must be unique.
3683-
3684- >>> import transaction
3685- >>> transaction.commit()
3686- >>> fp = hw_fingerprint_set.createFingerprint(u'IBM T41')
3687- >>> Store.of(fp).flush()
3688- Traceback (most recent call last):
3689- ...
3690- IntegrityError: ... violates unique constraint "hwsystemfingerprint...
3691- <BLANKLINE>
3692-
3693- >>> transaction.abort()
3694-
3695-IHWSystemFingerprint.getByName returns a fingerprint...
3696-
3697- >>> fp = hw_fingerprint_set.getByName(u'IBM T41')
3698- >>> fp.fingerprint
3699- u'IBM T41'
3700-
3701-...or None, if no entry exists.
3702-
3703- >>> print(hw_fingerprint_set.getByName(u'DEC PDP11'))
3704- None
3705-
3706-IHWSubmissionSet.createSubmission creates a new entry in the
3707-HWSubmission table.
3708-
3709- >>> import pytz
3710- >>> from StringIO import StringIO
3711- >>> from datetime import datetime
3712- >>> from lp.hardwaredb.interfaces.hwdb import (
3713- ... HWSubmissionFormat,
3714- ... IHWSubmissionSet,
3715- ... )
3716- >>> date_created = datetime(2007, 4, 1, tzinfo=pytz.timezone('UTC'))
3717- >>> date_submitted = datetime(2007, 4, 2, tzinfo=pytz.timezone('UTC'))
3718- >>> submission_data = 'submission data'
3719- >>> hw_submission_set = getUtility(IHWSubmissionSet)
3720- >>> submission = hw_submission_set.createSubmission(
3721- ... date_created=date_created,
3722- ... format=HWSubmissionFormat.VERSION_1,
3723- ... private=False,
3724- ... contactable=False,
3725- ... submission_key=u'unique-id-1',
3726- ... emailaddress=u'test@canonical.com',
3727- ... distroarchseries=None,
3728- ... raw_submission=StringIO(submission_data),
3729- ... filename=u'hwinfo.txt',
3730- ... filesize=len(submission_data),
3731- ... system_fingerprint=u'Dell Inspiron 1234')
3732-
3733-submission_key must be unique. The attempt to create a HWSubmission entry
3734-with an already existing submission_key raises HWSubmissionError.
3735-
3736- >>> submission = hw_submission_set.createSubmission(
3737- ... date_created=date_created,
3738- ... format=HWSubmissionFormat.VERSION_1,
3739- ... private=False,
3740- ... contactable=False,
3741- ... submission_key=u'unique-id-1',
3742- ... emailaddress=u'test@canonical.com',
3743- ... distroarchseries=None,
3744- ... raw_submission=StringIO(submission_data),
3745- ... filename=u'hwinfo.txt',
3746- ... filesize=len(submission_data),
3747- ... system_fingerprint=u'Dell Inspiron 1234')
3748- Traceback (most recent call last):
3749- ...
3750- HWSubmissionKeyNotUnique: A submission with this ID already exists
3751-
3752-The field `owner` points to the Person record of the submitter, if the
3753-submitted emailaddress belongs to an existing Launchpad account.
3754-
3755- >>> submission.owner.displayname
3756- u'Sample Person'
3757-
3758-If no Person record is yet known for the submitter's email address,
3759-the field `owner` is None.
3760-
3761- >>> from lp.registry.interfaces.person import IPersonSet
3762- >>> beeblebrox = getUtility(IPersonSet).getByEmail(
3763- ... 'beeblebrox@example.com')
3764- >>> print(beeblebrox)
3765- None
3766-
3767- >>> submission = hw_submission_set.createSubmission(
3768- ... date_created=date_created,
3769- ... format=HWSubmissionFormat.VERSION_1,
3770- ... private=False,
3771- ... contactable=False,
3772- ... submission_key=u'unique-id-2',
3773- ... emailaddress=u'beeblebrox@example.com',
3774- ... distroarchseries=None,
3775- ... raw_submission=StringIO(submission_data),
3776- ... filename=u'hwinfo.txt',
3777- ... filesize=len(submission_data),
3778- ... system_fingerprint=u'Acer 6789')
3779- >>> print(submission.owner)
3780- None
3781-
3782-The submitted data can be retrieved via IHWSubmissionSet.getBySubmissionKey.
3783-
3784- >>> submission = hw_submission_set.getBySubmissionKey(u'unique-id-1')
3785- >>> submission.submission_key, submission.system_fingerprint.fingerprint
3786- (u'unique-id-1', u'Dell Inspiron 1234')
3787-
3788-If a submission is marked as private, it is only returned by
3789-IHWSubmissionSet.getBySubmissionKey if the parameter `user` matches the
3790-owner of the submission...
3791-
3792- >>> submission = hw_submission_set.createSubmission(
3793- ... date_created=date_created,
3794- ... format=HWSubmissionFormat.VERSION_1,
3795- ... private=True,
3796- ... contactable=False,
3797- ... submission_key=u'private-submission',
3798- ... emailaddress=u'test@canonical.com',
3799- ... distroarchseries=None,
3800- ... raw_submission=StringIO(submission_data),
3801- ... filename=u'hwinfo.txt',
3802- ... filesize=len(submission_data),
3803- ... system_fingerprint=u'Dell Inspiron 1234')
3804- >>> print(hw_submission_set.getBySubmissionKey(u'private-submission'))
3805- None
3806- >>> sample_person = getUtility(IPersonSet).getByEmail('test@canonical.com')
3807- >>> sample_person.displayname
3808- u'Sample Person'
3809- >>> submission = hw_submission_set.getBySubmissionKey(
3810- ... u'private-submission', sample_person)
3811- >>> submission
3812- <HWSubmission at ...>
3813-
3814-... or if `user` is an admin.
3815-
3816- >>> foobar = getUtility(IPersonSet).getByEmail('foo.bar@canonical.com')
3817- >>> submission = hw_submission_set.getBySubmissionKey(
3818- ... u'private-submission', foobar)
3819- >>> submission
3820- <HWSubmission at ...>
3821-
3822-Only the owner and admins can view the submission details.
3823-
3824- >>> submission.submission_key, submission.system_fingerprint.fingerprint
3825- Traceback (most recent call last):
3826- ...
3827- Unauthorized: (...'submission_key', 'launchpad.View')
3828-
3829- >>> login('test@canonical.com')
3830- >>> submission.submission_key, submission.system_fingerprint.fingerprint
3831- (u'private-submission', u'Dell Inspiron 1234')
3832-
3833- >>> login('foo.bar@canonical.com')
3834- >>> submission.submission_key, submission.system_fingerprint.fingerprint
3835- (u'private-submission', u'Dell Inspiron 1234')
3836-
3837-Passing another person than the owner or an admin as the parameter `user`
3838-does not return private submissions.
3839-
3840- >>> no_priv = getUtility(IPersonSet).getByEmail('no-priv@canonical.com')
3841- >>> no_priv.displayname
3842- u'No Privileges Person'
3843- >>> print(hw_submission_set.getBySubmissionKey(u'private-submission',
3844- ... no_priv))
3845- None
3846-
3847- >>> login(ANONYMOUS)
3848-
3849-If no submission exists for a given ID, None is returned.
3850-
3851- >>> print(hw_submission_set.getBySubmissionKey(u'unknown-ID'))
3852- None
3853-
3854-IHWSubmissionSet.getByFingerprintName returns all submissions for a
3855-given fingerprint name. Private submissions are excluded, if the parameter
3856-`user` is omitted or if user is neither the owner nor an admin.
3857-
3858- >>> submissions = hw_submission_set.getByFingerprintName(
3859- ... u'Dell Inspiron 1234')
3860- >>> [(s.submission_key, s.system_fingerprint.fingerprint, s.private)
3861- ... for s in submissions]
3862- [(u'unique-id-1', u'Dell Inspiron 1234', False)]
3863- >>> submissions = hw_submission_set.getByFingerprintName(
3864- ... u'Dell Inspiron 1234', no_priv)
3865- >>> [(s.submission_key, s.system_fingerprint.fingerprint, s.private)
3866- ... for s in submissions]
3867- [(u'unique-id-1', u'Dell Inspiron 1234', False)]
3868- >>> login('test@canonical.com')
3869- >>> submissions = hw_submission_set.getByFingerprintName(
3870- ... u'Dell Inspiron 1234', sample_person)
3871- >>> [(s.submission_key, s.system_fingerprint.fingerprint, s.private)
3872- ... for s in submissions]
3873- [(u'private-submission', u'Dell Inspiron 1234', True),
3874- (u'unique-id-1', u'Dell Inspiron 1234', False)]
3875- >>> submissions = hw_submission_set.getByFingerprintName(
3876- ... u'Dell Inspiron 1234', foobar)
3877- >>> [(s.submission_key, s.system_fingerprint.fingerprint, s.private)
3878- ... for s in submissions]
3879- [(u'private-submission', u'Dell Inspiron 1234', True),
3880- (u'unique-id-1', u'Dell Inspiron 1234', False)]
3881-
3882-If no submissions exist for the given system fingerprint, an empty result
3883-set is returned.
3884-
3885- >>> list(hw_submission_set.getByFingerprintName('DEC PDP11'))
3886- []
3887-
3888-IHWSubmissionSet.getByOwner returns all submissions of a person. Again,
3889-only non-private submissions are returned if no parameter `user` is passed
3890-to the method, or if the passed parameter is neither the owner nor an admin.
3891-
3892- >>> submissions = hw_submission_set.getByOwner(sample_person)
3893- >>> [(s.submission_key, s.system_fingerprint.fingerprint)
3894- ... for s in submissions]
3895- [(u'unique-id-1', u'Dell Inspiron 1234'),
3896- (u'sample-submission', u'MSI MS-7369'),
3897- (u'test_submission_id_1', u'TONKA TUFFBOOK2600')]
3898- >>> submissions = hw_submission_set.getByOwner(sample_person,
3899- ... user=no_priv)
3900- >>> [(s.submission_key, s.system_fingerprint.fingerprint)
3901- ... for s in submissions]
3902- [(u'unique-id-1', u'Dell Inspiron 1234'),
3903- (u'sample-submission', u'MSI MS-7369'),
3904- (u'test_submission_id_1', u'TONKA TUFFBOOK2600')]
3905- >>> submissions = hw_submission_set.getByOwner(sample_person,
3906- ... user=sample_person)
3907- >>> [(s.submission_key, s.system_fingerprint.fingerprint)
3908- ... for s in submissions]
3909- [(u'private-submission', u'Dell Inspiron 1234'),
3910- (u'unique-id-1', u'Dell Inspiron 1234'),
3911- (u'sample-submission', u'MSI MS-7369'),
3912- (u'test_submission_id_1', u'TONKA TUFFBOOK2600')]
3913- >>> submissions = hw_submission_set.getByOwner(sample_person,
3914- ... user=foobar)
3915- >>> [(s.submission_key, s.system_fingerprint.fingerprint)
3916- ... for s in submissions]
3917- [(u'private-submission', u'Dell Inspiron 1234'),
3918- (u'unique-id-1', u'Dell Inspiron 1234'),
3919- (u'sample-submission', u'MSI MS-7369'),
3920- (u'test_submission_id_1', u'TONKA TUFFBOOK2600')]
3921-
3922-When an anonymous submitter later registers a Launchpad account, the field
3923-`owner` is updated.
3924-
3925- >>> from lp.services.identity.interfaces.emailaddress import IEmailAddressSet
3926- >>> from lp.registry.interfaces.person import PersonCreationRationale
3927- >>> user = getUtility(IPersonSet).ensurePerson(
3928- ... u'beeblebrox@example.com', u'Beeblebrox',
3929- ... PersonCreationRationale.OWNER_CREATED_LAUNCHPAD)
3930- >>> email = getUtility(IEmailAddressSet).getByEmail(
3931- ... u'beeblebrox@example.com')
3932- >>> user.validateAndEnsurePreferredEmail(email)
3933- >>> transaction.commit()
3934- >>> from lp.scripts.garbo import HWSubmissionEmailLinker
3935- >>> from lp.services.log.logger import DevNullLogger
3936- >>> HWSubmissionEmailLinker(log=DevNullLogger()).run()
3937- >>> submission = hw_submission_set.getBySubmissionKey(u'unique-id-2')
3938- >>> print(submission.owner.displayname)
3939- Beeblebrox
3940-
3941-If somebody has a Launchpad account, but submits HWDB test data using
3942-an email address which they have not added to their account, the submission
3943-will have the `owner` field set to None.
3944-
3945- >>> submission = hw_submission_set.createSubmission(
3946- ... date_created=date_created,
3947- ... format=HWSubmissionFormat.VERSION_1,
3948- ... private=False,
3949- ... contactable=False,
3950- ... submission_key=u'unique-id-4',
3951- ... emailaddress=u'beeblebrox@beeblebrox.net',
3952- ... distroarchseries=None,
3953- ... raw_submission=StringIO(submission_data),
3954- ... filename=u'hwinfo.txt',
3955- ... filesize=len(submission_data),
3956- ... system_fingerprint=u'Acer 6789')
3957- >>> Store.of(submission).flush()
3958- >>> print(submission.owner)
3959- None
3960-
3961-When they add this email address to their list of addresses in Launchpad,
3962-the field `owner` is updated.
3963-
3964- >>> email = getUtility(IEmailAddressSet).new(
3965- ... u'beeblebrox@beeblebrox.net', user)
3966- >>> transaction.commit()
3967- >>> ignored = login_person(user)
3968- >>> user.validateAndEnsurePreferredEmail(email)
3969- >>> transaction.commit()
3970- >>> HWSubmissionEmailLinker(log=DevNullLogger()).run()
3971- >>> submission = hw_submission_set.getBySubmissionKey(u'unique-id-2')
3972- >>> print(submission.owner.displayname)
3973- Beeblebrox
3974-
3975-=== Submission Records without an email address ===
3976-
3977-A submission does not necessarily have an email address (anonymous
3978-submission). In this case the owner is always None.
3979-
3980- >>> submission_no_owner = hw_submission_set.createSubmission(
3981- ... date_created=date_created,
3982- ... format=HWSubmissionFormat.VERSION_1,
3983- ... private=False,
3984- ... contactable=False,
3985- ... submission_key=u'unique-id-5',
3986- ... emailaddress=None,
3987- ... distroarchseries=None,
3988- ... raw_submission=StringIO(submission_data),
3989- ... filename=u'hwinfo.txt',
3990- ... filesize=len(submission_data),
3991- ... system_fingerprint=u'Dell Inspiron 1234')
3992- >>> Store.of(submission_no_owner).flush()
3993- >>> print(submission_no_owner.raw_emailaddress)
3994- None
3995- >>> print(submission_no_owner.owner)
3996- None
3997-
3998-== Retrieving Submissions by Status ==
3999-
4000-The set of submissions with a given status can be retrieved by
4001-IHWSubmissionSet.getByStatus(). Only the publicly visible
4002-submissions are returned if no user is specified.
4003-
4004- >>> from lp.hardwaredb.interfaces.hwdb import (
4005- ... HWSubmissionProcessingStatus)
4006- >>> def print_submissions(submissions):
4007- ... for submission in submissions:
4008- ... print(submission.submission_key, submission.private, end=' ')
4009- ... if submission.owner is not None:
4010- ... print(submission.owner.displayname, end=' ')
4011- ... else:
4012- ... print('(no owner)', end=' ')
4013- ... print(submission.status.name)
4014- >>> new_submissions = hw_submission_set.getByStatus(
4015- ... HWSubmissionProcessingStatus.SUBMITTED)
4016- >>> print_submissions(new_submissions)
4017- test_submission_id_1 False Sample Person SUBMITTED
4018- unique-id-1 False Sample Person SUBMITTED
4019- unique-id-2 False Beeblebrox SUBMITTED
4020- unique-id-4 False Beeblebrox SUBMITTED
4021- unique-id-5 False (no owner) SUBMITTED
4022-
4023-If a user is passed, private submissions of this user are returned too.
4024-
4025- >>> login('test@canonical.com')
4026- >>> from lp.hardwaredb.interfaces.hwdb import (
4027- ... HWSubmissionProcessingStatus)
4028- >>> new_submissions = hw_submission_set.getByStatus(
4029- ... HWSubmissionProcessingStatus.SUBMITTED, user=sample_person)
4030- >>> print_submissions(new_submissions)
4031- test_submission_id_1 False Sample Person SUBMITTED
4032- unique-id-1 False Sample Person SUBMITTED
4033- unique-id-2 False Beeblebrox SUBMITTED
4034- private-submission True Sample Person SUBMITTED
4035- unique-id-4 False Beeblebrox SUBMITTED
4036- unique-id-5 False (no owner) SUBMITTED
4037-
4038-Submissions of other users are not returned.
4039-
4040- >>> from lp.hardwaredb.interfaces.hwdb import (
4041- ... HWSubmissionProcessingStatus)
4042- >>> new_submissions = hw_submission_set.getByStatus(
4043- ... HWSubmissionProcessingStatus.SUBMITTED, user=no_priv)
4044- >>> print_submissions(new_submissions)
4045- test_submission_id_1 False Sample Person SUBMITTED
4046- unique-id-1 False Sample Person SUBMITTED
4047- unique-id-2 False Beeblebrox SUBMITTED
4048- unique-id-4 False Beeblebrox SUBMITTED
4049- unique-id-5 False (no owner) SUBMITTED
4050-
4051-For admins, IHWSubmissionSet.getByStatus() returns private and public
4052-submissions...
4053-
4054- >>> foobar = getUtility(IPersonSet).getByEmail('foo.bar@canonical.com')
4055- >>> login('foo.bar@canonical.com')
4056- >>> from lp.hardwaredb.interfaces.hwdb import (
4057- ... HWSubmissionProcessingStatus)
4058- >>> new_submissions = hw_submission_set.getByStatus(
4059- ... HWSubmissionProcessingStatus.SUBMITTED, user=foobar)
4060- >>> print_submissions(new_submissions)
4061- test_submission_id_1 False Sample Person SUBMITTED
4062- unique-id-1 False Sample Person SUBMITTED
4063- unique-id-2 False Beeblebrox SUBMITTED
4064- private-submission True Sample Person SUBMITTED
4065- unique-id-4 False Beeblebrox SUBMITTED
4066- unique-id-5 False (no owner) SUBMITTED
4067-
4068-...as well as for the janitor.
4069-
4070- >>> from lp.app.interfaces.launchpad import ILaunchpadCelebrities
4071- >>> janitor = getUtility(ILaunchpadCelebrities).janitor
4072- >>> new_submissions = hw_submission_set.getByStatus(
4073- ... HWSubmissionProcessingStatus.SUBMITTED, user=janitor)
4074- >>> print_submissions(new_submissions)
4075- test_submission_id_1 False Sample Person SUBMITTED
4076- unique-id-1 False Sample Person SUBMITTED
4077- unique-id-2 False Beeblebrox SUBMITTED
4078- private-submission True Sample Person SUBMITTED
4079- unique-id-4 False Beeblebrox SUBMITTED
4080- unique-id-5 False (no owner) SUBMITTED
4081-
4082-Searching for other statuses is possible too.
4083-
4084- >>> submission_no_owner.status = HWSubmissionProcessingStatus.PROCESSED
4085- >>> processed_submissions = hw_submission_set.getByStatus(
4086- ... HWSubmissionProcessingStatus.PROCESSED, user=foobar)
4087- >>> print_submissions(processed_submissions)
4088- sample-submission False Sample Person PROCESSED
4089- unique-id-5 False (no owner) PROCESSED
4090-
4091-== Links to Bugs ==
4092-
4093-HWDB submissions can be linked to bugs. These links are created by
4094-IHWSubmissionBugSet.create().
4095-
4096- >>> from lp.bugs.interfaces.bug import IBugSet
4097- >>> from lp.hardwaredb.interfaces.hwdb import IHWSubmissionBugSet
4098- >>> bug_one = getUtility(IBugSet).get(1)
4099- >>> submission_bug_set = getUtility(IHWSubmissionBugSet)
4100- >>> submission_bug = submission_bug_set.create(
4101- ... submission_no_owner, bug_one)
4102- >>> transaction.commit()
4103- >>> print(submission_bug.submission.submission_key)
4104- unique-id-5
4105- >>> submission_bug.bug.id
4106- 1
4107-
4108-Links between a bug and a submission are unique. If we call
4109-IHWSubmissionBugSet.create() twice for the same bug and HWDB submission,
4110-the method returns the existing record.
4111-
4112- >>> second_link = submission_bug_set.create(submission_no_owner, bug_one)
4113- >>> second_link.id == submission_bug.id
4114- True
4115-
4116-HWSubmissionBugSet.submissionsForBug() returns all submissions linked to
4117-a given bug.
4118-
4119- >>> for submission in submission_bug_set.submissionsForBug(bug_one):
4120- ... print(submission.submission_key)
4121- unique-id-5
4122-
4123-Private submissions are only returned if the current user is an admin
4124-or the owner of the private submission.
4125-
4126- >>> submission = hw_submission_set.getBySubmissionKey(
4127- ... u'private-submission', sample_person)
4128- >>> submission_bug_set.create(submission, bug_one)
4129- <HWSubmissionBug at...
4130- >>> for submission in submission_bug_set.submissionsForBug(
4131- ... bug_one, user=sample_person):
4132- ... print(submission.submission_key)
4133- private-submission
4134- unique-id-5
4135-
4136- >>> for submission in submission_bug_set.submissionsForBug(
4137- ... bug_one, user=foobar):
4138- ... print(submission.submission_key)
4139- private-submission
4140- unique-id-5
4141-
4142-Other registered persons can see only public submissions...
4143-
4144- >>> for submission in submission_bug_set.submissionsForBug(
4145- ... bug_one, user=no_priv):
4146- ... print(submission.submission_key)
4147- unique-id-5
4148-
4149-...as well as anonymous users.
4150-
4151- >>> for submission in submission_bug_set.submissionsForBug(
4152- ... bug_one):
4153- ... print(submission.submission_key)
4154- unique-id-5
4155-
4156-Existing links can also be removed.
4157-
4158- >>> submission_bug_set.remove(submission_no_owner, bug_one)
4159- >>> submission_bug_set.submissionsForBug(bug_one).count()
4160- 0
4161-
4162- >>> for submission in submission_bug_set.submissionsForBug(
4163- ... bug_one, user=foobar):
4164- ... print(submission.submission_key)
4165- private-submission
4166-
4167-
4168-== General Search Method ==
4169-
4170-IHWSubmissionSet.search() allows the look up of submissions which
4171-contain a specfic device, a specific driver or which are made for a
4172-specific distribution or processor architecture.
4173-
4174-All parameters are optional; if none are given, all publicly visible
4175-submissions are returned.
4176-
4177- >>> for submission in hw_submission_set.search():
4178- ... print(submission.submission_key)
4179- test_submission_id_1
4180- sample-submission
4181- unique-id-1
4182- unique-id-2
4183- unique-id-4
4184- unique-id-5
4185-
4186-If the parameter `user` is specified, private submissions from this user
4187-are returned too.
4188-
4189- >>> for submission in hw_submission_set.search(user=sample_person):
4190- ... print(submission.submission_key)
4191- test_submission_id_1
4192- sample-submission
4193- unique-id-1
4194- unique-id-2
4195- private-submission
4196- unique-id-4
4197- unique-id-5
4198-
4199-Admins have access to all submissions.
4200-
4201- >>> for submission in hw_submission_set.search(user=foobar):
4202- ... print(submission.submission_key)
4203- test_submission_id_1
4204- sample-submission
4205- unique-id-1
4206- unique-id-2
4207- private-submission
4208- unique-id-4
4209- unique-id-5
4210-
4211-If a distribution is specified, only those submissions that were made
4212-for that distribution are returned.
4213-
4214- >>> from lp.registry.interfaces.distribution import (
4215- ... IDistributionSet)
4216- >>> distribution_set = getUtility(IDistributionSet)
4217- >>> ubuntu = distribution_set.getByName('ubuntu')
4218- >>> for submission in hw_submission_set.search(distribution=ubuntu):
4219- ... print(submission.submission_key)
4220- sample-submission
4221-
4222- >>> debian = distribution_set.getByName('debian')
4223- >>> print(hw_submission_set.search(distribution=debian).count())
4224- 0
4225-
4226-If an architecture is specified, only those submissions that were made
4227-for that architecture are returned.
4228-
4229- >>> for submission in hw_submission_set.search(architecture='i386'):
4230- ... print(submission.submission_key)
4231- sample-submission
4232-
4233- >>> print(hw_submission_set.search(architecture='amd64').count())
4234- 0
4235-
4236-
4237-If a device is specified, only those submissions that include
4238-the device are returned.
4239-
4240- >>> from lp.hardwaredb.interfaces.hwdb import HWBus, IHWDeviceSet
4241- >>> device_set = getUtility(IHWDeviceSet)
4242- >>> msi_mainboard = device_set.getByDeviceID(
4243- ... HWBus.SYSTEM, 'MSI', 'MS-7369')
4244- >>> for submission in hw_submission_set.search(device=msi_mainboard):
4245- ... print(submission.submission_key)
4246- sample-submission
4247-
4248-If a driver is specified, only those submissions for that driver
4249-are returned.
4250-
4251- >>> from lp.hardwaredb.interfaces.hwdb import IHWDriverSet
4252- >>> driver_set = getUtility(IHWDriverSet)
4253- >>> ehci_driver = driver_set.getByPackageAndName(
4254- ... 'linux-image-2.6.24-19-generic', 'ehci_hcd')
4255- >>> for submission in hw_submission_set.search(driver=ehci_driver):
4256- ... print(submission.submission_key)
4257- sample-submission
4258-
4259-If a distroseries is specified, only submissions for that distroseries
4260-are returned.
4261-
4262- >>> from lp.testing.factory import LaunchpadObjectFactory
4263- >>> factory = LaunchpadObjectFactory()
4264-
4265- >>> warty = ubuntu['warty']
4266- >>> warty_arch_series = factory.makeDistroArchSeries(distroseries=warty)
4267- >>> submission = factory.makeHWSubmission(distroarchseries=warty_arch_series)
4268- >>> for submission in hw_submission_set.search(distroseries=warty):
4269- ... print(submission.distroarchseries.distroseries.name)
4270- warty
4271-
4272-It is also possible to search for a distroseries and architecture.
4273-
4274- >>> from lp.buildmaster.interfaces.processor import IProcessorSet
4275- >>> amd64 = getUtility(IProcessorSet).getByName('amd64')
4276- >>> warty_amd64 = factory.makeDistroArchSeries(
4277- ... distroseries=warty, architecturetag='amd64',
4278- ... processor=amd64)
4279- >>> submission = factory.makeHWSubmission(distroarchseries=warty_amd64)
4280- >>> for submission in hw_submission_set.search(distroseries=warty, architecture='amd64'):
4281- ... print('%s %s ' % (
4282- ... submission.distroarchseries.distroseries.name,
4283- ... submission.distroarchseries.architecturetag))
4284- warty amd64
4285-
4286-And we can also search for submissions from a particular user.
4287-
4288- >>> from lp.registry.interfaces.person import IPersonSet
4289- >>> owner = getUtility(IPersonSet).getByName('name12')
4290- >>> set(submission.owner.name for submission
4291- ... in hw_submission_set.search(owner=owner))
4292- set([u'name12'])
4293diff --git a/lib/lp/hardwaredb/interfaces/__init__.py b/lib/lp/hardwaredb/interfaces/__init__.py
4294deleted file mode 100644
4295index e69de29..0000000
4296--- a/lib/lp/hardwaredb/interfaces/__init__.py
4297+++ /dev/null
4298diff --git a/lib/lp/hardwaredb/interfaces/hwdb.py b/lib/lp/hardwaredb/interfaces/hwdb.py
4299deleted file mode 100644
4300index e418abd..0000000
4301--- a/lib/lp/hardwaredb/interfaces/hwdb.py
4302+++ /dev/null
4303@@ -1,1717 +0,0 @@
4304-# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
4305-# GNU Affero General Public License version 3 (see the file LICENSE).
4306-
4307-"""Interfaces related to the hardware database."""
4308-
4309-__metaclass__ = type
4310-
4311-__all__ = [
4312- 'HWBus',
4313- 'HWDB_SUBMISSIONS_DISABLED_FEATURE_FLAG',
4314- 'HWSubmissionFormat',
4315- 'HWSubmissionKeyNotUnique',
4316- 'HWSubmissionProcessingStatus',
4317- 'HWSubmissionsDisabledError',
4318- 'IHWDBApplication',
4319- 'IHWDevice',
4320- 'IHWDeviceClass',
4321- 'IHWDeviceClassSet',
4322- 'IHWDeviceDriverLink',
4323- 'IHWDeviceDriverLinkSet',
4324- 'IHWDeviceNameVariant',
4325- 'IHWDeviceNameVariantSet',
4326- 'IHWDeviceSet',
4327- 'IHWDriver',
4328- 'IHWDriverName',
4329- 'IHWDriverPackageName',
4330- 'IHWDriverSet',
4331- 'IHWSubmission',
4332- 'IHWSubmissionBug',
4333- 'IHWSubmissionBugSet',
4334- 'IHWSubmissionForm',
4335- 'IHWSubmissionSet',
4336- 'IHWSubmissionDevice',
4337- 'IHWSubmissionDeviceSet',
4338- 'IHWSystemFingerprint',
4339- 'IHWSystemFingerprintSet',
4340- 'IHWVendorID',
4341- 'IHWVendorIDSet',
4342- 'IHWVendorName',
4343- 'IHWVendorNameSet',
4344- 'IllegalQuery',
4345- 'ParameterError',
4346- ]
4347-
4348-from lazr.enum import (
4349- DBEnumeratedType,
4350- DBItem,
4351- )
4352-from lazr.restful.declarations import (
4353- call_with,
4354- error_status,
4355- export_destructor_operation,
4356- export_read_operation,
4357- export_write_operation,
4358- exported,
4359- exported_as_webservice_entry,
4360- operation_parameters,
4361- operation_returns_collection_of,
4362- operation_returns_entry,
4363- REQUEST_USER,
4364- )
4365-from lazr.restful.fields import (
4366- CollectionField,
4367- Reference,
4368- )
4369-from lazr.restful.interface import copy_field
4370-from six.moves import http_client
4371-from zope.component import getUtility
4372-from zope.interface import (
4373- Attribute,
4374- Interface,
4375- )
4376-from zope.schema import (
4377- ASCIILine,
4378- Bool,
4379- Bytes,
4380- Choice,
4381- Datetime,
4382- Int,
4383- List,
4384- TextLine,
4385- )
4386-
4387-from lp import _
4388-from lp.app.interfaces.launchpad import IPrivacy
4389-from lp.app.validators import LaunchpadValidationError
4390-from lp.app.validators.email import valid_email
4391-from lp.app.validators.name import valid_name
4392-from lp.registry.interfaces.distribution import IDistribution
4393-from lp.registry.interfaces.distroseries import IDistroSeries
4394-from lp.registry.interfaces.person import IPerson
4395-from lp.registry.interfaces.product import License
4396-from lp.services.webapp.interfaces import ILaunchpadApplication
4397-from lp.services.webservice.apihelpers import (
4398- patch_collection_property,
4399- patch_reference_property,
4400- )
4401-from lp.soyuz.interfaces.distroarchseries import IDistroArchSeries
4402-
4403-
4404-HWDB_SUBMISSIONS_DISABLED_FEATURE_FLAG = 'hardwaredb.submissions.disabled'
4405-
4406-
4407-@error_status(http_client.GONE)
4408-class HWSubmissionsDisabledError(Exception):
4409- """An exception saying that hardware database submissions are disabled."""
4410-
4411- def __init__(self, message=None):
4412- if message is None:
4413- message = (
4414- "Launchpad's hardware database is obsolete and is no longer "
4415- "accepting submissions. Please use "
4416- "https://answers.launchpad.net/launchpad/+addquestion to tell "
4417- "us about your requirements if you still need it.")
4418- super(HWSubmissionsDisabledError, self).__init__(message)
4419-
4420-
4421-def validate_new_submission_key(submission_key):
4422- """Check, if submission_key already exists in HWDBSubmission."""
4423- if not valid_name(submission_key):
4424- raise LaunchpadValidationError(
4425- 'Submission key can contain only lowercase alphanumerics.')
4426- submission_set = getUtility(IHWSubmissionSet)
4427- if submission_set.submissionIdExists(submission_key):
4428- raise LaunchpadValidationError(
4429- 'Submission key already exists.')
4430- return True
4431-
4432-
4433-def validate_email_address(emailaddress):
4434- """Validate an email address.
4435-
4436- Returns True for valid addresses, else raises LaunchpadValidationError.
4437- The latter allows convenient error handling by LaunchpadFormView.
4438- """
4439- if not valid_email(emailaddress):
4440- raise LaunchpadValidationError(
4441- 'Invalid email address')
4442- return True
4443-
4444-
4445-class HWSubmissionKeyNotUnique(Exception):
4446- """Prevent two or more submission with identical submission_key."""
4447-
4448-
4449-class HWSubmissionProcessingStatus(DBEnumeratedType):
4450- """The status of a submission to the hardware database."""
4451-
4452- INVALID = DBItem(0, """
4453- Invalid submission
4454-
4455- The submitted data could not be parsed.
4456- """)
4457-
4458- SUBMITTED = DBItem(1, """
4459- Submitted
4460-
4461- The submitted data has not yet been processed.
4462- """)
4463-
4464- PROCESSED = DBItem(2, """
4465- Processed
4466-
4467- The submitted data has been processed.
4468- """)
4469-
4470-
4471-class HWSubmissionFormat(DBEnumeratedType):
4472- """The format version of the submitted data."""
4473-
4474- VERSION_1 = DBItem(1, "Version 1")
4475-
4476-
4477-@exported_as_webservice_entry(publish_web_link=False)
4478-class IHWSubmission(Interface, IPrivacy):
4479- """Raw submission data for the hardware database.
4480-
4481- See doc/hwdb.txt for details about the attributes.
4482- """
4483-
4484- date_created = exported(
4485- Datetime(
4486- title=_(u'Date Created'), required=True, readonly=True))
4487- date_submitted = exported(
4488- Datetime(
4489- title=_(u'Date Submitted'), required=True, readonly=True))
4490- format = exported(
4491- Choice(
4492- title=_(u'Format Version'), required=True,
4493- vocabulary=HWSubmissionFormat, readonly=True))
4494- status = exported(
4495- Choice(
4496- title=_(u'Submission Status'), required=True,
4497- vocabulary=HWSubmissionProcessingStatus, readonly=True))
4498- # This is redefined from IPrivacy.private because the attribute is
4499- # is required.
4500- private = exported(
4501- Bool(
4502- title=_(u'Private Submission'), required=True))
4503- contactable = exported(
4504- Bool(
4505- title=_(u'Contactable'), required=True, readonly=True))
4506- submission_key = exported(
4507- TextLine(
4508- title=_(u'Unique Submission ID'), required=True, readonly=True))
4509- owner = exported(
4510- Reference(
4511- IPerson, title=_(u"The owner of this submission"), readonly=True))
4512- distroarchseries = Attribute(
4513- _(u'The DistroArchSeries'))
4514- raw_submission = exported(
4515- Bytes(title=_(u'The raw submission data'), required=True,
4516- readonly=True))
4517- system_fingerprint = Attribute(
4518- _(u'The system this submmission was made on'))
4519- raw_emailaddress = TextLine(
4520- title=_('Email address'), required=True)
4521-
4522- devices = exported(
4523- CollectionField(
4524- title=_(u"The HWSubmissionDevice records for this submission."),
4525- value_type=Reference(schema=Interface)))
4526-
4527-
4528-class IHWSubmissionForm(Interface):
4529- """The schema used to build the HW submission form."""
4530-
4531- date_created = Datetime(
4532- title=_(u'Date Created'), required=True)
4533- format = Choice(
4534- title=_(u'Format Version'), required=True,
4535- vocabulary=HWSubmissionFormat)
4536- private = Bool(
4537- title=_(u'Private Submission'), required=True)
4538- contactable = Bool(
4539- title=_(u'Contactable'), required=True)
4540- submission_key = ASCIILine(
4541- title=_(u'Unique Submission Key'), required=True,
4542- constraint=validate_new_submission_key)
4543- emailaddress = TextLine(
4544- title=_(u'Email address'), required=True,
4545- constraint=validate_email_address)
4546- distribution = TextLine(
4547- title=_(u'Distribution'), required=True)
4548- distroseries = TextLine(
4549- title=_(u'Distribution Release'), required=True)
4550- architecture = TextLine(
4551- title=_(u'Processor Architecture'), required=True)
4552- system = TextLine(
4553- title=_(u'System name'), required=True)
4554- submission_data = Bytes(
4555- title=_(u'Submission data'), required=True)
4556-
4557-
4558-class IHWSubmissionSet(Interface):
4559- """The set of HWDBSubmissions."""
4560-
4561- def createSubmission(date_created, format, private, contactable,
4562- submission_key, emailaddress, distroarchseries,
4563- raw_submission, filename, filesize, system):
4564- """Store submitted raw hardware information in a Librarian file.
4565-
4566- If a submission with an identical submission_key already exists,
4567- an HWSubmissionKeyNotUnique exception is raised."""
4568-
4569- def getBySubmissionKey(submission_key, user=None):
4570- """Return the submission with the given submission key, or None.
4571-
4572- If a submission is marked as private, it is only returned if
4573- user == HWSubmission.owner, of if user is an admin.
4574- """
4575-
4576- def getByFingerprintName(name, user=None):
4577- """Return the submissions for the given system fingerprint string.
4578-
4579- If a submission is marked as private, it is only returned if
4580- user == HWSubmission.owner, or if user is an admin.
4581- """
4582-
4583- def getByOwner(owner, user=None):
4584- """Return the submissions for the given person.
4585-
4586- If a submission is marked as private, it is only returned if
4587- user == HWSubmission.owner, or if user is an admin.
4588- """
4589-
4590- def submissionIdExists(submission_key):
4591- """Return True, if a record with ths ID exists, else return False."""
4592-
4593- def getByStatus(status, user=None):
4594- """Return the submissions with the given status.
4595-
4596- :param status: A status as enumerated in
4597- `HWSubmissionProcessingStatus`.
4598- :param user: The `IPerson` running the query.
4599- :return: The submissions having the given status.
4600-
4601- If no user is specified, only public submissions are returned.
4602- If a regular user is specified, public submissions and private
4603- submissions owned by the user are returned.
4604- For admins and for the janitor, all submissions with the given
4605- status are returned.
4606- """
4607-
4608- def search(user=None, device=None, driver=None, distribution=None,
4609- distroseries=None, architecture=None, owner=None,
4610- created_before=None, created_after=None,
4611- submitted_before=None, submitted_after=None):
4612- """Return the submissions matiching the given parmeters.
4613-
4614- :param user: The `IPerson` running the query. Private submissions
4615- are returned only if the person running the query is the
4616- owner or an admin.
4617- :param device: Limit results to submissions containing this
4618- `IHWDevice`.
4619- :param driver: Limit results to submissions containing devices
4620- that use this `IHWDriver`.
4621- :param distribution: Limit results to submissions made for
4622- this `IDistribution`.
4623- :param distroseries: Limit results to submissions made for
4624- this `IDistroSeries`.
4625- :param architecture: Limit results to submissions made for
4626- a specific architecture.
4627- :param owner: Limit results to submissions from this person.
4628- :param created_before: Exclude results created after this
4629- date.
4630- :param created_after: Exclude results created before or on
4631- this date.
4632- :param submitted_before: Exclude results submitted after this
4633- date.
4634- :param submitted_after: Exclude results submitted before or on
4635- this date.
4636-
4637- Only one of :distribution: or :distroseries: may be supplied.
4638- """
4639-
4640- def numSubmissionsWithDevice(bus=None, vendor_id=None, product_id=None,
4641- driver_name=None, package_name=None,
4642- distro_target=None):
4643- """Count the number of submissions mentioning a device or a driver.
4644-
4645- :return: A tuple (submissions_with_device, all_submissions)
4646- where submissions_with_device is the number of submissions having
4647- the given device or driver and matching the distro_target
4648- criterion and where all_submissions is the number of submissions
4649- matching the distro_target criterion.
4650- :param bus: The `HWBus` of the device (optional).
4651- :param vendor_id: The vendor ID of the device (optional).
4652- :param product_id: The product ID of the device (optional).
4653- :param driver_name: The name of the driver used for the device
4654- (optional).
4655- :param package_name: The name of the package the driver is a part of.
4656- (optional).
4657- :param distro_target: Limit the count to submissions made for the
4658- given distribution, distroseries or distroarchseries.
4659- (optional).
4660-
4661- At least each of bus, vendor_id, product_id must not be None or
4662- driver_name must not be None.
4663- """
4664-
4665- def numOwnersOfDevice(bus=None, vendor_id=None, product_id=None,
4666- driver_name=None, package_name=None,
4667- distro_target=None):
4668- """The number of people owning a device or using a driver.
4669-
4670- :return: A tuple (device_owners, all_hardware_reporters)
4671- where device_owners is the number of people who made a HWDB
4672- submission containing the given device or driver, optionally
4673- limited to submissions made for the given distro_target.
4674- all_hardware_reporters is the number of persons who made
4675- a HWDB submission, optionally limited to submission made
4676- on the given distro_target installation.
4677- :param bus: The `HWBus` of the device (optional).
4678- :param vendor_id: The vendor ID of the device (optional).
4679- :param product_id: The product ID of the device (optional).
4680- :param driver_name: The name of the driver used for the device
4681- (optional).
4682- :param package_name: The name of the package the driver is a part of.
4683- (optional).
4684- :param distro_target: Limit the count to submissions made for the
4685- given distribution, distroseries or distroarchseries.
4686- (optional).
4687-
4688- At least each of bus, vendor_id, product_id must not be None or
4689- driver_name must not be None.
4690- """
4691-
4692- def deviceDriverOwnersAffectedByBugs(
4693- bus=None, vendor_id=None, product_id=None, driver_name=None,
4694- package_name=None, bug_ids=None, bug_tags=None, affected_by_bug=False,
4695- subscribed_to_bug=False, user=None):
4696- """Return persons affected by given bugs and owning a given device.
4697-
4698- :param bus: The `HWBus` of the device.
4699- :param vendor_id: The vendor ID of the device.
4700- :param product_id: The product ID of the device.
4701- :param driver_name: Limit the search to devices controlled by the
4702- given driver.
4703- :param package_name: Limit the search to devices controlled by a
4704- driver from the given package.
4705- :param bug_ids: A sequence of bug IDs for which affected device
4706- owners are looked up.
4707- :param bug_tags: A sequence of bug tags.
4708- :param affected_by_bug: If True, those persons are looked up that
4709- have marked themselves as being affected by a one of the bugs
4710- matching the bug criteria.
4711- :param subscribed_to_bug: If True, those persons are looked up that
4712- are subscribed to a bug matching one of the bug criteria.
4713- :param user: The person making the query.
4714-
4715- `bug_ids` must be a non-empty sequence of bug IDs, or `bug_tags`
4716- must be a non-empty sequence of bug tags.
4717-
4718- The parameters `bus`, `vendor_id`, `product_id` must not be None, or
4719- `driver_name` must not be None.
4720-
4721- By default, only those persons are returned which have reported a
4722- bug matching the given bug conditions.
4723-
4724- Owners of private submissions are returned only if user is the
4725- owner of the private submission or if user is an admin.
4726- """
4727-
4728- def hwInfoByBugRelatedUsers(
4729- bug_ids=None, bug_tags=None, affected_by_bug=False,
4730- subscribed_to_bug=False, user=None):
4731- """Return a list of owners and devices related to given bugs.
4732-
4733- Actually returns a list of tuples where the tuple is of the form,
4734- (person name, bus name, vendor id, product id).`
4735-
4736- :param bug_ids: A sequence of bug IDs for which affected
4737- are looked up.
4738- :param bug_tags: A sequence of bug tags
4739- :param affected_by_bug: If True, those persons are looked up that
4740- have marked themselves as being affected by a one of the bugs
4741- matching the bug criteria.
4742- :param subscribed_to_bug: If True, those persons are looked up that
4743- are subscribed to a bug matching one of the bug criteria.
4744- :param user: The person making the query.
4745- """
4746-
4747-
4748-class IHWSystemFingerprint(Interface):
4749- """Identifiers of a computer system."""
4750-
4751- fingerprint = Attribute(u'A unique identifier of a system')
4752-
4753-
4754-class IHWSystemFingerprintSet(Interface):
4755- """The set of HWSystemFingerprints."""
4756-
4757- def getByName(fingerprint):
4758- """Lookup an IHWSystemFingerprint by its value.
4759-
4760- Return None, if a fingerprint `fingerprint` does not exist."""
4761-
4762- def createFingerprint(fingerprint):
4763- """Create an entry in the fingerprint list.
4764-
4765- Return the new entry."""
4766-
4767-
4768-@exported_as_webservice_entry(publish_web_link=False)
4769-class IHWDriver(Interface):
4770- """Information about a device driver."""
4771-
4772- id = exported(
4773- Int(title=u'Driver ID', required=True, readonly=True))
4774-
4775- package_name = exported(
4776- TextLine(
4777- title=u'Package Name', required=False,
4778- description=_("The name of the package written without spaces in "
4779- "lowercase letters and numbers."),
4780- default=u''))
4781-
4782- name = exported(
4783- TextLine(
4784- title=u'Driver Name', required=True,
4785- description=_("The name of the driver written without spaces in "
4786- "lowercase letters and numbers.")))
4787-
4788- license = exported(
4789- Choice(
4790- title=u'License of the Driver', required=False,
4791- vocabulary=License))
4792-
4793- @operation_parameters(
4794- distribution=Reference(
4795- IDistribution,
4796- title=u'A Distribution',
4797- description=(
4798- u'If specified, the result set is limited to sumbissions '
4799- 'made for the given distribution.'),
4800- required=False),
4801- distroseries=Reference(
4802- IDistroSeries,
4803- title=u'A Distribution Series',
4804- description=(
4805- u'If specified, the result set is limited to sumbissions '
4806- 'made for the given distribution series.'),
4807- required=False),
4808- architecture=TextLine(
4809- title=u'A processor architecture',
4810- description=(
4811- u'If specified, the result set is limited to sumbissions '
4812- 'made for the given architecture.'),
4813- required=False),
4814- owner=copy_field(IHWSubmission['owner']))
4815- @operation_returns_collection_of(IHWSubmission)
4816- @export_read_operation()
4817- def getSubmissions(distribution=None, distroseries=None,
4818- architecture=None, owner=None):
4819- """List all submissions which mention this driver.
4820-
4821- :param distribution: Limit results to submissions for this
4822- `IDistribution`.
4823- :param distroseries: Limit results to submissions for this
4824- `IDistroSeries`.
4825- :param architecture: Limit results to submissions for this
4826- architecture.
4827- :param owner: Limit results to submissions from this person.
4828-
4829- Only submissions matching all given criteria are returned.
4830- Only one of :distribution: or :distroseries: may be supplied.
4831- """
4832-
4833-
4834-class IHWDriverSet(Interface):
4835- """The set of device drivers."""
4836-
4837- def create(package_name, name, license):
4838- """Create a new IHWDriver instance.
4839-
4840- :param package_name: The name of the packages containing the driver.
4841- :param name: The name of the driver.
4842- :param license: The license of the driver.
4843- :return: The new IHWDriver instance.
4844- """
4845-
4846- def getByPackageAndName(package_name, name):
4847- """Return an IHWDriver instance for the given parameters.
4848-
4849- :param package_name: The name of the packages containing the driver.
4850- :param name: The name of the driver.
4851- :return: An IHWDriver instance or None, if no record exists for
4852- the given parameters.
4853- """
4854-
4855- def getOrCreate(package_name, name, license=None):
4856- """Return an IHWDriver instance or create one.
4857-
4858- :param package_name: The name of the packages containing the driver.
4859- :param name: The name of the driver.
4860- :param license: The license of the driver.
4861- :return: An IHWDriver instance or None, if no record exists for
4862- the given parameters.
4863- """
4864-
4865- def search(package_name=None, name=None):
4866- """Return the drivers matching the given parameters.
4867-
4868- :param package_name: The name of the packages containing the driver.
4869- If package_name is not given or None, the result set is
4870- not limited to a specific package name.
4871- If package_name == '', those records are returned where
4872- record.package_name == '' or record.package_name is None.
4873- Otherwise only records matching the given name are returned.
4874- :param name: The name of the driver.
4875- If name is not given or None, the result set is not limited to
4876- a specific driver name.
4877- Otherwise only records matching the given name are returned.
4878- :return: A sequence of IHWDriver instances.
4879- """
4880-
4881- def getByID(id):
4882- """Return an IHWDriver record with the given database ID.
4883-
4884- :param id: The database ID.
4885- :return: An IHWDriver instance.
4886- """
4887-
4888- def all_driver_names():
4889- """Return all known distinct driver names appearing in HWDriver."""
4890-
4891- def all_package_names():
4892- """Return all known distinct package names appearing in HWDriver."""
4893-
4894-
4895-@exported_as_webservice_entry(publish_web_link=False)
4896-class IHWDriverName(Interface):
4897- """A driver name as appearing in `IHWDriver`.
4898- """
4899-
4900- name = exported(
4901- TextLine(
4902- title=u'Driver Name', required=True, readonly=True,
4903- description=_("The name of a driver as it appears in "
4904- "IHWDriver.")))
4905-
4906-
4907-@exported_as_webservice_entry(publish_web_link=False)
4908-class IHWDriverPackageName(Interface):
4909- """A driver name as appearing in `IHWDriver`.
4910- """
4911-
4912- package_name = exported(
4913- TextLine(
4914- title=u'Package Name', required=True, readonly=True,
4915- description=_("The name of a package as it appears in "
4916- "IHWDriver.")))
4917-
4918-
4919-# Identification of a hardware device.
4920-#
4921-# In theory, a tuple (bus, vendor ID, product ID) should identify
4922-# a device unambiguously. In practice, there are several cases where
4923-# this tuple can identify more than one device:
4924-#
4925-# - A USB chip or chipset may be used in different devices.
4926-# A real world example:
4927-# - Plustek sold different scanner models with the USB ID
4928-# 0x7b3/0x0017. Some of these scanners have for example a
4929-# different maximum scan size.
4930-#
4931-# Hence we identify a device by tuple (bus, vendor ID, product ID,
4932-# variant). In the example above, we might use (HWBus.USB, '0x7b3',
4933-# '0x0017', 'OpticPro UT12') and (HWBus.USB, '0x7b3', '0x0017',
4934-# 'OpticPro UT16')
4935-
4936-class HWBus(DBEnumeratedType):
4937- """The bus that connects a device to a computer."""
4938-
4939- SYSTEM = DBItem(0, 'System')
4940-
4941- PCI = DBItem(1, 'PCI')
4942-
4943- USB = DBItem(2, 'USB')
4944-
4945- IEEE1394 = DBItem(3, 'IEEE1394')
4946-
4947- SCSI = DBItem(4, 'SCSI')
4948-
4949- PARALLEL = DBItem(5, 'Parallel Port')
4950-
4951- SERIAL = DBItem(6, 'Serial port')
4952-
4953- IDE = DBItem(7, 'IDE')
4954-
4955- ATA = DBItem(8, 'ATA')
4956-
4957- FLOPPY = DBItem(9, 'Floppy')
4958-
4959- IPI = DBItem(10, 'IPI')
4960-
4961- SATA = DBItem(11, 'SATA')
4962-
4963- SAS = DBItem(12, 'SAS')
4964-
4965- PCCARD = DBItem(13, 'PC Card (32 bit)')
4966-
4967- PCMCIA = DBItem(14, 'PCMCIA (16 bit)')
4968-
4969-
4970-class IHWVendorName(Interface):
4971- """A list of vendor names."""
4972- name = TextLine(title=u'Vendor Name', required=True)
4973-
4974-
4975-class IHWVendorNameSet(Interface):
4976- """The set of vendor names."""
4977- def create(name):
4978- """Create and return a new vendor name.
4979-
4980- :return: A new IHWVendorName instance.
4981-
4982- An IntegrityError is raised, if the name already exists.
4983- """
4984-
4985- def getByName(name):
4986- """Return the IHWVendorName record for the given name.
4987-
4988- :param name: The vendor name.
4989- :return: An IHWVendorName instance where IHWVendorName.name==name
4990- or None, if no such instance exists.
4991- """
4992-
4993-
4994-@exported_as_webservice_entry(publish_web_link=False)
4995-class IHWVendorID(Interface):
4996- """A list of vendor IDs for different busses associated with vendor names.
4997- """
4998- id = exported(
4999- Int(title=u'The Database ID', required=True, readonly=True))
5000-
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to status/vote changes: