1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
|
ExternalBugTracker bug imports
==============================
Some ExternalBugTracker implementations support importing bugs from the
remote bug tracker into Launchpad. They indicate that they support doing
this by implementing ISupportsBugImport, and implement all the specified
methods.
>>> from zope.interface import implements
>>> from lp.bugs.interfaces.externalbugtracker import ISupportsBugImport
>>> from lp.bugs.externalbugtracker import (
... ExternalBugTracker)
>>> class BugImportingExternalBugTracker(ExternalBugTracker):
... implements(ISupportsBugImport)
...
... _bugs = {}
...
... def getBugReporter(self, remote_bug):
... display_name, email = self._bugs[remote_bug]['reporter']
... return display_name, email
... def getBugSummaryAndDescription(self, remote_bug):
... return (
... "Sample summary %s" % remote_bug,
... "Sample description %s." % remote_bug)
... def getBugTargetName(self, remote_bug):
... return self._bugs[remote_bug]['package']
>>> from lp.bugs.interfaces.bugtracker import BugTrackerType
>>> from lp.registry.interfaces.distribution import IDistributionSet
>>> from lp.bugs.tests.externalbugtracker import (
... new_bugtracker)
>>> bugtracker = new_bugtracker(BugTrackerType.BUGZILLA)
>>> external_bugtracker = BugImportingExternalBugTracker(
... 'http://example.com/')
When importing bugs, the reporter is automatically created in Launchpad,
if he doesn't exist.
>>> from lp.registry.interfaces.person import IPersonSet
>>> print getUtility(IPersonSet).getByEmail('joe.bloggs@example.com')
None
The method that imports a bug is importBug(). In addition to the
ISupportBugImports external bug tracker, it requires the corresponding
IBugTracker in Launchpad, and the bug target, in which the bug should be
imported into, and the remote bug number. At the moment only
distributions are supported as the bug target.
# Make sane data to play this test.
>>> from canonical.config import config
>>> from canonical.testing.layers import LaunchpadZopelessLayer
>>> transaction.commit()
>>> LaunchpadZopelessLayer.switchDbUser('launchpad')
>>> debian = getUtility(IDistributionSet).getByName('debian')
>>> evolution_dsp = debian.getSourcePackage('evolution')
>>> ignore = factory.makeSourcePackagePublishingHistory(
... distroseries=debian.currentseries,
... sourcepackagename=evolution_dsp.sourcepackagename)
>>> transaction.commit()
>>> LaunchpadZopelessLayer.switchDbUser(config.checkwatches.dbuser)
>>> from lp.bugs.scripts.checkwatches import CheckwatchesMaster
>>> debian = getUtility(IDistributionSet).getByName('debian')
>>> external_bugtracker._bugs['3'] = {
... 'package': 'evolution',
... 'reporter': ("Joe Bloggs", "joe.bloggs@example.com")}
>>> transaction.commit()
>>> bug_watch_updater = CheckwatchesMaster(LaunchpadZopelessLayer.txn)
>>> bug = bug_watch_updater.importBug(
... external_bugtracker, bugtracker, debian, '3')
The summary and descriptions of the imported bugs are what was returned
by getBugSummaryAndDescription().
>>> bug.title
u'Sample summary 3'
>>> bug.description
u'Sample description 3.'
The bug reporter, as returned by getBugReporter(), got automatically created.
>>> getUtility(IPersonSet).getByEmail(
... 'joe.bloggs@example.com') is not None
True
>>> print bug.owner.displayname
Joe Bloggs
Since he didn't have a Launchpad account before, he doesn't have a
preferred e-mail address, and the one that is associated with his
account is marked as NEW, since we don't know whether it's valid.
>>> from lp.services.identity.interfaces.emailaddress import (
... IEmailAddressSet)
>>> reporter_email_addresses = getUtility(IEmailAddressSet).getByPerson(
... bug.owner)
>>> for email_address in reporter_email_addresses:
... print "%s: %s" % (email_address.email, email_address.status.name)
joe.bloggs@example.com: NEW
>>> print bug.owner.preferredemail
None
>>> bug.owner.creation_rationale.name
'BUGIMPORT'
>>> bug.owner.creation_comment
u'when importing bug #3 from http://...'
No one got subscribed to the created bug, since the relevant people
already get e-mail notifications via the external bug tracker.
>>> [person.name for person in bug.getDirectSubscribers()]
[]
The bug got filed against the evolution package in Debian, and it has a
bug watch pointing to the original remote bug, so that the bug report is
kept in sync.
>>> [added_task] = bug.bugtasks
>>> added_task.bugtargetname
u'evolution (Debian)'
>>> added_task.bugwatch.bugtracker.name
u'bugzilla-checkwatches-1'
>>> added_task.bugwatch.remotebug
u'3'
Non-existent source package
---------------------------
If a package doesn't exist in Launchpad already, it will be filed on the
distribution itself, with no source package specified. The package is
always included in the description of Debian bugs, so that information
isn't normally lost. A warning is also logged, so that the one running
the script gets notified about it.
>>> external_bugtracker._bugs['5'] = {
... 'package': 'no-such-package',
... 'reporter': ("Joe Bloggs", "joe.bloggs@example.com")}
>>> print debian.getSourcePackage('no-such-package')
None
>>> bug = bug_watch_updater.importBug(
... external_bugtracker, bugtracker, debian, '5')
WARNING:...:Unknown debian package (#5 at http://...): no-such-package
(OOPS-...)
>>> [added_task] = bug.bugtasks
>>> added_task.distribution.name
u'debian'
>>> print added_task.sourcepackagename
None
Syncing status
--------------
After the bug watch has been created for the imported bug, the status is
not synced immediately. The status will be updated the next time all the
bug watches for this bug tracker gets updated. This is to avoid making
one request per imported bug.
>>> added_task.status.name
'NEW'
>>> print added_task.bugwatch.lastchecked
None
Reporter already registered in Launchpad
----------------------------------------
Even if the reporter of the bug has an account in Launchpad (and thus a
valid e-mail address), he still won't be subscribed to the imported bug.
>>> no_priv = getUtility(IPersonSet).getByName('no-priv')
>>> no_priv.preferredemail is not None
True
>>> external_bugtracker._bugs['7'] = {
... 'package': 'evolution',
... 'reporter': ('Not Used', no_priv.preferredemail.email)}
>>> bug = bug_watch_updater.importBug(
... external_bugtracker, bugtracker, debian, '7')
>>> bug.owner.name
u'no-priv'
>>> bug.owner.displayname
u'No Privileges Person'
>>> [person.name for person in bug.getDirectSubscribers()]
[]
|