13155.1.17
by Curtis Hovey
Updated the copyrights in the very old branch. |
1 |
# Copyright 2009-2011 Canonical Ltd. This software is licensed under the
|
8687.15.15
by Karl Fogel
Add the copyright header block to files under lib/lp/bugs/. |
2 |
# GNU Affero General Public License version 3 (see the file LICENSE).
|
3 |
||
4983.1.2
by Curtis Hovey
Added pylint exceptions to database classes. |
4 |
# pylint: disable-msg=E0611,W0212
|
1670
by Canonical.com Patch Queue Manager
Big lot of database clean-up r=stub except for resolution of conflicts. |
5 |
|
6 |
__metaclass__ = type |
|
5308.1.20
by Gavin Panella
First lot of review changes suggested by Barry. |
7 |
__all__ = [ |
8 |
'BugTracker', |
|
7675.837.20
by Bryce Harrington
Tidy up code |
9 |
'BugTrackerSet', |
5308.1.20
by Gavin Panella
First lot of review changes suggested by Barry. |
10 |
'BugTrackerAlias', |
11 |
'BugTrackerAliasSet', |
|
7675.837.2
by Bryce Harrington
Alphabetize class order |
12 |
'BugTrackerComponent', |
13 |
'BugTrackerComponentGroup', |
|
11562.3.2
by Robert Collins
Move Active/Inactive batch navigators to batching for reuse and define a more useful api for getting sets of trackers. |
14 |
'BugTrackerSet', |
7675.837.7
by Bryce Harrington
Implement routines for adding and getting component groups |
15 |
]
|
7675.604.2
by Gavin Panella
Fix lint. |
16 |
|
17 |
from datetime import datetime |
|
5308.1.12
by Gavin Panella
Working, but needs more comprehensive testing. |
18 |
from itertools import chain |
5613.1.12
by Graham Binns
Fixed an assload of lint errors. |
19 |
# splittype is not formally documented, but is in urllib.__all__, is
|
20 |
# simple, and is heavily used by the rest of urllib, hence is unlikely
|
|
21 |
# to change or go away.
|
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
22 |
from urllib import ( |
23 |
quote, |
|
24 |
splittype, |
|
25 |
)
|
|
26 |
||
27 |
from lazr.uri import URI |
|
28 |
from pytz import timezone |
|
3018.2.1
by Stuart Bishop
Refactor celebrities to use a descriptor, removing need for boilerplate code. Also optimizes database access, ensuring at most one database query per celebrity per request. |
29 |
from sqlobject import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
30 |
BoolCol, |
31 |
ForeignKey, |
|
32 |
OR, |
|
33 |
SQLMultipleJoin, |
|
34 |
SQLObjectNotFound, |
|
35 |
StringCol, |
|
36 |
)
|
|
5796.13.14
by Gavin Panella
Show imported_bug_comments working on newly added data; order by BugMessage ASC not DESC. |
37 |
from sqlobject.sqlbuilder import AND |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
38 |
from storm.expr import ( |
39 |
Count, |
|
40 |
Desc, |
|
41 |
Not, |
|
11132.4.21
by Graham Binns
Merged devel, resolved conflicts, instituted world peace. |
42 |
SQL, |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
43 |
)
|
12442.2.9
by j.c.sackett
Ran import reformatter per review. |
44 |
from storm.locals import ( |
45 |
Bool, |
|
46 |
Int, |
|
47 |
Reference, |
|
48 |
ReferenceSet, |
|
49 |
Unicode, |
|
50 |
)
|
|
7238.4.7
by Graham Binns
Updated BugTracker.getBugWatchesNeedingUpdate() and associated tests. |
51 |
from storm.store import Store |
12442.2.9
by j.c.sackett
Ran import reformatter per review. |
52 |
from zope.component import getUtility |
53 |
from zope.interface import implements |
|
7238.4.7
by Graham Binns
Updated BugTracker.getBugWatchesNeedingUpdate() and associated tests. |
54 |
|
12442.2.9
by j.c.sackett
Ran import reformatter per review. |
55 |
from lp.app.errors import NotFoundError |
13130.1.12
by Curtis Hovey
Sorted imports. |
56 |
from lp.app.interfaces.launchpad import ILaunchpadCelebrities |
12442.2.2
by j.c.sackett
Moved validators to app, which makes more sense. |
57 |
from lp.app.validators.email import valid_email |
58 |
from lp.app.validators.name import sanitize_name |
|
8687.4.1
by Graham Binns
Tidied up the lp.bugs.models.bugtracker imports. |
59 |
from lp.bugs.interfaces.bugtracker import ( |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
60 |
BugTrackerType, |
61 |
IBugTracker, |
|
62 |
IBugTrackerAlias, |
|
63 |
IBugTrackerAliasSet, |
|
7675.837.2
by Bryce Harrington
Alphabetize class order |
64 |
IBugTrackerComponent, |
65 |
IBugTrackerComponentGroup, |
|
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
66 |
IBugTrackerSet, |
67 |
SINGLE_PRODUCT_BUGTRACKERTYPES, |
|
68 |
)
|
|
69 |
from lp.bugs.interfaces.bugtrackerperson import BugTrackerPersonAlreadyExists |
|
8523.3.1
by Gavin Panella
Bugs tree reorg after automated migration. |
70 |
from lp.bugs.model.bug import Bug |
71 |
from lp.bugs.model.bugmessage import BugMessage |
|
8687.4.1
by Graham Binns
Tidied up the lp.bugs.models.bugtracker imports. |
72 |
from lp.bugs.model.bugtrackerperson import BugTrackerPerson |
8523.3.1
by Gavin Panella
Bugs tree reorg after automated migration. |
73 |
from lp.bugs.model.bugwatch import BugWatch |
11403.1.4
by Henning Eggers
Reformatted imports using format-imports script r32. |
74 |
from lp.registry.interfaces.person import ( |
75 |
IPersonSet, |
|
76 |
validate_public_person, |
|
77 |
)
|
|
14606.3.1
by William Grant
Merge canonical.database into lp.services.database. |
78 |
from lp.services.database.enumcol import EnumCol |
79 |
from lp.services.database.lpstorm import IStore |
|
80 |
from lp.services.database.sqlbase import ( |
|
81 |
flush_database_updates, |
|
82 |
SQLBase, |
|
83 |
)
|
|
12243.4.3
by j.c.sackett
Moved lp.services.stormbase to lp.services.database.stormbase |
84 |
from lp.services.database.stormbase import StormBase |
14606.3.1
by William Grant
Merge canonical.database into lp.services.database. |
85 |
from lp.services.helpers import shortlist |
86 |
from lp.services.webapp.interfaces import ( |
|
87 |
DEFAULT_FLAVOR, |
|
88 |
IStoreSelector, |
|
89 |
MAIN_STORE, |
|
90 |
)
|
|
5308.1.1
by Gavin Panella
Interfaces and database classes for bug tracker aliases. |
91 |
|
92 |
||
93 |
def normalise_leading_slashes(rest): |
|
94 |
"""Ensure that the 'rest' segment of a URL starts with //."""
|
|
6059.1.20
by Gavin Panella
Default title to baseurl when creating a bugtracker; Fix inconsistencies when searching for bugtrackers. |
95 |
return '//' + rest.lstrip('/') |
5308.1.1
by Gavin Panella
Interfaces and database classes for bug tracker aliases. |
96 |
|
97 |
||
98 |
def normalise_base_url(base_url): |
|
99 |
"""Convert https to http, and normalise scheme for others."""
|
|
5308.1.20
by Gavin Panella
First lot of review changes suggested by Barry. |
100 |
schema, rest = splittype(base_url) |
5308.1.1
by Gavin Panella
Interfaces and database classes for bug tracker aliases. |
101 |
if schema == 'https': |
102 |
return 'http:' + rest |
|
103 |
elif schema is None: |
|
104 |
return 'http:' + normalise_leading_slashes(base_url) |
|
105 |
else: |
|
106 |
return '%s:%s' % (schema, rest) |
|
107 |
||
108 |
||
109 |
def base_url_permutations(base_url): |
|
110 |
"""Return all the possible variants of a base URL.
|
|
111 |
||
112 |
Sometimes the URL ends with slash, sometimes not. Sometimes http
|
|
113 |
is used, sometimes https. This gives a list of all possible
|
|
114 |
variants, so that queryByBaseURL can match a base URL, even if it
|
|
115 |
doesn't match exactly what is stored in the database.
|
|
116 |
||
117 |
>>> base_url_permutations('http://foo/bar')
|
|
118 |
['http://foo/bar', 'http://foo/bar/',
|
|
119 |
'https://foo/bar', 'https://foo/bar/']
|
|
120 |
"""
|
|
121 |
http_schemas = ['http', 'https'] |
|
5308.1.20
by Gavin Panella
First lot of review changes suggested by Barry. |
122 |
url_schema, rest = splittype(base_url) |
5308.1.1
by Gavin Panella
Interfaces and database classes for bug tracker aliases. |
123 |
if url_schema in http_schemas or url_schema is None: |
124 |
possible_schemas = http_schemas |
|
125 |
rest = normalise_leading_slashes(rest) |
|
126 |
else: |
|
127 |
# This else-clause is here since we have no strict
|
|
128 |
# requirement that bug trackers have to have http URLs.
|
|
129 |
possible_schemas = [url_schema] |
|
130 |
alternative_urls = [base_url] |
|
131 |
for schema in possible_schemas: |
|
132 |
url = "%s:%s" % (schema, rest) |
|
133 |
if url != base_url: |
|
134 |
alternative_urls.append(url) |
|
135 |
if url.endswith('/'): |
|
136 |
alternative_urls.append(url[:-1]) |
|
137 |
else: |
|
138 |
alternative_urls.append(url + '/') |
|
139 |
return alternative_urls |
|
1716.1.90
by Christian Reis
Delintifying some of the database classes |
140 |
|
6059.1.31
by Gavin Panella
Clean up some lint. |
141 |
|
5613.1.20
by Graham Binns
Added a test for make_bugtracker_name(); also made make_bugtracker_name() less collision-y. |
142 |
def make_bugtracker_name(uri): |
143 |
"""Return a name string for a bug tracker based on a URI.
|
|
5613.1.2
by Graham Binns
databas.BugWatchSet.extractBugTrackerAndBug() now works for email addresses. |
144 |
|
5613.1.20
by Graham Binns
Added a test for make_bugtracker_name(); also made make_bugtracker_name() less collision-y. |
145 |
:param uri: The base URI to be used to identify the bug tracker,
|
146 |
e.g. http://bugs.example.com or mailto:bugs@example.com
|
|
5613.1.2
by Graham Binns
databas.BugWatchSet.extractBugTrackerAndBug() now works for email addresses. |
147 |
"""
|
5613.1.20
by Graham Binns
Added a test for make_bugtracker_name(); also made make_bugtracker_name() less collision-y. |
148 |
base_uri = URI(uri) |
149 |
if base_uri.scheme == 'mailto': |
|
150 |
if valid_email(base_uri.path): |
|
151 |
base_name = base_uri.path.split('@', 1)[0] |
|
5613.1.2
by Graham Binns
databas.BugWatchSet.extractBugTrackerAndBug() now works for email addresses. |
152 |
else: |
6205.2.5
by Gavin Panella
Raise AssertionError instead of ValueError. |
153 |
raise AssertionError( |
5613.1.20
by Graham Binns
Added a test for make_bugtracker_name(); also made make_bugtracker_name() less collision-y. |
154 |
'Not a valid email address: %s' % base_uri.path) |
5613.1.2
by Graham Binns
databas.BugWatchSet.extractBugTrackerAndBug() now works for email addresses. |
155 |
else: |
5613.1.20
by Graham Binns
Added a test for make_bugtracker_name(); also made make_bugtracker_name() less collision-y. |
156 |
base_name = base_uri.host |
5613.1.2
by Graham Binns
databas.BugWatchSet.extractBugTrackerAndBug() now works for email addresses. |
157 |
|
12599.4.2
by Leonard Richardson
Merge from trunk. |
158 |
return 'auto-%s' % sanitize_name(base_name) |
5613.1.2
by Graham Binns
databas.BugWatchSet.extractBugTrackerAndBug() now works for email addresses. |
159 |
|
1102
by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs |
160 |
|
6205.2.1
by Gavin Panella
New function make_bugtracker_title. |
161 |
def make_bugtracker_title(uri): |
162 |
"""Return a title string for a bug tracker based on a URI.
|
|
163 |
||
164 |
:param uri: The base URI to be used to identify the bug tracker,
|
|
165 |
e.g. http://bugs.example.com or mailto:bugs@example.com
|
|
166 |
"""
|
|
167 |
base_uri = URI(uri) |
|
168 |
if base_uri.scheme == 'mailto': |
|
169 |
if valid_email(base_uri.path): |
|
170 |
local_part, domain = base_uri.path.split('@', 1) |
|
171 |
domain_parts = domain.split('.') |
|
172 |
return 'Email to %s@%s' % (local_part, domain_parts[0]) |
|
173 |
else: |
|
6205.2.5
by Gavin Panella
Raise AssertionError instead of ValueError. |
174 |
raise AssertionError( |
6205.2.1
by Gavin Panella
New function make_bugtracker_title. |
175 |
'Not a valid email address: %s' % base_uri.path) |
176 |
else: |
|
6205.2.2
by Gavin Panella
Include the path in the bugtracker title. |
177 |
return base_uri.host + base_uri.path |
6205.2.1
by Gavin Panella
New function make_bugtracker_title. |
178 |
|
179 |
||
12243.4.2
by j.c.sackett
Updated all uses of storm.base.Storm with lp.services.stormbase.StormBase |
180 |
class BugTrackerComponent(StormBase): |
7675.891.31
by Bryce Harrington
Move BugTrackerComponent back up to top of file. |
181 |
"""The software component in the remote bug tracker.
|
182 |
||
183 |
Most bug trackers organize bug reports by the software 'component'
|
|
184 |
they affect. This class provides a mapping of this upstream component
|
|
185 |
to the corresponding source package in the distro.
|
|
186 |
"""
|
|
187 |
implements(IBugTrackerComponent) |
|
188 |
__storm_table__ = 'BugTrackerComponent' |
|
189 |
||
190 |
id = Int(primary=True) |
|
191 |
name = Unicode(allow_none=False) |
|
192 |
||
193 |
component_group_id = Int('component_group') |
|
194 |
component_group = Reference( |
|
195 |
component_group_id, |
|
196 |
'BugTrackerComponentGroup.id') |
|
197 |
||
198 |
is_visible = Bool(allow_none=False) |
|
199 |
is_custom = Bool(allow_none=False) |
|
200 |
||
201 |
distribution_id = Int('distribution') |
|
202 |
distribution = Reference( |
|
203 |
distribution_id, |
|
204 |
'Distribution.id') |
|
205 |
||
206 |
source_package_name_id = Int('source_package_name') |
|
207 |
source_package_name = Reference( |
|
208 |
source_package_name_id, |
|
209 |
'SourcePackageName.id') |
|
210 |
||
211 |
def _get_distro_source_package(self): |
|
212 |
"""Retrieves the corresponding source package"""
|
|
213 |
if self.distribution is None or self.source_package_name is None: |
|
214 |
return None |
|
215 |
return self.distribution.getSourcePackage( |
|
216 |
self.source_package_name) |
|
217 |
||
218 |
def _set_distro_source_package(self, dsp): |
|
219 |
"""Links this component to its corresponding source package"""
|
|
220 |
if dsp is None: |
|
221 |
self.distribution = None |
|
222 |
self.source_package_name = None |
|
223 |
else: |
|
224 |
self.distribution = dsp.distribution |
|
7675.891.35
by Bryce Harrington
Re-merge API branch this branch depends on. |
225 |
self.source_package_name = dsp.sourcepackagename |
7675.891.31
by Bryce Harrington
Move BugTrackerComponent back up to top of file. |
226 |
|
7675.891.35
by Bryce Harrington
Re-merge API branch this branch depends on. |
227 |
distro_source_package = property( |
228 |
_get_distro_source_package, |
|
229 |
_set_distro_source_package, |
|
230 |
None, |
|
231 |
"""The distribution's source package for this component""") |
|
7675.891.31
by Bryce Harrington
Move BugTrackerComponent back up to top of file. |
232 |
|
233 |
||
12243.4.2
by j.c.sackett
Updated all uses of storm.base.Storm with lp.services.stormbase.StormBase |
234 |
class BugTrackerComponentGroup(StormBase): |
7675.891.31
by Bryce Harrington
Move BugTrackerComponent back up to top of file. |
235 |
"""A collection of components in a remote bug tracker.
|
236 |
||
237 |
Some bug trackers organize sets of components into higher level
|
|
238 |
groups, such as Bugzilla's 'product'.
|
|
239 |
"""
|
|
240 |
implements(IBugTrackerComponentGroup) |
|
241 |
__storm_table__ = 'BugTrackerComponentGroup' |
|
242 |
||
243 |
id = Int(primary=True) |
|
244 |
name = Unicode(allow_none=False) |
|
245 |
bug_tracker_id = Int('bug_tracker') |
|
246 |
bug_tracker = Reference(bug_tracker_id, 'BugTracker.id') |
|
247 |
components = ReferenceSet( |
|
248 |
id, |
|
249 |
BugTrackerComponent.component_group_id, |
|
250 |
order_by=BugTrackerComponent.name) |
|
251 |
||
252 |
def addComponent(self, component_name): |
|
253 |
"""Adds a component that is synced from a remote bug tracker"""
|
|
254 |
||
255 |
component = BugTrackerComponent() |
|
256 |
component.name = component_name |
|
257 |
component.component_group = self |
|
258 |
||
259 |
store = IStore(BugTrackerComponent) |
|
260 |
store.add(component) |
|
261 |
store.flush() |
|
262 |
||
263 |
return component |
|
264 |
||
265 |
def getComponent(self, component_name): |
|
13210.2.2
by Bryce Harrington
Update docstring. Either name or id number is permitted. |
266 |
"""Retrieves a component by the given name or id number.
|
7675.891.31
by Bryce Harrington
Move BugTrackerComponent back up to top of file. |
267 |
|
268 |
None is returned if there is no component by that name in the
|
|
269 |
group.
|
|
270 |
"""
|
|
271 |
||
272 |
if component_name is None: |
|
273 |
return None |
|
7675.1188.12
by Bryce Harrington
Switch from using the component name in the path to using id's. |
274 |
elif component_name.isdigit(): |
275 |
component_id = int(component_name) |
|
276 |
return Store.of(self).find( |
|
277 |
BugTrackerComponent, |
|
278 |
BugTrackerComponent.id == component_id, |
|
279 |
BugTrackerComponent.component_group == self.id).one() |
|
7675.891.31
by Bryce Harrington
Move BugTrackerComponent back up to top of file. |
280 |
else: |
281 |
return Store.of(self).find( |
|
282 |
BugTrackerComponent, |
|
7675.1188.11
by Bryce Harrington
Re-merge db-devel trunk |
283 |
BugTrackerComponent.name == component_name, |
284 |
BugTrackerComponent.component_group == self.id).one() |
|
7675.891.31
by Bryce Harrington
Move BugTrackerComponent back up to top of file. |
285 |
|
286 |
def addCustomComponent(self, component_name): |
|
287 |
"""Adds a component locally that isn't synced from a remote tracker
|
|
288 |
"""
|
|
289 |
||
290 |
component = BugTrackerComponent() |
|
291 |
component.name = component_name |
|
292 |
component.component_group = self |
|
293 |
component.is_custom = True |
|
294 |
||
295 |
store = IStore(BugTrackerComponent) |
|
296 |
store.add(component) |
|
297 |
store.flush() |
|
298 |
||
299 |
return component |
|
300 |
||
301 |
||
1102
by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs |
302 |
class BugTracker(SQLBase): |
5308.1.1
by Gavin Panella
Interfaces and database classes for bug tracker aliases. |
303 |
"""A class to access the BugTracker table in the database.
|
304 |
||
305 |
Each BugTracker is a distinct instance of that bug tracking
|
|
306 |
tool. For example, each Bugzilla deployment is a separate
|
|
307 |
BugTracker. bugzilla.mozilla.org and bugzilla.gnome.org are each
|
|
308 |
distinct BugTrackers.
|
|
1102
by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs |
309 |
"""
|
310 |
implements(IBugTracker) |
|
1716.3.31
by kiko
Order the bugtracker listing, by title, so the end-user is not confused |
311 |
|
1102
by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs |
312 |
_table = 'BugTracker' |
1716.3.31
by kiko
Order the bugtracker listing, by title, so the end-user is not confused |
313 |
|
2048
by Canonical.com Patch Queue Manager
debbugssync, hct enabling, and ui fixes. r=jamesh |
314 |
bugtrackertype = EnumCol(dbName='bugtrackertype', |
315 |
schema=BugTrackerType, notNull=True) |
|
1102
by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs |
316 |
name = StringCol(notNull=True, unique=True) |
317 |
title = StringCol(notNull=True) |
|
5852.2.2
by James Henstridge
fix some columns that claimed to be notNull=True but are in fact not not null |
318 |
summary = StringCol(notNull=False) |
1102
by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs |
319 |
baseurl = StringCol(notNull=True) |
7675.85.2
by Jonathan Lange
Undo revision generated by step 2 of process. |
320 |
active = Bool( |
321 |
name='active', allow_none=False, default=True) |
|
322 |
||
5485.1.17
by Edwin Grubbs
Fixed indentation |
323 |
owner = ForeignKey( |
324 |
dbName='owner', foreignKey='Person', |
|
5821.2.40
by James Henstridge
* Move all the uses of public_person_validator over to the Storm |
325 |
storm_validator=validate_public_person, notNull=True) |
1102
by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs |
326 |
contactdetails = StringCol(notNull=False) |
7147.1.5
by Graham Binns
Added a has_lp_plugin field to IBugTracker. |
327 |
has_lp_plugin = BoolCol(notNull=False, default=False) |
3691.139.3
by Bjorn Tillenius
a Project should have only one bug tracker. |
328 |
projects = SQLMultipleJoin( |
10724.1.6
by Henning Eggers
Vocabulary names. |
329 |
'ProjectGroup', joinColumn='bugtracker', orderBy='name') |
5005.2.2
by Gavin Panella
Implementation. |
330 |
products = SQLMultipleJoin( |
331 |
'Product', joinColumn='bugtracker', orderBy='name') |
|
8687.4.1
by Graham Binns
Tidied up the lp.bugs.models.bugtracker imports. |
332 |
watches = SQLMultipleJoin( |
333 |
'BugWatch', joinColumn='bugtracker', orderBy='-datecreated', |
|
334 |
prejoins=['bug']) |
|
7675.837.8
by Bryce Harrington
Add factory methods for creating component/component_group tests |
335 |
|
7634.3.19
by Graham Binns
Review changes for Danilo. |
336 |
_filing_url_patterns = { |
337 |
BugTrackerType.BUGZILLA: ( |
|
7849.7.3
by Graham Binns
Added trackers for SourceForge, RT and Bugzilla. |
338 |
"%(base_url)s/enter_bug.cgi?product=%(remote_product)s" |
339 |
"&short_desc=%(summary)s&long_desc=%(description)s"), |
|
8342.4.1
by Graham Binns
Merged Google Code watches stuff back into the branch. |
340 |
BugTrackerType.GOOGLE_CODE: ( |
10007.1.1
by luke at faraone
Remove literal "&" from BugTrackerType.GOOGLE_CODE, replace with "&". |
341 |
"%(base_url)s/entry?summary=%(summary)s&" |
8342.4.1
by Graham Binns
Merged Google Code watches stuff back into the branch. |
342 |
"comment=%(description)s"), |
7849.7.7
by Graham Binns
Added nonsense for Mantis. |
343 |
BugTrackerType.MANTIS: ( |
344 |
"%(base_url)s/bug_report_advanced_page.php" |
|
345 |
"?summary=%(summary)s&description=%(description)s"), |
|
7849.7.5
by Graham Binns
Added search links for Roundup. |
346 |
BugTrackerType.PHPPROJECT: ( |
347 |
"%(base_url)s/report.php" |
|
348 |
"?in[sdesc]=%(summary)s&in[ldesc]=%(description)s"), |
|
7849.7.6
by Graham Binns
Added bug filing links for Roundup. |
349 |
BugTrackerType.ROUNDUP: ( |
350 |
"%(base_url)s/issue?@template=item&title=%(summary)s" |
|
351 |
"&@note=%(description)s"), |
|
7634.3.19
by Graham Binns
Review changes for Danilo. |
352 |
BugTrackerType.RT: ( |
7849.7.3
by Graham Binns
Added trackers for SourceForge, RT and Bugzilla. |
353 |
"%(base_url)s/Ticket/Create.html?Queue=%(remote_product)s" |
354 |
"&Subject=%(summary)s&Content=%(description)s"), |
|
7634.3.19
by Graham Binns
Review changes for Danilo. |
355 |
BugTrackerType.SAVANE: ( |
356 |
"%(base_url)s/bugs/?func=additem&group=%(remote_product)s"), |
|
357 |
BugTrackerType.SOURCEFORGE: ( |
|
358 |
"%(base_url)s/%(tracker)s/?func=add&" |
|
7849.7.5
by Graham Binns
Added search links for Roundup. |
359 |
"group_id=%(group_id)s&atid=%(at_id)s"), |
11807.5.2
by Deryck Hodge
Fix the filing url patterns for Trac, to get test passing |
360 |
BugTrackerType.TRAC: ( |
361 |
"%(base_url)s/newticket?summary=%(summary)s&" |
|
362 |
"description=%(description)s"), |
|
7634.3.19
by Graham Binns
Review changes for Danilo. |
363 |
}
|
364 |
||
365 |
_search_url_patterns = { |
|
366 |
BugTrackerType.BUGZILLA: ( |
|
7849.7.3
by Graham Binns
Added trackers for SourceForge, RT and Bugzilla. |
367 |
"%(base_url)s/query.cgi?product=%(remote_product)s" |
368 |
"&short_desc=%(summary)s"), |
|
8342.4.1
by Graham Binns
Merged Google Code watches stuff back into the branch. |
369 |
BugTrackerType.GOOGLE_CODE: "%(base_url)s/list?q=%(summary)s", |
7767.1.1
by Graham Binns
Added a search URL for debbugs. |
370 |
BugTrackerType.DEBBUGS: ( |
7849.7.8
by Graham Binns
Finished adding summary and description for upstream bugtracker links. |
371 |
"%(base_url)s/cgi-bin/search.cgi?phrase=%(summary)s" |
372 |
"&attribute_field=package&attribute_operator=STROREQ"
|
|
373 |
"&attribute_value=%(remote_product)s"), |
|
7634.3.19
by Graham Binns
Review changes for Danilo. |
374 |
BugTrackerType.MANTIS: "%(base_url)s/view_all_bug_page.php", |
7849.7.5
by Graham Binns
Added search links for Roundup. |
375 |
BugTrackerType.PHPPROJECT: ( |
376 |
"%(base_url)s/search.php?search_for=%(summary)s"), |
|
377 |
BugTrackerType.ROUNDUP: ( |
|
378 |
"%(base_url)s/issue?@template=search&@search_text=%(summary)s"), |
|
7634.3.19
by Graham Binns
Review changes for Danilo. |
379 |
BugTrackerType.RT: ( |
7634.3.10
by Graham Binns
Added tests for search URLS. |
380 |
"%(base_url)s/Search/Build.html?Query=Queue = " |
7849.7.3
by Graham Binns
Added trackers for SourceForge, RT and Bugzilla. |
381 |
"'%(remote_product)s' AND Subject LIKE '%(summary)s'"), |
7344.3.3
by Graham Binns
Added core functionality. |
382 |
BugTrackerType.SAVANE: ( |
7634.3.19
by Graham Binns
Review changes for Danilo. |
383 |
"%(base_url)s/bugs/?func=search&group=%(remote_product)s"), |
7344.3.3
by Graham Binns
Added core functionality. |
384 |
BugTrackerType.SOURCEFORGE: ( |
7849.7.3
by Graham Binns
Added trackers for SourceForge, RT and Bugzilla. |
385 |
"%(base_url)s/search/?group_id=%(group_id)s" |
386 |
"&some_word=%(summary)s&type_of_search=artifact"), |
|
7849.7.5
by Graham Binns
Added search links for Roundup. |
387 |
BugTrackerType.TRAC: "%(base_url)s/search?ticket=on&q=%(summary)s", |
7344.3.3
by Graham Binns
Added core functionality. |
388 |
}
|
389 |
||
2048
by Canonical.com Patch Queue Manager
debbugssync, hct enabling, and ui fixes. r=jamesh |
390 |
@property
|
8687.4.2
by Graham Binns
The gnome-bugs bugtracker now uses a custom URL for its bug filing link. |
391 |
def _custom_filing_url_patterns(self): |
392 |
"""Return a dict of bugtracker-specific bugfiling URL patterns."""
|
|
393 |
gnome_bugzilla = getUtility(ILaunchpadCelebrities).gnome_bugzilla |
|
394 |
return { |
|
395 |
gnome_bugzilla: ( |
|
396 |
"%(base_url)s/enter_bug.cgi?product=%(remote_product)s" |
|
397 |
"&short_desc=%(summary)s&comment=%(description)s"), |
|
398 |
}
|
|
399 |
||
400 |
@property
|
|
2048
by Canonical.com Patch Queue Manager
debbugssync, hct enabling, and ui fixes. r=jamesh |
401 |
def latestwatches(self): |
7344.3.7
by Graham Binns
Cleanup for Brad and Paul. |
402 |
"""See `IBugTracker`."""
|
3024.1.35
by Christian Reis
Implement performance fixes on the top timeout pages, mainly through the use of prejoins, properties and one cachedproperty: bugtracker-index, person-packages, distribution-allpackages, distroreleaselanguage, products-all, products-index, bug listings and a few others. This should make even soft timeouts on those pages hopefully disappear. |
403 |
return self.watches[:10] |
404 |
||
7634.3.2
by Graham Binns
Added BugTracker.requires_remote_product and tests. |
405 |
@property
|
7634.3.5
by Graham Binns
Renamed BugTracker.requires_remote_product -> multi_product per allenap's ideas. Corrected docstrings. |
406 |
def multi_product(self): |
7634.3.7
by Graham Binns
Review changes. |
407 |
"""Return True if this BugTracker tracks multiple projects."""
|
7634.3.5
by Graham Binns
Renamed BugTracker.requires_remote_product -> multi_product per allenap's ideas. Corrected docstrings. |
408 |
if self.bugtrackertype not in SINGLE_PRODUCT_BUGTRACKERTYPES: |
7634.3.2
by Graham Binns
Added BugTracker.requires_remote_product and tests. |
409 |
return True |
410 |
else: |
|
411 |
return False |
|
412 |
||
7849.7.1
by Graham Binns
Added summary and description parameters to getBugFilingAndSearchLinks(). |
413 |
def getBugFilingAndSearchLinks(self, remote_product, summary=None, |
13405.8.1
by Bryce Harrington
Add optional remote_component parameter to getBugFilingAndSearchLinks |
414 |
description=None, remote_component=None): |
7344.3.2
by Graham Binns
Added tests and basics. |
415 |
"""See `IBugTracker`."""
|
7634.3.19
by Graham Binns
Review changes for Danilo. |
416 |
bugtracker_urls = {'bug_filing_url': None, 'bug_search_url': None} |
7634.3.9
by Graham Binns
BugTracker.getBugFilingLink() -> BugTracker->getBugFilingAndSearchLinks(). |
417 |
|
7634.3.5
by Graham Binns
Renamed BugTracker.requires_remote_product -> multi_product per allenap's ideas. Corrected docstrings. |
418 |
if remote_product is None and self.multi_product: |
7634.3.4
by Graham Binns
Added a test for bugtrackers that don't need a remote product to product.txt. |
419 |
# Don't try to return anything if remote_product is required
|
420 |
# for this BugTrackerType and one hasn't been passed.
|
|
7767.1.5
by Graham Binns
Removed the (now unnecessary) test fixes that I had to put in when trunk broke. |
421 |
return bugtracker_urls |
7634.3.7
by Graham Binns
Review changes. |
422 |
|
423 |
if remote_product is None: |
|
7634.3.2
by Graham Binns
Added BugTracker.requires_remote_product and tests. |
424 |
# Turn the remote product into an empty string so that
|
425 |
# quote() doesn't blow up later on.
|
|
426 |
remote_product = '' |
|
427 |
||
13405.8.2
by Bryce Harrington
Add remote_component to url_components |
428 |
if remote_component is None: |
429 |
# Ditto for remote component.
|
|
430 |
remote_component = '' |
|
431 |
||
8687.4.2
by Graham Binns
The gnome-bugs bugtracker now uses a custom URL for its bug filing link. |
432 |
if self in self._custom_filing_url_patterns: |
433 |
# Some bugtrackers are customised to accept different
|
|
434 |
# querystring parameters from the default. We special-case
|
|
435 |
# these.
|
|
436 |
bug_filing_pattern = self._custom_filing_url_patterns[self] |
|
437 |
else: |
|
438 |
bug_filing_pattern = self._filing_url_patterns.get( |
|
439 |
self.bugtrackertype, None) |
|
440 |
||
7634.3.19
by Graham Binns
Review changes for Danilo. |
441 |
bug_search_pattern = self._search_url_patterns.get( |
442 |
self.bugtrackertype, None) |
|
7344.3.7
by Graham Binns
Cleanup for Brad and Paul. |
443 |
|
7344.3.3
by Graham Binns
Added core functionality. |
444 |
# Make sure that we don't put > 1 '/' in returned URLs.
|
445 |
base_url = self.baseurl.rstrip('/') |
|
446 |
||
7849.7.1
by Graham Binns
Added summary and description parameters to getBugFilingAndSearchLinks(). |
447 |
# If summary or description are None, convert them to empty
|
448 |
# strings to that we don't try to pass anything to the upstream
|
|
449 |
# bug tracker.
|
|
450 |
if summary is None: |
|
451 |
summary = '' |
|
452 |
if description is None: |
|
453 |
description = '' |
|
454 |
||
8132.2.1
by Graham Binns
BugTracker.getBugFilingAndSearchLinks() now handles unicode properly. |
455 |
# UTF-8 encode the description and summary so that quote()
|
456 |
# doesn't break if they contain unicode characters it doesn't
|
|
457 |
# understand.
|
|
458 |
summary = summary.encode('utf-8') |
|
459 |
description = description.encode('utf-8') |
|
460 |
||
7344.3.8
by Graham Binns
Fixed a silly coding snafu. |
461 |
if self.bugtrackertype == BugTrackerType.SOURCEFORGE: |
13128.1.1
by Graham Binns
Added test and fix. |
462 |
try: |
463 |
# SourceForge bug trackers use a group ID and an ATID to
|
|
464 |
# file a bug, rather than a product name. remote_product
|
|
465 |
# should be an ampersand-separated string in the form
|
|
466 |
# 'group_id&atid'
|
|
467 |
group_id, at_id = remote_product.split('&') |
|
468 |
except ValueError: |
|
469 |
# If remote_product contains something that's not valid
|
|
470 |
# in a SourceForge context we just return early.
|
|
471 |
return None |
|
7344.3.3
by Graham Binns
Added core functionality. |
472 |
|
473 |
# If this bug tracker is the SourceForge celebrity the link
|
|
474 |
# is to the new bug tracker rather than the old one.
|
|
475 |
sf_celeb = getUtility(ILaunchpadCelebrities).sourceforge_tracker |
|
476 |
if self == sf_celeb: |
|
477 |
tracker = 'tracker2' |
|
478 |
else: |
|
479 |
tracker = 'tracker' |
|
480 |
||
7634.3.10
by Graham Binns
Added tests for search URLS. |
481 |
url_components = { |
7344.3.3
by Graham Binns
Added core functionality. |
482 |
'base_url': base_url, |
7344.3.9
by Graham Binns
Fix and tests for bug 304849 |
483 |
'tracker': quote(tracker), |
484 |
'group_id': quote(group_id), |
|
485 |
'at_id': quote(at_id), |
|
7849.7.8
by Graham Binns
Finished adding summary and description for upstream bugtracker links. |
486 |
'summary': quote(summary), |
487 |
'description': quote(description), |
|
7634.3.10
by Graham Binns
Added tests for search URLS. |
488 |
}
|
7344.3.3
by Graham Binns
Added core functionality. |
489 |
|
7344.3.5
by Graham Binns
Documentation and a minor code tweak. |
490 |
else: |
7634.3.10
by Graham Binns
Added tests for search URLS. |
491 |
url_components = { |
7344.3.5
by Graham Binns
Documentation and a minor code tweak. |
492 |
'base_url': base_url, |
7344.3.9
by Graham Binns
Fix and tests for bug 304849 |
493 |
'remote_product': quote(remote_product), |
13405.8.2
by Bryce Harrington
Add remote_component to url_components |
494 |
'remote_component': quote(remote_component), |
7849.7.8
by Graham Binns
Finished adding summary and description for upstream bugtracker links. |
495 |
'summary': quote(summary), |
496 |
'description': quote(description), |
|
7634.3.10
by Graham Binns
Added tests for search URLS. |
497 |
}
|
498 |
||
7634.3.19
by Graham Binns
Review changes for Danilo. |
499 |
if bug_filing_pattern is not None: |
500 |
bugtracker_urls['bug_filing_url'] = ( |
|
501 |
bug_filing_pattern % url_components) |
|
502 |
if bug_search_pattern is not None: |
|
503 |
bugtracker_urls['bug_search_url'] = ( |
|
504 |
bug_search_pattern % url_components) |
|
7344.3.2
by Graham Binns
Added tests and basics. |
505 |
|
7634.3.9
by Graham Binns
BugTracker.getBugFilingLink() -> BugTracker->getBugFilingAndSearchLinks(). |
506 |
return bugtracker_urls |
507 |
||
2950.2.1
by James Henstridge
Make /malone/bugtrackers/$bugtrackername/$remotebug redirect to the |
508 |
def getBugsWatching(self, remotebug): |
7344.3.2
by Graham Binns
Added tests and basics. |
509 |
"""See `IBugTracker`."""
|
5613.1.4
by Graham Binns
BugTracker.getBugsWathching() now always returns [] when called on an email address bug tracker. |
510 |
# We special-case email address bug trackers. Since we don't
|
511 |
# record a remote bug id for them we can never know which bugs
|
|
512 |
# are already watching a remote bug.
|
|
513 |
if self.bugtrackertype == BugTrackerType.EMAILADDRESS: |
|
514 |
return [] |
|
515 |
||
2950.2.1
by James Henstridge
Make /malone/bugtrackers/$bugtrackername/$remotebug redirect to the |
516 |
return shortlist(Bug.select(AND(BugWatch.q.bugID == Bug.q.id, |
517 |
BugWatch.q.bugtrackerID == self.id, |
|
518 |
BugWatch.q.remotebug == remotebug), |
|
519 |
distinct=True, |
|
520 |
orderBy=['datecreated'])) |
|
521 |
||
7675.604.7
by Gavin Panella
Add new properties to BugTracker: watches_ready_to_check, watches_with_unpushed_comments and watches_needing_update. |
522 |
@property
|
523 |
def watches_ready_to_check(self): |
|
524 |
return Store.of(self).find( |
|
7238.4.7
by Graham Binns
Updated BugTracker.getBugWatchesNeedingUpdate() and associated tests. |
525 |
BugWatch, |
7337.7.3
by Graham Binns
Review changes for Gavin. |
526 |
BugWatch.bugtracker == self, |
7675.595.6
by Graham Binns
Updated tests to take account of the lastcheck -> next_check transition. |
527 |
Not(BugWatch.next_check == None), |
528 |
BugWatch.next_check <= datetime.now(timezone('UTC'))) |
|
7238.4.7
by Graham Binns
Updated BugTracker.getBugWatchesNeedingUpdate() and associated tests. |
529 |
|
7675.604.7
by Gavin Panella
Add new properties to BugTracker: watches_ready_to_check, watches_with_unpushed_comments and watches_needing_update. |
530 |
@property
|
531 |
def watches_with_unpushed_comments(self): |
|
532 |
return Store.of(self).find( |
|
7238.4.7
by Graham Binns
Updated BugTracker.getBugWatchesNeedingUpdate() and associated tests. |
533 |
BugWatch, |
7337.7.3
by Graham Binns
Review changes for Gavin. |
534 |
BugWatch.bugtracker == self, |
7238.4.7
by Graham Binns
Updated BugTracker.getBugWatchesNeedingUpdate() and associated tests. |
535 |
BugMessage.bugwatch == BugWatch.id, |
7675.604.7
by Gavin Panella
Add new properties to BugTracker: watches_ready_to_check, watches_with_unpushed_comments and watches_needing_update. |
536 |
BugMessage.remote_comment_id == None).config(distinct=True) |
537 |
||
538 |
@property
|
|
539 |
def watches_needing_update(self): |
|
540 |
"""All watches needing some sort of update.
|
|
541 |
||
542 |
:return: The union of `watches_ready_to_check` and
|
|
543 |
`watches_with_unpushed_comments`.
|
|
544 |
"""
|
|
545 |
return self.watches_ready_to_check.union( |
|
546 |
self.watches_with_unpushed_comments) |
|
547 |
||
5308.1.22
by Gavin Panella
Small changes as suggested by Barry in review. |
548 |
# Join to return a list of BugTrackerAliases relating to this
|
549 |
# BugTracker.
|
|
5308.1.3
by Gavin Panella
Change aliases to be like IBug.tags. |
550 |
_bugtracker_aliases = SQLMultipleJoin( |
5308.1.12
by Gavin Panella
Working, but needs more comprehensive testing. |
551 |
'BugTrackerAlias', joinColumn='bugtracker') |
5308.1.3
by Gavin Panella
Change aliases to be like IBug.tags. |
552 |
|
553 |
def _get_aliases(self): |
|
5308.1.20
by Gavin Panella
First lot of review changes suggested by Barry. |
554 |
"""See `IBugTracker.aliases`."""
|
5308.1.12
by Gavin Panella
Working, but needs more comprehensive testing. |
555 |
alias_urls = set(alias.base_url for alias in self._bugtracker_aliases) |
556 |
# Although it does no harm if the current baseurl is also an
|
|
5906.3.5
by Gavin Panella
Demonstrate that minor changes to the main location of a bug tracker can be made without going insane. |
557 |
# alias, we hide it and all its permutations to avoid
|
558 |
# confusion.
|
|
559 |
alias_urls.difference_update(base_url_permutations(self.baseurl)) |
|
5308.1.23
by Gavin Panella
Make bugtracker.aliases returns a tuple. |
560 |
return tuple(sorted(alias_urls)) |
5308.1.3
by Gavin Panella
Change aliases to be like IBug.tags. |
561 |
|
5308.1.12
by Gavin Panella
Working, but needs more comprehensive testing. |
562 |
def _set_aliases(self, alias_urls): |
5308.1.20
by Gavin Panella
First lot of review changes suggested by Barry. |
563 |
"""See `IBugTracker.aliases`."""
|
5308.1.9
by Gavin Panella
Redefine deletion of aliases as setting to an empty list so that moving parts are in one place. |
564 |
if alias_urls is None: |
5308.1.12
by Gavin Panella
Working, but needs more comprehensive testing. |
565 |
alias_urls = set() |
566 |
else: |
|
567 |
alias_urls = set(alias_urls) |
|
5308.1.9
by Gavin Panella
Redefine deletion of aliases as setting to an empty list so that moving parts are in one place. |
568 |
|
5308.1.3
by Gavin Panella
Change aliases to be like IBug.tags. |
569 |
current_aliases_by_url = dict( |
570 |
(alias.base_url, alias) for alias in self._bugtracker_aliases) |
|
5308.1.20
by Gavin Panella
First lot of review changes suggested by Barry. |
571 |
# Make a set of the keys, i.e. a set of current URLs.
|
5308.1.3
by Gavin Panella
Change aliases to be like IBug.tags. |
572 |
current_alias_urls = set(current_aliases_by_url) |
573 |
||
5308.1.20
by Gavin Panella
First lot of review changes suggested by Barry. |
574 |
# URLs we need to add as aliases.
|
5308.1.3
by Gavin Panella
Change aliases to be like IBug.tags. |
575 |
to_add = alias_urls - current_alias_urls |
5308.1.20
by Gavin Panella
First lot of review changes suggested by Barry. |
576 |
# URL aliases we need to delete.
|
5308.1.3
by Gavin Panella
Change aliases to be like IBug.tags. |
577 |
to_del = current_alias_urls - alias_urls |
578 |
||
579 |
for url in to_add: |
|
580 |
BugTrackerAlias(bugtracker=self, base_url=url) |
|
581 |
for url in to_del: |
|
582 |
alias = current_aliases_by_url[url] |
|
583 |
alias.destroySelf() |
|
584 |
||
5308.1.20
by Gavin Panella
First lot of review changes suggested by Barry. |
585 |
aliases = property( |
586 |
_get_aliases, _set_aliases, None, |
|
587 |
"""A list of the alias URLs. See `IBugTracker`.
|
|
5308.1.12
by Gavin Panella
Working, but needs more comprehensive testing. |
588 |
|
5308.1.20
by Gavin Panella
First lot of review changes suggested by Barry. |
589 |
The aliases are found by querying BugTrackerAlias. Assign an
|
590 |
iterable of URLs or None to set or remove aliases.
|
|
591 |
""") |
|
5308.1.3
by Gavin Panella
Change aliases to be like IBug.tags. |
592 |
|
5796.13.1
by Gavin Panella
Implementation of deleting bug trackers. |
593 |
@property
|
5796.13.4
by Gavin Panella
Don't query for Messages, just get BugMessages. |
594 |
def imported_bug_messages(self): |
5796.13.1
by Gavin Panella
Implementation of deleting bug trackers. |
595 |
"""See `IBugTracker`."""
|
5796.13.4
by Gavin Panella
Don't query for Messages, just get BugMessages. |
596 |
return BugMessage.select( |
597 |
AND((BugMessage.q.bugwatchID == BugWatch.q.id), |
|
5796.13.5
by Gavin Panella
Documentation for imported_bug_messages; sort the bug messages too. |
598 |
(BugWatch.q.bugtrackerID == self.id)), |
5796.13.14
by Gavin Panella
Show imported_bug_comments working on newly added data; order by BugMessage ASC not DESC. |
599 |
orderBy=BugMessage.q.id) |
5796.13.1
by Gavin Panella
Implementation of deleting bug trackers. |
600 |
|
6331.3.12
by Graham Binns
Moved BugTrackerPersonSet logic into BugTracker. |
601 |
def getLinkedPersonByName(self, name): |
602 |
"""Return the Person with a given name on this bugtracker."""
|
|
603 |
return BugTrackerPerson.selectOneBy(name=name, bugtracker=self) |
|
604 |
||
605 |
def linkPersonToSelf(self, name, person): |
|
606 |
"""See `IBugTrackerSet`."""
|
|
607 |
# Check that this name isn't already in use for this bugtracker.
|
|
608 |
if self.getLinkedPersonByName(name) is not None: |
|
609 |
raise BugTrackerPersonAlreadyExists( |
|
610 |
"Name '%s' is already in use for bugtracker '%s'." % |
|
611 |
(name, self.name)) |
|
612 |
||
613 |
bugtracker_person = BugTrackerPerson( |
|
614 |
name=name, bugtracker=self, person=person) |
|
615 |
||
616 |
return bugtracker_person |
|
617 |
||
6325.2.38
by Graham Binns
Moved ensurePerson... into BugTracker. |
618 |
def ensurePersonForSelf( |
6325.2.37
by Graham Binns
Merged bugtracker person branch. |
619 |
self, display_name, email, rationale, creation_comment): |
620 |
"""Return a Person that is linked to this bug tracker."""
|
|
621 |
# If we have an email address to work with we can use
|
|
622 |
# ensurePerson() to get the Person we need.
|
|
623 |
if email is not None: |
|
624 |
return getUtility(IPersonSet).ensurePerson( |
|
625 |
email, display_name, rationale, creation_comment) |
|
626 |
||
627 |
# First, see if there's already a BugTrackerPerson for this
|
|
628 |
# display_name on this bugtracker. If there is, return it.
|
|
629 |
bugtracker_person = self.getLinkedPersonByName(display_name) |
|
630 |
||
631 |
if bugtracker_person is not None: |
|
632 |
return bugtracker_person.person |
|
633 |
||
634 |
# Generate a valid Launchpad name for the Person.
|
|
635 |
base_canonical_name = ( |
|
6325.2.38
by Graham Binns
Moved ensurePerson... into BugTracker. |
636 |
"%s-%s" % (sanitize_name(display_name), self.name)) |
6325.2.37
by Graham Binns
Merged bugtracker person branch. |
637 |
canonical_name = base_canonical_name |
638 |
||
639 |
person_set = getUtility(IPersonSet) |
|
640 |
index = 0 |
|
641 |
while person_set.getByName(canonical_name) is not None: |
|
642 |
index += 1 |
|
643 |
canonical_name = "%s-%s" % (base_canonical_name, index) |
|
644 |
||
645 |
person = person_set.createPersonWithoutEmail( |
|
646 |
canonical_name, rationale, creation_comment, |
|
647 |
displayname=display_name) |
|
648 |
||
649 |
# Link the Person to the bugtracker for future reference.
|
|
650 |
bugtracker_person = self.linkPersonToSelf(display_name, person) |
|
651 |
||
652 |
return person |
|
653 |
||
11132.4.22
by Graham Binns
Added an AuthorizationBase class for Bugtracker so that we don't have to futz around with permissions. |
654 |
def resetWatches(self, new_next_check=None): |
9600.2.4
by Graham Binns
Added resetWatches() method to IBugTracker. |
655 |
"""See `IBugTracker`."""
|
11132.4.1
by Graham Binns
Added a test for the new randomisation code. Expressed in Storm, it breaks. |
656 |
if new_next_check is None: |
657 |
new_next_check = SQL( |
|
11132.4.11
by Graham Binns
Changed 7 days to 1; 7 just causes problems. |
658 |
"now() at time zone 'UTC' + (random() * interval '1 day')") |
7675.595.6
by Graham Binns
Updated tests to take account of the lastcheck -> next_check transition. |
659 |
|
9600.2.4
by Graham Binns
Added resetWatches() method to IBugTracker. |
660 |
store = Store.of(self) |
11132.4.2
by Graham Binns
resetWatches() now randomises the next_check times for all bug watches unless told not to. |
661 |
store.find(BugWatch, BugWatch.bugtracker == self).set( |
662 |
next_check=new_next_check, lastchecked=None, |
|
663 |
last_error_type=None) |
|
9600.2.4
by Graham Binns
Added resetWatches() method to IBugTracker. |
664 |
|
7675.837.7
by Bryce Harrington
Implement routines for adding and getting component groups |
665 |
def addRemoteComponentGroup(self, component_group_name): |
666 |
"""See `IBugTracker`."""
|
|
7675.837.21
by Bryce Harrington
Fix lintian issues |
667 |
|
7675.837.15
by Bryce Harrington
Enable storing data into the database now that permissions are there. |
668 |
if component_group_name is None: |
669 |
component_group_name = "default" |
|
670 |
component_group = BugTrackerComponentGroup() |
|
671 |
component_group.name = component_group_name |
|
7675.837.12
by Bryce Harrington
Persist components and component_groups |
672 |
component_group.bug_tracker = self |
7675.837.11
by Bryce Harrington
Hook up component groups to their bug trackers |
673 |
|
7675.837.12
by Bryce Harrington
Persist components and component_groups |
674 |
store = IStore(BugTrackerComponentGroup) |
675 |
store.add(component_group) |
|
7675.837.15
by Bryce Harrington
Enable storing data into the database now that permissions are there. |
676 |
store.commit() |
7675.837.11
by Bryce Harrington
Hook up component groups to their bug trackers |
677 |
|
7675.837.8
by Bryce Harrington
Add factory methods for creating component/component_group tests |
678 |
return component_group |
7675.837.7
by Bryce Harrington
Implement routines for adding and getting component groups |
679 |
|
7675.837.40
by Bryce Harrington
Restore getAllRemoteComponentGroups() |
680 |
def getAllRemoteComponentGroups(self): |
681 |
"""See `IBugTracker`."""
|
|
682 |
component_groups = [] |
|
683 |
||
684 |
component_groups = Store.of(self).find( |
|
685 |
BugTrackerComponentGroup, |
|
686 |
BugTrackerComponentGroup.bug_tracker == self.id) |
|
687 |
component_groups = component_groups.order_by( |
|
688 |
BugTrackerComponentGroup.name) |
|
689 |
return component_groups |
|
690 |
||
7675.837.11
by Bryce Harrington
Hook up component groups to their bug trackers |
691 |
def getRemoteComponentGroup(self, component_group_name): |
7675.837.7
by Bryce Harrington
Implement routines for adding and getting component groups |
692 |
"""See `IBugTracker`."""
|
7675.837.13
by Bryce Harrington
Attempt to get getAllRemoteComponentGroups() hooked up, but something |
693 |
component_group = None |
7675.837.15
by Bryce Harrington
Enable storing data into the database now that permissions are there. |
694 |
store = IStore(BugTrackerComponentGroup) |
13210.1.1
by Bryce Harrington
Verify component_group_name isn't None before dereferencing |
695 |
if component_group_name is None: |
696 |
return None |
|
697 |
elif component_group_name.isdigit(): |
|
7675.1188.12
by Bryce Harrington
Switch from using the component name in the path to using id's. |
698 |
component_group_id = int(component_group_name) |
699 |
component_group = store.find( |
|
700 |
BugTrackerComponentGroup, |
|
13155.1.13
by Curtis Hovey
Use find().one() because the db has a sane constraint. |
701 |
BugTrackerComponentGroup.id == component_group_id).one() |
7675.1188.12
by Bryce Harrington
Switch from using the component name in the path to using id's. |
702 |
else: |
703 |
component_group = store.find( |
|
704 |
BugTrackerComponentGroup, |
|
13155.1.13
by Curtis Hovey
Use find().one() because the db has a sane constraint. |
705 |
BugTrackerComponentGroup.name == component_group_name).one() |
7675.837.13
by Bryce Harrington
Attempt to get getAllRemoteComponentGroups() hooked up, but something |
706 |
return component_group |
7675.837.7
by Bryce Harrington
Implement routines for adding and getting component groups |
707 |
|
13155.1.19
by Curtis Hovey
Rename getRemoteComponentForDistroSourcePackage to getRemoteComponentForDistroSourcePackageName |
708 |
def getRemoteComponentForDistroSourcePackageName( |
709 |
self, distribution, sourcepackagename): |
|
7675.1188.26
by Bryce Harrington
Review by thumper: Move check for existing component links out of |
710 |
"""See `IBugTracker`."""
|
7675.1188.30
by Bryce Harrington
Check for (and fix) bad distro name |
711 |
if distribution is None: |
712 |
return None |
|
13155.1.19
by Curtis Hovey
Rename getRemoteComponentForDistroSourcePackage to getRemoteComponentForDistroSourcePackageName |
713 |
dsp = distribution.getSourcePackage(sourcepackagename) |
13155.1.13
by Curtis Hovey
Use find().one() because the db has a sane constraint. |
714 |
if dsp is None: |
715 |
return None |
|
716 |
return Store.of(self).find( |
|
7675.1188.26
by Bryce Harrington
Review by thumper: Move check for existing component links out of |
717 |
BugTrackerComponent, |
718 |
BugTrackerComponent.distribution == distribution.id, |
|
719 |
BugTrackerComponent.source_package_name == |
|
13155.1.13
by Curtis Hovey
Use find().one() because the db has a sane constraint. |
720 |
dsp.sourcepackagename.id).one() |
7675.1188.26
by Bryce Harrington
Review by thumper: Move check for existing component links out of |
721 |
|
6325.2.37
by Graham Binns
Merged bugtracker person branch. |
722 |
|
1670
by Canonical.com Patch Queue Manager
Big lot of database clean-up r=stub except for resolution of conflicts. |
723 |
class BugTrackerSet: |
11132.4.2
by Graham Binns
resetWatches() now randomises the next_check times for all bug watches unless told not to. |
724 |
"""Implements IBugTrackerSet for a container or set of BugTrackers,
|
1670
by Canonical.com Patch Queue Manager
Big lot of database clean-up r=stub except for resolution of conflicts. |
725 |
either the full set in the db, or a subset.
|
726 |
"""
|
|
1102
by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs |
727 |
|
728 |
implements(IBugTrackerSet) |
|
729 |
||
730 |
table = BugTracker |
|
1382
by Canonical.com Patch Queue Manager
new page layout |
731 |
|
732 |
def __init__(self): |
|
5512.2.9
by Matthew Paul Thomas
Applies the same love to the 'Register an external bug tracker' page. |
733 |
self.title = 'Bug trackers registered in Launchpad' |
1670
by Canonical.com Patch Queue Manager
Big lot of database clean-up r=stub except for resolution of conflicts. |
734 |
|
3018.2.1
by Stuart Bishop
Refactor celebrities to use a descriptor, removing need for boilerplate code. Also optimizes database access, ensuring at most one database query per celebrity per request. |
735 |
def get(self, bugtracker_id, default=None): |
5308.1.20
by Gavin Panella
First lot of review changes suggested by Barry. |
736 |
"""See `IBugTrackerSet`."""
|
3018.2.1
by Stuart Bishop
Refactor celebrities to use a descriptor, removing need for boilerplate code. Also optimizes database access, ensuring at most one database query per celebrity per request. |
737 |
try: |
738 |
return BugTracker.get(bugtracker_id) |
|
739 |
except SQLObjectNotFound: |
|
740 |
return default |
|
741 |
||
3018.2.2
by Stuart Bishop
Add BugTrackerSet.getByName |
742 |
def getByName(self, name, default=None): |
5308.1.20
by Gavin Panella
First lot of review changes suggested by Barry. |
743 |
"""See `IBugTrackerSet`."""
|
3018.2.2
by Stuart Bishop
Add BugTrackerSet.getByName |
744 |
return self.table.selectOne(self.table.q.name == name) |
745 |
||
1102
by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs |
746 |
def __getitem__(self, name): |
1670
by Canonical.com Patch Queue Manager
Big lot of database clean-up r=stub except for resolution of conflicts. |
747 |
item = self.table.selectOne(self.table.q.name == name) |
748 |
if item is None: |
|
2628
by Canonical.com Patch Queue Manager
[trivial] converted a bunch of browser:traverse into navigation |
749 |
raise NotFoundError(name) |
1670
by Canonical.com Patch Queue Manager
Big lot of database clean-up r=stub except for resolution of conflicts. |
750 |
else: |
751 |
return item |
|
1102
by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs |
752 |
|
753 |
def __iter__(self): |
|
1716.3.31
by kiko
Order the bugtracker listing, by title, so the end-user is not confused |
754 |
for row in self.table.select(orderBy="title"): |
1102
by Canonical.com Patch Queue Manager
Lucille had some XXXs which should have been NOTEs |
755 |
yield row |
756 |
||
2048
by Canonical.com Patch Queue Manager
debbugssync, hct enabling, and ui fixes. r=jamesh |
757 |
def queryByBaseURL(self, baseurl): |
5308.1.20
by Gavin Panella
First lot of review changes suggested by Barry. |
758 |
"""See `IBugTrackerSet`."""
|
6059.1.20
by Gavin Panella
Default title to baseurl when creating a bugtracker; Fix inconsistencies when searching for bugtrackers. |
759 |
# All permutations we'll search for.
|
5308.1.12
by Gavin Panella
Working, but needs more comprehensive testing. |
760 |
permutations = base_url_permutations(baseurl) |
6059.1.20
by Gavin Panella
Default title to baseurl when creating a bugtracker; Fix inconsistencies when searching for bugtrackers. |
761 |
# Construct the search. All the important parts in the next
|
762 |
# expression are lazily evaluated. SQLObject queries do not
|
|
763 |
# execute any SQL until results are pulled, so the first query
|
|
764 |
# to return a match will be the last query executed.
|
|
5308.1.12
by Gavin Panella
Working, but needs more comprehensive testing. |
765 |
matching_bugtrackers = chain( |
766 |
# Search for any permutation in BugTracker.
|
|
767 |
BugTracker.select( |
|
768 |
OR(*(BugTracker.q.baseurl == url |
|
769 |
for url in permutations))), |
|
770 |
# Search for any permutation in BugTrackerAlias.
|
|
771 |
(alias.bugtracker for alias in |
|
772 |
BugTrackerAlias.select( |
|
773 |
OR(*(BugTrackerAlias.q.base_url == url |
|
6059.1.24
by Gavin Panella
Stop doing substring searches for bugtrackers. |
774 |
for url in permutations))))) |
5308.1.20
by Gavin Panella
First lot of review changes suggested by Barry. |
775 |
# Return the first match.
|
5308.1.12
by Gavin Panella
Working, but needs more comprehensive testing. |
776 |
for bugtracker in matching_bugtrackers: |
5093.1.1
by Tom Berger
Fix bug #117452 by prefixing the base url of a new bug tracker with http:// if it isnt present |
777 |
return bugtracker |
3691.186.1
by Bjorn Tillenius
make BugTrackerSet.queryByBaseURL ignore http vs. https differences. |
778 |
return None |
2048
by Canonical.com Patch Queue Manager
debbugssync, hct enabling, and ui fixes. r=jamesh |
779 |
|
7675.604.14
by Gavin Panella
Bring back the BugTrackerSet.search() method; it's needed for the web API. |
780 |
def search(self): |
781 |
"""See `IBugTrackerSet`."""
|
|
782 |
return BugTracker.select() |
|
783 |
||
11562.3.2
by Robert Collins
Move Active/Inactive batch navigators to batching for reuse and define a more useful api for getting sets of trackers. |
784 |
def trackers(self, active=None): |
785 |
# Without context, cannot tell what store flavour is desirable.
|
|
786 |
store = getUtility(IStoreSelector).get(MAIN_STORE, DEFAULT_FLAVOR) |
|
787 |
if active is not None: |
|
13155.1.13
by Curtis Hovey
Use find().one() because the db has a sane constraint. |
788 |
clauses = [BugTracker.active == active] |
11562.3.2
by Robert Collins
Move Active/Inactive batch navigators to batching for reuse and define a more useful api for getting sets of trackers. |
789 |
else: |
790 |
clauses = [] |
|
791 |
results = store.find(BugTracker, *clauses) |
|
792 |
results.order_by(BugTracker.name) |
|
793 |
return results |
|
794 |
||
2048
by Canonical.com Patch Queue Manager
debbugssync, hct enabling, and ui fixes. r=jamesh |
795 |
def ensureBugTracker(self, baseurl, owner, bugtrackertype, |
796 |
title=None, summary=None, contactdetails=None, name=None): |
|
5308.1.20
by Gavin Panella
First lot of review changes suggested by Barry. |
797 |
"""See `IBugTrackerSet`."""
|
6059.1.20
by Gavin Panella
Default title to baseurl when creating a bugtracker; Fix inconsistencies when searching for bugtrackers. |
798 |
# Try to find an existing bug tracker that matches.
|
799 |
bugtracker = self.queryByBaseURL(baseurl) |
|
800 |
if bugtracker is not None: |
|
801 |
return bugtracker |
|
802 |
# Create the bugtracker; we don't know about it.
|
|
2048
by Canonical.com Patch Queue Manager
debbugssync, hct enabling, and ui fixes. r=jamesh |
803 |
if name is None: |
5613.1.21
by Graham Binns
Added collision avoidance and testing thereof. |
804 |
base_name = make_bugtracker_name(baseurl) |
805 |
# If we detect that this name exists already we mutate it
|
|
806 |
# until it doesn't.
|
|
807 |
name = base_name |
|
808 |
name_increment = 1 |
|
809 |
while self.getByName(name) is not None: |
|
810 |
name = "%s-%d" % (base_name, name_increment) |
|
811 |
name_increment += 1 |
|
4631.1.12
by Tom Berger
don't allow to be null, as per mark's request |
812 |
if title is None: |
6205.2.3
by Gavin Panella
Generate bug tracker titles with make_bugtracker_title. |
813 |
title = make_bugtracker_title(baseurl) |
6059.1.20
by Gavin Panella
Default title to baseurl when creating a bugtracker; Fix inconsistencies when searching for bugtrackers. |
814 |
bugtracker = BugTracker( |
815 |
name=name, bugtrackertype=bugtrackertype, |
|
2048
by Canonical.com Patch Queue Manager
debbugssync, hct enabling, and ui fixes. r=jamesh |
816 |
title=title, summary=summary, baseurl=baseurl, |
817 |
contactdetails=contactdetails, owner=owner) |
|
818 |
flush_database_updates() |
|
819 |
return bugtracker |
|
820 |
||
2292
by Canonical.com Patch Queue Manager
[r=bjornt] make bugtrackers use auto forms |
821 |
@property
|
7675.604.1
by Gavin Panella
Rename BugTrackerSet.bugtracker_count to just count. |
822 |
def count(self): |
823 |
return IStore(self.table).find(self.table).count() |
|
2048
by Canonical.com Patch Queue Manager
debbugssync, hct enabling, and ui fixes. r=jamesh |
824 |
|
7675.604.3
by Gavin Panella
Get a list of all bug tracker names from a query instead of iterating through model objects. |
825 |
@property
|
826 |
def names(self): |
|
827 |
return IStore(self.table).find(self.table).values(self.table.name) |
|
828 |
||
2908.2.2
by Brad Bollenbach
fixes based on code review |
829 |
def getMostActiveBugTrackers(self, limit=None): |
5308.1.20
by Gavin Panella
First lot of review changes suggested by Barry. |
830 |
"""See `IBugTrackerSet`."""
|
7675.837.26
by Bryce Harrington
Review by gmb - requested clarification of table name in this routine |
831 |
store = IStore(BugTracker) |
7675.837.21
by Bryce Harrington
Fix lintian issues |
832 |
result = store.find( |
7675.837.26
by Bryce Harrington
Review by gmb - requested clarification of table name in this routine |
833 |
BugTracker, |
834 |
BugTracker.id == BugWatch.bugtrackerID) |
|
835 |
result = result.group_by(BugTracker) |
|
7675.604.4
by Gavin Panella
Make getMostActiveBugTrackers() more efficient. |
836 |
result = result.order_by(Desc(Count(BugWatch))) |
837 |
if limit is not None: |
|
2908.2.2
by Brad Bollenbach
fixes based on code review |
838 |
return result[:limit] |
839 |
else: |
|
840 |
return result |
|
841 |
||
5742.1.4
by Christian Robottom Reis
Display product information for each bugtracker in the bugtracker index page. Add an API to IBugTrackerSet to allow us to fetch all products and projects in one fell swoop. Improve testing of IBugTrackerSet pages. |
842 |
def getPillarsForBugtrackers(self, bugtrackers): |
843 |
"""See `IBugTrackerSet`."""
|
|
7675.110.3
by Curtis Hovey
Ran the migration script to move registry code to lp.registry. |
844 |
from lp.registry.model.product import Product |
10724.1.1
by Henning Eggers
First batch of Project -> ProjectGrpoup renamings. |
845 |
from lp.registry.model.projectgroup import ProjectGroup |
5742.1.4
by Christian Robottom Reis
Display product information for each bugtracker in the bugtracker index page. Add an API to IBugTrackerSet to allow us to fetch all products and projects in one fell swoop. Improve testing of IBugTrackerSet pages. |
846 |
ids = [str(b.id) for b in bugtrackers] |
847 |
products = Product.select( |
|
848 |
"bugtracker in (%s)" % ",".join(ids), orderBy="name") |
|
10724.1.1
by Henning Eggers
First batch of Project -> ProjectGrpoup renamings. |
849 |
projects = ProjectGroup.select( |
5742.1.4
by Christian Robottom Reis
Display product information for each bugtracker in the bugtracker index page. Add an API to IBugTrackerSet to allow us to fetch all products and projects in one fell swoop. Improve testing of IBugTrackerSet pages. |
850 |
"bugtracker in (%s)" % ",".join(ids), orderBy="name") |
851 |
ret = {} |
|
852 |
for product in products: |
|
853 |
ret.setdefault(product.bugtracker, []).append(product) |
|
854 |
for project in projects: |
|
855 |
ret.setdefault(project.bugtracker, []).append(project) |
|
856 |
return ret |
|
857 |
||
5308.1.1
by Gavin Panella
Interfaces and database classes for bug tracker aliases. |
858 |
|
859 |
class BugTrackerAlias(SQLBase): |
|
860 |
"""See `IBugTrackerAlias`."""
|
|
861 |
implements(IBugTrackerAlias) |
|
862 |
||
863 |
bugtracker = ForeignKey( |
|
864 |
foreignKey="BugTracker", dbName="bugtracker", notNull=True) |
|
865 |
base_url = StringCol(notNull=True) |
|
866 |
||
867 |
||
868 |
class BugTrackerAliasSet: |
|
869 |
"""See `IBugTrackerAliasSet`."""
|
|
870 |
implements(IBugTrackerAliasSet) |
|
871 |
||
5308.1.3
by Gavin Panella
Change aliases to be like IBug.tags. |
872 |
table = BugTrackerAlias |
873 |
||
5308.1.12
by Gavin Panella
Working, but needs more comprehensive testing. |
874 |
def queryByBugTracker(self, bugtracker): |
5308.1.1
by Gavin Panella
Interfaces and database classes for bug tracker aliases. |
875 |
"""See IBugTrackerSet."""
|
5308.1.22
by Gavin Panella
Small changes as suggested by Barry in review. |
876 |
return self.table.selectBy(bugtracker=bugtracker.id) |