Merge lp:~cjwatson/launchpad/productseries-ubuntupkg-dsp-vocab into lp:launchpad
- productseries-ubuntupkg-dsp-vocab
- Merge into devel
Proposed by
Colin Watson
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Merged at revision: | 18195 | ||||||||
Proposed branch: | lp:~cjwatson/launchpad/productseries-ubuntupkg-dsp-vocab | ||||||||
Merge into: | lp:launchpad | ||||||||
Prerequisite: | lp:~cjwatson/launchpad/distribution-filebug-dsp-vocab | ||||||||
Diff against target: |
526 lines (+164/-86) 7 files modified
lib/lp/app/widgets/popup.py (+85/-1) lib/lp/bugs/browser/bugtracker.py (+2/-2) lib/lp/bugs/browser/widgets/bugtask.py (+11/-74) lib/lp/registry/browser/productseries.py (+33/-4) lib/lp/registry/browser/tests/test_packaging.py (+20/-3) lib/lp/registry/tests/test_distributionsourcepackage_vocabulary.py (+11/-0) lib/lp/registry/vocabularies.py (+2/-2) |
||||||||
To merge this branch: | bzr merge lp:~cjwatson/launchpad/productseries-ubuntupkg-dsp-vocab | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
William Grant | code | Approve | |
Review via email: mp+305367@code.launchpad.net |
Commit message
Convert ProductSeries:
Description of the change
Convert ProductSeries:
I had to move most of BugTaskSourcePa
To post a comment you must log in.
Revision history for this message
William Grant (wgrant) : | # |
review:
Approve
(code)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/app/widgets/popup.py' |
2 | --- lib/lp/app/widgets/popup.py 2016-07-21 20:22:00 +0000 |
3 | +++ lib/lp/app/widgets/popup.py 2016-09-09 17:05:20 +0000 |
4 | @@ -4,21 +4,38 @@ |
5 | """Single selection widget using a popup to select one item from many.""" |
6 | |
7 | __metaclass__ = type |
8 | +__all__ = [ |
9 | + "BugTrackerPickerWidget", |
10 | + "DistributionSourcePackagePickerWidget", |
11 | + "PersonPickerWidget", |
12 | + "SearchForUpstreamPopupWidget", |
13 | + "SourcePackageNameWidgetBase", |
14 | + "UbuntuSourcePackageNameWidget", |
15 | + "VocabularyPickerWidget", |
16 | + ] |
17 | |
18 | from lazr.restful.utils import safe_hasattr |
19 | import simplejson |
20 | from z3c.ptcompat import ViewPageTemplateFile |
21 | +from zope.component import getUtility |
22 | +from zope.formlib.interfaces import ConversionError |
23 | from zope.formlib.itemswidgets import ( |
24 | ItemsWidgetBase, |
25 | SingleDataHelper, |
26 | ) |
27 | -from zope.schema.interfaces import IChoice |
28 | +from zope.schema.interfaces import ( |
29 | + IChoice, |
30 | + InvalidValue, |
31 | + ) |
32 | |
33 | from lp.app.browser.stringformatter import FormattersAPI |
34 | from lp.app.browser.vocabulary import ( |
35 | get_person_picker_entry_metadata, |
36 | vocabulary_filters, |
37 | ) |
38 | +from lp.app.errors import NotFoundError |
39 | +from lp.app.interfaces.launchpad import ILaunchpadCelebrities |
40 | +from lp.services.features import getFeatureFlag |
41 | from lp.services.propertycache import cachedproperty |
42 | from lp.services.webapp import canonical_url |
43 | from lp.services.webapp.escaping import structured |
44 | @@ -288,3 +305,70 @@ |
45 | return self._prefix + 'distribution' |
46 | |
47 | distribution_name = '' |
48 | + |
49 | + |
50 | +class SourcePackageNameWidgetBase(DistributionSourcePackagePickerWidget): |
51 | + """A base widget for choosing a SourcePackageName. |
52 | + |
53 | + It accepts both binary and source package names. Widgets inheriting |
54 | + from this must implement `getDistribution`. |
55 | + |
56 | + Most views should use LaunchpadTargetWidget or |
57 | + DistributionSourcePackagePickerWidget instead, but this is useful in |
58 | + cases where the distribution is fixed in some other way. |
59 | + """ |
60 | + |
61 | + # Pages that use this widget don't display the distribution. |
62 | + distribution_id = '' |
63 | + |
64 | + def __init__(self, field, vocabulary, request): |
65 | + super(SourcePackageNameWidgetBase, self).__init__( |
66 | + field, vocabulary, request) |
67 | + self.cached_values = {} |
68 | + |
69 | + def getDistribution(self): |
70 | + """Get the distribution used for package validation. |
71 | + |
72 | + The package name has to be published in the returned distribution. |
73 | + """ |
74 | + raise NotImplementedError |
75 | + |
76 | + def _toFieldValue(self, input): |
77 | + if not input: |
78 | + return self.context.missing_value |
79 | + |
80 | + distribution = self.getDistribution() |
81 | + cached_value = self.cached_values.get(input) |
82 | + if cached_value: |
83 | + return cached_value |
84 | + if bool(getFeatureFlag('disclosure.dsp_picker.enabled')): |
85 | + try: |
86 | + self.context.vocabulary.setDistribution(distribution) |
87 | + return self.context.vocabulary.getTermByToken(input).value |
88 | + except LookupError: |
89 | + raise ConversionError( |
90 | + "Launchpad doesn't know of any source package named" |
91 | + " '%s' in %s." % (input, distribution.displayname)) |
92 | + # Else the untrusted SPN vocab was used so it needs secondary |
93 | + # verification. |
94 | + try: |
95 | + source = distribution.guessPublishedSourcePackageName(input) |
96 | + except NotFoundError: |
97 | + try: |
98 | + source = self.convertTokensToValues([input])[0] |
99 | + except InvalidValue: |
100 | + raise ConversionError( |
101 | + "Launchpad doesn't know of any source package named" |
102 | + " '%s' in %s." % (input, distribution.displayname)) |
103 | + self.cached_values[input] = source |
104 | + return source |
105 | + |
106 | + |
107 | +class UbuntuSourcePackageNameWidget(SourcePackageNameWidgetBase): |
108 | + """A widget to select Ubuntu packages.""" |
109 | + |
110 | + distribution_name = 'ubuntu' |
111 | + |
112 | + def getDistribution(self): |
113 | + """See `SourcePackageNameWidgetBase`""" |
114 | + return getUtility(ILaunchpadCelebrities).ubuntu |
115 | |
116 | === modified file 'lib/lp/bugs/browser/bugtracker.py' |
117 | --- lib/lp/bugs/browser/bugtracker.py 2015-09-28 17:38:45 +0000 |
118 | +++ lib/lp/bugs/browser/bugtracker.py 2016-09-09 17:05:20 +0000 |
119 | @@ -1,4 +1,4 @@ |
120 | -# Copyright 2009-2013 Canonical Ltd. This software is licensed under the |
121 | +# Copyright 2009-2016 Canonical Ltd. This software is licensed under the |
122 | # GNU Affero General Public License version 3 (see the file LICENSE). |
123 | |
124 | """Bug tracker views.""" |
125 | @@ -40,8 +40,8 @@ |
126 | from lp.app.interfaces.launchpad import ILaunchpadCelebrities |
127 | from lp.app.validators import LaunchpadValidationError |
128 | from lp.app.widgets.itemswidgets import LaunchpadRadioWidget |
129 | +from lp.app.widgets.popup import UbuntuSourcePackageNameWidget |
130 | from lp.app.widgets.textwidgets import DelimitedListWidget |
131 | -from lp.bugs.browser.widgets.bugtask import UbuntuSourcePackageNameWidget |
132 | from lp.bugs.interfaces.bugtracker import ( |
133 | BugTrackerType, |
134 | IBugTracker, |
135 | |
136 | === modified file 'lib/lp/bugs/browser/widgets/bugtask.py' |
137 | --- lib/lp/bugs/browser/widgets/bugtask.py 2016-09-09 17:05:19 +0000 |
138 | +++ lib/lp/bugs/browser/widgets/bugtask.py 2016-09-09 17:05:20 +0000 |
139 | @@ -15,13 +15,11 @@ |
140 | "DBItemDisplayWidget", |
141 | "FileBugSourcePackageNameWidget", |
142 | "NewLineToSpacesWidget", |
143 | - "UbuntuSourcePackageNameWidget", |
144 | ] |
145 | |
146 | from z3c.ptcompat import ViewPageTemplateFile |
147 | from zope.component import getUtility |
148 | from zope.formlib.interfaces import ( |
149 | - ConversionError, |
150 | IDisplayWidget, |
151 | IInputWidget, |
152 | InputErrors, |
153 | @@ -39,24 +37,17 @@ |
154 | implementer, |
155 | Interface, |
156 | ) |
157 | -from zope.schema.interfaces import ( |
158 | - InvalidValue, |
159 | - ValidationError, |
160 | - ) |
161 | +from zope.schema.interfaces import ValidationError |
162 | from zope.schema.vocabulary import getVocabularyRegistry |
163 | |
164 | from lp import _ |
165 | from lp.app.browser.tales import TeamFormatterAPI |
166 | -from lp.app.errors import ( |
167 | - NotFoundError, |
168 | - UnexpectedFormData, |
169 | - ) |
170 | -from lp.app.interfaces.launchpad import ILaunchpadCelebrities |
171 | +from lp.app.errors import UnexpectedFormData |
172 | from lp.app.widgets.helpers import get_widget_template |
173 | from lp.app.widgets.launchpadtarget import LaunchpadTargetWidget |
174 | from lp.app.widgets.popup import ( |
175 | - DistributionSourcePackagePickerWidget, |
176 | PersonPickerWidget, |
177 | + SourcePackageNameWidgetBase, |
178 | ) |
179 | from lp.app.widgets.textwidgets import ( |
180 | StrippedTextWidget, |
181 | @@ -483,27 +474,14 @@ |
182 | return vocabulary |
183 | |
184 | |
185 | -class BugTaskSourcePackageNameWidget(DistributionSourcePackagePickerWidget): |
186 | +class BugTaskSourcePackageNameWidget(SourcePackageNameWidgetBase): |
187 | """A widget for associating a bugtask with a SourcePackageName. |
188 | |
189 | It accepts both binary and source package names. |
190 | """ |
191 | |
192 | - # Pages that use this widget don't display the distribution, but this |
193 | - # can only be used by bugtasks on the distribution in question so the |
194 | - # vocabulary will be able to work it out for itself. |
195 | - distribution_id = '' |
196 | - |
197 | - def __init__(self, field, vocabulary, request): |
198 | - super(BugTaskSourcePackageNameWidget, self).__init__( |
199 | - field, vocabulary, request) |
200 | - self.cached_values = {} |
201 | - |
202 | def getDistribution(self): |
203 | - """Get the distribution used for package validation. |
204 | - |
205 | - The package name has to be published in the returned distribution. |
206 | - """ |
207 | + """See `SourcePackageNameWidgetBase`.""" |
208 | field = self.context |
209 | distribution = field.context.distribution |
210 | if distribution is None and field.context.distroseries is not None: |
211 | @@ -513,39 +491,8 @@ |
212 | " bugtasks on distributions or on distribution series.") |
213 | return distribution |
214 | |
215 | - def _toFieldValue(self, input): |
216 | - if not input: |
217 | - return self.context.missing_value |
218 | - |
219 | - distribution = self.getDistribution() |
220 | - cached_value = self.cached_values.get(input) |
221 | - if cached_value: |
222 | - return cached_value |
223 | - if bool(getFeatureFlag('disclosure.dsp_picker.enabled')): |
224 | - try: |
225 | - self.context.vocabulary.setDistribution(distribution) |
226 | - return self.context.vocabulary.getTermByToken(input).value |
227 | - except LookupError: |
228 | - raise ConversionError( |
229 | - "Launchpad doesn't know of any source package named" |
230 | - " '%s' in %s." % (input, distribution.displayname)) |
231 | - # Else the untrusted SPN vocab was used so it needs secondary |
232 | - # verification. |
233 | - try: |
234 | - source = distribution.guessPublishedSourcePackageName(input) |
235 | - except NotFoundError: |
236 | - try: |
237 | - source = self.convertTokensToValues([input])[0] |
238 | - except InvalidValue: |
239 | - raise ConversionError( |
240 | - "Launchpad doesn't know of any source package named" |
241 | - " '%s' in %s." % (input, distribution.displayname)) |
242 | - self.cached_values[input] = source |
243 | - return source |
244 | - |
245 | - |
246 | -class BugTaskAlsoAffectsSourcePackageNameWidget( |
247 | - BugTaskSourcePackageNameWidget): |
248 | + |
249 | +class BugTaskAlsoAffectsSourcePackageNameWidget(SourcePackageNameWidgetBase): |
250 | """Package widget for +distrotask. |
251 | |
252 | This widget works the same as `BugTaskSourcePackageNameWidget`, except |
253 | @@ -555,7 +502,7 @@ |
254 | distribution_id = 'field.distribution' |
255 | |
256 | def getDistribution(self): |
257 | - """See `BugTaskSourcePackageNameWidget`.""" |
258 | + """See `SourcePackageNameWidgetBase`.""" |
259 | distribution_name = self.request.form.get('field.distribution') |
260 | if distribution_name is None: |
261 | raise UnexpectedFormData( |
262 | @@ -568,7 +515,7 @@ |
263 | return distribution |
264 | |
265 | |
266 | -class FileBugSourcePackageNameWidget(BugTaskSourcePackageNameWidget): |
267 | +class FileBugSourcePackageNameWidget(SourcePackageNameWidgetBase): |
268 | """Package widget for +filebug. |
269 | |
270 | This widget works the same as `BugTaskSourcePackageNameWidget`, except |
271 | @@ -577,7 +524,7 @@ |
272 | """ |
273 | |
274 | def getDistribution(self): |
275 | - """See `BugTaskSourcePackageNameWidget`.""" |
276 | + """See `SourcePackageNameWidgetBase`.""" |
277 | field = self.context |
278 | pillar = field.context.pillar |
279 | assert IDistribution.providedBy(pillar), ( |
280 | @@ -586,7 +533,7 @@ |
281 | return pillar |
282 | |
283 | def _toFieldValue(self, input): |
284 | - """See `BugTaskSourcePackageNameWidget`.""" |
285 | + """See `SourcePackageNameWidgetBase`.""" |
286 | source = super(FileBugSourcePackageNameWidget, self)._toFieldValue( |
287 | input) |
288 | if (source is not None and |
289 | @@ -604,16 +551,6 @@ |
290 | return source |
291 | |
292 | |
293 | -class UbuntuSourcePackageNameWidget(BugTaskSourcePackageNameWidget): |
294 | - """A widget to select Ubuntu packages.""" |
295 | - |
296 | - distribution_name = 'ubuntu' |
297 | - |
298 | - def getDistribution(self): |
299 | - """See `BugTaskSourcePackageNameWidget`""" |
300 | - return getUtility(ILaunchpadCelebrities).ubuntu |
301 | - |
302 | - |
303 | @implementer(IDisplayWidget) |
304 | class AssigneeDisplayWidget(BrowserWidget): |
305 | """A widget for displaying an assignee.""" |
306 | |
307 | === modified file 'lib/lp/registry/browser/productseries.py' |
308 | --- lib/lp/registry/browser/productseries.py 2015-09-29 00:05:21 +0000 |
309 | +++ lib/lp/registry/browser/productseries.py 2016-09-09 17:05:20 +0000 |
310 | @@ -1,4 +1,4 @@ |
311 | -# Copyright 2009-2015 Canonical Ltd. This software is licensed under the |
312 | +# Copyright 2009-2016 Canonical Ltd. This software is licensed under the |
313 | # GNU Affero General Public License version 3 (see the file LICENSE). |
314 | |
315 | """View classes for `IProductSeries`.""" |
316 | @@ -28,6 +28,7 @@ |
317 | |
318 | from operator import attrgetter |
319 | |
320 | +from lazr.restful.interface import copy_field |
321 | from z3c.ptcompat import ViewPageTemplateFile |
322 | from zope.component import getUtility |
323 | from zope.formlib import form |
324 | @@ -57,6 +58,7 @@ |
325 | from lp.app.enums import ServiceUsage |
326 | from lp.app.errors import NotFoundError |
327 | from lp.app.interfaces.launchpad import ILaunchpadCelebrities |
328 | +from lp.app.widgets.popup import UbuntuSourcePackageNameWidget |
329 | from lp.app.widgets.textwidgets import StrippedTextWidget |
330 | from lp.blueprints.browser.specificationtarget import ( |
331 | HasSpecificationsMenuMixin, |
332 | @@ -86,6 +88,9 @@ |
333 | from lp.registry.browser.product import ProductSetBranchView |
334 | from lp.registry.enums import VCSType |
335 | from lp.registry.errors import CannotPackageProprietaryProduct |
336 | +from lp.registry.interfaces.distributionsourcepackage import ( |
337 | + IDistributionSourcePackage, |
338 | + ) |
339 | from lp.registry.interfaces.packaging import ( |
340 | IPackaging, |
341 | IPackagingUtil, |
342 | @@ -93,6 +98,7 @@ |
343 | from lp.registry.interfaces.productseries import IProductSeries |
344 | from lp.registry.interfaces.series import SeriesStatus |
345 | from lp.services.config import config |
346 | +from lp.services.features import getFeatureFlag |
347 | from lp.services.propertycache import cachedproperty |
348 | from lp.services.webapp import ( |
349 | ApplicationMenu, |
350 | @@ -482,10 +488,25 @@ |
351 | return list(self.context.releases[:12]) |
352 | |
353 | |
354 | +class IPackagingForm(IPackaging): |
355 | + |
356 | + sourcepackagename = copy_field( |
357 | + IPackaging['sourcepackagename'], |
358 | + vocabularyName='DistributionSourcePackage') |
359 | + |
360 | + |
361 | class ProductSeriesUbuntuPackagingView(LaunchpadFormView): |
362 | |
363 | - schema = IPackaging |
364 | + @property |
365 | + def schema(self): |
366 | + """See `LaunchpadFormView`.""" |
367 | + if bool(getFeatureFlag('disclosure.dsp_picker.enabled')): |
368 | + return IPackagingForm |
369 | + else: |
370 | + return IPackaging |
371 | + |
372 | field_names = ['sourcepackagename', 'distroseries'] |
373 | + custom_widget('sourcepackagename', UbuntuSourcePackageNameWidget) |
374 | page_title = 'Ubuntu source packaging' |
375 | label = page_title |
376 | |
377 | @@ -497,7 +518,11 @@ |
378 | self._ubuntu_series = self._ubuntu.currentseries |
379 | try: |
380 | package = self.context.getPackage(self._ubuntu_series) |
381 | - self.default_sourcepackagename = package.sourcepackagename |
382 | + if bool(getFeatureFlag('disclosure.dsp_picker.enabled')): |
383 | + self.default_sourcepackagename = self._ubuntu.getSourcePackage( |
384 | + package.sourcepackagename) |
385 | + else: |
386 | + self.default_sourcepackagename = package.sourcepackagename |
387 | except NotFoundError: |
388 | # The package has never been set. |
389 | self.default_sourcepackagename = None |
390 | @@ -555,6 +580,8 @@ |
391 | def validate(self, data): |
392 | productseries = self.context |
393 | sourcepackagename = data.get('sourcepackagename', None) |
394 | + if IDistributionSourcePackage.providedBy(sourcepackagename): |
395 | + sourcepackagename = sourcepackagename.sourcepackagename |
396 | distroseries = self._getSubmittedSeries(data) |
397 | |
398 | packaging_util = getUtility(IPackagingUtil) |
399 | @@ -595,6 +622,8 @@ |
400 | # ubuntu series. if none exists, one will be created |
401 | distroseries = self._getSubmittedSeries(data) |
402 | sourcepackagename = data['sourcepackagename'] |
403 | + if IDistributionSourcePackage.providedBy(sourcepackagename): |
404 | + sourcepackagename = sourcepackagename.sourcepackagename |
405 | if getUtility(IPackagingUtil).packagingEntryExists( |
406 | sourcepackagename, distroseries, productseries=self.context): |
407 | # There is no change. |
408 | @@ -602,7 +631,7 @@ |
409 | try: |
410 | self.context.setPackaging( |
411 | distroseries, sourcepackagename, self.user) |
412 | - except CannotPackageProprietaryProduct, e: |
413 | + except CannotPackageProprietaryProduct as e: |
414 | self.request.response.addErrorNotification(str(e)) |
415 | |
416 | |
417 | |
418 | === modified file 'lib/lp/registry/browser/tests/test_packaging.py' |
419 | --- lib/lp/registry/browser/tests/test_packaging.py 2016-06-17 15:46:57 +0000 |
420 | +++ lib/lp/registry/browser/tests/test_packaging.py 2016-09-09 17:05:20 +0000 |
421 | @@ -5,6 +5,10 @@ |
422 | |
423 | __metaclass__ = type |
424 | |
425 | +from testscenarios import ( |
426 | + load_tests_apply_scenarios, |
427 | + WithScenarios, |
428 | + ) |
429 | from zope.component import getUtility |
430 | |
431 | from lp.app.interfaces.launchpad import ILaunchpadCelebrities |
432 | @@ -15,6 +19,7 @@ |
433 | ) |
434 | from lp.registry.interfaces.product import IProductSet |
435 | from lp.registry.interfaces.sourcepackagename import ISourcePackageNameSet |
436 | +from lp.services.features.testing import FeatureFixture |
437 | from lp.testing import ( |
438 | login, |
439 | logout, |
440 | @@ -28,13 +33,22 @@ |
441 | from lp.testing.views import create_initialized_view |
442 | |
443 | |
444 | -class TestProductSeriesUbuntuPackagingView(TestCaseWithFactory): |
445 | - """Browser tests for deletion of Packaging objects.""" |
446 | +class TestProductSeriesUbuntuPackagingView(WithScenarios, TestCaseWithFactory): |
447 | + """Browser tests for adding Packaging objects.""" |
448 | |
449 | layer = DatabaseFunctionalLayer |
450 | |
451 | + scenarios = [ |
452 | + ("spn_picker", {"features": {}}), |
453 | + ("dsp_picker", { |
454 | + "features": {u"disclosure.dsp_picker.enabled": u"on"}, |
455 | + }), |
456 | + ] |
457 | + |
458 | def setUp(self): |
459 | super(TestProductSeriesUbuntuPackagingView, self).setUp() |
460 | + if self.features: |
461 | + self.useFixture(FeatureFixture(self.features)) |
462 | self.ubuntu = getUtility(ILaunchpadCelebrities).ubuntu |
463 | self.hoary = self.ubuntu.getSeries('hoary') |
464 | self.sourcepackagename = self.factory.makeSourcePackageName('hot') |
465 | @@ -88,7 +102,7 @@ |
466 | 'hot</a> package in Hoary is already linked to another series.'] |
467 | self.assertEqual(view_errors, view.errors) |
468 | |
469 | - def test_sourcepackgename_required(self): |
470 | + def test_sourcepackagename_required(self): |
471 | # A source package name must be provided. |
472 | form = { |
473 | 'field.distroseries': 'hoary', |
474 | @@ -188,3 +202,6 @@ |
475 | productseries=productseries, |
476 | sourcepackagename=package_name, |
477 | distroseries=distroseries)) |
478 | + |
479 | + |
480 | +load_tests = load_tests_apply_scenarios |
481 | |
482 | === modified file 'lib/lp/registry/tests/test_distributionsourcepackage_vocabulary.py' |
483 | --- lib/lp/registry/tests/test_distributionsourcepackage_vocabulary.py 2016-09-09 17:05:19 +0000 |
484 | +++ lib/lp/registry/tests/test_distributionsourcepackage_vocabulary.py 2016-09-09 17:05:20 +0000 |
485 | @@ -175,6 +175,17 @@ |
486 | self.assertEqual(dsp.name, term.title) |
487 | self.assertEqual(dsp, term.value) |
488 | |
489 | + def test_toTerm_dsp_no_distribution(self): |
490 | + # The vocabulary can convert a DSP to a term even if it does not yet |
491 | + # have a distribution. |
492 | + dsp = self.factory.makeDistributionSourcePackage( |
493 | + sourcepackagename='foo', with_db=False) |
494 | + vocabulary = DistributionSourcePackageVocabulary(None) |
495 | + term = vocabulary.toTerm(dsp) |
496 | + self.assertEqual(dsp.name, term.token) |
497 | + self.assertEqual(dsp.name, term.title) |
498 | + self.assertEqual(dsp, term.value) |
499 | + |
500 | def test_getTermByToken_error(self): |
501 | # An error is raised if the token does not match a official DSP. |
502 | distro = self.factory.makeDistribution() |
503 | |
504 | === modified file 'lib/lp/registry/vocabularies.py' |
505 | --- lib/lp/registry/vocabularies.py 2016-09-09 17:05:19 +0000 |
506 | +++ lib/lp/registry/vocabularies.py 2016-09-09 17:05:20 +0000 |
507 | @@ -2073,7 +2073,6 @@ |
508 | |
509 | def toTerm(self, spn_or_dsp): |
510 | """See `IVocabulary`.""" |
511 | - self._assertHasDistribution() |
512 | dsp = None |
513 | binary_names = None |
514 | if isinstance(spn_or_dsp, tuple): |
515 | @@ -2088,9 +2087,10 @@ |
516 | if IDistributionSourcePackage.providedBy(spn_or_dsp): |
517 | dsp = spn_or_dsp |
518 | elif spn_or_dsp is not None: |
519 | + self._assertHasDistribution() |
520 | dsp = self.distribution.getSourcePackage(spn_or_dsp) |
521 | if dsp is not None: |
522 | - if dsp == self.dsp or dsp.is_official: |
523 | + if dsp == self.dsp or dsp.is_official or self.distribution is None: |
524 | if binary_names: |
525 | # Search already did the hard work of looking up binary |
526 | # names. |