Merge lp:~jcsackett/launchpad/add-enums-to-models into lp:launchpad
- add-enums-to-models
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Brad Crittenden |
Approved revision: | no longer in the source branch. |
Merged at revision: | 11410 |
Proposed branch: | lp:~jcsackett/launchpad/add-enums-to-models |
Merge into: | lp:launchpad |
Prerequisite: | lp:~bac/launchpad/progress-enums |
Diff against target: |
643 lines (+351/-54) 7 files modified
lib/lp/registry/browser/product.py (+3/-17) lib/lp/registry/configure.zcml (+4/-1) lib/lp/registry/doc/distribution.txt (+16/-3) lib/lp/registry/doc/product.txt (+0/-4) lib/lp/registry/model/distribution.py (+87/-21) lib/lp/registry/model/product.py (+67/-8) lib/lp/registry/tests/test_service_usage.py (+174/-0) |
To merge this branch: | bzr merge lp:~jcsackett/launchpad/add-enums-to-models |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Brad Crittenden (community) | code | Approve | |
Review via email: mp+33255@code.launchpad.net |
Commit message
Wraps the usage_enums (e.g. official_
Description of the change
= Summary =
IServiceUsage provides enums to give better data on how a product or distribution uses launchpad, in place of the old bool fields (e.g. official_rosetta). However, when we roll out these enums, they will default to UNKNOWN until we can migrate data.
This branch creates properties using the enums (moved to _[ENUM] format) to use the old bool data until data is set for the enum, so we can start using the enums in code.
== Proposed fix ==
Create properties using getters and setters to intelligent find the data from the new and old attributes, and set them properly moving forward.
== Pre-implementation notes ==
Talked with Curtis.
== Implementation details ==
As above.
This branch incorporates Brad's work on the progress bar, as they need to land together. ~bac/launchpad/
== Tests ==
bin/test -vvc -t UsageEnums
== Demo and Q/A ==
Go to a project on launchpad.dev and ensure the configuration and status
links are correct.
= Launchpad lint =
= Launchpad lint =
Checking for conflicts and issues in changed files.
Linting changed files:
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
./lib/lp/
901: E301 expected 1 blank line, found 2
./lib/lp/
1181: E231 missing whitespace after ','
1185: E231 missing whitespace after ','
1197: E231 missing whitespace after ','
E301 from comment issue
E231 from creation of tuple (something = ('some tuple',))
j.c.sackett (jcsackett) wrote : | # |
> In def test_codehostin
> Same question for def test_bug_
A bad job of refactoring early on? I must have just missed it when I moved the call to makeDistribution up into setUp.
>
> We discussed on IRC refactoring the tests since they are mostly the same.
There is now one BaseTestCase that does most of the work, with subclass that define the target to product or distribution.
Thanks for the pointers, Brad.
=== modified file 'lib/lp/
--- lib/lp/
+++ lib/lp/
@@ -10,155 +10,17 @@
from lazr.lifecycle.
from lp.registry.
TestDistro
-from lp.app.enums import ServiceUsage
from lp.registry.
from lp.registry.
from lp.registry.
from lp.soyuz.
IDistribut
-from lp.testing import (
- login_person,
- TestCaseWithFac
- )
+from lp.testing import TestCaseWithFactory
from canonical.
DatabaseFu
-class TestDistributio
- """Tests the usage enums for the distribution."""
-
- layer = DatabaseFunctio
-
- def setUp(self):
- super(TestDistr
- self.distribution = self.factory.
-
- def test_answers_
- # By default, we don't know anything about a distribution
- self.assertEqual(
- ServiceUsage.
- self.distributi
-
- def test_answers_
- # If the old bool says they use Launchpad, return LAUNCHPAD
- # if the ServiceUsage is unknown.
- login_person(
- self.distributi
- self.assertEqual(
- ServiceUsage.
- self.distributi
-
- def test_answers_
- # If the enum has something other than UNKNOWN as its status,
- # use that.
- login_person(
- self.distributi
- self.assertEqual(
- ServiceUsage.
- self.distributi
-
- def test_answers_
- login_person(
- self.distributi
- self.distributi
- self.assertEqual(
- False,
- self.distributi
- self.distributi
- self.assertEqual(
- True,
- self.distributi
-
- def test_codehostin
- ...
Robert Collins (lifeless) wrote : | # |
On Sat, Aug 21, 2010 at 9:58 AM, j.c.sackett
<email address hidden> wrote:
> +
> +# Manually create the TestLoader list, because the UsageEnumsBaseT
> +# shouldn't run.
> +test_list = [
> + __name__ + ".TestDistribut
> + __name__ + ".TestProductUs
> + ]
> +
> +
> +def test_suite():
> + return unittest.
There are a few slightly better ways of doing this.
Class UsageEnumsMixinIn
....stuff
class TestDistributio
...
class TestProductUsag
...
is one.
Another is to use testscenarios, and your parameterisation would be
more explicit, but we don't use that in lp today AFAIK, so I won't
suggest adding it in (but you could get much the same helpers from
bzrlib.testing).
These are better because they don't have a class that looks-to-loaders
like a valid test case, but isn't.
-Rob
Preview Diff
1 | === modified file 'lib/lp/registry/browser/product.py' |
2 | --- lib/lp/registry/browser/product.py 2010-08-22 20:27:48 +0000 |
3 | +++ lib/lp/registry/browser/product.py 2010-08-22 20:27:49 +0000 |
4 | @@ -50,8 +50,6 @@ |
5 | ) |
6 | from operator import attrgetter |
7 | |
8 | -from lazr.delegates import delegates |
9 | -from lazr.restful.interface import copy_field |
10 | import pytz |
11 | from z3c.ptcompat import ViewPageTemplateFile |
12 | from zope.app.form.browser import ( |
13 | @@ -79,7 +77,8 @@ |
14 | |
15 | from canonical.cachedproperty import cachedproperty |
16 | from canonical.config import config |
17 | -<<<<<<< TREE |
18 | +from lazr.delegates import delegates |
19 | +from lazr.restful.interface import copy_field |
20 | from canonical.launchpad import ( |
21 | _, |
22 | helpers, |
23 | @@ -89,20 +88,6 @@ |
24 | MultiStepView, |
25 | StepView, |
26 | ) |
27 | -======= |
28 | -from lazr.delegates import delegates |
29 | -from lazr.restful.interface import copy_field |
30 | -from canonical.launchpad import _ |
31 | -from lp.services.fields import PillarAliases, PublicPersonChoice |
32 | -from lp.app.enums import ServiceUsage |
33 | -from lp.app.errors import NotFoundError |
34 | -from lp.app.interfaces.headings import IEditableContextTitle |
35 | -from lp.blueprints.browser.specificationtarget import ( |
36 | - HasSpecificationsMenuMixin) |
37 | -from lp.bugs.interfaces.bugtask import RESOLVED_BUGTASK_STATUSES |
38 | -from lp.code.browser.sourcepackagerecipelisting import HasRecipesMenuMixin |
39 | -from lp.services.worlddata.interfaces.country import ICountry |
40 | ->>>>>>> MERGE-SOURCE |
41 | from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities |
42 | from canonical.launchpad.interfaces.librarian import ILibraryFileAliasSet |
43 | from canonical.launchpad.mail import ( |
44 | @@ -157,6 +142,7 @@ |
45 | QuestionTargetFacetMixin, |
46 | QuestionTargetTraversalMixin, |
47 | ) |
48 | +from lp.app.enums import ServiceUsage |
49 | from lp.app.errors import NotFoundError |
50 | from lp.app.interfaces.headings import IEditableContextTitle |
51 | from lp.blueprints.browser.specificationtarget import ( |
52 | |
53 | === modified file 'lib/lp/registry/configure.zcml' |
54 | --- lib/lp/registry/configure.zcml 2010-08-22 20:27:48 +0000 |
55 | +++ lib/lp/registry/configure.zcml 2010-08-22 20:27:49 +0000 |
56 | @@ -1090,7 +1090,7 @@ |
57 | interface="lp.registry.interfaces.product.IProductEditRestricted"/> |
58 | <require |
59 | permission="launchpad.Edit" |
60 | - set_schema="lp.app.interfaces.launchpad.IServiceUsage"/> |
61 | + set_schema="lp.app.interfaces.launchpad.IServiceUsage"/> |
62 | <require |
63 | permission="launchpad.Edit" |
64 | set_attributes="bug_reporting_guidelines |
65 | @@ -1405,6 +1405,9 @@ |
66 | permission="launchpad.Edit" |
67 | interface="lp.registry.interfaces.distribution.IDistributionEditRestricted"/> |
68 | <require |
69 | + permission="launchpad.Edit" |
70 | + set_schema="lp.app.interfaces.launchpad.IServiceUsage"/> |
71 | + <require |
72 | permission="launchpad.Moderate" |
73 | interface="lp.registry.interfaces.distribution.IDistributionDriverRestricted"/> |
74 | <require |
75 | |
76 | === modified file 'lib/lp/registry/doc/distribution.txt' |
77 | --- lib/lp/registry/doc/distribution.txt 2010-08-06 14:49:35 +0000 |
78 | +++ lib/lp/registry/doc/distribution.txt 2010-08-22 20:27:49 +0000 |
79 | @@ -397,13 +397,26 @@ |
80 | >>> print ubuntu.bug_tracking_usage.name |
81 | LAUNCHPAD |
82 | |
83 | -While the other attributes are not yet used. |
84 | +While the other attributes track the other official_ attributes. |
85 | |
86 | + >>> print ubuntu.official_rosetta |
87 | + True |
88 | >>> print ubuntu.translations_usage.name |
89 | - UNKNOWN |
90 | + LAUNCHPAD |
91 | + >>> print ubuntu.official_answers |
92 | + True |
93 | >>> print ubuntu.answers_usage.name |
94 | - UNKNOWN |
95 | + LAUNCHPAD |
96 | + >>> print ubuntu.official_blueprints |
97 | + True |
98 | >>> print ubuntu.blueprints_usage.name |
99 | + LAUNCHPAD |
100 | + |
101 | +If the official_ attributes are False, the usage enums don't know anything. |
102 | + |
103 | + >>> login_person(ubuntu.owner.teamowner) |
104 | + >>> ubuntu.official_rosetta = False |
105 | + >>> print ubuntu.translations_usage.name |
106 | UNKNOWN |
107 | |
108 | A distribution *cannot* specify that it uses codehosting. Currently there's |
109 | |
110 | === modified file 'lib/lp/registry/doc/product.txt' |
111 | --- lib/lp/registry/doc/product.txt 2010-08-06 14:49:35 +0000 |
112 | +++ lib/lp/registry/doc/product.txt 2010-08-22 20:27:49 +0000 |
113 | @@ -501,15 +501,11 @@ |
114 | False |
115 | >>> print firefox.codehosting_usage.name |
116 | UNKNOWN |
117 | - >>> print firefox.uses_launchpad |
118 | - False |
119 | >>> firefox.development_focus.branch = factory.makeBranch(product=firefox) |
120 | >>> print firefox.official_codehosting |
121 | True |
122 | >>> print firefox.codehosting_usage.name |
123 | LAUNCHPAD |
124 | - >>> print firefox.uses_launchpad |
125 | - True |
126 | |
127 | We can also find all the products that have branches. |
128 | |
129 | |
130 | === modified file 'lib/lp/registry/model/distribution.py' |
131 | --- lib/lp/registry/model/distribution.py 2010-08-20 20:31:18 +0000 |
132 | +++ lib/lp/registry/model/distribution.py 2010-08-22 20:27:49 +0000 |
133 | @@ -63,6 +63,11 @@ |
134 | ILaunchpadCelebrities, |
135 | ) |
136 | from canonical.launchpad.interfaces.lpstorm import IStore |
137 | +from lp.registry.model.announcement import MakesAnnouncements |
138 | +from lp.soyuz.model.archive import Archive |
139 | +from lp.soyuz.model.binarypackagename import BinaryPackageName |
140 | +from lp.soyuz.model.binarypackagerelease import ( |
141 | + BinaryPackageRelease) |
142 | from canonical.launchpad.validators.name import ( |
143 | sanitize_name, |
144 | valid_name, |
145 | @@ -273,7 +278,6 @@ |
146 | else: |
147 | alsoProvides(self, IDerivativeDistribution) |
148 | |
149 | - |
150 | @property |
151 | def uploaders(self): |
152 | """See `IDistribution`.""" |
153 | @@ -310,21 +314,85 @@ |
154 | return True in (self.official_malone, self.official_rosetta, |
155 | self.official_blueprints, self.official_answers) |
156 | |
157 | - answers_usage = EnumCol( |
158 | + _answers_usage = EnumCol( |
159 | dbName="answers_usage", notNull=True, |
160 | schema=ServiceUsage, |
161 | default=ServiceUsage.UNKNOWN) |
162 | - blueprints_usage = EnumCol( |
163 | + |
164 | + def _get_answers_usage(self): |
165 | + if self._answers_usage != ServiceUsage.UNKNOWN: |
166 | + # If someone has set something with the enum, use it. |
167 | + return self._answers_usage |
168 | + elif self.official_answers: |
169 | + return ServiceUsage.LAUNCHPAD |
170 | + return self._answers_usage |
171 | + |
172 | + def _set_answers_usage(self, val): |
173 | + self._answers_usage = val |
174 | + if val == ServiceUsage.LAUNCHPAD: |
175 | + self.official_answers = True |
176 | + else: |
177 | + self.official_answers = False |
178 | + |
179 | + answers_usage = property( |
180 | + _get_answers_usage, |
181 | + _set_answers_usage, |
182 | + doc="Indicates if the product uses the answers service.") |
183 | + |
184 | + _blueprints_usage = EnumCol( |
185 | dbName="blueprints_usage", notNull=True, |
186 | schema=ServiceUsage, |
187 | default=ServiceUsage.UNKNOWN) |
188 | - translations_usage = EnumCol( |
189 | + |
190 | + def _get_blueprints_usage(self): |
191 | + if self._blueprints_usage != ServiceUsage.UNKNOWN: |
192 | + # If someone has set something with the enum, use it. |
193 | + return self._blueprints_usage |
194 | + elif self.official_blueprints: |
195 | + return ServiceUsage.LAUNCHPAD |
196 | + return self._blueprints_usage |
197 | + |
198 | + def _set_blueprints_usage(self, val): |
199 | + self._blueprints_usage = val |
200 | + if val == ServiceUsage.LAUNCHPAD: |
201 | + self.official_blueprints = True |
202 | + else: |
203 | + self.official_blueprints = False |
204 | + |
205 | + blueprints_usage = property( |
206 | + _get_blueprints_usage, |
207 | + _set_blueprints_usage, |
208 | + doc="Indicates if the product uses the blueprints service.") |
209 | + |
210 | + _translations_usage = EnumCol( |
211 | dbName="translations_usage", notNull=True, |
212 | schema=ServiceUsage, |
213 | default=ServiceUsage.UNKNOWN) |
214 | + |
215 | + def _get_translations_usage(self): |
216 | + if self._translations_usage != ServiceUsage.UNKNOWN: |
217 | + # If someone has set something with the enum, use it. |
218 | + return self._translations_usage |
219 | + elif self.official_rosetta: |
220 | + return ServiceUsage.LAUNCHPAD |
221 | + return self._translations_usage |
222 | + |
223 | + def _set_translations_usage(self, val): |
224 | + self._translations_usage = val |
225 | + if val == ServiceUsage.LAUNCHPAD: |
226 | + self.official_rosetta = True |
227 | + else: |
228 | + self.official_rosetta = False |
229 | + |
230 | + translations_usage = property( |
231 | + _get_translations_usage, |
232 | + _set_translations_usage, |
233 | + doc="Indicates if the product uses the translations service.") |
234 | + |
235 | @property |
236 | def codehosting_usage(self): |
237 | return ServiceUsage.NOT_APPLICABLE |
238 | + |
239 | @property |
240 | def bug_tracking_usage(self): |
241 | if not self.official_malone: |
242 | @@ -551,9 +619,9 @@ |
243 | if not self.full_functionality: |
244 | return None |
245 | |
246 | - urls = {'http_base_url' : http_base_url, |
247 | - 'ftp_base_url' : ftp_base_url, |
248 | - 'rsync_base_url' : rsync_base_url} |
249 | + urls = {'http_base_url': http_base_url, |
250 | + 'ftp_base_url': ftp_base_url, |
251 | + 'rsync_base_url': rsync_base_url} |
252 | for name, value in urls.items(): |
253 | if value is not None: |
254 | urls[name] = IDistributionMirror[name].normalize(value) |
255 | @@ -766,7 +834,7 @@ |
256 | |
257 | # filter based on completion. see the implementation of |
258 | # Specification.is_complete() for more details |
259 | - completeness = Specification.completeness_clause |
260 | + completeness = Specification.completeness_clause |
261 | |
262 | if SpecificationFilter.COMPLETE in filter: |
263 | query += ' AND ( %s ) ' % completeness |
264 | @@ -1091,15 +1159,15 @@ |
265 | find_spec = ( |
266 | DistributionSourcePackageCache, |
267 | SourcePackageName, |
268 | - SQL('rank(fti, ftq(%s)) AS rank' % sqlvalues(text)) |
269 | + SQL('rank(fti, ftq(%s)) AS rank' % sqlvalues(text)), |
270 | ) |
271 | origin = [ |
272 | DistributionSourcePackageCache, |
273 | Join( |
274 | SourcePackageName, |
275 | DistributionSourcePackageCache.sourcepackagename == |
276 | - SourcePackageName.id |
277 | - ) |
278 | + SourcePackageName.id, |
279 | + ), |
280 | ] |
281 | |
282 | publishing_condition = '' |
283 | @@ -1140,8 +1208,7 @@ |
284 | quote(text), quote_like(text), has_packaging_condition, |
285 | publishing_condition) |
286 | dsp_caches_with_ranks = store.using(*origin).find( |
287 | - find_spec, condition |
288 | - ).order_by('rank DESC') |
289 | + find_spec, condition).order_by('rank DESC') |
290 | |
291 | return dsp_caches_with_ranks |
292 | |
293 | @@ -1160,8 +1227,7 @@ |
294 | cache, source_package_name, rank = result |
295 | return DistributionSourcePackage( |
296 | self, |
297 | - source_package_name |
298 | - ) |
299 | + source_package_name) |
300 | |
301 | # Return the decorated result set so the consumer of these |
302 | # results will only see DSPs |
303 | @@ -1225,7 +1291,7 @@ |
304 | extra_clauses = ( |
305 | BinaryPackageRelease.binarypackagenameID == |
306 | DistroSeriesPackageCache.binarypackagenameID, |
307 | - Match(search_vector_column, query_function) |
308 | + Match(search_vector_column, query_function), |
309 | ) |
310 | where_spec = (self._binaryPackageSearchClause + extra_clauses) |
311 | |
312 | @@ -1481,11 +1547,11 @@ |
313 | # XXX Julian 2007-08-16 |
314 | # These component names should be Soyuz-wide constants. |
315 | componentMapToArchivePurpose = { |
316 | - 'main' : ArchivePurpose.PRIMARY, |
317 | - 'restricted' : ArchivePurpose.PRIMARY, |
318 | - 'universe' : ArchivePurpose.PRIMARY, |
319 | - 'multiverse' : ArchivePurpose.PRIMARY, |
320 | - 'partner' : ArchivePurpose.PARTNER, |
321 | + 'main': ArchivePurpose.PRIMARY, |
322 | + 'restricted': ArchivePurpose.PRIMARY, |
323 | + 'universe': ArchivePurpose.PRIMARY, |
324 | + 'multiverse': ArchivePurpose.PRIMARY, |
325 | + 'partner': ArchivePurpose.PARTNER, |
326 | 'contrib': ArchivePurpose.PRIMARY, |
327 | 'non-free': ArchivePurpose.PRIMARY, |
328 | } |
329 | |
330 | === modified file 'lib/lp/registry/model/product.py' |
331 | --- lib/lp/registry/model/product.py 2010-08-22 20:27:48 +0000 |
332 | +++ lib/lp/registry/model/product.py 2010-08-22 20:27:49 +0000 |
333 | @@ -39,10 +39,6 @@ |
334 | from zope.security.proxy import removeSecurityProxy |
335 | |
336 | from canonical.cachedproperty import cachedproperty |
337 | -<<<<<<< TREE |
338 | -======= |
339 | -from lazr.delegates import delegates |
340 | ->>>>>>> MERGE-SOURCE |
341 | from canonical.database.constants import UTC_NOW |
342 | from canonical.database.datetimecol import UtcDateTimeCol |
343 | from canonical.database.enumcol import EnumCol |
344 | @@ -67,7 +63,6 @@ |
345 | MAIN_STORE, |
346 | ) |
347 | from canonical.launchpad.webapp.sorting import sorted_version_numbers |
348 | -from canonical.lazr.utils import safe_hasattr |
349 | from lp.answers.interfaces.faqtarget import IFAQTarget |
350 | from lp.answers.interfaces.questioncollection import ( |
351 | QUESTION_STATUS_DEFAULT_SEARCH, |
352 | @@ -323,24 +318,26 @@ |
353 | # XXX Need to remove official_codehosting column from Product |
354 | # table. |
355 | return self.development_focus.branch is not None |
356 | + |
357 | @property |
358 | def official_anything(self): |
359 | return True in (self.official_malone, self.official_rosetta, |
360 | self.official_blueprints, self.official_answers, |
361 | self.official_codehosting) |
362 | |
363 | - answers_usage = EnumCol( |
364 | + _answers_usage = EnumCol( |
365 | dbName="answers_usage", notNull=True, |
366 | schema=ServiceUsage, |
367 | default=ServiceUsage.UNKNOWN) |
368 | - blueprints_usage = EnumCol( |
369 | + _blueprints_usage = EnumCol( |
370 | dbName="blueprints_usage", notNull=True, |
371 | schema=ServiceUsage, |
372 | default=ServiceUsage.UNKNOWN) |
373 | - translations_usage = EnumCol( |
374 | + _translations_usage = EnumCol( |
375 | dbName="translations_usage", notNull=True, |
376 | schema=ServiceUsage, |
377 | default=ServiceUsage.UNKNOWN) |
378 | + |
379 | @property |
380 | def codehosting_usage(self): |
381 | if self.development_focus.branch is None: |
382 | @@ -350,6 +347,7 @@ |
383 | elif self.development_focus.branch.branch_type == BranchType.MIRRORED: |
384 | return ServiceUsage.EXTERNAL |
385 | return ServiceUsage.NOT_APPLICABLE |
386 | + |
387 | @property |
388 | def bug_tracking_usage(self): |
389 | if self.official_malone: |
390 | @@ -358,6 +356,7 @@ |
391 | return ServiceUsage.UNKNOWN |
392 | else: |
393 | return ServiceUsage.EXTERNAL |
394 | + |
395 | @property |
396 | def uses_launchpad(self): |
397 | """Does this distribution actually use Launchpad?""" |
398 | @@ -573,6 +572,66 @@ |
399 | super(Product, self).__storm_invalidated__() |
400 | self._cached_licenses = None |
401 | |
402 | + def _get_answers_usage(self): |
403 | + if self._answers_usage != ServiceUsage.UNKNOWN: |
404 | + # If someone has set something with the enum, use it. |
405 | + return self._answers_usage |
406 | + elif self.official_answers: |
407 | + return ServiceUsage.LAUNCHPAD |
408 | + return self._answers_usage |
409 | + |
410 | + def _set_answers_usage(self, val): |
411 | + self._answers_usage = val |
412 | + if val == ServiceUsage.LAUNCHPAD: |
413 | + self.official_answers = True |
414 | + else: |
415 | + self.official_answers = False |
416 | + |
417 | + answers_usage = property( |
418 | + _get_answers_usage, |
419 | + _set_answers_usage, |
420 | + doc="Indicates if the product uses the answers service.") |
421 | + |
422 | + def _get_blueprints_usage(self): |
423 | + if self._blueprints_usage != ServiceUsage.UNKNOWN: |
424 | + # If someone has set something with the enum, use it. |
425 | + return self._blueprints_usage |
426 | + elif self.official_blueprints: |
427 | + return ServiceUsage.LAUNCHPAD |
428 | + return self._blueprints_usage |
429 | + |
430 | + def _set_blueprints_usage(self, val): |
431 | + self._blueprints_usage = val |
432 | + if val == ServiceUsage.LAUNCHPAD: |
433 | + self.official_blueprints = True |
434 | + else: |
435 | + self.official_blueprints = False |
436 | + |
437 | + blueprints_usage = property( |
438 | + _get_blueprints_usage, |
439 | + _set_blueprints_usage, |
440 | + doc="Indicates if the product uses the blueprints service.") |
441 | + |
442 | + def _get_translations_usage(self): |
443 | + if self._translations_usage != ServiceUsage.UNKNOWN: |
444 | + # If someone has set something with the enum, use it. |
445 | + return self._translations_usage |
446 | + elif self.official_rosetta: |
447 | + return ServiceUsage.LAUNCHPAD |
448 | + return self._translations_usage |
449 | + |
450 | + def _set_translations_usage(self, val): |
451 | + self._translations_usage = val |
452 | + if val == ServiceUsage.LAUNCHPAD: |
453 | + self.official_rosetta = True |
454 | + else: |
455 | + self.official_rosetta = False |
456 | + |
457 | + translations_usage = property( |
458 | + _get_translations_usage, |
459 | + _set_translations_usage, |
460 | + doc="Indicates if the product uses the translations service.") |
461 | + |
462 | def _getLicenses(self): |
463 | """Get the licenses as a tuple.""" |
464 | if self._cached_licenses is None: |
465 | |
466 | === added file 'lib/lp/registry/tests/test_service_usage.py' |
467 | --- lib/lp/registry/tests/test_service_usage.py 1970-01-01 00:00:00 +0000 |
468 | +++ lib/lp/registry/tests/test_service_usage.py 2010-08-22 20:27:49 +0000 |
469 | @@ -0,0 +1,174 @@ |
470 | +# Copyright 2010 Canonical Ltd. This software is licensed under the |
471 | +# GNU Affero General Public License version 3 (see the file LICENSE). |
472 | + |
473 | +__metaclass__ = type |
474 | + |
475 | +import unittest |
476 | + |
477 | +from canonical.testing import DatabaseFunctionalLayer |
478 | + |
479 | +from lp.app.enums import ServiceUsage |
480 | +from lp.testing import ( |
481 | + login_person, |
482 | + TestCaseWithFactory, |
483 | + ) |
484 | + |
485 | + |
486 | +class UsageEnumsMixin(object): |
487 | + """Base class for testing the UsageEnums on their pillars.""" |
488 | + |
489 | + def setUp(self): |
490 | + self.target = None |
491 | + |
492 | + def test_answers_usage_no_data(self): |
493 | + # By default, we don't know anything about a target |
494 | + self.assertEqual( |
495 | + ServiceUsage.UNKNOWN, |
496 | + self.target.answers_usage) |
497 | + |
498 | + def test_answers_usage_using_bool(self): |
499 | + # If the old bool says they use Launchpad, return LAUNCHPAD |
500 | + # if the ServiceUsage is unknown. |
501 | + login_person(self.target.owner) |
502 | + self.target.official_answers = True |
503 | + self.assertEqual( |
504 | + ServiceUsage.LAUNCHPAD, |
505 | + self.target.answers_usage) |
506 | + |
507 | + def test_answers_usage_with_enum_data(self): |
508 | + # If the enum has something other than UNKNOWN as its status, |
509 | + # use that. |
510 | + login_person(self.target.owner) |
511 | + self.target.answers_usage = ServiceUsage.EXTERNAL |
512 | + self.assertEqual( |
513 | + ServiceUsage.EXTERNAL, |
514 | + self.target.answers_usage) |
515 | + |
516 | + def test_answers_setter(self): |
517 | + login_person(self.target.owner) |
518 | + self.target.official_answers = True |
519 | + self.target.answers_usage = ServiceUsage.EXTERNAL |
520 | + self.assertEqual( |
521 | + False, |
522 | + self.target.official_answers) |
523 | + self.target.answers_usage = ServiceUsage.LAUNCHPAD |
524 | + self.assertEqual( |
525 | + True, |
526 | + self.target.official_answers) |
527 | + |
528 | + def test_codehosting_usage(self): |
529 | + # Only test get for codehosting; this has no setter because the |
530 | + # state is derived from other data. |
531 | + self.assertEqual( |
532 | + ServiceUsage.UNKNOWN, |
533 | + self.target.codehosting_usage) |
534 | + |
535 | + def test_translations_usage_no_data(self): |
536 | + # By default, we don't know anything about a target |
537 | + self.assertEqual( |
538 | + ServiceUsage.UNKNOWN, |
539 | + self.target.translations_usage) |
540 | + |
541 | + def test_translations_usage_using_bool(self): |
542 | + # If the old bool says they use Launchpad, return LAUNCHPAD |
543 | + # if the ServiceUsage is unknown. |
544 | + login_person(self.target.owner) |
545 | + self.target.official_rosetta = True |
546 | + self.assertEqual( |
547 | + ServiceUsage.LAUNCHPAD, |
548 | + self.target.translations_usage) |
549 | + |
550 | + def test_translations_usage_with_enum_data(self): |
551 | + # If the enum has something other than UNKNOWN as its status, |
552 | + # use that. |
553 | + login_person(self.target.owner) |
554 | + self.target.translations_usage = ServiceUsage.EXTERNAL |
555 | + self.assertEqual( |
556 | + ServiceUsage.EXTERNAL, |
557 | + self.target.translations_usage) |
558 | + |
559 | + def test_translations_setter(self): |
560 | + login_person(self.target.owner) |
561 | + self.target.official_rosetta = True |
562 | + self.target.translations_usage = ServiceUsage.EXTERNAL |
563 | + self.assertEqual( |
564 | + False, |
565 | + self.target.official_rosetta) |
566 | + self.target.translations_usage = ServiceUsage.LAUNCHPAD |
567 | + self.assertEqual( |
568 | + True, |
569 | + self.target.official_rosetta) |
570 | + |
571 | + def test_bug_tracking_usage(self): |
572 | + # Only test get for bug_tracking; this has no setter because the |
573 | + # state is derived from other data. |
574 | + self.assertEqual( |
575 | + ServiceUsage.UNKNOWN, |
576 | + self.target.bug_tracking_usage) |
577 | + |
578 | + def test_blueprints_usage_no_data(self): |
579 | + # By default, we don't know anything about a target |
580 | + self.assertEqual( |
581 | + ServiceUsage.UNKNOWN, |
582 | + self.target.blueprints_usage) |
583 | + |
584 | + def test_blueprints_usage_using_bool(self): |
585 | + # If the old bool says they use Launchpad, return LAUNCHPAD |
586 | + # if the ServiceUsage is unknown. |
587 | + login_person(self.target.owner) |
588 | + self.target.official_blueprints = True |
589 | + self.assertEqual( |
590 | + ServiceUsage.LAUNCHPAD, |
591 | + self.target.blueprints_usage) |
592 | + |
593 | + def test_blueprints_usage_with_enum_data(self): |
594 | + # If the enum has something other than UNKNOWN as its status, |
595 | + # use that. |
596 | + login_person(self.target.owner) |
597 | + self.target.blueprints_usage = ServiceUsage.EXTERNAL |
598 | + self.assertEqual( |
599 | + ServiceUsage.EXTERNAL, |
600 | + self.target.blueprints_usage) |
601 | + |
602 | + def test_blueprints_setter(self): |
603 | + login_person(self.target.owner) |
604 | + self.target.official_blueprints = True |
605 | + self.target.blueprints_usage = ServiceUsage.EXTERNAL |
606 | + self.assertEqual( |
607 | + False, |
608 | + self.target.official_blueprints) |
609 | + self.target.blueprints_usage = ServiceUsage.LAUNCHPAD |
610 | + self.assertEqual( |
611 | + True, |
612 | + self.target.official_blueprints) |
613 | + |
614 | + |
615 | +class TestDistributionUsageEnums(TestCaseWithFactory, UsageEnumsMixin): |
616 | + """Tests the usage enums for the distribution.""" |
617 | + |
618 | + layer = DatabaseFunctionalLayer |
619 | + |
620 | + def setUp(self): |
621 | + super(TestDistributionUsageEnums, self).setUp() |
622 | + self.target = self.factory.makeDistribution() |
623 | + |
624 | + def test_codehosting_usage(self): |
625 | + # This method must be changed for Distribution, because its |
626 | + # enum defaults to different data. |
627 | + self.assertEqual( |
628 | + ServiceUsage.NOT_APPLICABLE, |
629 | + self.target.codehosting_usage) |
630 | + |
631 | + |
632 | +class TestProductUsageEnums(TestCaseWithFactory, UsageEnumsMixin): |
633 | + """Tests the usage enums for the product.""" |
634 | + |
635 | + layer = DatabaseFunctionalLayer |
636 | + |
637 | + def setUp(self): |
638 | + super(TestProductUsageEnums, self).setUp() |
639 | + self.target = self.factory.makeProduct() |
640 | + |
641 | + |
642 | +def test_suite(): |
643 | + return unittest.TestLoader().loadTestsFromName(__name__) |
Hi Jon,
In def test_codehostin g_usage( self): why do you make a new distribution instead of using self.distribution?
Same question for def test_bug_ tracking_ usage(self) :
We discussed on IRC refactoring the tests since they are mostly the same.
Otherwise this branch rocks. Look forward to seeing it landed.