Merge lp:~brian-murray/launchpad/bug-320596 into lp:launchpad
- bug-320596
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Brian Murray |
Approved revision: | no longer in the source branch. |
Merged at revision: | 11458 |
Proposed branch: | lp:~brian-murray/launchpad/bug-320596 |
Merge into: | lp:launchpad |
Diff against target: |
362 lines (+176/-112) 5 files modified
lib/lp/bugs/interfaces/bugtarget.py (+120/-108) lib/lp/bugs/interfaces/bugtask.py (+2/-2) lib/lp/bugs/stories/webservice/xx-bug-target.txt (+2/-2) lib/lp/bugs/tests/test_bugtask.py (+9/-0) lib/lp/bugs/tests/test_searchtasks_webservice.py (+43/-0) |
To merge this branch: | bzr merge lp:~brian-murray/launchpad/bug-320596 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Abel Deuring (community) | code | Approve | |
Robert Collins (community) | Needs Fixing | ||
Review via email: mp+30690@code.launchpad.net |
Commit message
For the devel version of the API have omit_targeted searchTasks parameter default to False.
Description of the change
Remove the default value of True for omit_targeted so that bug tasks targeted to a milestone are no longer hidden in search results.
Tests modified:
bin/test -cvvt xx-bug.txt -t bugtask-search.txt
Brian Murray (brian-murray) wrote : | # |
I think having the default value of omit_targeted be False in the API is actually broken. This is a different default value than the web interface and resulted in terribly confusing behavior - see bug 320596 (and its duplicates). However, I'll special case the default value of it if you think that is best.
Robert Collins (lifeless) wrote : | # |
I don't hold the value to be sacred; however its my understanding that
we promised not to change the behaviour of the 1.0 API - we can change
devel, just not 1.0.
Brian Murray (brian-murray) wrote : | # |
This is ready for review again. omit_targeted is left defaulting to True and in devel the default value is changed to False.
Abel Deuring (adeuring) wrote : | # |
Hi Brian,
nice work! Just one minor nitpicks: I find the name "modifiable_params" and "modified_params" a bit confusing. What about "params_
Preview Diff
1 | === modified file 'lib/lp/bugs/interfaces/bugtarget.py' |
2 | --- lib/lp/bugs/interfaces/bugtarget.py 2010-08-20 20:31:18 +0000 |
3 | +++ lib/lp/bugs/interfaces/bugtarget.py 2010-08-26 20:46:45 +0000 |
4 | @@ -29,11 +29,13 @@ |
5 | exported, |
6 | LAZR_WEBSERVICE_EXPORTED, |
7 | operation_parameters, |
8 | + operation_removed_in_version, |
9 | operation_returns_collection_of, |
10 | REQUEST_USER, |
11 | ) |
12 | from lazr.restful.fields import Reference |
13 | from lazr.restful.interface import copy_field |
14 | + |
15 | from zope.interface import ( |
16 | Attribute, |
17 | Interface, |
18 | @@ -57,6 +59,117 @@ |
19 | ) |
20 | from lp.services.fields import Tag |
21 | |
22 | +search_tasks_params_for_api_1_0 = { |
23 | + "order_by": List( |
24 | + title=_('List of fields by which the results are ordered.'), |
25 | + value_type=Text(), |
26 | + required=False), |
27 | + "search_text": copy_field(IBugTaskSearch['searchtext']), |
28 | + "status": copy_field(IBugTaskSearch['status']), |
29 | + "importance": copy_field(IBugTaskSearch['importance']), |
30 | + "assignee": Reference(schema=Interface), |
31 | + "bug_reporter": Reference(schema=Interface), |
32 | + "bug_supervisor": Reference(schema=Interface), |
33 | + "bug_commenter": Reference(schema=Interface), |
34 | + "bug_subscriber": Reference(schema=Interface), |
35 | + "structural_subscriber": Reference(schema=Interface), |
36 | + "owner": Reference(schema=Interface), |
37 | + "affected_user": Reference(schema=Interface), |
38 | + "has_patch": copy_field(IBugTaskSearch['has_patch']), |
39 | + "has_cve": copy_field(IBugTaskSearch['has_cve']), |
40 | + "tags": copy_field(IBugTaskSearch['tag']), |
41 | + "tags_combinator": copy_field(IBugTaskSearch['tags_combinator']), |
42 | + "omit_duplicates": copy_field(IBugTaskSearch['omit_dupes']), |
43 | + "omit_targeted": copy_field(IBugTaskSearch['omit_targeted']), |
44 | + "status_upstream": copy_field(IBugTaskSearch['status_upstream']), |
45 | + "milestone_assignment": copy_field(IBugTaskSearch['milestone_assignment']), |
46 | + "milestone": copy_field(IBugTaskSearch['milestone']), |
47 | + "component": copy_field(IBugTaskSearch['component']), |
48 | + "nominated_for": Reference(schema=Interface), |
49 | + "has_no_package": copy_field(IBugTaskSearch['has_no_package']), |
50 | + "hardware_bus": Choice( |
51 | + title=_(u"The bus of a hardware device related to a bug"), |
52 | + # The vocabulary should be HWBus; this is fixed in |
53 | + # _schema_circular_imports to avoid circular imports. |
54 | + vocabulary=DBEnumeratedType, required=False), |
55 | + "hardware_vendor_id": TextLine( |
56 | + title=_( |
57 | + u"The vendor ID of a hardware device related to a bug."), |
58 | + description=_( |
59 | + u"Allowed values of the vendor ID depend on the bus of the " |
60 | + "device.\n\n" |
61 | + "Vendor IDs of PCI, PCCard and USB devices are hexadecimal " |
62 | + "string representations of 16 bit integers in the format " |
63 | + "'0x01ab': The prefix '0x', followed by exactly 4 digits; " |
64 | + "where a digit is one of the characters 0..9, a..f. The " |
65 | + "characters A..F are not allowed.\n\n" |
66 | + "SCSI vendor IDs are strings with exactly 8 characters. " |
67 | + "Shorter names are right-padded with space (0x20) characters." |
68 | + "\n\n" |
69 | + "IDs for other buses may be arbitrary strings."), |
70 | + required=False), |
71 | + "hardware_product_id": TextLine( |
72 | + title=_( |
73 | + u"The product ID of a hardware device related to a bug."), |
74 | + description=_( |
75 | + u"Allowed values of the product ID depend on the bus of the " |
76 | + "device.\n\n" |
77 | + "Product IDs of PCI, PCCard and USB devices are hexadecimal " |
78 | + "string representations of 16 bit integers in the format " |
79 | + "'0x01ab': The prefix '0x', followed by exactly 4 digits; " |
80 | + "where a digit is one of the characters 0..9, a..f. The " |
81 | + "characters A..F are not allowed.\n\n" |
82 | + "SCSI product IDs are strings with exactly 16 characters. " |
83 | + "Shorter names are right-padded with space (0x20) characters." |
84 | + "\n\n" |
85 | + "IDs for other buses may be arbitrary strings."), |
86 | + required=False), |
87 | + "hardware_driver_name": TextLine( |
88 | + title=_( |
89 | + u"The driver controlling a hardware device related to a " |
90 | + "bug."), |
91 | + required=False), |
92 | + "hardware_driver_package_name": TextLine( |
93 | + title=_( |
94 | + u"The package of the driver which controls a hardware " |
95 | + "device related to a bug."), |
96 | + required=False), |
97 | + "hardware_owner_is_bug_reporter": Bool( |
98 | + title=_( |
99 | + u"Search for bugs reported by people who own the given " |
100 | + "device or who use the given hardware driver."), |
101 | + required=False), |
102 | + "hardware_owner_is_affected_by_bug": Bool( |
103 | + title=_( |
104 | + u"Search for bugs where people affected by a bug own the " |
105 | + "given device or use the given hardware driver."), |
106 | + required=False), |
107 | + "hardware_owner_is_subscribed_to_bug": Bool( |
108 | + title=_( |
109 | + u"Search for bugs where a bug subscriber owns the " |
110 | + "given device or uses the given hardware driver."), |
111 | + required=False), |
112 | + "hardware_is_linked_to_bug": Bool( |
113 | + title=_( |
114 | + u"Search for bugs which are linked to hardware reports " |
115 | + "which contain the given device or whcih contain a device" |
116 | + "controlled by the given driver."), |
117 | + required=False), |
118 | + "linked_branches": Choice( |
119 | + title=_( |
120 | + u"Search for bugs that are linked to branches or for bugs " |
121 | + "that are not linked to branches."), |
122 | + vocabulary=BugBranchSearch, required=False), |
123 | + "modified_since": Datetime( |
124 | + title=_( |
125 | + u"Search for bugs that have been modified since the given " |
126 | + "date."), |
127 | + required=False), |
128 | + } |
129 | +search_tasks_params_for_api_devel = search_tasks_params_for_api_1_0.copy() |
130 | +search_tasks_params_for_api_devel["omit_targeted"] = copy_field( |
131 | + IBugTaskSearch['omit_targeted'], default=False) |
132 | + |
133 | |
134 | class IHasBugs(Interface): |
135 | """An entity which has a collection of bug tasks.""" |
136 | @@ -85,114 +198,13 @@ |
137 | "True if a BugTask has ever been reported for this target.") |
138 | |
139 | @call_with(search_params=None, user=REQUEST_USER) |
140 | - @operation_parameters( |
141 | - order_by=List( |
142 | - title=_('List of fields by which the results are ordered.'), |
143 | - value_type=Text(), |
144 | - required=False), |
145 | - search_text=copy_field(IBugTaskSearch['searchtext']), |
146 | - status=copy_field(IBugTaskSearch['status']), |
147 | - importance=copy_field(IBugTaskSearch['importance']), |
148 | - assignee=Reference(schema=Interface), |
149 | - bug_reporter=Reference(schema=Interface), |
150 | - bug_supervisor=Reference(schema=Interface), |
151 | - bug_commenter=Reference(schema=Interface), |
152 | - bug_subscriber=Reference(schema=Interface), |
153 | - structural_subscriber=Reference(schema=Interface), |
154 | - owner=Reference(schema=Interface), |
155 | - affected_user=Reference(schema=Interface), |
156 | - has_patch=copy_field(IBugTaskSearch['has_patch']), |
157 | - has_cve=copy_field(IBugTaskSearch['has_cve']), |
158 | - tags=copy_field(IBugTaskSearch['tag']), |
159 | - tags_combinator=copy_field(IBugTaskSearch['tags_combinator']), |
160 | - omit_duplicates=copy_field(IBugTaskSearch['omit_dupes']), |
161 | - omit_targeted=copy_field(IBugTaskSearch['omit_targeted']), |
162 | - status_upstream=copy_field(IBugTaskSearch['status_upstream']), |
163 | - milestone_assignment=copy_field( |
164 | - IBugTaskSearch['milestone_assignment']), |
165 | - milestone=copy_field(IBugTaskSearch['milestone']), |
166 | - component=copy_field(IBugTaskSearch['component']), |
167 | - nominated_for=Reference(schema=Interface), |
168 | - has_no_package=copy_field(IBugTaskSearch['has_no_package']), |
169 | - hardware_bus=Choice( |
170 | - title=u'The bus of a hardware device related to a bug', |
171 | - # The vocabulary should be HWBus; this is fixed in |
172 | - # _schema_circular_imports to avoid circular imports. |
173 | - vocabulary=DBEnumeratedType, required=False), |
174 | - hardware_vendor_id=TextLine( |
175 | - title=( |
176 | - u"The vendor ID of a hardware device related to a bug."), |
177 | - description=( |
178 | - u"Allowed values of the vendor ID depend on the bus of the " |
179 | - "device.\n\n" |
180 | - "Vendor IDs of PCI, PCCard and USB devices are hexadecimal " |
181 | - "string representations of 16 bit integers in the format " |
182 | - "'0x01ab': The prefix '0x', followed by exactly 4 digits; " |
183 | - "where a digit is one of the characters 0..9, a..f. The " |
184 | - "characters A..F are not allowed.\n\n" |
185 | - "SCSI vendor IDs are strings with exactly 8 characters. " |
186 | - "Shorter names are right-padded with space (0x20) characters." |
187 | - "\n\n" |
188 | - "IDs for other buses may be arbitrary strings."), |
189 | - required=False), |
190 | - hardware_product_id=TextLine( |
191 | - title=( |
192 | - u"The product ID of a hardware device related to a bug."), |
193 | - description=( |
194 | - u"Allowed values of the product ID depend on the bus of the " |
195 | - "device.\n\n" |
196 | - "Product IDs of PCI, PCCard and USB devices are hexadecimal " |
197 | - "string representations of 16 bit integers in the format " |
198 | - "'0x01ab': The prefix '0x', followed by exactly 4 digits; " |
199 | - "where a digit is one of the characters 0..9, a..f. The " |
200 | - "characters A..F are not allowed.\n\n" |
201 | - "SCSI product IDs are strings with exactly 16 characters. " |
202 | - "Shorter names are right-padded with space (0x20) characters." |
203 | - "\n\n" |
204 | - "IDs for other buses may be arbitrary strings."), |
205 | - required=False), |
206 | - hardware_driver_name=TextLine( |
207 | - title=( |
208 | - u"The driver controlling a hardware device related to a " |
209 | - "bug."), |
210 | - required=False), |
211 | - hardware_driver_package_name=TextLine( |
212 | - title=( |
213 | - u"The package of the driver which controls a hardware " |
214 | - "device related to a bug."), |
215 | - required=False), |
216 | - hardware_owner_is_bug_reporter=Bool( |
217 | - title=( |
218 | - u"Search for bugs reported by people who own the given " |
219 | - "device or who use the given hardware driver."), |
220 | - required=False), |
221 | - hardware_owner_is_affected_by_bug=Bool( |
222 | - title=( |
223 | - u"Search for bugs where people affected by a bug own the " |
224 | - "given device or use the given hardware driver."), |
225 | - required=False), |
226 | - hardware_owner_is_subscribed_to_bug=Bool( |
227 | - title=( |
228 | - u"Search for bugs where a bug subscriber owns the " |
229 | - "given device or uses the given hardware driver."), |
230 | - required=False), |
231 | - hardware_is_linked_to_bug=Bool( |
232 | - title=( |
233 | - u"Search for bugs which are linked to hardware reports " |
234 | - "which contain the given device or whcih contain a device" |
235 | - "controlled by the given driver."), |
236 | - required=False), |
237 | - linked_branches=Choice( |
238 | - title=( |
239 | - u"Search for bugs that are linked to branches or for bugs " |
240 | - "that are not linked to branches."), |
241 | - vocabulary=BugBranchSearch, required=False), |
242 | - modified_since=Datetime( |
243 | - title=( |
244 | - u"Search for bugs that have been modified since the given " |
245 | - "date."), |
246 | - required=False), |
247 | - ) |
248 | + @operation_parameters(**search_tasks_params_for_api_devel) |
249 | + @operation_returns_collection_of(IBugTask) |
250 | + @export_read_operation() |
251 | + @operation_removed_in_version('devel') |
252 | + |
253 | + @call_with(search_params=None, user=REQUEST_USER) |
254 | + @operation_parameters(**search_tasks_params_for_api_1_0) |
255 | @operation_returns_collection_of(IBugTask) |
256 | @export_read_operation() |
257 | def searchTasks(search_params, user=None, |
258 | |
259 | === modified file 'lib/lp/bugs/interfaces/bugtask.py' |
260 | --- lib/lp/bugs/interfaces/bugtask.py 2010-08-22 18:31:30 +0000 |
261 | +++ lib/lp/bugs/interfaces/bugtask.py 2010-08-26 20:46:45 +0000 |
262 | @@ -892,7 +892,7 @@ |
263 | title=_('Omit bugs marked as duplicate,'), required=False, |
264 | default=True) |
265 | omit_targeted = Bool( |
266 | - title=_('Omit bugs targeted to series'), required=False, |
267 | + title=_('Omit bugs targeted to a series'), required=False, |
268 | default=True) |
269 | statusexplanation = TextLine( |
270 | title=_("Status notes"), required=False) |
271 | @@ -1063,7 +1063,7 @@ |
272 | |
273 | |
274 | class IDistroSeriesBugTask(IBugTask): |
275 | - """A bug needing fixing in a distrorealease, or a specific package.""" |
276 | + """A bug needing fixing in a distrorelease, or a specific package.""" |
277 | sourcepackagename = Choice( |
278 | title=_("Source Package Name"), required=True, |
279 | vocabulary='SourcePackageName') |
280 | |
281 | === modified file 'lib/lp/bugs/stories/webservice/xx-bug-target.txt' |
282 | --- lib/lp/bugs/stories/webservice/xx-bug-target.txt 2010-07-14 15:42:40 +0000 |
283 | +++ lib/lp/bugs/stories/webservice/xx-bug-target.txt 2010-08-26 20:46:45 +0000 |
284 | @@ -57,8 +57,8 @@ |
285 | >>> product = factory.makeProduct(name='tags-test-product', owner=salgado) |
286 | >>> logout() |
287 | |
288 | -The webserice client is logged in as salgado, so we can add a new |
289 | -official tag. |
290 | +The webservice client is logged in as salgado, so we can add a new official |
291 | +tag. |
292 | |
293 | >>> print webservice.named_post( |
294 | ... '/tags-test-product', 'addOfficialBugTag', |
295 | |
296 | === modified file 'lib/lp/bugs/tests/test_bugtask.py' |
297 | --- lib/lp/bugs/tests/test_bugtask.py 2010-08-22 18:31:30 +0000 |
298 | +++ lib/lp/bugs/tests/test_bugtask.py 2010-08-26 20:46:45 +0000 |
299 | @@ -830,6 +830,15 @@ |
300 | self.assertStatementCount(1, |
301 | lambda:[task.getConjoinedMaster for task in tasks]) |
302 | |
303 | + def test_omit_targeted_default_is_false(self): |
304 | + # The default value of omit_targeted is false so bugs targeted |
305 | + # to a series are not hidden. |
306 | + target = self.factory.makeDistroRelease() |
307 | + self.login() |
308 | + task1 = self.factory.makeBugTask(target=target) |
309 | + default_result = target.searchTasks(None) |
310 | + self.assertEqual([task1], list(default_result)) |
311 | + |
312 | |
313 | def test_suite(): |
314 | suite = unittest.TestSuite() |
315 | |
316 | === added file 'lib/lp/bugs/tests/test_searchtasks_webservice.py' |
317 | --- lib/lp/bugs/tests/test_searchtasks_webservice.py 1970-01-01 00:00:00 +0000 |
318 | +++ lib/lp/bugs/tests/test_searchtasks_webservice.py 2010-08-26 20:46:45 +0000 |
319 | @@ -0,0 +1,43 @@ |
320 | +# Copyright 2009-2010 Canonical Ltd. This software is licensed under the |
321 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
322 | + |
323 | +"""Webservice unit tests related to Launchpad Bugs.""" |
324 | + |
325 | +__metaclass__ = type |
326 | + |
327 | +from unittest import TestLoader |
328 | + |
329 | +from canonical.launchpad.ftests import login |
330 | +from lp.testing import TestCaseWithFactory |
331 | +from canonical.launchpad.testing.pages import LaunchpadWebServiceCaller |
332 | +from canonical.testing import DatabaseFunctionalLayer |
333 | + |
334 | + |
335 | +class TestOmitTargetedParameter(TestCaseWithFactory): |
336 | + """Test all values for the omit_targeted search parameter.""" |
337 | + layer = DatabaseFunctionalLayer |
338 | + |
339 | + def setUp(self): |
340 | + TestCaseWithFactory.setUp(self) |
341 | + login('foo.bar@canonical.com') |
342 | + self.distro = self.factory.makeDistribution(name='mebuntu') |
343 | + self.release = self.factory.makeDistroRelease(name='inkanyamba', |
344 | + distribution=self.distro) |
345 | + self.bug = self.factory.makeBugTask(target=self.release) |
346 | + |
347 | + self.webservice = LaunchpadWebServiceCaller('launchpad-library', |
348 | + 'salgado-change-anything') |
349 | + |
350 | + def test_omit_targeted_old_default_true(self): |
351 | + response = self.webservice.named_get('/mebuntu/inkanyamba', |
352 | + 'searchTasks', api_version='1.0').jsonBody() |
353 | + self.assertEqual(response['total_size'], 0) |
354 | + |
355 | + def test_omit_targeted_new_default_false(self): |
356 | + response = self.webservice.named_get('/mebuntu/inkanyamba', |
357 | + 'searchTasks', api_version='devel').jsonBody() |
358 | + self.assertEqual(response['total_size'], 1) |
359 | + |
360 | + |
361 | +def test_suite(): |
362 | + return TestLoader().loadTestsFromName(__name__) |
So, I have some needs fixing and a question.
needs fixing: please don't add these things to doctests: none of your tests look like documentation, so they shouldn't be expressed as documentation.
question: looks like you're breaking the 1.0 API to me, I thought that wasn't permitted.