Merge lp:~allenap/launchpad/bugs-with-blueprints-bug-707103 into lp:launchpad
- bugs-with-blueprints-bug-707103
- Merge into devel
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Gavin Panella | ||||
Approved revision: | no longer in the source branch. | ||||
Merged at revision: | 12296 | ||||
Proposed branch: | lp:~allenap/launchpad/bugs-with-blueprints-bug-707103 | ||||
Merge into: | lp:launchpad | ||||
Diff against target: |
390 lines (+147/-30) 6 files modified
lib/lp/bugs/interfaces/bugtarget.py (+26/-9) lib/lp/bugs/interfaces/bugtask.py (+28/-10) lib/lp/bugs/model/bugtarget.py (+2/-1) lib/lp/bugs/model/bugtask.py (+19/-0) lib/lp/bugs/tests/test_bugtask_search.py (+16/-0) lib/lp/bugs/tests/test_searchtasks_webservice.py (+56/-10) |
||||
To merge this branch: | bzr merge lp:~allenap/launchpad/bugs-with-blueprints-bug-707103 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Henning Eggers (community) | code | Approve | |
Review via email: mp+47866@code.launchpad.net |
Commit message
[r=henninge]
Description of the change
Make it possible to search for bugs with or without linked Blueprints. I will update the advanced search in a subsequent branch; this branch just deals with the internal and webservice API.
Gavin Panella (allenap) wrote : | # |
> [Sorry, somehow my mail client messed up. I hope you can figure out which
> lines my comments are referring to.]
Wow, it really nuked it :)
>
> Hi Gavin,
> thanks for addressing this issue. Webservice API is not my strong side
> so please forgive if I make the wrong assumptions.
> The real problem in this branch that I see is
> test_linked_
> see my comments below.
>
> review needs-fixing
>
> Cheers,
> Henning
>
>> === modified file 'lib/lp/
>> lib/lp/
>> +++ lib/lp/
>> +0000
> [...]
>> @@ -203,16 +215,21 @@ has_bugtasks = Attribute( "True if a BugTask
>> has ever been reported for this target.")
>>
>> + # searchTasks devel API declaration.
>> @call_with(
>> @operation_
>> @operation_
>> @export_
>> (decorators are run last to first).
>> @operation_
>>
>> + # searchTasks default API declaration.
>> @call_with(
>> @operation_
>> @operation_
>> @operation_
>> @export_
>> user=None, order_by=None, search_text=None, status=None,
>> importance=None,
>
> I think it is due to my lack of webservice foo but I don't understand
> how this works. Why are the decorators repeating themselves? Is that
> the proper way to handle that? I am just asking so you can double
> check, I don't expect a full explanation atm. ;-) Thanks for the added
> comments, though.
It's a bit crazy. While fixing this branch I filed a couple of bugs
against lazr.restful because of it, but here goes...
Everything has to be read in reverse, then we have to realise that
annotations are assembled onto a stack.
* This block declares the default API for searchTasks.
export_
operation_
operation_
call_
* This is a weird operation. It declares that the operation above is
not available in the devel API version by pushing a new version onto
the annotations stack and setting its type to "removed_
operation_
* This block now declares the devel API for searchTasks. The
annotation on the stack is already for the devel version by virtue
of operation_
changes the annotation type to "read_operation".
export_
operation_
operation_
call_
>
>> === modified file 'lib/lp/
>> lib/lp/
>> lib/lp/
Henning Eggers (henninge) wrote : | # |
Thanks for your reply an the explanations.
>> Hm, did you re-sort this manually or did some tool do it? For the
>> imports fixing script I implemented case insensitive sorting. But
>> that does not touch __all__.
>
>A tool did it for me: Emacs :)
>
>(I set sort-fold-case before using sort-lines.)
>
>Is it wrong?
Since we don't have a written-down convention on it, it is not. ;-) I was merely wondering because for the import formatting I had used case-insensitive sorting, after a little discussion, because it is easier for humans to parse. But we never mentioned to use the same for __all__ although that would make sense to me. I was just wondering if you did this consciously (and have an opinion) or not. I guess the latter. No big deal, though.
You missed a major comment, though, which I am sure is due to the wacky formatting of my reply. I apologize for that again. Here it is:
> === modified file 'lib/lp/
> @@ -35,3 +38,51 @@
> response = self.webservice
> 'searchTasks', api_version=
> self.assertEqua
> +
> + def test_linked_
> + response = self.webservice
> + 'searchTasks', api_version=
> + self.assertEqua
> +
I am not really sure I understand what this test does. I don't see
where the code refers to the new search parameter. Actually, it looks
identical to the previous test. Something missing here?
I won't block you on this because of my currently long feedback loop and I trust you will be able to either explain or fix it.
Thanks again!
Gavin Panella (allenap) wrote : | # |
> Thanks for your reply an the explanations.
>
> >> Hm, did you re-sort this manually or did some tool do it? For the
> >> imports fixing script I implemented case insensitive sorting. But
> >> that does not touch __all__.
> >
> >A tool did it for me: Emacs :)
> >
> >(I set sort-fold-case before using sort-lines.)
> >
> >Is it wrong?
>
> Since we don't have a written-down convention on it, it is not. ;-) I was
> merely wondering because for the import formatting I had used case-insensitive
> sorting, after a little discussion, because it is easier for humans to parse.
> But we never mentioned to use the same for __all__ although that would make
> sense to me. I was just wondering if you did this consciously (and have an
> opinion) or not. I guess the latter. No big deal, though.
Ah, I thought we had agreed to sort case-insensitively. My preference
is actually for case-sensitive sorting since it is the default in
Emacs, and because I, strangely, find it easier to read.
> You missed a major comment, though, which I am sure is due to the wacky
> formatting of my reply. I apologize for that again. Here it is:
Oops, thanks.
> > === modified file 'lib/lp/
> > @@ -35,3 +38,51 @@
> > response = self.webservice
> > 'searchTasks', api_version=
> > self.assertEqua
> > +
> > + def test_linked_
> > + response = self.webservice
> > + 'searchTasks', api_version=
> > + self.assertEqua
> > +
>
> I am not really sure I understand what this test does. I don't see
> where the code refers to the new search parameter. Actually, it looks
> identical to the previous test. Something missing here?
It was a copy and paste error! Thanks for spotting it.
Preview Diff
1 | === modified file 'lib/lp/bugs/interfaces/bugtarget.py' |
2 | --- lib/lp/bugs/interfaces/bugtarget.py 2010-12-02 16:14:30 +0000 |
3 | +++ lib/lp/bugs/interfaces/bugtarget.py 2011-02-01 16:35:45 +0000 |
4 | @@ -35,7 +35,6 @@ |
5 | ) |
6 | from lazr.restful.fields import Reference |
7 | from lazr.restful.interface import copy_field |
8 | - |
9 | from zope.interface import ( |
10 | Attribute, |
11 | Interface, |
12 | @@ -52,6 +51,7 @@ |
13 | |
14 | from canonical.launchpad import _ |
15 | from lp.bugs.interfaces.bugtask import ( |
16 | + BugBlueprintSearch, |
17 | BugBranchSearch, |
18 | BugTagsSearchCombinator, |
19 | IBugTask, |
20 | @@ -59,7 +59,8 @@ |
21 | ) |
22 | from lp.services.fields import Tag |
23 | |
24 | -search_tasks_params_for_api_1_0 = { |
25 | + |
26 | +search_tasks_params_common = { |
27 | "order_by": List( |
28 | title=_('List of fields by which the results are ordered.'), |
29 | value_type=Text(), |
30 | @@ -80,7 +81,6 @@ |
31 | "tags": copy_field(IBugTaskSearch['tag']), |
32 | "tags_combinator": copy_field(IBugTaskSearch['tags_combinator']), |
33 | "omit_duplicates": copy_field(IBugTaskSearch['omit_dupes']), |
34 | - "omit_targeted": copy_field(IBugTaskSearch['omit_targeted']), |
35 | "status_upstream": copy_field(IBugTaskSearch['status_upstream']), |
36 | "milestone_assignment": copy_field( |
37 | IBugTaskSearch['milestone_assignment']), |
38 | @@ -172,9 +172,21 @@ |
39 | "date."), |
40 | required=False), |
41 | } |
42 | -search_tasks_params_for_api_devel = search_tasks_params_for_api_1_0.copy() |
43 | -search_tasks_params_for_api_devel["omit_targeted"] = copy_field( |
44 | - IBugTaskSearch['omit_targeted'], default=False) |
45 | + |
46 | +search_tasks_params_for_api_default = dict( |
47 | + search_tasks_params_common, |
48 | + omit_targeted=copy_field( |
49 | + IBugTaskSearch['omit_targeted'])) |
50 | + |
51 | +search_tasks_params_for_api_devel = dict( |
52 | + search_tasks_params_common, |
53 | + omit_targeted=copy_field( |
54 | + IBugTaskSearch['omit_targeted'], default=False), |
55 | + linked_blueprints=Choice( |
56 | + title=_( |
57 | + u"Search for bugs that are linked to blueprints or for " |
58 | + u"bugs that are not linked to blueprints."), |
59 | + vocabulary=BugBlueprintSearch, required=False)) |
60 | |
61 | |
62 | class IHasBugs(Interface): |
63 | @@ -203,16 +215,21 @@ |
64 | has_bugtasks = Attribute( |
65 | "True if a BugTask has ever been reported for this target.") |
66 | |
67 | + # searchTasks devel API declaration. |
68 | @call_with(search_params=None, user=REQUEST_USER) |
69 | @operation_parameters(**search_tasks_params_for_api_devel) |
70 | @operation_returns_collection_of(IBugTask) |
71 | @export_read_operation() |
72 | + |
73 | + # Pop the *default* version (decorators are run last to first). |
74 | @operation_removed_in_version('devel') |
75 | |
76 | + # searchTasks default API declaration. |
77 | @call_with(search_params=None, user=REQUEST_USER) |
78 | - @operation_parameters(**search_tasks_params_for_api_1_0) |
79 | + @operation_parameters(**search_tasks_params_for_api_default) |
80 | @operation_returns_collection_of(IBugTask) |
81 | @export_read_operation() |
82 | + |
83 | def searchTasks(search_params, user=None, |
84 | order_by=None, search_text=None, |
85 | status=None, importance=None, |
86 | @@ -232,8 +249,8 @@ |
87 | hardware_owner_is_affected_by_bug=False, |
88 | hardware_owner_is_subscribed_to_bug=False, |
89 | hardware_is_linked_to_bug=False, linked_branches=None, |
90 | - structural_subscriber=None, modified_since=None, |
91 | - created_since=None, prejoins=[]): |
92 | + linked_blueprints=None, structural_subscriber=None, |
93 | + modified_since=None, created_since=None, prejoins=[]): |
94 | """Search the IBugTasks reported on this entity. |
95 | |
96 | :search_params: a BugTaskSearchParams object |
97 | |
98 | === modified file 'lib/lp/bugs/interfaces/bugtask.py' |
99 | --- lib/lp/bugs/interfaces/bugtask.py 2010-12-17 04:26:11 +0000 |
100 | +++ lib/lp/bugs/interfaces/bugtask.py 2011-02-01 16:35:45 +0000 |
101 | @@ -9,6 +9,7 @@ |
102 | |
103 | __all__ = [ |
104 | 'BUG_SUPERVISOR_BUGTASK_STATUSES', |
105 | + 'BugBlueprintSearch', |
106 | 'BugBranchSearch', |
107 | 'BugTagsSearchCombinator', |
108 | 'BugTaskImportance', |
109 | @@ -28,8 +29,6 @@ |
110 | 'IDistroBugTask', |
111 | 'IDistroSeriesBugTask', |
112 | 'IFrontPageBugTaskSearch', |
113 | - 'IllegalRelatedBugTasksParams', |
114 | - 'IllegalTarget', |
115 | 'INominationsReviewTableBatchNavigator', |
116 | 'INullBugTask', |
117 | 'IPersonBugTaskSearch', |
118 | @@ -37,13 +36,16 @@ |
119 | 'IRemoveQuestionFromBugTaskForm', |
120 | 'IUpstreamBugTask', |
121 | 'IUpstreamProductBugTaskSearch', |
122 | + 'IllegalRelatedBugTasksParams', |
123 | + 'IllegalTarget', |
124 | 'RESOLVED_BUGTASK_STATUSES', |
125 | 'UNRESOLVED_BUGTASK_STATUSES', |
126 | 'UserCannotEditBugTaskAssignee', |
127 | 'UserCannotEditBugTaskImportance', |
128 | 'UserCannotEditBugTaskMilestone', |
129 | 'UserCannotEditBugTaskStatus', |
130 | - 'valid_remote_bug_url'] |
131 | + 'valid_remote_bug_url', |
132 | + ] |
133 | |
134 | from lazr.enum import ( |
135 | DBEnumeratedType, |
136 | @@ -340,7 +342,7 @@ |
137 | """Bug branch search option. |
138 | |
139 | The possible values to search for bugs having branches attached |
140 | - or not having branches attched. |
141 | + or not having branches attached. |
142 | """ |
143 | |
144 | ALL = Item("Show all bugs") |
145 | @@ -350,6 +352,20 @@ |
146 | BUGS_WITHOUT_BRANCHES = Item("Show only Bugs without linked Branches") |
147 | |
148 | |
149 | +class BugBlueprintSearch(EnumeratedType): |
150 | + """Bug blueprint search option. |
151 | + |
152 | + The possible values to search for bugs having blueprints attached |
153 | + or not having blueprints attached. |
154 | + """ |
155 | + |
156 | + ALL = Item("Show all bugs") |
157 | + |
158 | + BUGS_WITH_BLUEPRINTS = Item("Show only Bugs with linked Blueprints") |
159 | + |
160 | + BUGS_WITHOUT_BLUEPRINTS = Item("Show only Bugs without linked Blueprints") |
161 | + |
162 | + |
163 | # XXX: Brad Bollenbach 2005-12-02 bugs=5320: |
164 | # In theory, INCOMPLETE belongs in UNRESOLVED_BUGTASK_STATUSES, but the |
165 | # semantics of our current reports would break if it were added to the |
166 | @@ -1144,9 +1160,9 @@ |
167 | hardware_owner_is_affected_by_bug=False, |
168 | hardware_owner_is_subscribed_to_bug=False, |
169 | hardware_is_linked_to_bug=False, |
170 | - linked_branches=None, structural_subscriber=None, |
171 | - modified_since=None, created_since=None, |
172 | - exclude_conjoined_tasks=False): |
173 | + linked_branches=None, linked_blueprints=None, |
174 | + structural_subscriber=None, modified_since=None, |
175 | + created_since=None, exclude_conjoined_tasks=False): |
176 | |
177 | self.bug = bug |
178 | self.searchtext = searchtext |
179 | @@ -1189,6 +1205,7 @@ |
180 | hardware_owner_is_subscribed_to_bug) |
181 | self.hardware_is_linked_to_bug = hardware_is_linked_to_bug |
182 | self.linked_branches = linked_branches |
183 | + self.linked_blueprints = linked_blueprints |
184 | self.structural_subscriber = structural_subscriber |
185 | self.modified_since = modified_since |
186 | self.created_since = created_since |
187 | @@ -1265,8 +1282,8 @@ |
188 | hardware_owner_is_affected_by_bug=False, |
189 | hardware_owner_is_subscribed_to_bug=False, |
190 | hardware_is_linked_to_bug=False, linked_branches=None, |
191 | - structural_subscriber=None, modified_since=None, |
192 | - created_since=None): |
193 | + linked_blueprints=None, structural_subscriber=None, |
194 | + modified_since=None, created_since=None): |
195 | """Create and return a new instance using the parameter list.""" |
196 | search_params = cls(user=user, orderby=order_by) |
197 | |
198 | @@ -1332,7 +1349,8 @@ |
199 | hardware_owner_is_subscribed_to_bug) |
200 | search_params.hardware_is_linked_to_bug = ( |
201 | hardware_is_linked_to_bug) |
202 | - search_params.linked_branches=linked_branches |
203 | + search_params.linked_branches = linked_branches |
204 | + search_params.linked_blueprints = linked_blueprints |
205 | search_params.structural_subscriber = structural_subscriber |
206 | search_params.modified_since = modified_since |
207 | search_params.created_since = created_since |
208 | |
209 | === modified file 'lib/lp/bugs/model/bugtarget.py' |
210 | --- lib/lp/bugs/model/bugtarget.py 2010-11-30 21:39:25 +0000 |
211 | +++ lib/lp/bugs/model/bugtarget.py 2011-02-01 16:35:45 +0000 |
212 | @@ -94,7 +94,8 @@ |
213 | hardware_owner_is_affected_by_bug=False, |
214 | hardware_owner_is_subscribed_to_bug=False, |
215 | hardware_is_linked_to_bug=False, linked_branches=None, |
216 | - modified_since=None, created_since=None, prejoins=[]): |
217 | + linked_blueprints=None, modified_since=None, |
218 | + created_since=None, prejoins=[]): |
219 | """See `IHasBugs`.""" |
220 | if status is None: |
221 | # If no statuses are supplied, default to the |
222 | |
223 | === modified file 'lib/lp/bugs/model/bugtask.py' |
224 | --- lib/lp/bugs/model/bugtask.py 2011-01-20 04:50:35 +0000 |
225 | +++ lib/lp/bugs/model/bugtask.py 2011-02-01 16:35:45 +0000 |
226 | @@ -103,6 +103,7 @@ |
227 | from lp.bugs.interfaces.bugtask import ( |
228 | BUG_SUPERVISOR_BUGTASK_STATUSES, |
229 | BugBranchSearch, |
230 | + BugBlueprintSearch, |
231 | BugTaskImportance, |
232 | BugTaskSearchParams, |
233 | BugTaskStatus, |
234 | @@ -2066,6 +2067,10 @@ |
235 | # we don't need to add any clause. |
236 | pass |
237 | |
238 | + linked_blueprints_clause = self._buildBlueprintRelatedClause(params) |
239 | + if linked_blueprints_clause is not None: |
240 | + extra_clauses.append(linked_blueprints_clause) |
241 | + |
242 | if params.modified_since: |
243 | extra_clauses.append( |
244 | "Bug.date_last_updated > %s" % ( |
245 | @@ -2318,6 +2323,20 @@ |
246 | ', '.join(tables), ' AND '.join(clauses)) |
247 | return clause |
248 | |
249 | + def _buildBlueprintRelatedClause(self, params): |
250 | + """Find bugs related to Blueprints, or not.""" |
251 | + linked_blueprints = params.linked_blueprints |
252 | + if linked_blueprints == BugBlueprintSearch.BUGS_WITH_BLUEPRINTS: |
253 | + return "EXISTS (%s)" % ( |
254 | + "SELECT 1 FROM SpecificationBug" |
255 | + " WHERE SpecificationBug.bug = Bug.id") |
256 | + elif linked_blueprints == BugBlueprintSearch.BUGS_WITHOUT_BLUEPRINTS: |
257 | + return "NOT EXISTS (%s)" % ( |
258 | + "SELECT 1 FROM SpecificationBug" |
259 | + " WHERE SpecificationBug.bug = Bug.id") |
260 | + else: |
261 | + return None |
262 | + |
263 | def buildOrigin(self, join_tables, prejoin_tables, clauseTables): |
264 | """Build the parameter list for Store.using(). |
265 | |
266 | |
267 | === modified file 'lib/lp/bugs/tests/test_bugtask_search.py' |
268 | --- lib/lp/bugs/tests/test_bugtask_search.py 2011-01-13 17:00:41 +0000 |
269 | +++ lib/lp/bugs/tests/test_bugtask_search.py 2011-02-01 16:35:45 +0000 |
270 | @@ -31,6 +31,7 @@ |
271 | from lp.bugs.interfaces.bugattachment import BugAttachmentType |
272 | from lp.bugs.interfaces.bugtask import ( |
273 | BugBranchSearch, |
274 | + BugBlueprintSearch, |
275 | BugTaskImportance, |
276 | BugTaskSearchParams, |
277 | BugTaskStatus, |
278 | @@ -445,6 +446,21 @@ |
279 | user=None, linked_branches=BugBranchSearch.BUGS_WITHOUT_BRANCHES) |
280 | self.assertSearchFinds(params, self.bugtasks[1:]) |
281 | |
282 | + def test_blueprints_linked(self): |
283 | + # Search results can be limited to bugs with or without linked |
284 | + # blueprints. |
285 | + with person_logged_in(self.owner): |
286 | + blueprint = self.factory.makeSpecification() |
287 | + blueprint.linkBug(self.bugtasks[0].bug) |
288 | + params = self.getBugTaskSearchParams( |
289 | + user=None, linked_blueprints=( |
290 | + BugBlueprintSearch.BUGS_WITH_BLUEPRINTS)) |
291 | + self.assertSearchFinds(params, self.bugtasks[:1]) |
292 | + params = self.getBugTaskSearchParams( |
293 | + user=None, linked_blueprints=( |
294 | + BugBlueprintSearch.BUGS_WITHOUT_BLUEPRINTS)) |
295 | + self.assertSearchFinds(params, self.bugtasks[1:]) |
296 | + |
297 | def test_limit_search_to_one_bug(self): |
298 | # Search results can be limited to a given bug. |
299 | params = self.getBugTaskSearchParams( |
300 | |
301 | === modified file 'lib/lp/bugs/tests/test_searchtasks_webservice.py' |
302 | --- lib/lp/bugs/tests/test_searchtasks_webservice.py 2010-10-04 19:50:45 +0000 |
303 | +++ lib/lp/bugs/tests/test_searchtasks_webservice.py 2011-02-01 16:35:45 +0000 |
304 | @@ -5,26 +5,29 @@ |
305 | |
306 | __metaclass__ = type |
307 | |
308 | -from canonical.launchpad.ftests import login |
309 | -from lp.testing import TestCaseWithFactory |
310 | from canonical.launchpad.testing.pages import LaunchpadWebServiceCaller |
311 | from canonical.testing.layers import DatabaseFunctionalLayer |
312 | +from lp.testing import ( |
313 | + person_logged_in, |
314 | + TestCaseWithFactory, |
315 | + ) |
316 | |
317 | |
318 | class TestOmitTargetedParameter(TestCaseWithFactory): |
319 | """Test all values for the omit_targeted search parameter.""" |
320 | + |
321 | layer = DatabaseFunctionalLayer |
322 | |
323 | def setUp(self): |
324 | - TestCaseWithFactory.setUp(self) |
325 | - login('foo.bar@canonical.com') |
326 | - self.distro = self.factory.makeDistribution(name='mebuntu') |
327 | - self.release = self.factory.makeDistroRelease(name='inkanyamba', |
328 | - distribution=self.distro) |
329 | + super(TestOmitTargetedParameter, self).setUp() |
330 | + self.owner = self.factory.makePerson() |
331 | + with person_logged_in(self.owner): |
332 | + self.distro = self.factory.makeDistribution(name='mebuntu') |
333 | + self.release = self.factory.makeDistroRelease( |
334 | + name='inkanyamba', distribution=self.distro) |
335 | self.bug = self.factory.makeBugTask(target=self.release) |
336 | - |
337 | - self.webservice = LaunchpadWebServiceCaller('launchpad-library', |
338 | - 'salgado-change-anything') |
339 | + self.webservice = LaunchpadWebServiceCaller( |
340 | + 'launchpad-library', 'salgado-change-anything') |
341 | |
342 | def test_omit_targeted_old_default_true(self): |
343 | response = self.webservice.named_get('/mebuntu/inkanyamba', |
344 | @@ -35,3 +38,46 @@ |
345 | response = self.webservice.named_get('/mebuntu/inkanyamba', |
346 | 'searchTasks', api_version='devel').jsonBody() |
347 | self.assertEqual(response['total_size'], 1) |
348 | + |
349 | + |
350 | +class TestLinkedBlueprintsParameter(TestCaseWithFactory): |
351 | + """Tests for the linked_blueprints parameter.""" |
352 | + |
353 | + layer = DatabaseFunctionalLayer |
354 | + |
355 | + def setUp(self): |
356 | + super(TestLinkedBlueprintsParameter, self).setUp() |
357 | + self.owner = self.factory.makePerson() |
358 | + with person_logged_in(self.owner): |
359 | + self.product = self.factory.makeProduct() |
360 | + self.bug = self.factory.makeBugTask(target=self.product) |
361 | + self.webservice = LaunchpadWebServiceCaller( |
362 | + 'launchpad-library', 'salgado-change-anything') |
363 | + |
364 | + def search(self, api_version, **kwargs): |
365 | + return self.webservice.named_get( |
366 | + '/%s' % self.product.name, 'searchTasks', |
367 | + api_version=api_version, **kwargs).jsonBody() |
368 | + |
369 | + def test_linked_blueprints_in_devel(self): |
370 | + # Searching for linked Blueprints works in the devel API. |
371 | + self.search("devel", linked_blueprints="Show all bugs") |
372 | + |
373 | + def test_linked_blueprints_in_devel_2(self): |
374 | + # The linked_blueprints is considered. An error is returned if its |
375 | + # value is not a member of BugBlueprintSearch. |
376 | + self.assertRaises( |
377 | + ValueError, self.search, "devel", |
378 | + linked_blueprints="Teabags!") |
379 | + |
380 | + def test_linked_blueprints_not_in_1_0(self): |
381 | + # Searching for linked Blueprints does not work in the 1.0 API. No |
382 | + # validation is performed for the linked_blueprints parameter, and |
383 | + # thus no error is returned when we pass rubbish. |
384 | + self.search("1.0", linked_blueprints="Teabags!") |
385 | + |
386 | + def test_linked_blueprints_not_in_beta(self): |
387 | + # Searching for linked Blueprints does not work in the beta API. No |
388 | + # validation is performed for the linked_blueprints parameter, and |
389 | + # thus no error is returned when we pass rubbish. |
390 | + self.search("beta", linked_blueprints="Teabags!") |
[Sorry, somehow my mail client messed up. I hope you can figure out which lines my comments are referring to.]
Hi Gavin, blueprints_ in_devel which I am sure needs fixing. Please
thanks for addressing this issue. Webservice API is not my strong side
so please forgive if I make the wrong assumptions.
The real problem in this branch that I see is
test_linked_
see my comments below.
review needs-fixing
Cheers,
Henning
> > === modified file 'lib/lp/ bugs/interfaces /bugtarget. py' --- bugs/interfaces /bugtarget. py 2010-12-02 16:14:30 +0000 bugs/interfaces /bugtarget. py 2011-01-31 14:57:17 search_ params= None, user=REQUEST_USER) parameters( **search_ tasks_params_ for_api_ devel) returns_ collection_ of(IBugTask) read_operation( ) + + # Pop the *default* version removed_ in_version( 'devel' ) search_ params= None, user=REQUEST_USER) - parameters( **search_ tasks_params_ for_api_ 1_0) + parameters( **search_ tasks_params_ for_api_ default) returns_ collection_ of(IBugTask) read_operation( ) + def searchTasks( search_ params,
> > lib/lp/
> > +++ lib/lp/
> > +0000
[...]
> > @@ -203,16 +215,21 @@ has_bugtasks = Attribute( "True if a BugTask
> > has ever been reported for this target.")
> >
> > + # searchTasks devel API declaration.
> > @call_with(
> > @operation_
> > @operation_
> > @export_
> > (decorators are run last to first).
> > @operation_
> >
> > + # searchTasks default API declaration.
> > @call_with(
> > @operation_
> > @operation_
> > @operation_
> > @export_
> > user=None, order_by=None, search_text=None, status=None,
> > importance=None,
I think it is due to my lack of webservice foo but I don't understand
how this works. Why are the decorators repeating themselves? Is that
the proper way to handle that? I am just asking so you can double
check, I don't expect a full explanation atm. ;-) Thanks for the added
comments, though.
> > === modified file 'lib/lp/ bugs/interfaces /bugtask. py' --- bugs/interfaces /bugtask. py 2010-12-17 04:26:11 +0000 +++ bugs/interfaces /bugtask. py 2011-01-31 14:57:17 +0000 @@ _BUGTASK_ STATUSES' , + arch', 'BugBranchSearch', ombinator' , 'BugTaskImporta nce', @@ -28,8 +29,6 @@ ugTask' , askSearch' , - 'IllegalRelated BugTasksParams' , -
> > lib/lp/
> > lib/lp/
> > -9,6 +9,7 @@
> >
> > __all__ = [ 'BUG_SUPERVISOR
> > 'BugBlueprintSe
> > 'BugTagsSearchC
> > 'IDistroBugTask', 'IDistroSeriesB
> > 'IFrontPageBugT
> > 'IllegalTarget',
Hm, did you re-sort this manually or did some tool do it? For the
imports fixing script I implemented case insensitive sorting. But
that does not touch __all__.
> > 'INominationsRe viewTableBatchN avigator' , 'INullBugTask', Search' , @@ -37,13 +36,16 @@ nFromBugTaskFor m', 'IUpstreamBugTask', ctBugTaskSearch ', + BugTasksParams' , + 'IllegalTarget', BUGTASK_ STATUSES' , 'UNRESOLVED_ BUGTASK_ STATUSES' , BugTaskAssignee ', BugTaskImportan ce', BugTaskMileston e', 'UserCannotEdit BugTaskStatus' , - remote_ bug_url' ] + 'valid_ remote_ bug_url' , + ]
> > 'IPersonBugTask
> > 'IRemoveQuestio
> > 'IUpstreamProdu
> > 'IllegalRelated
> > 'RESOLVED_
> > 'UserCannotEdit
> > 'UserCannotEdit
> > 'UserCannotEdit
> > 'valid_
> >
> > from lazr.enum import ( DBEnumeratedType, @@ -340,7 +342,7 @@
> > """Bug branch search option.
> >
> > The possible values to search for bugs having branche...