Merge lp:~jcsackett/launchpad/deprecate-official_rosetta into lp:launchpad

Proposed by j.c.sackett
Status: Merged
Approved by: j.c.sackett
Approved revision: no longer in the source branch.
Merged at revision: 11520
Proposed branch: lp:~jcsackett/launchpad/deprecate-official_rosetta
Merge into: lp:launchpad
Diff against target: 3172 lines (+649/-426)
51 files modified
lib/lp/app/enums.py (+6/-1)
lib/lp/registry/browser/distribution.py (+2/-1)
lib/lp/registry/browser/pillar.py (+11/-8)
lib/lp/registry/browser/tests/pillar-views.txt (+4/-3)
lib/lp/registry/browser/tests/productseries-views.txt (+6/-4)
lib/lp/registry/doc/distribution.txt (+125/-114)
lib/lp/registry/doc/product.txt (+62/-44)
lib/lp/registry/doc/project.txt (+24/-15)
lib/lp/registry/model/projectgroup.py (+4/-1)
lib/lp/testing/factory.py (+7/-4)
lib/lp/translations/browser/potemplate.py (+4/-2)
lib/lp/translations/browser/product.py (+11/-8)
lib/lp/translations/browser/tests/language-views.txt (+4/-1)
lib/lp/translations/browser/tests/test_breadcrumbs.py (+3/-2)
lib/lp/translations/doc/potmsgset.txt (+59/-33)
lib/lp/translations/doc/translationimportqueue.txt (+54/-25)
lib/lp/translations/doc/translationmessage-destroy.txt (+10/-5)
lib/lp/translations/doc/translations-export-to-branch.txt (+10/-6)
lib/lp/translations/doc/translationsoverview.txt (+14/-6)
lib/lp/translations/model/potemplate.py (+11/-10)
lib/lp/translations/model/potmsgset.py (+8/-7)
lib/lp/translations/model/translationsoverview.py (+6/-3)
lib/lp/translations/model/translationsperson.py (+4/-0)
lib/lp/translations/scripts/translations_to_branch.py (+3/-0)
lib/lp/translations/stories/buildfarm/xx-build-summary.txt (+8/-4)
lib/lp/translations/stories/importqueue/xx-entry-details.txt (+9/-5)
lib/lp/translations/stories/productseries/xx-productseries-export-to-branch.txt (+9/-6)
lib/lp/translations/stories/productseries/xx-productseries-translations.txt (+5/-3)
lib/lp/translations/stories/standalone/custom-language-codes.txt (+5/-3)
lib/lp/translations/stories/standalone/xx-potemplate-index.txt (+28/-12)
lib/lp/translations/stories/standalone/xx-product-export.txt (+9/-5)
lib/lp/translations/stories/standalone/xx-product-translations.txt (+0/-1)
lib/lp/translations/stories/standalone/xx-template-description-escaping.txt (+3/-1)
lib/lp/translations/stories/translationfocus/xx-product-translationfocus.txt (+5/-3)
lib/lp/translations/stories/translationgroups/xx-change-translation-policy.txt (+5/-1)
lib/lp/translations/templates/product-portlet-not-using-launchpad.pt (+1/-1)
lib/lp/translations/templates/productseries-translations.pt (+1/-1)
lib/lp/translations/tests/test_autoapproval.py (+9/-8)
lib/lp/translations/tests/test_empty_messages.py (+13/-11)
lib/lp/translations/tests/test_hastranslationtemplates.py (+5/-4)
lib/lp/translations/tests/test_pofile.py (+17/-14)
lib/lp/translations/tests/test_potemplate.py (+3/-2)
lib/lp/translations/tests/test_potmsgset.py (+11/-8)
lib/lp/translations/tests/test_productserieslanguage.py (+9/-4)
lib/lp/translations/tests/test_shared_potemplate.py (+3/-2)
lib/lp/translations/tests/test_suggestions.py (+10/-4)
lib/lp/translations/tests/test_translatablemessage.py (+9/-7)
lib/lp/translations/tests/test_translatedlanguage.py (+5/-2)
lib/lp/translations/tests/test_translations_to_review.py (+6/-3)
lib/lp/translations/windmill/tests/test_documentation_links.py (+2/-1)
lib/lp/translations/windmill/tests/test_import_queue.py (+7/-7)
To merge this branch: bzr merge lp:~jcsackett/launchpad/deprecate-official_rosetta
Reviewer Review Type Date Requested Status
Leonard Richardson (community) Approve
Review via email: mp+34229@code.launchpad.net

Commit message

Replaces use of official_rosetta with translations_usage where possible, so the richer data provided by the enum can be used to drive decisions.

Description of the change

= Summary =

Replaces, where possible, usage of official_rosetta with the translations_usage property.

== Proposed fix ==

Where code uses official_rosetta, use translations_usage instead so that we can take advantage of richer data.

== Pre-implementation notes ==

Spoke with Curtis Hovey (sinzui) and Brad Crittenden (bac).

== Implementation details ==

As in Proposed fix.

SQL queries using official_rosetta have been left alone until data migration occurs.

== Tests ==

No new tests written.

To fully test the refactor:

bin/test -m lib.lp.registry
bin/test -m lib.lp.translations

== Demo and Q/A ==

In Launchpad.dev, nothing should crash when reviewing translations or performing translation related actions.

= Launchpad lint =

This touched enough old files that the lint output is huge. I will fix all valid lint errors before committing, but I didn't want to pollute the diff too much nor make this MP a wall of text.

To post a comment you must log in.
Revision history for this message
Leonard Richardson (leonardr) wrote :

Needs bugs for the two problems marked with XXXes (lines 422 et al, and line 453). Other than that, it looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/app/enums.py'
2--- lib/lp/app/enums.py 2010-08-20 20:31:18 +0000
3+++ lib/lp/app/enums.py 2010-09-09 15:34:46 +0000
4@@ -1,11 +1,12 @@
5 # Copyright 2010 Canonical Ltd. This software is licensed under the
6 # GNU Affero General Public License version 3 (see the file LICENSE).
7
8-"""Enumerations used in the lp/app modules."""
9+"""Enumerations and related utilities used in the lp/app modules."""
10
11 __metaclass__ = type
12 __all__ = [
13 'ServiceUsage',
14+ 'service_uses_launchpad',
15 ]
16
17 from lazr.enum import (
18@@ -45,3 +46,7 @@
19
20 The pillar does not use this type of service in Launchpad or externally.
21 """)
22+
23+
24+def service_uses_launchpad(usage_enum):
25+ return usage_enum == ServiceUsage.LAUNCHPAD
26
27=== modified file 'lib/lp/registry/browser/distribution.py'
28--- lib/lp/registry/browser/distribution.py 2010-09-03 03:12:39 +0000
29+++ lib/lp/registry/browser/distribution.py 2010-09-09 15:34:46 +0000
30@@ -74,6 +74,7 @@
31 from canonical.launchpad.webapp.breadcrumb import Breadcrumb
32 from canonical.launchpad.webapp.interfaces import ILaunchBag
33 from canonical.widgets.image import ImageChangeWidget
34+from lp.app.enums import service_uses_launchpad
35 from lp.answers.browser.faqtarget import FAQTargetNavigationMixin
36 from lp.answers.browser.questiontarget import (
37 QuestionTargetFacetMixin,
38@@ -135,7 +136,7 @@
39 if self.context.codehosting_usage == ServiceUsage.LAUNCHPAD:
40 url = canonical_url(self.context, rootsite='code')
41 uses.append(href_template % (url, 'Branches'))
42- if self.context.official_rosetta:
43+ if service_uses_launchpad(self.context.translations_usage):
44 url = canonical_url(self.context, rootsite='translations')
45 uses.append(href_template % (url, 'Translations'))
46
47
48=== modified file 'lib/lp/registry/browser/pillar.py'
49--- lib/lp/registry/browser/pillar.py 2010-09-03 03:12:39 +0000
50+++ lib/lp/registry/browser/pillar.py 2010-09-09 15:34:46 +0000
51@@ -30,7 +30,10 @@
52 nearest,
53 )
54 from canonical.launchpad.webapp.tales import MenuAPI
55-from lp.app.enums import ServiceUsage
56+from lp.app.enums import (
57+ ServiceUsage,
58+ service_uses_launchpad,
59+ )
60 from lp.app.interfaces.launchpad import IServiceUsage
61 from lp.registry.browser.structuralsubscription import (
62 StructuralSubscriptionMenuMixin,
63@@ -72,7 +75,7 @@
64 def help_translate(self):
65 return Link(
66 '', 'Help translate', site='translations', icon='translations',
67- enabled=self.pillar.official_rosetta)
68+ enabled=service_uses_launchpad(self.pillar.translations_usage))
69
70 def submit_code(self):
71 if self.pillar.codehosting_usage in [
72@@ -104,7 +107,7 @@
73 self.official_malone = False
74 self.official_answers = False
75 self.official_blueprints = False
76- self.official_rosetta = False
77+ self.translations_usage = ServiceUsage.UNKNOWN
78 self.codehosting_usage = ServiceUsage.UNKNOWN
79 pillar = nearest(self.context, IPillar)
80 if IProjectGroup.providedBy(pillar):
81@@ -121,7 +124,7 @@
82 self.codehosting_usage = distribution.codehosting_usage
83 elif IDistributionSourcePackage.providedBy(self.context):
84 self.official_blueprints = False
85- self.official_rosetta = False
86+ self.translations_usage = ServiceUsage.UNKNOWN
87 else:
88 # The context is used by all apps.
89 pass
90@@ -136,8 +139,7 @@
91 self.official_answers = True
92 if pillar.official_blueprints:
93 self.official_blueprints = True
94- if pillar.official_rosetta:
95- self.official_rosetta = True
96+ self.translations_usage = IServiceUsage(pillar).translations_usage
97 self.codehosting_usage = IServiceUsage(pillar).codehosting_usage
98
99 @property
100@@ -145,8 +147,9 @@
101 """This `IPillar` uses Launchpad."""
102 return (
103 self.official_malone or self.official_answers
104- or self.official_blueprints or self.official_rosetta
105- or self.codehosting_usage == ServiceUsage.LAUNCHPAD)
106+ or self.official_blueprints
107+ or service_uses_launchpad(self.translations_usage)
108+ or service_uses_launchpad(self.codehosting_usage))
109
110 @property
111 def enabled_links(self):
112
113=== modified file 'lib/lp/registry/browser/tests/pillar-views.txt'
114--- lib/lp/registry/browser/tests/pillar-views.txt 2010-08-27 17:45:57 +0000
115+++ lib/lp/registry/browser/tests/pillar-views.txt 2010-09-09 15:34:46 +0000
116@@ -35,8 +35,8 @@
117 True
118 >>> view.official_answers
119 True
120- >>> view.official_rosetta
121- False
122+ >>> view.translations_usage.name
123+ 'UNKNOWN'
124 >>> view.official_blueprints
125 False
126 >>> view.codehosting_usage.name
127@@ -230,9 +230,10 @@
128 set the links. Despite the fact that the distribution uses blueprints,
129 and translations those links are not enabled for DistributionSourcePackages.
130
131+ >>> from lp.app.enums import ServiceUsage
132 >>> login_person(distribution.owner)
133 >>> distribution.official_blueprints = True
134- >>> distribution.official_rosetta = True
135+ >>> distribution.translations_usage = ServiceUsage.LAUNCHPAD
136 >>> package = factory.makeDistributionSourcePackage(
137 ... sourcepackagename="box",
138 ... distribution=distribution)
139
140=== modified file 'lib/lp/registry/browser/tests/productseries-views.txt'
141--- lib/lp/registry/browser/tests/productseries-views.txt 2010-09-03 06:06:40 +0000
142+++ lib/lp/registry/browser/tests/productseries-views.txt 2010-09-09 15:34:46 +0000
143@@ -23,11 +23,12 @@
144 The ProductSeries involvement view uses the ProductSeriesInvolvedMenu when
145 rendering links:
146
147+ >>> from lp.app.enums import ServiceUsage
148 >>> login_person(product.owner)
149 >>> product.official_answers = True
150 >>> product.official_blueprints = True
151 >>> product.official_malone = True
152- >>> product.official_rosetta = True
153+ >>> product.translations_usage = ServiceUsage.LAUNCHPAD
154 >>> view = create_view(series, '+get-involved')
155
156 # official_answers is always false for product series.
157@@ -37,10 +38,11 @@
158 True
159 >>> print view.official_malone
160 True
161- >>> print view.official_rosetta
162- True
163+ >>> print view.translations_usage.name
164+ LAUNCHPAD
165 >>> print view.codehosting_usage.name
166 UNKNOWN
167+
168 >>> for link in view.enabled_links:
169 ... print link.url
170 http://bugs.launchpad.dev/app/simple/+filebug
171@@ -476,7 +478,7 @@
172 A series cannot be deleted if it is has translation templates.
173
174 >>> translated_series = factory.makeProductSeries(product=product)
175- >>> product.official_rosetta = True
176+ >>> product.translations_usage = ServiceUsage.LAUNCHPAD
177 >>> po_template = factory.makePOTemplate(
178 ... name='gibberish', productseries=translated_series)
179 >>> translated_view = create_initialized_view(
180
181=== modified file 'lib/lp/registry/doc/distribution.txt'
182--- lib/lp/registry/doc/distribution.txt 2010-08-23 00:51:30 +0000
183+++ lib/lp/registry/doc/distribution.txt 2010-09-09 15:34:46 +0000
184@@ -1,4 +1,5 @@
185-= Distributions =
186+Distributions
187+=============
188
189 From the DerivationOverview spec
190 <https://launchpad.canonical.com/DerivationOverview>:
191@@ -143,7 +144,8 @@
192 False
193
194
195-== Distribution Sorting ==
196+Distribution Sorting
197+--------------------
198
199 If you ask for all the distributions in the DistributionSet you should get
200 Ubuntu (and all flavours of it) first and the rest alphabetically:
201@@ -164,7 +166,8 @@
202 True
203
204
205-=== Searching for DistributionSourcePackages ===
206+Searching for DistributionSourcePackages
207+........................................
208
209 The distribution also allows you to look for source packages that match
210 a certain string through the magic of fti. For instance:
211@@ -232,7 +235,8 @@
212 DistributionSourcePackage: alsa-utils
213
214
215-=== Searching for binary packages ===
216+Searching for binary packages
217+.............................
218
219 There are two useful functions for searching binary packages related
220 to the distribution, searchBinaryPackages() and searchBinaryPackagesFTI().
221@@ -291,7 +295,8 @@
222 [u'mozilla-firefox']
223
224
225-=== Finding distroseriess and pockets from distribution names ===
226+Finding distroseriess and pockets from distribution names
227+.........................................................
228
229 A distribution knows what distroseriess it has. Those distroseriess have
230 pockets which have suffixes used by the archive publisher. Because we
231@@ -336,26 +341,27 @@
232 NotFoundError: 'hoary-bullshit'
233
234
235-=== Upload related stuff ===
236+Upload related stuff
237+....................
238
239 When uploading to a distribution we need to query its uploaders. Each
240 uploader record is in fact an ArchivePermission record that tells us
241 what component is uploadable to by what person or group of people.
242
243- >>> from operator import attrgetter
244- >>> for permission in sorted(
245- ... ubuntu.uploaders, key=attrgetter("id")):
246- ... assert not permission.archive.is_ppa
247- ... print permission.component.name
248- ... print permission.person.displayname
249- universe
250- Ubuntu Team
251- restricted
252- Ubuntu Team
253- main
254- Ubuntu Team
255- partner
256- Canonical Partner Developers
257+ >>> from operator import attrgetter
258+ >>> for permission in sorted(
259+ ... ubuntu.uploaders, key=attrgetter("id")):
260+ ... assert not permission.archive.is_ppa
261+ ... print permission.component.name
262+ ... print permission.person.displayname
263+ universe
264+ Ubuntu Team
265+ restricted
266+ Ubuntu Team
267+ main
268+ Ubuntu Team
269+ partner
270+ Canonical Partner Developers
271
272 When processing an upload we may want to find a file (E.g. if an
273 incomplete source is uploaded).
274@@ -375,7 +381,8 @@
275 AssertionError: searching in an explicitly empty space is pointless
276
277
278-=== Launchpad Usage ===
279+Launchpad Usage
280+...............
281
282 A distribution can specify if it uses Malone, Rosetta, or Answers
283 officially. Ubuntu uses all of them:
284@@ -385,8 +392,8 @@
285 >>> ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
286 >>> ubuntu.official_malone
287 True
288- >>> ubuntu.official_rosetta
289- True
290+ >>> ubuntu.translations_usage.name
291+ 'LAUNCHPAD'
292 >>> ubuntu.official_answers
293 True
294 >>> ubuntu.official_blueprints
295@@ -397,12 +404,12 @@
296 >>> print ubuntu.bug_tracking_usage.name
297 LAUNCHPAD
298
299-While the other attributes track the other official_ attributes.
300+While the other attributes track the other official_ attributes.
301
302 >>> print ubuntu.official_rosetta
303 True
304 >>> print ubuntu.translations_usage.name
305- LAUNCHPAD
306+ LAUNCHPAD
307 >>> print ubuntu.official_answers
308 True
309 >>> print ubuntu.answers_usage.name
310@@ -412,7 +419,8 @@
311 >>> print ubuntu.blueprints_usage.name
312 LAUNCHPAD
313
314-If the official_ attributes are False, the usage enums don't know anything.
315+If the official_ attributes are False and the enum hasn't been set,
316+the usage enums don't know anything.
317
318 >>> login_person(ubuntu.owner.teamowner)
319 >>> ubuntu.official_rosetta = False
320@@ -422,37 +430,35 @@
321 A distribution *cannot* specify that it uses codehosting. Currently there's
322 no way for a distribution to use codehosting.
323
324- >>> ubuntu.official_codehosting
325- False
326- >>> ubuntu.official_codehosting = True
327- Traceback (most recent call last):
328- ForbiddenAttribute: ('official_codehosting', ...)
329-
330+ >>> from lp.app.enums import ServiceUsage
331 >>> print ubuntu.codehosting_usage.name
332 NOT_APPLICABLE
333+ >>> ubuntu.codehosting_usage = ServiceUsage.LAUNCHPAD
334+ Traceback (most recent call last):
335+ AttributeError: can't set attribute...
336
337 While Debian uses none:
338
339 >>> debian = getUtility(ILaunchpadCelebrities).debian
340- >>> debian.official_malone
341- False
342- >>> debian.official_rosetta
343- False
344- >>> debian.official_answers
345- False
346- >>> debian.official_codehosting
347- False
348- >>> debian.official_blueprints
349- False
350+ >>> print debian.bug_tracking_usage.name
351+ UNKNOWN
352+ >>> print debian.translations_usage.name
353+ UNKNOWN
354+ >>> print debian.answers_usage.name
355+ UNKNOWN
356+ >>> print debian.codehosting_usage.name
357+ NOT_APPLICABLE
358+ >>> print debian.blueprints_usage.name
359+ UNKNOWN
360
361 Gentoo only uses Malone
362
363- >>> print gentoo.official_malone
364- True
365- >>> print gentoo.official_rosetta
366- False
367- >>> print gentoo.official_answers
368- False
369+ >>> print gentoo.bug_tracking_usage.name
370+ LAUNCHPAD
371+ >>> print gentoo.translations_usage.name
372+ UNKNOWN
373+ >>> print gentoo.answers_usage.name
374+ UNKNOWN
375
376 Launchpad admins and the distro owner can set these fields.
377
378@@ -464,9 +470,9 @@
379 >>> debian.official_malone = True
380 >>> debian.official_malone
381 True
382- >>> debian.official_rosetta = True
383- >>> debian.official_rosetta
384- True
385+ >>> debian.translations_usage = ServiceUsage.LAUNCHPAD
386+ >>> debian.translations_usage.name
387+ 'LAUNCHPAD'
388
389 >>> debian_owner = factory.makePerson()
390 >>> debian.owner = debian_owner
391@@ -484,12 +490,13 @@
392 >>> debian.official_malone = True
393 Traceback (most recent call last):
394 Unauthorized: (..., 'official_malone', 'launchpad.Edit')
395- >>> debian.official_rosetta = True
396+ >>> debian.translations_usage = ServiceUsage.LAUNCHPAD
397 Traceback (most recent call last):
398- Unauthorized: (..., 'official_rosetta', 'launchpad.Edit')
399-
400-
401-=== Specification Listings ===
402+ Unauthorized: (..., 'translations_usage', 'launchpad.Edit')
403+
404+
405+Specification Listings
406+......................
407
408 We should be able to get lists of specifications in different states
409 related to a distro.
410@@ -497,90 +504,93 @@
411 Basically, we can filter by completeness, and by whether or not the spec is
412 informational.
413
414- >>> kubuntu = distroset.getByName("kubuntu")
415+ >>> kubuntu = distroset.getByName("kubuntu")
416
417- >>> from canonical.launchpad.interfaces import SpecificationFilter
418+ >>> from canonical.launchpad.interfaces import SpecificationFilter
419
420 First, there should be one informational spec for kubuntu, but it is
421 complete so it will not show up unless we explicitly ask for complete specs:
422
423- >>> filter = [SpecificationFilter.INFORMATIONAL]
424- >>> kubuntu.specifications(filter=filter).count()
425- 0
426- >>> filter = [SpecificationFilter.INFORMATIONAL,
427- ... SpecificationFilter.COMPLETE]
428- >>> kubuntu.specifications(filter=filter).count()
429- 1
430+ >>> filter = [SpecificationFilter.INFORMATIONAL]
431+ >>> kubuntu.specifications(filter=filter).count()
432+ 0
433+ >>> filter = [SpecificationFilter.INFORMATIONAL,
434+ ... SpecificationFilter.COMPLETE]
435+ >>> kubuntu.specifications(filter=filter).count()
436+ 1
437
438
439 There are 2 completed specs for Kubuntu:
440
441- >>> filter = [SpecificationFilter.COMPLETE]
442- >>> for spec in kubuntu.specifications(filter=filter):
443- ... print spec.name, spec.is_complete
444- thinclient-local-devices True
445- usplash-on-hibernation True
446+ >>> filter = [SpecificationFilter.COMPLETE]
447+ >>> for spec in kubuntu.specifications(filter=filter):
448+ ... print spec.name, spec.is_complete
449+ thinclient-local-devices True
450+ usplash-on-hibernation True
451
452
453 And there are four incomplete specs:
454
455- >>> filter = [SpecificationFilter.INCOMPLETE]
456- >>> for spec in kubuntu.specifications(filter=filter):
457- ... print spec.name, spec.is_complete
458- cluster-installation False
459- revu False
460- kde-desktopfile-langpacks False
461- krunch-desktop-plan False
462+ >>> filter = [SpecificationFilter.INCOMPLETE]
463+ >>> for spec in kubuntu.specifications(filter=filter):
464+ ... print spec.name, spec.is_complete
465+ cluster-installation False
466+ revu False
467+ kde-desktopfile-langpacks False
468+ krunch-desktop-plan False
469
470
471 If we ask for all specs, we get them in the order of priority.
472
473- >>> filter = [SpecificationFilter.ALL]
474- >>> for spec in kubuntu.specifications(filter=filter):
475- ... print spec.priority.title, spec.name
476- Essential cluster-installation
477- High revu
478- Medium thinclient-local-devices
479- Low usplash-on-hibernation
480- Undefined kde-desktopfile-langpacks
481- Not krunch-desktop-plan
482+ >>> filter = [SpecificationFilter.ALL]
483+ >>> for spec in kubuntu.specifications(filter=filter):
484+ ... print spec.priority.title, spec.name
485+ Essential cluster-installation
486+ High revu
487+ Medium thinclient-local-devices
488+ Low usplash-on-hibernation
489+ Undefined kde-desktopfile-langpacks
490+ Not krunch-desktop-plan
491
492
493 And if we ask just for specs, we get the incomplete ones.
494
495- >>> for spec in kubuntu.specifications():
496- ... print spec.name, spec.is_complete
497- cluster-installation False
498- revu False
499- kde-desktopfile-langpacks False
500- krunch-desktop-plan False
501+ >>> for spec in kubuntu.specifications():
502+ ... print spec.name, spec.is_complete
503+ cluster-installation False
504+ revu False
505+ kde-desktopfile-langpacks False
506+ krunch-desktop-plan False
507
508 We can filter for specifications that contain specific text:
509
510- >>> for spec in kubuntu.specifications(filter=['package']):
511- ... print spec.name
512- revu
513+ >>> for spec in kubuntu.specifications(filter=['package']):
514+ ... print spec.name
515+ revu
516
517 We can get only valid specs (those that are not obsolete or superseded):
518
519- >>> from canonical.launchpad.interfaces import SpecificationDefinitionStatus
520- >>> login('mark@example.com')
521- >>> for spec in kubuntu.specifications():
522- ... # Do this here, otherwise, the change will be flush before
523- ... # updateLifecycleStatus() acts and an IntegrityError will be
524- ... # raised.
525- ... owner = spec.owner
526- ... if spec.name in ['cluster-installation', 'revu']:
527- ... spec.definition_status = SpecificationDefinitionStatus.OBSOLETE
528- ... if spec.name in ['krunch-desktop-plan']:
529- ... spec.definition_status = SpecificationDefinitionStatus.SUPERSEDED
530- ... shim = spec.updateLifecycleStatus(owner)
531- >>> for spec in kubuntu.valid_specifications:
532- ... print spec.name
533- kde-desktopfile-langpacks
534-
535-
536-== Milestones ==
537+ >>> from canonical.launchpad.interfaces import (
538+ ... SpecificationDefinitionStatus,
539+ ... )
540+ >>> login('mark@example.com')
541+ >>> for spec in kubuntu.specifications():
542+ ... # Do this here, otherwise, the change will be flush before
543+ ... # updateLifecycleStatus() acts and an IntegrityError will be
544+ ... # raised.
545+ ... owner = spec.owner
546+ ... if spec.name in ['cluster-installation', 'revu']:
547+ ... spec.definition_status = SpecificationDefinitionStatus.OBSOLETE
548+ ... if spec.name in ['krunch-desktop-plan']:
549+ ... spec.definition_status = SpecificationDefinitionStatus.SUPERSEDED
550+ ... shim = spec.updateLifecycleStatus(owner)
551+ >>> for spec in kubuntu.valid_specifications:
552+ ... print spec.name
553+ kde-desktopfile-langpacks
554+
555+
556+Milestones
557+----------
558
559 We can use IDistribution.milestones to get all milestones associated with any
560 series of a distribution.
561@@ -623,7 +633,8 @@
562 [u'3.1', u'3.1-rc1', u'woody-rc1']
563
564
565-== Archives ==
566+Archives
567+--------
568
569 A distribution archive (primary, partner, debug or copy) can be retrieved
570 by name using IDistribution.getArchive.
571
572=== modified file 'lib/lp/registry/doc/product.txt'
573--- lib/lp/registry/doc/product.txt 2010-08-25 15:48:05 +0000
574+++ lib/lp/registry/doc/product.txt 2010-09-09 15:34:46 +0000
575@@ -1,4 +1,5 @@
576-= Product =
577+Product
578+=======
579
580 Launchpad keeps track of the "upstream" world as well as the "distro" world.
581 The anchorpiece of the "upstream" world is the Product, which is a piece of
582@@ -162,7 +163,8 @@
583 Obsolete Junk
584
585
586-== Translatable Products ==
587+Translatable Products
588+---------------------
589
590 IProductSet will also tell us which products can be translated:
591
592@@ -217,11 +219,11 @@
593 The packaging table allows us to list source and distro source packages
594 related to a certain upstream:
595
596- >>> alsa = productset.getByName('alsa-utils')
597- >>> [(sp.name, sp.distroseries.name) for sp in alsa.sourcepackages]
598- [(u'alsa-utils', u'sid'), (u'alsa-utils', u'warty')]
599- >>> [(sp.name, sp.distribution.name) for sp in alsa.distrosourcepackages]
600- [(u'alsa-utils', u'debian'), (u'alsa-utils', u'ubuntu')]
601+ >>> alsa = productset.getByName('alsa-utils')
602+ >>> [(sp.name, sp.distroseries.name) for sp in alsa.sourcepackages]
603+ [(u'alsa-utils', u'sid'), (u'alsa-utils', u'warty')]
604+ >>> [(sp.name, sp.distribution.name) for sp in alsa.distrosourcepackages]
605+ [(u'alsa-utils', u'debian'), (u'alsa-utils', u'ubuntu')]
606
607 The date_next_suggest_packaging attribute records the date when Launchpad can
608 resume suggesting Ubuntu packages that the project provides. A value of None
609@@ -270,7 +272,8 @@
610 >>> from canonical.launchpad.interfaces import IBugTrackerSet
611
612 >>> login_person(firefox.owner)
613- >>> gnome_bugzilla = getUtility(IBugTrackerSet).getByName('gnome-bugzilla')
614+ >>> bug_tracker_set = getUtility(IBugTrackerSet)
615+ >>> gnome_bugzilla = bug_tracker_set.getByName('gnome-bugzilla')
616 >>> firefox.project.bugtracker = gnome_bugzilla
617 >>> firefox.getExternalBugTracker() is None
618 True
619@@ -307,7 +310,8 @@
620 True
621
622
623-== Answer Tracking ==
624+Answer Tracking
625+---------------
626
627 Firefox uses the Answer Tracker as the official application to provide
628 answers to questions.
629@@ -321,7 +325,8 @@
630 False
631
632
633-== Product Creation ==
634+Product Creation
635+----------------
636
637 We can create new products with the createProduct() method:
638
639@@ -374,20 +379,21 @@
640 True
641
642
643-== Specification Listings ==
644+Specification Listings
645+----------------------
646
647 We should be able to set whether or not a Product uses specifications
648 officially. It defaults to False.
649
650- >>> firefox = productset.getByName('firefox')
651- >>> firefox.official_blueprints
652- False
653+ >>> firefox = productset.getByName('firefox')
654+ >>> firefox.official_blueprints
655+ False
656
657 We can change it to True.
658
659- >>> firefox.official_blueprints = True
660- >>> firefox.official_blueprints
661- True
662+ >>> firefox.official_blueprints = True
663+ >>> firefox.official_blueprints
664+ True
665
666 We should be able to get lists of specifications in different states
667 related to a product.
668@@ -395,39 +401,40 @@
669 Basically, we can filter by completeness, and by whether or not the spec is
670 informational.
671
672- >>> firefox = productset.getByName('firefox')
673- >>> from canonical.launchpad.interfaces import SpecificationFilter
674+ >>> firefox = productset.getByName('firefox')
675+ >>> from canonical.launchpad.interfaces import SpecificationFilter
676
677 First, there should be only one informational spec for firefox:
678
679- >>> filter = [SpecificationFilter.INFORMATIONAL]
680- >>> for spec in firefox.specifications(filter=filter):
681- ... print spec.name
682- extension-manager-upgrades
683+ >>> filter = [SpecificationFilter.INFORMATIONAL]
684+ >>> for spec in firefox.specifications(filter=filter):
685+ ... print spec.name
686+ extension-manager-upgrades
687
688
689 There are no completed specs for firefox:
690
691- >>> filter = [SpecificationFilter.COMPLETE]
692- >>> for spec in firefox.specifications(filter=filter):
693- ... print spec.name
694+ >>> filter = [SpecificationFilter.COMPLETE]
695+ >>> for spec in firefox.specifications(filter=filter):
696+ ... print spec.name
697
698
699 And there are five incomplete specs:
700
701- >>> filter = [SpecificationFilter.INCOMPLETE]
702- >>> firefox.specifications(filter=filter).count()
703- 5
704+ >>> filter = [SpecificationFilter.INCOMPLETE]
705+ >>> firefox.specifications(filter=filter).count()
706+ 5
707
708 We can filter for specifications that contain specific text:
709
710- >>> for spec in firefox.specifications(filter=['new']):
711- ... print spec.name
712- canvas
713- e4x
714-
715-
716-== Milestones ==
717+ >>> for spec in firefox.specifications(filter=['new']):
718+ ... print spec.name
719+ canvas
720+ e4x
721+
722+
723+Milestones
724+----------
725
726 We can use IProduct.milestones to get all milestones associated with any
727 ProductSeries of a product.
728@@ -470,7 +477,8 @@
729 [u'1.0.0', u'0.9.2', u'0.9.1', u'0.9', u'1.0', u'1.0-rc1']
730
731
732-== Release ==
733+Release
734+-------
735
736 All the releases for a Product can be retrieved through the releases property.
737
738@@ -489,7 +497,8 @@
739 0.9.1
740
741
742-== Products With Branches ==
743+Products With Branches
744+----------------------
745
746 Products are considered to officially support Launchpad as a location
747 for their branches after a branch is set for the development focus
748@@ -568,7 +577,8 @@
749 landscape
750
751
752-== Primary translatable ==
753+Primary translatable
754+--------------------
755
756 Primary translatable series in a product should follow series where
757 development is focused on. To be able to do changes to facilitate
758@@ -583,12 +593,18 @@
759 >>> from lp.translations.interfaces.potemplate import IPOTemplateSet
760 >>> potemplate_set = getUtility(IPOTemplateSet)
761
762+We're going to be setting the ServiceUsage values for products, so we
763+need those enums.
764+
765+ >>> from lp.app.enums import ServiceUsage
766+
767 Firefox has two series, but no translatable series either:
768
769 >>> firefox = productset.getByName('firefox')
770 >>> for firefoxseries in firefox.series:
771- ... print '%s %s' % (firefoxseries.displayname,
772- ... list(firefoxseries.getCurrentTranslationTemplates()))
773+ ... print '%s %s' % (
774+ ... firefoxseries.displayname,
775+ ... list(firefoxseries.getCurrentTranslationTemplates()))
776 1.0 []
777 trunk []
778 >>> print firefox.primary_translatable
779@@ -616,7 +632,7 @@
780 And set that product as using translations officially. We need it so
781 translations are available.
782
783- >>> firefox.official_rosetta = True
784+ >>> firefox.translations_usage = ServiceUsage.LAUNCHPAD
785
786 The primary_translatable now points at firefox 1.0:
787
788@@ -642,7 +658,8 @@
789 1.0
790
791
792-= Series list =
793+Series list
794+===========
795
796 The series for a product are returned as a sorted list, with the
797 exception that the current development focus is first.
798@@ -697,7 +714,8 @@
799 ... print series.name
800 trunk
801
802-= Changing ownership =
803+Changing ownership
804+==================
805
806 If the owner of a project changes, all series and productreleases
807 owned by the old owner are transfered to the new owner.
808
809=== modified file 'lib/lp/registry/doc/project.txt'
810--- lib/lp/registry/doc/project.txt 2010-06-07 07:52:45 +0000
811+++ lib/lp/registry/doc/project.txt 2010-09-09 15:34:46 +0000
812@@ -1,4 +1,5 @@
813-= ProjectGroups =
814+ProjectGroups
815+=============
816
817 A ProjectGroup is a group of Products, making it possible to for
818 example see all bugs in the ProjectGroup's Product, or make them share a
819@@ -11,7 +12,8 @@
820 >>> projectset = getUtility(IProjectGroupSet)
821
822
823-== Creating new projects ==
824+Creating new projects
825+---------------------
826
827 When creating a new project there are a bunch of things we need to provide.
828 While some of them (homepageurl, icon, logo and mugshot) are optional, others
829@@ -28,7 +30,8 @@
830 u'project-test'
831
832
833-== Looking up existing projects ==
834+Looking up existing projects
835+----------------------------
836
837 To fetch a project we use IProjectGroupSet.getByName() or
838 IProjectGroupSet.__getitem__. The former will, by default, return active and
839@@ -98,7 +101,8 @@
840 >>> print projectgroups.getByName('gnome', ignore_inactive=True)
841 None
842
843-== Products which are part of a project ==
844+Products which are part of a project
845+------------------------------------
846
847 The products which are part of a given project are given by a project's
848 .products property. Note that only active products are included and they're
849@@ -122,7 +126,8 @@
850 >>> flush_database_updates()
851
852
853-== Specification Listings ==
854+Specification Listings
855+----------------------
856
857 We should be able to generate filtered lists of specs on a project.
858
859@@ -200,7 +205,8 @@
860 e4x
861
862
863-== Specification Listings for a ProjectGroupSeries ==
864+Specification Listings for a ProjectGroupSeries
865+-----------------------------------------------
866
867 An IProjectGroupSeries object can be retrieved by IProjectGroup.getSeries.
868
869@@ -314,7 +320,8 @@
870 e4x
871
872
873-== translatables ==
874+Translatables
875+-------------
876
877 A project would have IProduct objects that have resources to translate. This
878 method return us the ones that are translatable and officially using Rosetta
879@@ -349,8 +356,8 @@
880
881 That is using Rosetta officially.
882
883- >>> evolution.official_rosetta
884- True
885+ >>> print evolution.translations_usage.name
886+ LAUNCHPAD
887
888 GNOME project has also another product, netapplet.
889
890@@ -361,8 +368,8 @@
891 But it was not returned from 'translatables' method because it's not using
892 Rosetta officially.
893
894- >>> netapplet.official_rosetta
895- False
896+ >>> print netapplet.translations_usage.name
897+ UNKNOWN
898
899 And thus, it doesn't have any translatable series.
900
901@@ -376,7 +383,8 @@
902 1
903
904
905-== Milestones ==
906+Milestones
907+----------
908
909 A project can have virtual milestones. If any of its products has milestones,
910 these milestones are also associated with the project.
911@@ -398,7 +406,8 @@
912 1.1. active: True
913 1.1 active: True
914
915-ProjectGroup.all_milestones is a list of all milestones associated with a project.
916+ProjectGroup.all_milestones is a list of all milestones associated with a
917+project.
918
919 >>> milestones = gnome.all_milestones
920 >>> for milestone in milestones:
921@@ -410,8 +419,8 @@
922 1.1. active: True
923 1.1 active: True
924
925-ProjectGroup.getMilestone(name) returns the project milestone with the name `name'
926-or None, if no milestone with this name exists.
927+ProjectGroup.getMilestone(name) returns the project milestone with the name
928+`name' or None, if no milestone with this name exists.
929
930 >>> milestone = gnome.getMilestone('1.1')
931 >>> print milestone.name
932
933=== modified file 'lib/lp/registry/model/projectgroup.py'
934--- lib/lp/registry/model/projectgroup.py 2010-08-24 19:06:33 +0000
935+++ lib/lp/registry/model/projectgroup.py 2010-09-09 15:34:46 +0000
936@@ -202,6 +202,9 @@
937
938 def translatables(self):
939 """See `IProjectGroup`."""
940+ # XXX j.c.sackett 2010-08-30 bug=627631 Once data migration has
941+ # happened for the usage enums, this sql needs to be updated to
942+ # check for the translations_usage, not official_rosetta.
943 return Product.select('''
944 Product.project = %s AND
945 Product.official_rosetta = TRUE AND
946@@ -271,7 +274,7 @@
947
948 # filter based on completion. see the implementation of
949 # Specification.is_complete() for more details
950- completeness = Specification.completeness_clause
951+ completeness = Specification.completeness_clause
952
953 if SpecificationFilter.COMPLETE in filter:
954 query += ' AND ( %s ) ' % completeness
955
956=== modified file 'lib/lp/testing/factory.py'
957--- lib/lp/testing/factory.py 2010-09-09 14:11:43 +0000
958+++ lib/lp/testing/factory.py 2010-09-09 15:34:46 +0000
959@@ -93,6 +93,7 @@
960 IStoreSelector,
961 MAIN_STORE,
962 )
963+from lp.app.enums import ServiceUsage
964 from lp.archiveuploader.dscfile import DSCFile
965 from lp.archiveuploader.uploadpolicy import BuildDaemonUploadPolicy
966 from lp.blueprints.interfaces.specification import (
967@@ -838,7 +839,7 @@
968 self, name=None, project=None, displayname=None,
969 licenses=None, owner=None, registrant=None,
970 title=None, summary=None, official_malone=None,
971- official_rosetta=None, bug_supervisor=None):
972+ translations_usage=None, bug_supervisor=None):
973 """Create and return a new, arbitrary Product."""
974 if owner is None:
975 owner = self.makePerson()
976@@ -867,8 +868,9 @@
977 registrant=registrant)
978 if official_malone is not None:
979 removeSecurityProxy(product).official_malone = official_malone
980- if official_rosetta is not None:
981- removeSecurityProxy(product).official_rosetta = official_rosetta
982+ if translations_usage is not None:
983+ naked_product = removeSecurityProxy(product)
984+ naked_product.translations_usage = translations_usage
985 if bug_supervisor is not None:
986 naked_product = removeSecurityProxy(product)
987 naked_product.bug_supervisor = bug_supervisor
988@@ -2176,7 +2178,8 @@
989 productseries = self.makeProductSeries(owner=owner)
990 # Make it use Translations, otherwise there's little point
991 # to us creating a template for it.
992- removeSecurityProxy(productseries).product.official_rosetta = True
993+ naked_series = removeSecurityProxy(productseries)
994+ naked_series.product.translations_usage = ServiceUsage.LAUNCHPAD
995 templateset = getUtility(IPOTemplateSet)
996 subset = templateset.getSubset(
997 distroseries, sourcepackagename, productseries)
998
999=== modified file 'lib/lp/translations/browser/potemplate.py'
1000--- lib/lp/translations/browser/potemplate.py 2010-08-25 20:04:40 +0000
1001+++ lib/lp/translations/browser/potemplate.py 2010-09-09 15:34:46 +0000
1002@@ -61,6 +61,7 @@
1003 from canonical.launchpad.webapp.launchpadform import ReturnToReferrerMixin
1004 from canonical.launchpad.webapp.menu import structured
1005 from canonical.lazr.utils import smartquote
1006+from lp.app.enums import service_uses_launchpad
1007 from lp.app.errors import NotFoundError
1008 from lp.registry.browser.productseries import ProductSeriesFacets
1009 from lp.registry.browser.sourcepackage import SourcePackageFacets
1010@@ -794,9 +795,10 @@
1011 product_or_distro = potemplate.productseries.product
1012 else:
1013 product_or_distro = potemplate.distroseries.distribution
1014- official_rosetta = product_or_distro.official_rosetta
1015+ translations_usage = product_or_distro.translations_usage
1016
1017- if official_rosetta and potemplate.iscurrent:
1018+ if (service_uses_launchpad(translations_usage) and
1019+ potemplate.iscurrent):
1020 # This template is available for translation.
1021 return potemplate
1022 elif check_permission('launchpad.Edit', potemplate):
1023
1024=== modified file 'lib/lp/translations/browser/product.py'
1025--- lib/lp/translations/browser/product.py 2010-08-24 10:45:57 +0000
1026+++ lib/lp/translations/browser/product.py 2010-09-09 15:34:46 +0000
1027@@ -19,6 +19,7 @@
1028 )
1029 from canonical.launchpad.webapp.authorization import check_permission
1030 from canonical.launchpad.webapp.menu import NavigationMenu
1031+from lp.app.enums import service_uses_launchpad
1032 from lp.registry.browser.product import ProductEditView
1033 from lp.registry.interfaces.product import IProduct
1034 from lp.registry.interfaces.productseries import IProductSeries
1035@@ -51,12 +52,14 @@
1036 def translationdownload(self):
1037 text = 'Download'
1038 preferred_series = self.context.primary_translatable
1039- enabled = (self.context.official_rosetta and
1040- preferred_series is not None)
1041+ enabled = (service_uses_launchpad(self.context.translations_usage)
1042+ and preferred_series is not None)
1043 link = ''
1044 if enabled:
1045 link = canonical_url(
1046- preferred_series, rootsite='translations', view_name='+export')
1047+ preferred_series,
1048+ rootsite='translations',
1049+ view_name='+export')
1050 text = 'Download "%s"' % preferred_series.name
1051
1052 return Link(link, text, icon='download', enabled=enabled)
1053@@ -90,19 +93,19 @@
1054 @cachedproperty
1055 def uses_translations(self):
1056 """Whether this product has translatable templates."""
1057- return (self.context.official_rosetta and
1058- self.primary_translatable is not None)
1059+ return (service_uses_launchpad(self.context.translations_usage)
1060+ and self.primary_translatable is not None)
1061
1062 @cachedproperty
1063 def no_translations_available(self):
1064 """Has no translation templates but does support translations."""
1065- return (self.context.official_rosetta and
1066- self.primary_translatable is None)
1067+ return (service_uses_launchpad(self.context.translations_usage)
1068+ and self.primary_translatable is None)
1069
1070 @cachedproperty
1071 def show_page_content(self):
1072 """Whether the main content of the page should be shown."""
1073- return (self.context.official_rosetta or
1074+ return (service_uses_launchpad(self.context.translations_usage) or
1075 check_permission("launchpad.TranslationsAdmin", self.context))
1076
1077 @cachedproperty
1078
1079=== modified file 'lib/lp/translations/browser/tests/language-views.txt'
1080--- lib/lp/translations/browser/tests/language-views.txt 2010-07-16 16:51:52 +0000
1081+++ lib/lp/translations/browser/tests/language-views.txt 2010-09-09 15:34:46 +0000
1082@@ -143,7 +143,10 @@
1083
1084 Create a product, a template with one msgset and a pofile
1085
1086- >>> product = factory.makeProduct(official_rosetta=True)
1087+ >>> from lp.app.enums import ServiceUsage
1088+
1089+ >>> product = factory.makeProduct(
1090+ ... translations_usage=ServiceUsage.LAUNCHPAD)
1091 >>> template = factory.makePOTemplate(
1092 ... productseries=product.getSeries('trunk'))
1093 >>> potmsgset = factory.makePOTMsgSet(template)
1094
1095=== modified file 'lib/lp/translations/browser/tests/test_breadcrumbs.py'
1096--- lib/lp/translations/browser/tests/test_breadcrumbs.py 2010-08-20 20:31:18 +0000
1097+++ lib/lp/translations/browser/tests/test_breadcrumbs.py 2010-09-09 15:34:46 +0000
1098@@ -6,6 +6,7 @@
1099 from zope.component import getUtility
1100
1101 from canonical.lazr.utils import smartquote
1102+from lp.app.enums import ServiceUsage
1103 from lp.services.worlddata.interfaces.language import ILanguageSet
1104 from lp.testing.breadcrumbs import BaseBreadcrumbTestCase
1105 from lp.testing.factory import remove_security_proxy_and_shout_at_engineer
1106@@ -152,7 +153,7 @@
1107 def test_potemplate(self):
1108 product = self.factory.makeProduct(
1109 name='crumb-tester', displayname="Crumb Tester",
1110- official_rosetta=True)
1111+ translations_usage=ServiceUsage.LAUNCHPAD)
1112 series = self.factory.makeProductSeries(
1113 name="test", product=product)
1114 potemplate = self.factory.makePOTemplate(
1115@@ -176,7 +177,7 @@
1116 def test_pofiletranslate(self):
1117 product = self.factory.makeProduct(
1118 name='crumb-tester', displayname="Crumb Tester",
1119- official_rosetta=True)
1120+ translations_usage=ServiceUsage.LAUNCHPAD)
1121 series = self.factory.makeProductSeries(name="test", product=product)
1122 potemplate = self.factory.makePOTemplate(series, name="test-template")
1123 pofile = self.factory.makePOFile('eo', potemplate)
1124
1125=== modified file 'lib/lp/translations/doc/potmsgset.txt'
1126--- lib/lp/translations/doc/potmsgset.txt 2010-09-01 10:03:11 +0000
1127+++ lib/lp/translations/doc/potmsgset.txt 2010-09-09 15:34:46 +0000
1128@@ -1,4 +1,5 @@
1129-= POTMsgSet tests =
1130+POTMsgSet tests
1131+===============
1132
1133 POTMsgSet represents messages to translate that a POTemplate file has.
1134
1135@@ -17,7 +18,9 @@
1136 ... ILanguageSet, IPersonSet, IProductSet)
1137
1138 >>> potemplate = factory.makePOTemplate()
1139- >>> potmsgset = factory.makePOTMsgSet(potemplate=potemplate, singular="bla")
1140+ >>> potmsgset = factory.makePOTMsgSet(
1141+ ... potemplate=potemplate,
1142+ ... singular="bla")
1143
1144 Verify interface.
1145
1146@@ -31,7 +34,8 @@
1147 >>> import pytz
1148
1149
1150-== POTMsgSet.is_translation_credit and POTMsgSet.translation_credit_type ==
1151+POTMsgSet.is_translation_credit and POTMsgSet.translation_credit_type
1152+---------------------------------------------------------------------
1153
1154 A POTMsgSet can be translation credits. These have special msgids that may
1155 differ for historical reason for the same type of credit. The property
1156@@ -51,7 +55,8 @@
1157 Gnome credits message
1158
1159
1160-== POTMsgSet.normalizeWhitespaces ==
1161+POTMsgSet.normalizeWhitespaces
1162+------------------------------
1163
1164 This function copies the leading and trailing whitespaces from
1165 POTMsgSet's msgid into the 'text' argument.
1166@@ -96,7 +101,8 @@
1167 True
1168
1169
1170-== POTMsgSet.convertDotToSpace ==
1171+POTMsgSet.convertDotToSpace
1172+---------------------------
1173
1174 This method changes the u'\u2022' char by the normal white space.
1175
1176@@ -126,14 +132,17 @@
1177 u'a string with the char \u2022'
1178
1179
1180-== POTMsgSet.normalizeNewLines ==
1181+POTMsgSet.normalizeNewLines
1182+---------------------------
1183
1184 This method syncs the new line chars to use the same as the associated msgid.
1185
1186 As this test is too specific, we are going to change a msgid as we need for
1187 every test.
1188
1189- >>> potmsgset_windows = factory.makePOTMsgSet(potemplate, singular=u'\r\n')
1190+ >>> potmsgset_windows = factory.makePOTMsgSet(
1191+ ... potemplate,
1192+ ... singular=u'\r\n')
1193 >>> potmsgset_unix = factory.makePOTMsgSet(potemplate, singular=u'\n')
1194 >>> potmsgset_mac = factory.makePOTMsgSet(potemplate, singular=u'\r')
1195 >>> text_windows = u'\r\n'
1196@@ -180,7 +189,8 @@
1197 BrokenTextError: ...
1198
1199
1200-== POTMsgSet.applySanityFixes ==
1201+POTMsgSet.applySanityFixes
1202+--------------------------
1203
1204 This function applies all checks we know to fix broken input
1205
1206@@ -199,7 +209,8 @@
1207 u'\nTranslation\nto test\n'
1208
1209
1210-== POTMsgSet.updateTranslation ==
1211+POTMsgSet.updateTranslation
1212+---------------------------
1213
1214 This method is the core piece of Translations infrastructure: it
1215 updates a single language translation for a POTMsgSet, and modifies a
1216@@ -309,7 +320,8 @@
1217 >>> current.date_created is None
1218 False
1219
1220-=== Unsetting a translation from the import ===
1221+Unsetting a translation from the import
1222+.......................................
1223
1224 A translation can be removed from the import by being set to an empty string.
1225
1226@@ -349,7 +361,8 @@
1227 >>> upstream_pofile.updateStatistics()
1228 (0, 0, 0, 2)
1229
1230-=== Activating an existing suggestion ===
1231+Activating an existing suggestion
1232+.................................
1233
1234 Foo Bar is a privileged translator who can do reviews and submit translations
1235 directly, while No Privileges user can only submit suggestions.
1236@@ -438,7 +451,8 @@
1237 u'Foo Bar'
1238
1239
1240-== Plural forms ==
1241+Plural forms
1242+------------
1243
1244 Let's focus on handling of messages with plural forms.
1245
1246@@ -513,7 +527,8 @@
1247 [None, None, None]
1248
1249
1250-=== Missing forms ===
1251+Missing forms
1252+.............
1253
1254 Even when a message has a singular and a plural in English, a
1255 translation does not have to cover all plural forms available in the
1256@@ -538,7 +553,8 @@
1257 False
1258
1259
1260-=== Extraneous forms ===
1261+Extraneous forms
1262+................
1263
1264 It's not normally possible to input more plural forms for a translated
1265 message than the language has. But that number is configurable, and can
1266@@ -614,7 +630,8 @@
1267 possible.
1268
1269
1270-== isTranslationNewerThan ==
1271+isTranslationNewerThan
1272+----------------------
1273
1274 This method tells us whether the active translation was reviewed after
1275 the given timestamp.
1276@@ -633,7 +650,8 @@
1277 False
1278
1279
1280-== External translation suggestions ==
1281+External translation suggestions
1282+--------------------------------
1283
1284 External translation suggestions are current, imported or suggested
1285 translation for exactly the same English string, but in a different
1286@@ -670,7 +688,8 @@
1287 ... print line
1288
1289
1290-== POTMsgSet.getExternallyUsedTranslationMessages ==
1291+POTMsgSet.getExternallyUsedTranslationMessages
1292+----------------------------------------------
1293
1294 On one side, we have a translation template for the evolution product.
1295
1296@@ -692,10 +711,10 @@
1297
1298 Both, product and distribution use Launchpad Translations.
1299
1300- >>> evolution.official_rosetta
1301- True
1302- >>> ubuntu.official_rosetta
1303- True
1304+ >>> evolution.translations_usage.name
1305+ 'LAUNCHPAD'
1306+ >>> ubuntu.translations_usage.name
1307+ 'LAUNCHPAD'
1308
1309 And both translation templates are current
1310
1311@@ -754,7 +773,9 @@
1312 The same happens if the distribution is not officially using
1313 translations.
1314
1315- >>> ubuntu.official_rosetta = False
1316+ >>> from lp.app.enums import ServiceUsage
1317+
1318+ >>> ubuntu.translations_usage = ServiceUsage.NOT_APPLICABLE
1319
1320 # We set the template as current again so we are sure that we don't show
1321 # suggestions just due to the change to the official_rosetta flag.
1322@@ -767,7 +788,7 @@
1323
1324 And products not using translations officially have the same behaviour.
1325
1326- >>> evolution.official_rosetta = False
1327+ >>> evolution.translations_usage = ServiceUsage.NOT_APPLICABLE
1328 >>> transaction.commit()
1329 >>> suggestions = evo_distro_message.getExternallyUsedTranslationMessages(
1330 ... spanish)
1331@@ -776,12 +797,13 @@
1332
1333 Let's restore the flags for next section.
1334
1335- >>> ubuntu.official_rosetta = True
1336- >>> evolution.official_rosetta = True
1337+ >>> ubuntu.translations_usage = ServiceUsage.LAUNCHPAD
1338+ >>> evolution.translations_usage = ServiceUsage.LAUNCHPAD
1339 >>> transaction.commit()
1340
1341
1342-== POTMsgSet.getExternallySuggestedTranslationMessages ==
1343+POTMsgSet.getExternallySuggestedTranslationMessages
1344+---------------------------------------------------
1345
1346 This method returns a set of submissions that have suggested translations
1347 for the same msgid as the given POTMsgSet across the whole system.
1348@@ -876,7 +898,7 @@
1349 # We set the template as current again so we are sure that we don't show
1350 # suggestions just due to the change to the official_rosetta flag.
1351 >>> potmsgset_translated.potemplate.iscurrent = True
1352- >>> ubuntu.official_rosetta = False
1353+ >>> ubuntu.translations_usage = ServiceUsage.NOT_APPLICABLE
1354 >>> transaction.commit()
1355
1356 >>> wiki_submissions = (
1357@@ -886,7 +908,8 @@
1358 0
1359
1360
1361-== POTMsgSet.getCurrentDummyTranslationMessage ==
1362+POTMsgSet.getCurrentDummyTranslationMessage
1363+-------------------------------------------
1364
1365 Sometimes, there are POTMsgSet objects with no translations to a language,
1366 and we need to get dummy objects which emulate them to do read operations.
1367@@ -908,7 +931,8 @@
1368 AssertionError: There is already a translation message ...
1369
1370
1371-== Suggestions for translator credits ==
1372+Suggestions for translator credits
1373+----------------------------------
1374
1375 Messages with translator credits are translated automatically by
1376 Launchpad, so we should not get any suggestions for them.
1377@@ -936,8 +960,8 @@
1378
1379 Now, let's add 'translation-credits' message to a different POTemplate:
1380
1381- >>> new_credits = evolution_potemplate.createMessageSetFromText(
1382- ... singular_text=u'translation-credits', plural_text=None)
1383+ >>> new_credits = evolution_potemplate.createMessageSetFromText(
1384+ ... singular_text=u'translation-credits', plural_text=None)
1385
1386 However, this one doesn't show up as external suggestion for Spanish.
1387
1388@@ -946,7 +970,8 @@
1389 >>> new_credits.getExternallySuggestedTranslationMessages(spanish)
1390 []
1391
1392-== POTMsgSet.setSequence ==
1393+POTMsgSet.setSequence
1394+---------------------
1395
1396 Finally, the new `IPOTMsgSet` should have an entry in the
1397 `TranslationTemplateItem` table once we assign a sequence number.
1398@@ -998,7 +1023,8 @@
1399 0
1400
1401
1402-== POTMsgSet.flags ==
1403+POTMsgSet.flags
1404+---------------
1405
1406 The gettext format can associate flags with a POTMsgSet, such as "this
1407 is a fuzzily matched message" or "this message follows C format-string
1408
1409=== modified file 'lib/lp/translations/doc/translationimportqueue.txt'
1410--- lib/lp/translations/doc/translationimportqueue.txt 2010-07-13 21:49:34 +0000
1411+++ lib/lp/translations/doc/translationimportqueue.txt 2010-09-09 15:34:46 +0000
1412@@ -1,4 +1,5 @@
1413-= TranslationImportQueueEntry =
1414+TranslationImportQueueEntry
1415+===========================
1416
1417 The TranslationImportQueueEntry is an entry of the queue that will be imported
1418 into Rosetta.
1419@@ -14,7 +15,8 @@
1420 ... store.find(TranslationImportQueueEntry).remove()
1421
1422
1423-== getGuessedPOFile ==
1424+getGuessedPOFile
1425+----------------
1426
1427 This property gives us the IPOFile where we think we should import this entry.
1428
1429@@ -59,7 +61,8 @@
1430 ... u'po/sr.po', 'foo', True, rosetta_experts,
1431 ... productseries=evolution_productseries)
1432
1433-This entry has no information about the IPOFile where it should be attached to:
1434+This entry has no information about the IPOFile where it should be attached
1435+to:
1436
1437 >>> entry.import_into is None
1438 True
1439@@ -82,7 +85,8 @@
1440 ... sourcepackagename=evolution_sourcepackagename)
1441 >>> transaction.commit()
1442
1443-This entry has no information about the IPOFile where it should be attached to:
1444+This entry has no information about the IPOFile where it should be attached
1445+to:
1446
1447 >>> entry.import_into is None
1448 True
1449@@ -225,7 +229,8 @@
1450 >>> pofile.path
1451 u'po/sr.po'
1452
1453-=== getGuessedPOFile with KDE ===
1454+getGuessedPOFile with KDE
1455+.........................
1456
1457 Official KDE packages have a non standard layout where the .pot files are
1458 stored inside the sourcepackage with the binaries that will use it and the
1459@@ -363,7 +368,8 @@
1460 >>> transaction.abort()
1461
1462
1463-=== getGuessedPOFile with KOffice ===
1464+getGuessedPOFile with KOffice
1465+.............................
1466
1467 Like official KDE packages, KOffice stores the .pot and .po files in different
1468 packages, the only difference it has is that there is just one source package
1469@@ -403,7 +409,9 @@
1470
1471 And set this entry as already imported.
1472
1473- >>> koffice_pot_entry.setStatus(RosettaImportStatus.IMPORTED, rosetta_experts)
1474+ >>> koffice_pot_entry.setStatus(
1475+ ... RosettaImportStatus.IMPORTED,
1476+ ... rosetta_experts)
1477 >>> flush_database_updates()
1478
1479 Let's attach a .po file from koffice-l10n
1480@@ -449,7 +457,8 @@
1481 >>> transaction.abort()
1482
1483
1484-=== getGuessedPOFile with .po files in different directories ===
1485+getGuessedPOFile with .po files in different directories
1486+........................................................
1487
1488 Some packages have translations and templates inside the same package, but
1489 they don't have them inside the same directory. The layout is:
1490@@ -500,7 +509,9 @@
1491
1492 And set this entry as already imported.
1493
1494- >>> adept_pot_entry.setStatus(RosettaImportStatus.IMPORTED, rosetta_experts)
1495+ >>> adept_pot_entry.setStatus(
1496+ ... RosettaImportStatus.IMPORTED,
1497+ ... rosetta_experts)
1498 >>> flush_database_updates()
1499
1500 Let's attach a .po file now.
1501@@ -551,7 +562,9 @@
1502
1503 And set this entry as already imported.
1504
1505- >>> ktorrent_pot_entry.setStatus(RosettaImportStatus.IMPORTED, rosetta_experts)
1506+ >>> ktorrent_pot_entry.setStatus(
1507+ ... RosettaImportStatus.IMPORTED,
1508+ ... rosetta_experts)
1509 >>> flush_database_updates()
1510
1511 Let's attach a .po file now.
1512@@ -739,7 +752,8 @@
1513 >>> transaction.abort()
1514
1515
1516-== executeOptimisticBlock ==
1517+executeOptimisticBlock
1518+----------------------
1519
1520 This method looks on the queue to find entries to block based on other .pot
1521 entries that are stored on the same directory and are already blocked.
1522@@ -803,7 +817,8 @@
1523 True
1524
1525 On the other hand, this other one is for the same
1526-distroseries/sourcepackagename than the .pot file we have so it's also blocked.
1527+distroseries/sourcepackagename than the .pot file we have so it's also
1528+blocked.
1529
1530 >>> entry4 = translationimportqueue.get(4)
1531 >>> entry4.path
1532@@ -820,7 +835,8 @@
1533 True
1534
1535
1536-== getElapsedTimeText ==
1537+getElapsedTimeText
1538+-----------------
1539
1540 This method returns a string representing the elapsed time since the entry
1541 was added to the queue.
1542@@ -860,13 +876,15 @@
1543 '2 days 13 hours 5 minutes ago'
1544
1545
1546-= TranslationImportQueue =
1547+TranslationImportQueue
1548+======================
1549
1550 The translation import queue is the place where the new translation imports
1551 end before being imported into Rosetta.
1552
1553
1554-== getTemplatesOnSameDirectory ==
1555+getTemplatesOnSameDirectory
1556+---------------------------
1557
1558 This method allows us to get the set of .pot files we have on the same
1559 directory that a given entry.
1560@@ -905,7 +923,8 @@
1561 0
1562
1563
1564-== getRequestTargets ==
1565+getRequestTargets
1566+-----------------
1567
1568 >>> # Helper functions
1569 >>> def get_target_names(status=None):
1570@@ -1069,7 +1088,8 @@
1571 firefox Mozilla Firefox
1572 ubuntu/hoary Hoary
1573
1574-== addOrUpdateEntry() ==
1575+addOrUpdateEntry()
1576+------------------
1577
1578 addOrUpdateEntry adds a new entry to the import queue so we can handle it
1579 later with poimport script.
1580@@ -1264,7 +1284,8 @@
1581 >>> print entry.content.read()
1582 New bar content
1583
1584-= Filename filters =
1585+Filename filters
1586+================
1587
1588 A tarball doesn't always have everything in quite the right place. If
1589 you need to manipulate the file paths within a tarball before the files
1590@@ -1307,7 +1328,8 @@
1591 netapplet | None | new-directory/fr.po
1592
1593
1594-= Invalid data =
1595+Invalid data
1596+============
1597
1598 If administrators fail to correct certain errors in requests while approving
1599 them, and the admin user interface mistakenly accepts the approval, we may
1600@@ -1385,7 +1407,8 @@
1601 >>> clear_queue(translationimportqueue)
1602
1603
1604-== getRequestTargets output ordering ==
1605+getRequestTargets output ordering
1606+---------------------------------
1607
1608 The queue is populated with a wild mix of requests: for packages in
1609 different release series of Ubuntu, for packages in different distros,
1610@@ -1472,7 +1495,8 @@
1611 evolution Evolution
1612
1613
1614-== cleanUpQueue ==
1615+cleanUpQueue
1616+------------
1617
1618 The queue is cleaned up regularly.
1619
1620@@ -1489,7 +1513,8 @@
1621 0
1622
1623
1624-=== State and Age ===
1625+State and Age
1626+.............
1627
1628 Entries can be cleaned up because they have been in a specific state for
1629 at least a specified period of time.
1630@@ -1516,18 +1541,22 @@
1631 >>> print_queue_entries(translationimportqueue)
1632
1633
1634-=== Deactivated Products ===
1635+Deactivated Products
1636+....................
1637
1638 Another reason for deleting entries is that they belong to products that
1639 have been deactivated.
1640
1641 A user sets up Jokosher for translation, and uploads a template.
1642
1643+ >>> from lp.app.enums import ServiceUsage
1644+
1645 >>> jokosher = productset['jokosher']
1646 >>> jokosher_trunk = jokosher.getSeries('trunk')
1647- >>> jokosher.official_rosetta = True
1648+ >>> jokosher.translations_usage = ServiceUsage.LAUNCHPAD
1649 >>> syncUpdate(jokosher)
1650- >>> jokosher_subset = potemplateset.getSubset(productseries=jokosher_trunk)
1651+ >>> jokosher_subset = potemplateset.getSubset(
1652+ ... productseries=jokosher_trunk)
1653 >>> template = jokosher_subset.new(
1654 ... 'jokosher', 'jokosher', 'jokosher.pot', rosetta_experts)
1655 >>> syncUpdate(template)
1656
1657=== modified file 'lib/lp/translations/doc/translationmessage-destroy.txt'
1658--- lib/lp/translations/doc/translationmessage-destroy.txt 2009-07-02 17:16:50 +0000
1659+++ lib/lp/translations/doc/translationmessage-destroy.txt 2010-09-09 15:34:46 +0000
1660@@ -1,4 +1,5 @@
1661-== destroySelf ==
1662+destroySelf
1663+===========
1664
1665 (Note: this test runs as rosettaadmin to obtain the necessary
1666 privileges)
1667@@ -26,7 +27,8 @@
1668 SQLObjectNotFound:...
1669
1670
1671-== POFileTranslator update on remove ==
1672+POFileTranslator update on remove
1673+=================================
1674
1675 In two sharing POTemplates with one shared POTMsgSet with one shared
1676 translation, we get two POFileTranslator records for each of the POFiles.
1677@@ -35,16 +37,17 @@
1678 >>> # a global 'postgres' permission which allows everything.
1679 >>> LaunchpadZopelessLayer.switchDbUser('postgres')
1680 >>> from canonical.database.sqlbase import sqlvalues
1681+ >>> from lp.app.enums import ServiceUsage
1682 >>> from lp.translations.model.pofiletranslator import POFileTranslator
1683 >>> from lp.testing.factory import LaunchpadObjectFactory
1684 >>> factory = LaunchpadObjectFactory()
1685
1686- >>> foo = factory.makeProduct()
1687+ >>> foo = factory.makeProduct(
1688+ ... translations_usage=ServiceUsage.LAUNCHPAD)
1689 >>> foo_devel = factory.makeProductSeries(
1690 ... name='devel', product=foo)
1691 >>> foo_stable = factory.makeProductSeries(
1692 ... name='stable', product=foo)
1693- >>> foo.official_rosetta = True
1694 >>> devel_potemplate = factory.makePOTemplate(
1695 ... productseries=foo_devel, name="messages")
1696 >>> stable_potemplate = factory.makePOTemplate(foo_stable,
1697@@ -56,7 +59,9 @@
1698 >>> potmsgset = factory.makePOTMsgSet(devel_potemplate, sequence=1)
1699 >>> potmsgset.setSequence(stable_potemplate, 1)
1700 >>> tm = factory.makeTranslationMessage(
1701- ... pofile=devel_sr_pofile, potmsgset=potmsgset, translations=[u"blah"])
1702+ ... pofile=devel_sr_pofile,
1703+ ... potmsgset=potmsgset,
1704+ ... translations=[u"blah"])
1705 >>> print POFileTranslator.select(
1706 ... "latest_message=%s" % sqlvalues(tm)).count()
1707 2
1708
1709=== modified file 'lib/lp/translations/doc/translations-export-to-branch.txt'
1710--- lib/lp/translations/doc/translations-export-to-branch.txt 2010-07-20 17:50:45 +0000
1711+++ lib/lp/translations/doc/translations-export-to-branch.txt 2010-09-09 15:34:46 +0000
1712@@ -1,4 +1,5 @@
1713-= Exporting translations to a bzr branch =
1714+Exporting translations to a bzr branch
1715+======================================
1716
1717 The translations-export-to-branch script visits all ProductSeries with a
1718 translations_branch set, and for each, exports the series' translations
1719@@ -76,10 +77,11 @@
1720 branch.
1721
1722 >>> from zope.security.proxy import removeSecurityProxy
1723+ >>> from lp.app.enums import ServiceUsage
1724
1725 >>> gazblachko = removeSecurityProxy(factory.makeProduct(
1726 ... name='gazblachko', displayname='Gazblachko'))
1727- >>> gazblachko.official_rosetta = True
1728+ >>> gazblachko.translations_usage = ServiceUsage.LAUNCHPAD
1729
1730 >>> branch = removeSecurityProxy(factory.makeBranch(
1731 ... name='gazpo', owner=gazblachko.owner, product=gazblachko))
1732@@ -162,13 +164,13 @@
1733 When Gazblachko stops using Launchpad for Translations, the exports stop
1734 also.
1735
1736- >>> gazblachko.official_rosetta = False
1737+ >>> gazblachko.translations_usage = ServiceUsage.NOT_APPLICABLE
1738 >>> transaction.commit()
1739 >>> script.main()
1740 INFO Exporting to translations branches.
1741 INFO Processed 0 item(s); 0 failure(s), 0 unpushed branch(es).
1742
1743- >>> gazblachko.official_rosetta = True
1744+ >>> gazblachko.translations_usage = ServiceUsage.LAUNCHPAD
1745 >>> transaction.commit()
1746
1747
1748@@ -271,7 +273,8 @@
1749 collected for import yet.
1750
1751
1752-=== Branch races ===
1753+Branch races
1754+............
1755
1756 Any translations coming in through a branch push are safe once they're
1757 in the translations import queue. So the race window spans from the
1758@@ -299,7 +302,8 @@
1759 INFO Processed 1 item(s); 1 failure(s), 0 unpushed branch(es).
1760
1761
1762-=== Pending imports from same branch ===
1763+Pending imports from same branch
1764+................................
1765
1766 Another race condition is detected by the script itself: there may be
1767 pending translations BranchJobs on the branch.
1768
1769=== modified file 'lib/lp/translations/doc/translationsoverview.txt'
1770--- lib/lp/translations/doc/translationsoverview.txt 2009-07-24 12:55:03 +0000
1771+++ lib/lp/translations/doc/translationsoverview.txt 2010-09-09 15:34:46 +0000
1772@@ -1,4 +1,5 @@
1773-= TranslationsOverview =
1774+TranslationsOverview
1775+====================
1776
1777 This class provides a basic overview of the Launchpad Translations component.
1778 It includes data such as projects which have so far received the most
1779@@ -45,14 +46,16 @@
1780 18
1781
1782
1783-== _normalizeSizes ==
1784+_normalizeSizes
1785+---------------
1786
1787 This private method accepts a list of tuples (object, size) and
1788 normalizes `size` values into the range [MINIMUM_SIZE, MAXIMUM_SIZE].
1789
1790 >>> test_list = [('one', 3), ('two', 0), ('three', 1)]
1791 >>> from zope.security.proxy import removeSecurityProxy
1792- >>> result = removeSecurityProxy(overview)._normalizeSizes(test_list, 0, 3)
1793+ >>> naked_overview = removeSecurityProxy(overview)
1794+ >>> result = naked_overview._normalizeSizes(test_list, 0, 3)
1795 >>> for pillar in result:
1796 ... print "%s: %d" % (pillar['pillar'], pillar['weight'])
1797 one: 18
1798@@ -60,7 +63,8 @@
1799 three: 13
1800
1801
1802-== Getting the most translated pillars ==
1803+Getting the most translated pillars
1804+-----------------------------------
1805
1806 Method getMostTranslatedPillars() returns a list of dicts listing
1807 pillars with most translations karma so far, along with a relative
1808@@ -104,10 +108,13 @@
1809
1810 Adding a little bit of karma to upstart will put it in the list as well.
1811
1812+ >>> from lp.app.enums import ServiceUsage
1813+
1814 >>> start_karma_update()
1815 >>> upstart = product_set.getByName('upstart')
1816 >>> upstart_id = upstart.id
1817- >>> removeSecurityProxy(upstart).official_rosetta = True
1818+ >>> naked_upstart = removeSecurityProxy(upstart)
1819+ >>> naked_upstart.translations_usage = ServiceUsage.LAUNCHPAD
1820 >>> cache_entry = karmacachemanager.new(
1821 ... 50, carlos.id, translations.id, product_id=upstart_id)
1822 >>> finish_karma_update()
1823@@ -153,7 +160,8 @@
1824 Ubuntu: 24
1825
1826
1827-== Zero karma ==
1828+Zero karma
1829+----------
1830
1831 Sometimes a pillar appears to be listed in the karma cache with zero
1832 karma. Our algorithm takes the logarithm of its karma, but it's
1833
1834=== modified file 'lib/lp/translations/model/potemplate.py'
1835--- lib/lp/translations/model/potemplate.py 2010-09-03 03:12:39 +0000
1836+++ lib/lp/translations/model/potemplate.py 2010-09-09 15:34:46 +0000
1837@@ -64,6 +64,7 @@
1838 IMasterStore,
1839 IStore,
1840 )
1841+from lp.app.enums import service_uses_launchpad
1842 from lp.app.errors import NotFoundError
1843 from lp.registry.interfaces.person import validate_public_person
1844 from lp.registry.model.sourcepackagename import SourcePackageName
1845@@ -1322,8 +1323,7 @@
1846 preferred_matches = [
1847 match
1848 for match in matches
1849- if match.from_sourcepackagename == sourcepackagename
1850- ]
1851+ if match.from_sourcepackagename == sourcepackagename]
1852
1853 if len(preferred_matches) == 1:
1854 return preferred_matches[0]
1855@@ -1378,6 +1378,9 @@
1856
1857 def populateSuggestivePOTemplatesCache(self):
1858 """See `IPOTemplateSet`."""
1859+ # XXX j.c.sackett 2010-08-30 bug=627631 Once data migration has
1860+ # happened for the usage enums, this sql needs to be updated to
1861+ # check for the translations_usage, not official_rosetta.
1862 return IMasterStore(POTemplate).execute("""
1863 INSERT INTO SuggestivePOTemplate (
1864 SELECT POTemplate.id
1865@@ -1437,15 +1440,13 @@
1866 if self.product:
1867 subsets = [
1868 self.potemplateset.getSubset(productseries=series)
1869- for series in self.product.series
1870- ]
1871+ for series in self.product.series]
1872 else:
1873 subsets = [
1874 self.potemplateset.getSubset(
1875 distroseries=series,
1876 sourcepackagename=self.sourcepackagename)
1877- for series in self.distribution.series
1878- ]
1879+ for series in self.distribution.series]
1880 for subset in subsets:
1881 for template in subset:
1882 if name_pattern is None or re.match(name_pattern,
1883@@ -1548,8 +1549,7 @@
1884 msgset.flags = set([
1885 flag.strip()
1886 for flag in row.flags_comment.split(',')
1887- if flag
1888- ])
1889+ if flag])
1890
1891 # Store the message.
1892 messages.append(msgset)
1893@@ -1578,8 +1578,9 @@
1894 collection = self.getTemplatesCollection()
1895
1896 # XXX JeroenVermeulen 2010-07-15 bug=605924: Move the
1897- # official_rosetta distinction into browser code.
1898- if collection.target_pillar.official_rosetta:
1899+ # translations_usage distinction into browser code.
1900+ pillar = collection.target_pillar
1901+ if service_uses_launchpad(pillar.translations_usage):
1902 return collection.restrictCurrent(current_value)
1903 else:
1904 # Product/Distribution does not have translation enabled.
1905
1906=== modified file 'lib/lp/translations/model/potmsgset.py'
1907--- lib/lp/translations/model/potmsgset.py 2010-09-06 03:35:47 +0000
1908+++ lib/lp/translations/model/potmsgset.py 2010-09-09 15:34:46 +0000
1909@@ -361,6 +361,9 @@
1910 query = ["(NOT %s)" % in_use_clause]
1911 query.append('TranslationMessage.language = %s' % sqlvalues(language))
1912
1913+ # XXX j.c.sackett 2010-08-30 bug=627631 Once data migration has
1914+ # happened for the usage enums, this sql needs to be updated
1915+ # to check for the translations_usage, not official_rosetta.
1916 query.append('''
1917 potmsgset IN (
1918 SELECT POTMsgSet.id
1919@@ -381,7 +384,8 @@
1920 POTMsgSet.id <> %s AND
1921 msgid_singular = %s AND
1922 POTemplate.iscurrent AND
1923- (Product.official_rosetta OR Distribution.official_rosetta)
1924+ (Product.official_rosetta OR
1925+ Distribution.official_rosetta)
1926 )''' % sqlvalues(self, self.msgid_singular))
1927
1928 # Subquery to find the ids of TranslationMessages that are
1929@@ -396,8 +400,8 @@
1930 for form in xrange(TranslationConstants.MAX_PLURAL_FORMS)])
1931 ids_query_params = {
1932 'msgstrs': msgstrs,
1933- 'where': ' AND '.join(query)
1934- }
1935+ 'where': ' AND '.join(query),
1936+ }
1937 ids_query = '''
1938 SELECT DISTINCT ON (%(msgstrs)s)
1939 TranslationMessage.id
1940@@ -565,8 +569,7 @@
1941 # plural forms.
1942 order.extend([
1943 'msgstr%s NULLS FIRST' % quote(form)
1944- for form in remaining_plural_forms
1945- ])
1946+ for form in remaining_plural_forms])
1947 matches = list(
1948 TranslationMessage.select(' AND '.join(clauses), orderBy=order))
1949
1950@@ -722,7 +725,6 @@
1951 if is_imported or new_message == imported_message:
1952 new_message.is_imported = True
1953
1954-
1955 def _isTranslationMessageASuggestion(self, force_suggestion,
1956 pofile, submitter,
1957 force_edition_rights, is_imported,
1958@@ -1178,4 +1180,3 @@
1959 """See `IPOTMsgSet`."""
1960 return TranslationTemplateItem.selectBy(
1961 potmsgset=self, orderBy=['id'])
1962-
1963
1964=== modified file 'lib/lp/translations/model/translationsoverview.py'
1965--- lib/lp/translations/model/translationsoverview.py 2010-08-20 20:31:18 +0000
1966+++ lib/lp/translations/model/translationsoverview.py 2010-09-09 15:34:46 +0000
1967@@ -39,13 +39,15 @@
1968 new_size = int(round(
1969 real_minimum +
1970 (size - offset - real_minimum) * multiplier))
1971- normalized_sizes.append({'pillar' : pillar,
1972- 'weight' : new_size })
1973+ normalized_sizes.append({'pillar': pillar, 'weight': new_size})
1974 return normalized_sizes
1975
1976 def getMostTranslatedPillars(self, limit=50):
1977 """See `ITranslationsOverview`."""
1978
1979+ # XXX j.c.sackett 2010-08-30 bug=627631 Once data migration has
1980+ # happened for the usage enums, this sql needs to be updated
1981+ # to check for the translations_usage, not official_rosetta.
1982 query = """
1983 SELECT LOWER(COALESCE(product_name, distro_name)) AS name,
1984 product_id,
1985@@ -65,7 +67,8 @@
1986 distribution=distribution.id
1987 WHERE category=3 AND
1988 (product IS NOT NULL OR distribution IS NOT NULL) AND
1989- (product.official_rosetta OR distribution.official_rosetta)
1990+ (product.official_rosetta OR
1991+ distribution.official_rosetta)
1992 GROUP BY product.displayname, product.id,
1993 distribution.displayname, distribution.id
1994 HAVING SUM(karmavalue) > 0
1995
1996=== modified file 'lib/lp/translations/model/translationsperson.py'
1997--- lib/lp/translations/model/translationsperson.py 2010-08-27 10:53:40 +0000
1998+++ lib/lp/translations/model/translationsperson.py 2010-09-09 15:34:46 +0000
1999@@ -262,6 +262,10 @@
2000 The added joins may make the overall query non-distinct, so be
2001 sure to enforce distinctness.
2002 """
2003+ # XXX j.c.sackett 2010-08-30 bug=627631 Once data migration has
2004+ # happened for the usage enums, this query needs to be updated
2005+ # to check for the translations_usage, not official_rosetta.
2006+
2007 POTemplateJoin = Join(POTemplate, And(
2008 POTemplate.id == POFile.potemplateID,
2009 POTemplate.iscurrent == True))
2010
2011=== modified file 'lib/lp/translations/scripts/translations_to_branch.py'
2012--- lib/lp/translations/scripts/translations_to_branch.py 2010-08-20 20:31:18 +0000
2013+++ lib/lp/translations/scripts/translations_to_branch.py 2010-09-09 15:34:46 +0000
2014@@ -306,6 +306,9 @@
2015
2016 self.store = getUtility(IStoreSelector).get(MAIN_STORE, SLAVE_FLAVOR)
2017
2018+ # XXX j.c.sackett 2010-08-30 bug=627631 Once data migration has
2019+ # happened for the usage enums, this sql needs to be updated to
2020+ # check for the translations_usage, not official_rosetta.
2021 product_join = Join(
2022 ProductSeries, Product, ProductSeries.product == Product.id)
2023 productseries = self.store.using(product_join).find(
2024
2025=== modified file 'lib/lp/translations/stories/buildfarm/xx-build-summary.txt'
2026--- lib/lp/translations/stories/buildfarm/xx-build-summary.txt 2010-07-20 17:50:45 +0000
2027+++ lib/lp/translations/stories/buildfarm/xx-build-summary.txt 2010-09-09 15:34:46 +0000
2028@@ -1,9 +1,11 @@
2029-= TranslationTemplatesBuildJob Build Summary =
2030+TranslationTemplatesBuildJob Build Summary
2031+==========================================
2032
2033 The builders UI can show TranslationTemplateBuildJobs, although they
2034 look a little different from Soyuz-style jobs.
2035
2036-== Setup ==
2037+Setup
2038+-----
2039
2040 Create a builder working on a TranslationTemplatesBuildJob for a branch.
2041
2042@@ -13,6 +15,7 @@
2043 >>> from canonical.launchpad.interfaces.librarian import (
2044 ... ILibraryFileAliasSet)
2045 >>> from canonical.launchpad.scripts.logger import QuietFakeLogger
2046+ >>> from lp.app.enums import ServiceUsage
2047 >>> from lp.buildmaster.interfaces.buildqueue import IBuildQueueSet
2048 >>> from lp.testing.factory import (
2049 ... remove_security_proxy_and_shout_at_engineer)
2050@@ -32,7 +35,7 @@
2051 >>> productseries = factory.makeProductSeries(owner=owner)
2052 >>> product = productseries.product
2053 >>> naked_product = remove_security_proxy_and_shout_at_engineer(product)
2054- >>> naked_product.official_rosetta = True
2055+ >>> naked_product.translations_usage = ServiceUsage.LAUNCHPAD
2056 >>> branch = factory.makeProductBranch(product=product, owner=owner)
2057 >>> branch_url = branch.unique_name
2058
2059@@ -62,7 +65,8 @@
2060 ... return find_tag_by_id(browser.contents, 'current-build-summary')
2061
2062
2063-== Show summary ==
2064+Show summary
2065+------------
2066
2067 The job's summary shows that what type of job this is. It also links
2068 to the branch.
2069
2070=== modified file 'lib/lp/translations/stories/importqueue/xx-entry-details.txt'
2071--- lib/lp/translations/stories/importqueue/xx-entry-details.txt 2010-03-11 20:54:36 +0000
2072+++ lib/lp/translations/stories/importqueue/xx-entry-details.txt 2010-09-09 15:34:46 +0000
2073@@ -1,9 +1,11 @@
2074-= Entry details =
2075+Entry details
2076+=============
2077
2078 The translation import queue entry page shows various details about an
2079 entry and its target that may be helpful in queue review.
2080
2081 >>> from zope.security.proxy import removeSecurityProxy
2082+ >>> from lp.app.enums import ServiceUsage
2083 >>> from lp.translations.model.translationimportqueue import (
2084 ... TranslationImportQueue)
2085
2086@@ -11,8 +13,8 @@
2087
2088 >>> login(ANONYMOUS)
2089 >>> queue = TranslationImportQueue()
2090- >>> product = factory.makeProduct()
2091- >>> removeSecurityProxy(product).official_rosetta = True
2092+ >>> product = factory.makeProduct(
2093+ ... translations_usage=ServiceUsage.LAUNCHPAD)
2094 >>> trunk = product.getSeries('trunk')
2095 >>> uploader = factory.makePerson()
2096 >>> entry = queue.addOrUpdateEntry(
2097@@ -47,7 +49,8 @@
2098 http://...foo.pot
2099
2100
2101-== Existing templates ==
2102+Existing templates
2103+------------------
2104
2105 If there are translatable templates in the series, this will be stated
2106 and there will be a link to the templates list.
2107@@ -81,7 +84,8 @@
2108 ...
2109
2110
2111-== Source packages ==
2112+Source packages
2113+---------------
2114
2115 The portlet shows different (well, less) information for uploads
2116 attached to distribution packages.
2117
2118=== modified file 'lib/lp/translations/stories/productseries/xx-productseries-export-to-branch.txt'
2119--- lib/lp/translations/stories/productseries/xx-productseries-export-to-branch.txt 2009-09-02 16:35:54 +0000
2120+++ lib/lp/translations/stories/productseries/xx-productseries-export-to-branch.txt 2010-09-09 15:34:46 +0000
2121@@ -1,15 +1,16 @@
2122-= ProductSeries Translations Branch =
2123+ProductSeries Translations Branch
2124+=================================
2125
2126 If a ProductSeries has its translations_branch set, Launchpad will
2127 periodically commit snapshots of the series' translations to that
2128 branch.
2129
2130- >>> from zope.security.proxy import removeSecurityProxy
2131+ >>> from lp.app.enums import ServiceUsage
2132
2133 >>> login(ANONYMOUS)
2134 >>> owner = factory.makePerson(email='x@example.com', password='****')
2135- >>> product = factory.makeProduct(owner=owner)
2136- >>> removeSecurityProxy(product).official_rosetta = True
2137+ >>> product = factory.makeProduct(owner=owner,
2138+ ... translations_usage=ServiceUsage.LAUNCHPAD)
2139 >>> productseries = product.getSeries('trunk')
2140 >>> branch = factory.makeBranch(product=product, owner=owner)
2141 >>> branch_name = branch.name
2142@@ -99,7 +100,8 @@
2143 </div>
2144
2145
2146-== Disabling exports ==
2147+Disabling exports
2148+-----------------
2149
2150 The field can also be cleared in order to disable the exports.
2151
2152@@ -125,7 +127,8 @@
2153 None
2154
2155
2156-== Security ==
2157+Security
2158+--------
2159
2160 You can only set the translations_branch to a branch that you own.
2161 Otherwise you'd be giving Launchpad a blanket license to commit
2162
2163=== modified file 'lib/lp/translations/stories/productseries/xx-productseries-translations.txt'
2164--- lib/lp/translations/stories/productseries/xx-productseries-translations.txt 2010-03-31 20:25:33 +0000
2165+++ lib/lp/translations/stories/productseries/xx-productseries-translations.txt 2010-09-09 15:34:46 +0000
2166@@ -5,9 +5,10 @@
2167 a single product series, or instructions on how to set up a series for
2168 translation.
2169
2170+ >>> from lp.app.enums import ServiceUsage
2171 >>> login('foo.bar@canonical.com')
2172- >>> frobnicator = factory.makeProduct(name='frobnicator')
2173- >>> frobnicator.official_rosetta = True
2174+ >>> frobnicator = factory.makeProduct(name='frobnicator',
2175+ ... translations_usage=ServiceUsage.LAUNCHPAD)
2176 >>> frobnicator_trunk = frobnicator.getSeries('trunk')
2177 >>> frobnicator_trunk_url = canonical_url(
2178 ... frobnicator_trunk, rootsite='translations')
2179@@ -148,7 +149,8 @@
2180
2181 # Use the raw DB object to bypass the security proxy.
2182 >>> from lp.registry.model.product import Product
2183- >>> Product.byName('bazaar').official_rosetta = False
2184+ >>> product = Product.byName('bazaar')
2185+ >>> product.translations_usage = ServiceUsage.NOT_APPLICABLE
2186
2187 When the owner now visits the upload page for trunk, there's a notice.
2188
2189
2190=== modified file 'lib/lp/translations/stories/standalone/custom-language-codes.txt'
2191--- lib/lp/translations/stories/standalone/custom-language-codes.txt 2010-03-11 20:54:36 +0000
2192+++ lib/lp/translations/stories/standalone/custom-language-codes.txt 2010-09-09 15:34:46 +0000
2193@@ -11,11 +11,11 @@
2194 Custom language codes are attached to either a product or a source
2195 package.
2196
2197- >>> import re
2198 >>> from zope.component import getUtility
2199 >>> from zope.security.proxy import removeSecurityProxy
2200 >>> from canonical.launchpad.interfaces.launchpad import (
2201 ... ILaunchpadCelebrities)
2202+ >>> from lp.app.enums import ServiceUsage
2203
2204 >>> def find_custom_language_codes_link(browser):
2205 ... """Find reference to custom language codes on a page."""
2206@@ -29,7 +29,8 @@
2207 ... getUtility(ILaunchpadCelebrities).rosetta_experts)
2208 >>> product = factory.makeProduct(displayname="Foo", owner=owner)
2209 >>> trunk = product.getSeries('trunk')
2210- >>> removeSecurityProxy(product).official_rosetta = True
2211+ >>> naked_product = removeSecurityProxy(product)
2212+ >>> naked_product.translations_usage = ServiceUsage.LAUNCHPAD
2213 >>> template = factory.makePOTemplate(productseries=trunk)
2214 >>> product_page = canonical_url(product, rootsite='translations')
2215 >>> logout()
2216@@ -198,7 +199,8 @@
2217 >>> sourcepackagename = SourcePackageName(name='bar')
2218 >>> package = factory.makeSourcePackage(
2219 ... sourcepackagename=sourcepackagename, distroseries=distroseries)
2220- >>> removeSecurityProxy(distro).official_rosetta = True
2221+ >>> naked_distro = removeSecurityProxy(distro)
2222+ >>> naked_distro.translations_usage = ServiceUsage.LAUNCHPAD
2223 >>> other_series = factory.makeDistroRelease(distribution=distro)
2224 >>> template = factory.makePOTemplate(
2225 ... distroseries=package.distroseries,
2226
2227=== modified file 'lib/lp/translations/stories/standalone/xx-potemplate-index.txt'
2228--- lib/lp/translations/stories/standalone/xx-potemplate-index.txt 2010-02-16 21:21:14 +0000
2229+++ lib/lp/translations/stories/standalone/xx-potemplate-index.txt 2010-09-09 15:34:46 +0000
2230@@ -6,7 +6,7 @@
2231 -----------
2232
2233 The index page for a POTemplate lists all available translations
2234-for a source package. No Privileges Person visits the
2235+for a source package. No Privileges Person visits the
2236 evolution-2.2 POTemplate page.
2237
2238 >>> anon_browser.open("http://translations.launchpad.dev/"
2239@@ -85,7 +85,7 @@
2240 </p>
2241
2242
2243-DistroSeries and ProductSeries links to related templates
2244+DistroSeries and ProductSeries links to related templates
2245 ---------------------------------------------------------
2246
2247 We are presented not only with links to alternate templates from the same
2248@@ -117,8 +117,8 @@
2249 A source package with five templates is created.
2250
2251 >>> from zope.component import getUtility
2252- >>> from canonical.launchpad.interfaces.launchpad import (
2253- ... ILaunchpadCelebrities)
2254+ >>> from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
2255+
2256 >>> login('admin@canonical.com')
2257 >>> ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
2258 >>> hoary = ubuntu.getSeries('hoary')
2259@@ -212,8 +212,10 @@
2260 >>> from zope.component import getUtility
2261 >>> from canonical.launchpad.interfaces.launchpad import (
2262 ... ILaunchpadCelebrities)
2263+ >>> from lp.app.enums import ServiceUsage
2264 >>> login('admin@canonical.com')
2265- >>> product = factory.makeProduct(name="fusa", official_rosetta=True)
2266+ >>> product = factory.makeProduct(name="fusa",
2267+ ... translations_usage=ServiceUsage.LAUNCHPAD)
2268 >>> product_trunk = product.getSeries('trunk')
2269 >>> template = factory.makePOTemplate(
2270 ... productseries=product_trunk, name='first')
2271@@ -253,7 +255,9 @@
2272 Anonymous visitors see only a list of all existing templates, with no
2273 administration or download/upload links.
2274
2275- >>> anon_browser.open('http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
2276+ >>> anon_browser.open(
2277+ ... 'http://translations.launchpad.dev/'
2278+ ... 'ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
2279 >>> anon_browser.getLink('upload')
2280 Traceback (most recent call last):
2281 ...
2282@@ -267,7 +271,9 @@
2283 As an authenticated user, you should see the download link,
2284 but not the one for uploading file to this potemplate.
2285
2286- >>> user_browser.open('http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
2287+ >>> user_browser.open(
2288+ ... 'http://translations.launchpad.dev/'
2289+ ... 'ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
2290 >>> user_browser.getLink('upload')
2291 Traceback (most recent call last):
2292 ...
2293@@ -281,27 +287,37 @@
2294 Beside administering this template, "Change permissions"
2295 and "Change details" should be also accessible.
2296
2297- >>> admin_browser.open('http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
2298+ >>> admin_browser.open(
2299+ ... 'http://translations.launchpad.dev/'
2300+ ... 'ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
2301 >>> admin_browser.getLink('upload').click()
2302 >>> print admin_browser.url
2303 http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2/+upload
2304
2305- >>> admin_browser.open('http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
2306+ >>> admin_browser.open(
2307+ ... 'http://translations.launchpad.dev/'
2308+ ... 'ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
2309 >>> admin_browser.getLink('download').click()
2310 >>> print admin_browser.url
2311 http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2/+export
2312
2313- >>> admin_browser.open('http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
2314+ >>> admin_browser.open(
2315+ ... 'http://translations.launchpad.dev/'
2316+ ... 'ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
2317 >>> admin_browser.getLink('Administer this template').click()
2318 >>> print admin_browser.url
2319 http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2/+admin
2320
2321- >>> admin_browser.open('http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
2322+ >>> admin_browser.open(
2323+ ... 'http://translations.launchpad.dev/'
2324+ ... 'ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
2325 >>> admin_browser.getLink('Change details').click()
2326 >>> print admin_browser.url
2327 http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2/+edit
2328
2329- >>> admin_browser.open('http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
2330+ >>> admin_browser.open(
2331+ ... 'http://translations.launchpad.dev/'
2332+ ... 'ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
2333 >>> admin_browser.getLink('Change permissions').click()
2334 >>> print admin_browser.url
2335 http://translations.launchpad.dev/ubuntu/+settings
2336
2337=== modified file 'lib/lp/translations/stories/standalone/xx-product-export.txt'
2338--- lib/lp/translations/stories/standalone/xx-product-export.txt 2009-09-18 15:42:19 +0000
2339+++ lib/lp/translations/stories/standalone/xx-product-export.txt 2010-09-09 15:34:46 +0000
2340@@ -1,4 +1,5 @@
2341-= Downloading Product Series Translations =
2342+Downloading Product Series Translations
2343+=======================================
2344
2345 Products and product series that use Translations offer complete
2346 translation downloads.
2347@@ -33,16 +34,18 @@
2348 Your request has been received. Expect to receive an email shortly.
2349
2350
2351-== Use of Launchpad Translations ==
2352+Use of Launchpad Translations
2353+-----------------------------
2354
2355 The Download link is not shown if the product does not use Launchpad
2356 Translations.
2357
2358 # Use the DB classes directly to avoid having to setup a zope interaction
2359 # (i.e. login()) and bypass the security proxy.
2360+ >>> from lp.app.enums import ServiceUsage
2361 >>> from lp.registry.model.product import Product
2362 >>> product = Product.byName('evolution')
2363- >>> product.official_rosetta = False
2364+ >>> product.translations_usage = ServiceUsage.NOT_APPLICABLE
2365 >>> product.sync()
2366 >>> user_browser.open('http://translations.launchpad.dev/evolution')
2367 >>> user_browser.getLink('download')
2368@@ -51,14 +54,15 @@
2369 LinkNotFoundError
2370
2371 >>> # Restore previous state for subsequent tests, and verify
2372- >>> product.official_rosetta = True
2373+ >>> product.translations_usage = ServiceUsage.LAUNCHPAD
2374 >>> product.sync()
2375 >>> user_browser.open('http://translations.launchpad.dev/evolution')
2376 >>> user_browser.getLink('download') is not None
2377 True
2378
2379
2380-== Authorization ==
2381+Authorization
2382+-------------
2383
2384 Only logged-in users get the option to request downloads.
2385
2386
2387=== modified file 'lib/lp/translations/stories/standalone/xx-product-translations.txt'
2388--- lib/lp/translations/stories/standalone/xx-product-translations.txt 2010-08-25 00:01:57 +0000
2389+++ lib/lp/translations/stories/standalone/xx-product-translations.txt 2010-09-09 15:34:46 +0000
2390@@ -1,4 +1,3 @@
2391-====================
2392 Product Translations
2393 ====================
2394
2395
2396=== modified file 'lib/lp/translations/stories/standalone/xx-template-description-escaping.txt'
2397--- lib/lp/translations/stories/standalone/xx-template-description-escaping.txt 2009-09-14 15:41:21 +0000
2398+++ lib/lp/translations/stories/standalone/xx-template-description-escaping.txt 2010-09-09 15:34:46 +0000
2399@@ -1,12 +1,14 @@
2400 >>> import re
2401 >>> from zope.security.proxy import removeSecurityProxy
2402+ >>> from lp.app.enums import ServiceUsage
2403
2404 >>> login('foo.bar@canonical.com')
2405 >>> package = factory.makeSourcePackage()
2406 >>> template = removeSecurityProxy(factory.makePOTemplate(
2407 ... distroseries=package.distroseries,
2408 ... sourcepackagename=package.sourcepackagename))
2409- >>> template.distroseries.distribution.official_rosetta = True
2410+ >>> distribution = template.distroseries.distribution
2411+ >>> distribution.translations_usage = ServiceUsage.LAUNCHPAD
2412 >>> template.distroseries.hide_all_translations = False
2413 >>> template.description = "See http://example.com/ for an example!"
2414 >>> package_url = canonical_url(package, rootsite='translations')
2415
2416=== modified file 'lib/lp/translations/stories/translationfocus/xx-product-translationfocus.txt'
2417--- lib/lp/translations/stories/translationfocus/xx-product-translationfocus.txt 2010-01-20 20:21:42 +0000
2418+++ lib/lp/translations/stories/translationfocus/xx-product-translationfocus.txt 2010-09-09 15:34:46 +0000
2419@@ -1,9 +1,10 @@
2420 The translation focus of a product can be explicitly set to a specific series.
2421 When not set, launchpad recommends the development focus to translate.
2422
2423+ >>> from lp.app.enums import ServiceUsage
2424 >>> login('admin@canonical.com')
2425 >>> fooproject = factory.makeProduct(name="fooproject")
2426- >>> fooproject.official_rosetta = True
2427+ >>> fooproject.translations_usage = ServiceUsage.LAUNCHPAD
2428 >>> fooproject_trunk = fooproject.getSeries("trunk")
2429 >>> fooproject_url = canonical_url(
2430 ... fooproject, rootsite="translations")
2431@@ -25,7 +26,8 @@
2432 ...
2433 IndexError: list index out of range
2434
2435-== Setting the translation focus ==
2436+Setting the translation focus
2437+=============================
2438
2439 >>> login('admin@canonical.com')
2440 >>> from zope.security.proxy import removeSecurityProxy
2441@@ -35,7 +37,7 @@
2442 >>> pofile = factory.makePOFile("pt_BR", potemplate=pot_main)
2443 >>> logout()
2444
2445-When the translation focus is not set, Launchpad suggests the
2446+When the translation focus is not set, Launchpad suggests the
2447 development focus as the current series to be translated.
2448 It needs to be translatable.
2449
2450
2451=== modified file 'lib/lp/translations/stories/translationgroups/xx-change-translation-policy.txt'
2452--- lib/lp/translations/stories/translationgroups/xx-change-translation-policy.txt 2010-02-16 21:21:14 +0000
2453+++ lib/lp/translations/stories/translationgroups/xx-change-translation-policy.txt 2010-09-09 15:34:46 +0000
2454@@ -4,11 +4,15 @@
2455 A product owner, Rosetta expert, and Ubuntu translations coordinator
2456 browser is created.
2457
2458+ >>> from lp.app.enums import ServiceUsage
2459+
2460 >>> login('admin@canonical.com')
2461 >>> product_owner = factory.makePerson(
2462 ... email="po@ex.com", password="test")
2463 >>> chestii = factory.makeProduct(
2464- ... name='chestii', owner=product_owner, official_rosetta=True)
2465+ ... name='chestii',
2466+ ... owner=product_owner,
2467+ ... translations_usage=ServiceUsage.LAUNCHPAD)
2468 >>> logout()
2469 >>> dtc_browser = setupDTCBrowser()
2470 >>> re_browser = setupRosettaExpertBrowser()
2471
2472=== modified file 'lib/lp/translations/templates/product-portlet-not-using-launchpad.pt'
2473--- lib/lp/translations/templates/product-portlet-not-using-launchpad.pt 2010-03-15 20:17:21 +0000
2474+++ lib/lp/translations/templates/product-portlet-not-using-launchpad.pt 2010-09-09 15:34:46 +0000
2475@@ -5,7 +5,7 @@
2476 omit-tag="">
2477
2478 <div id="not-translated-in-launchpad"
2479- tal:condition="not: context/official_rosetta">
2480+ tal:condition="not: context/translations_usage/enumvalue:LAUNCHPAD">
2481 <strong>
2482 This project is not using Launchpad for translations.
2483 </strong>
2484
2485=== modified file 'lib/lp/translations/templates/productseries-translations.pt'
2486--- lib/lp/translations/templates/productseries-translations.pt 2009-12-16 15:21:36 +0000
2487+++ lib/lp/translations/templates/productseries-translations.pt 2010-09-09 15:34:46 +0000
2488@@ -30,7 +30,7 @@
2489 <a href="https://help.launchpad.net/Translations/YourProject">start
2490 translating your project</a>,
2491 <tal:uses-translations condition="not:
2492- context/product/official_rosetta">
2493+ context/product/translations_usage/enumvalue:LAUNCHPAD">
2494 you should enable translations in your project settings, and
2495 </tal:uses-translations>
2496 you can either
2497
2498=== modified file 'lib/lp/translations/tests/test_autoapproval.py'
2499--- lib/lp/translations/tests/test_autoapproval.py 2010-08-20 20:31:18 +0000
2500+++ lib/lp/translations/tests/test_autoapproval.py 2010-09-09 15:34:46 +0000
2501@@ -23,6 +23,7 @@
2502 from canonical.launchpad.interfaces.lpstorm import IMasterStore
2503 from canonical.launchpad.webapp.testing import verifyObject
2504 from canonical.testing import LaunchpadZopelessLayer
2505+from lp.app.enums import ServiceUsage
2506 from lp.registry.interfaces.series import SeriesStatus
2507 from lp.registry.model.distribution import Distribution
2508 from lp.registry.model.sourcepackagename import (
2509@@ -714,8 +715,8 @@
2510 # _get_pofile_from_language will find an enabled template, and
2511 # return either an existing POFile for the given language, or a
2512 # newly created one.
2513- product = self.factory.makeProduct()
2514- product.official_rosetta = True
2515+ product = self.factory.makeProduct(
2516+ translations_usage=ServiceUsage.LAUNCHPAD)
2517 trunk = product.getSeries('trunk')
2518 template = self.factory.makePOTemplate(
2519 productseries=trunk, translation_domain='domain')
2520@@ -732,8 +733,8 @@
2521 # _get_pofile_from_language will not consider a disabled
2522 # template as an auto-approval target, and so will not return a
2523 # POFile for it.
2524- product = self.factory.makeProduct()
2525- product.official_rosetta = True
2526+ product = self.factory.makeProduct(
2527+ translations_usage=ServiceUsage.LAUNCHPAD)
2528 trunk = product.getSeries('trunk')
2529 template = self.factory.makePOTemplate(
2530 productseries=trunk, translation_domain='domain')
2531@@ -750,8 +751,8 @@
2532 # When the template has translation credits, a new dummy translation
2533 # is created in the new POFile. Since this is running with gardener
2534 # privileges, we need to check that this works, too.
2535- product = self.factory.makeProduct()
2536- product.official_rosetta = True
2537+ product = self.factory.makeProduct(
2538+ translations_usage=ServiceUsage.LAUNCHPAD)
2539 trunk = product.getSeries('trunk')
2540 template = self.factory.makePOTemplate(
2541 productseries=trunk, translation_domain='domain')
2542@@ -778,8 +779,8 @@
2543
2544 def _makeProductEntry(self, path='foo.pot', status=None):
2545 """Simulate upload for a product."""
2546- product = self.factory.makeProduct()
2547- product.official_rosetta = True
2548+ product = self.factory.makeProduct(
2549+ translations_usage=ServiceUsage.LAUNCHPAD)
2550 trunk = product.getSeries('trunk')
2551 entry = self.queue.addOrUpdateEntry(
2552 path, '# contents', False, product.owner, productseries=trunk)
2553
2554=== modified file 'lib/lp/translations/tests/test_empty_messages.py'
2555--- lib/lp/translations/tests/test_empty_messages.py 2010-08-20 20:31:18 +0000
2556+++ lib/lp/translations/tests/test_empty_messages.py 2010-09-09 15:34:46 +0000
2557@@ -4,17 +4,17 @@
2558 __metaclass__ = type
2559
2560 from datetime import datetime
2561-import unittest
2562
2563 from pytz import timezone
2564 from zope.component import getUtility
2565
2566 from canonical.testing import LaunchpadZopelessLayer
2567+from lp.app.enums import ServiceUsage
2568 from lp.services.worlddata.interfaces.language import ILanguageSet
2569-from lp.testing.factory import LaunchpadObjectFactory
2570-
2571-
2572-class TestTranslationEmptyMessages(unittest.TestCase):
2573+from lp.testing import TestCaseWithFactory
2574+
2575+
2576+class TestTranslationEmptyMessages(TestCaseWithFactory):
2577 """Test behaviour of empty translation messages."""
2578
2579 layer = LaunchpadZopelessLayer
2580@@ -23,13 +23,15 @@
2581 """Set up context to test in."""
2582 # Pretend we have a product being translated to Serbian.
2583 # This is where we are going to be importing translations to.
2584- factory = LaunchpadObjectFactory()
2585- self.factory = factory
2586- self.productseries = factory.makeProductSeries()
2587- self.productseries.product.official_rosetta = True
2588- self.potemplate = factory.makePOTemplate(self.productseries)
2589+ super(TestTranslationEmptyMessages, self).setUp()
2590+ product = self.factory.makeProduct(
2591+ translations_usage=ServiceUsage.LAUNCHPAD)
2592+ self.productseries = self.factory.makeProductSeries(product=product)
2593+ self.potemplate = self.factory.makePOTemplate(self.productseries)
2594 self.serbian = getUtility(ILanguageSet).getLanguageByCode('sr')
2595- self.pofile_sr = factory.makePOFile('sr', potemplate=self.potemplate)
2596+ self.pofile_sr = self.factory.makePOFile(
2597+ 'sr',
2598+ potemplate=self.potemplate)
2599 self.now = datetime.now(timezone('UTC'))
2600
2601 def test_NoEmptyImporedTranslation(self):
2602
2603=== modified file 'lib/lp/translations/tests/test_hastranslationtemplates.py'
2604--- lib/lp/translations/tests/test_hastranslationtemplates.py 2010-08-20 20:31:18 +0000
2605+++ lib/lp/translations/tests/test_hastranslationtemplates.py 2010-09-09 15:34:46 +0000
2606@@ -6,6 +6,7 @@
2607 from zope.interface.verify import verifyObject
2608
2609 from canonical.testing import ZopelessDatabaseLayer
2610+from lp.app.enums import ServiceUsage
2611 from lp.testing import TestCaseWithFactory
2612 from lp.translations.interfaces.potemplate import IHasTranslationTemplates
2613 from lp.translations.interfaces.translationfileformat import (
2614@@ -152,7 +153,7 @@
2615
2616 # A product or distribution that doesn't use Launchpad for
2617 # translations has no current templates.
2618- self.product_or_distro.official_rosetta = False
2619+ self.product_or_distro.translations_usage = ServiceUsage.EXTERNAL
2620 self.assertFalse(self.container.has_current_translation_templates)
2621
2622 def test_getTranslationTemplateFormats(self):
2623@@ -205,7 +206,7 @@
2624 super(TestProductSeriesHasTranslationTemplates, self).setUp()
2625 self.container = self.factory.makeProductSeries()
2626 self.product_or_distro = self.container.product
2627- self.product_or_distro.official_rosetta = True
2628+ self.product_or_distro.translations_usage = ServiceUsage.LAUNCHPAD
2629
2630
2631 class TestSourcePackageHasTranslationTemplates(
2632@@ -223,7 +224,7 @@
2633 super(TestSourcePackageHasTranslationTemplates, self).setUp()
2634 self.container = self.factory.makeSourcePackage()
2635 self.product_or_distro = self.container.distroseries.distribution
2636- self.product_or_distro.official_rosetta = True
2637+ self.product_or_distro.translations_usage = ServiceUsage.LAUNCHPAD
2638
2639
2640 class TestDistroSeriesHasTranslationTemplates(
2641@@ -243,4 +244,4 @@
2642 super(TestDistroSeriesHasTranslationTemplates, self).setUp()
2643 self.container = self.factory.makeDistroRelease()
2644 self.product_or_distro = self.container.distribution
2645- self.product_or_distro.official_rosetta = True
2646+ self.product_or_distro.translations_usage = ServiceUsage.LAUNCHPAD
2647
2648=== modified file 'lib/lp/translations/tests/test_pofile.py'
2649--- lib/lp/translations/tests/test_pofile.py 2010-09-03 14:38:20 +0000
2650+++ lib/lp/translations/tests/test_pofile.py 2010-09-09 15:34:46 +0000
2651@@ -24,6 +24,7 @@
2652 LaunchpadZopelessLayer,
2653 ZopelessDatabaseLayer,
2654 )
2655+from lp.app.enums import ServiceUsage
2656 from lp.testing import TestCaseWithFactory
2657 from lp.translations.interfaces.pofile import IPOFileSet
2658 from lp.translations.interfaces.translatablemessage import (
2659@@ -46,12 +47,13 @@
2660 # Create a product with two series and a shared POTemplate
2661 # in different series ('devel' and 'stable').
2662 super(TestTranslationSharedPOFile, self).setUp()
2663- self.foo = self.factory.makeProduct(name='foo')
2664+ self.foo = self.factory.makeProduct(
2665+ name='foo',
2666+ translations_usage=ServiceUsage.LAUNCHPAD)
2667 self.foo_devel = self.factory.makeProductSeries(
2668 name='devel', product=self.foo)
2669 self.foo_stable = self.factory.makeProductSeries(
2670 name='stable', product=self.foo)
2671- self.foo.official_rosetta = True
2672
2673 # POTemplate is 'shared' if it has the same name ('messages').
2674 self.devel_potemplate = self.factory.makePOTemplate(
2675@@ -76,7 +78,8 @@
2676 'http://translations.launchpad.dev/foo/devel/+pots/messages/sr',
2677 canonical_url(self.devel_sr_pofile))
2678 self.assertEqual(
2679- 'http://translations.launchpad.dev/foo/devel/+pots/messages/sr/+details',
2680+ ('http://translations.launchpad.dev/'
2681+ 'foo/devel/+pots/messages/sr/+details'),
2682 canonical_url(self.devel_sr_pofile, view_name="+details"))
2683
2684 def test_findPOTMsgSetsContaining(self):
2685@@ -879,12 +882,12 @@
2686 # Create a product with two series and a shared POTemplate
2687 # in different series ('devel' and 'stable').
2688 super(TestSharedPOFileCreation, self).setUp()
2689- self.foo = self.factory.makeProduct()
2690+ self.foo = self.factory.makeProduct(
2691+ translations_usage=ServiceUsage.LAUNCHPAD)
2692 self.foo_devel = self.factory.makeProductSeries(
2693 name='devel', product=self.foo)
2694 self.foo_stable = self.factory.makeProductSeries(
2695 name='stable', product=self.foo)
2696- self.foo.official_rosetta = True
2697
2698 def test_pofile_creation_shared(self):
2699 # When a pofile is created in a POTemplate it is also created in
2700@@ -1009,12 +1012,12 @@
2701 # Create a product with two series and a shared POTemplate
2702 # in different series ('devel' and 'stable').
2703 super(TestTranslationPOFilePOTMsgSetOrdering, self).setUp()
2704- self.foo = self.factory.makeProduct()
2705+ self.foo = self.factory.makeProduct(
2706+ translations_usage=ServiceUsage.LAUNCHPAD)
2707 self.foo_devel = self.factory.makeProductSeries(
2708 name='devel', product=self.foo)
2709 self.foo_stable = self.factory.makeProductSeries(
2710 name='stable', product=self.foo)
2711- self.foo.official_rosetta = True
2712
2713 # POTemplate is 'shared' if it has the same name ('messages').
2714 self.devel_potemplate = self.factory.makePOTemplate(
2715@@ -1288,8 +1291,8 @@
2716 # We create a product with two series, and attach
2717 # a POTemplate and Serbian POFile to each, making
2718 # sure they share translations (potemplates have the same name).
2719- product = self.factory.makeProduct()
2720- product.official_rosetta = True
2721+ product = self.factory.makeProduct(
2722+ translations_usage=ServiceUsage.LAUNCHPAD)
2723 series1 = self.factory.makeProductSeries(product=product,
2724 name='one')
2725 series2 = self.factory.makeProductSeries(product=product,
2726@@ -1324,8 +1327,8 @@
2727 # This is a test for bug #414832 which caused sharing POFiles
2728 # of the touched POFile not to be returned if they had
2729 # IDs smaller than the touched POFile.
2730- product = self.factory.makeProduct()
2731- product.official_rosetta = True
2732+ product = self.factory.makeProduct(
2733+ translations_usage=ServiceUsage.LAUNCHPAD)
2734 series1 = self.factory.makeProductSeries(product=product,
2735 name='one')
2736 series2 = self.factory.makeProductSeries(product=product,
2737@@ -1357,7 +1360,7 @@
2738 # POFile to each, making sure they share translations
2739 # (potemplates have the same name).
2740 distro = self.factory.makeDistribution()
2741- distro.official_rosetta = True
2742+ distro.translations_usage = ServiceUsage.LAUNCHPAD
2743 series1 = self.factory.makeDistroRelease(distribution=distro,
2744 name='one')
2745 sourcepackagename = self.factory.makeSourcePackageName()
2746@@ -1395,9 +1398,9 @@
2747 # Make sure POFiles which are in different products
2748 # are not returned even though they have the same potemplate name.
2749 series1 = self.factory.makeProductSeries(name='one')
2750- series1.product.official_rosetta = True
2751+ series1.product.translations_usage = ServiceUsage.LAUNCHPAD
2752 series2 = self.factory.makeProductSeries(name='two')
2753- series2.product.official_rosetta = True
2754+ series1.product.translations_usage = ServiceUsage.LAUNCHPAD
2755 self.assertNotEqual(series1.product, series2.product)
2756
2757 potemplate1 = self.factory.makePOTemplate(name='shared',
2758
2759=== modified file 'lib/lp/translations/tests/test_potemplate.py'
2760--- lib/lp/translations/tests/test_potemplate.py 2010-08-20 20:31:18 +0000
2761+++ lib/lp/translations/tests/test_potemplate.py 2010-09-09 15:34:46 +0000
2762@@ -7,6 +7,7 @@
2763 from zope.security.proxy import removeSecurityProxy
2764
2765 from canonical.testing import DatabaseFunctionalLayer
2766+from lp.app.enums import ServiceUsage
2767 from lp.registry.interfaces.distribution import IDistributionSet
2768 from lp.services.worlddata.interfaces.language import ILanguageSet
2769 from lp.testing import TestCaseWithFactory
2770@@ -327,8 +328,8 @@
2771
2772 def setUp(self):
2773 super(TestTemplatePrecedence, self).setUp(user='mark@example.com')
2774- self.product = self.factory.makeProduct()
2775- self.product.official_rosetta = True
2776+ self.product = self.factory.makeProduct(
2777+ translations_usage=ServiceUsage.LAUNCHPAD)
2778 self.trunk = self.product.getSeries('trunk')
2779 self.one_dot_oh = self.factory.makeProductSeries(
2780 product=self.product, name='one')
2781
2782=== modified file 'lib/lp/translations/tests/test_potmsgset.py'
2783--- lib/lp/translations/tests/test_potmsgset.py 2010-08-20 20:31:18 +0000
2784+++ lib/lp/translations/tests/test_potmsgset.py 2010-09-09 15:34:46 +0000
2785@@ -20,6 +20,7 @@
2786
2787 from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
2788 from canonical.testing import ZopelessDatabaseLayer
2789+from lp.app.enums import ServiceUsage
2790 from lp.registry.interfaces.person import IPersonSet
2791 from lp.registry.interfaces.product import IProductSet
2792 from lp.services.worlddata.interfaces.language import ILanguageSet
2793@@ -45,12 +46,12 @@
2794 # Create a product with two series and a shared POTemplate
2795 # in different series ('devel' and 'stable').
2796 super(TestTranslationSharedPOTMsgSets, self).setUp()
2797- self.foo = self.factory.makeProduct()
2798+ self.foo = self.factory.makeProduct(
2799+ translations_usage=ServiceUsage.LAUNCHPAD)
2800 self.foo_devel = self.factory.makeProductSeries(
2801 name='devel', product=self.foo)
2802 self.foo_stable = self.factory.makeProductSeries(
2803 name='stable', product=self.foo)
2804- self.foo.official_rosetta = True
2805
2806 # POTemplate is 'shared' if it has the same name ('messages').
2807 self.devel_potemplate = self.factory.makePOTemplate(
2808@@ -324,7 +325,8 @@
2809 # Create an external POTemplate with a POTMsgSet using
2810 # the same English string as the one in self.potmsgset.
2811 external_template = self.factory.makePOTemplate()
2812- external_template.productseries.product.official_rosetta = True
2813+ product = external_template.productseries.product
2814+ product.translations_usage = ServiceUsage.LAUNCHPAD
2815 external_potmsgset = self.factory.makePOTMsgSet(
2816 external_template,
2817 singular=self.potmsgset.singular_text)
2818@@ -383,7 +385,8 @@
2819 # Create an external POTemplate with a POTMsgSet using
2820 # the same English string as the one in self.potmsgset.
2821 external_template = self.factory.makePOTemplate()
2822- external_template.productseries.product.official_rosetta = True
2823+ product = external_template.productseries.product
2824+ product.translations_usage = ServiceUsage.LAUNCHPAD
2825 external_potmsgset = self.factory.makePOTMsgSet(
2826 external_template,
2827 singular=self.potmsgset.singular_text)
2828@@ -738,10 +741,10 @@
2829 # create TranslationMessage objects.
2830 super(TestPOTMsgSetSuggestions, self).setUp()
2831 self.now = self.gen_now().next
2832- self.foo = self.factory.makeProduct()
2833+ self.foo = self.factory.makeProduct(
2834+ translations_usage=ServiceUsage.LAUNCHPAD)
2835 self.foo_main = self.factory.makeProductSeries(
2836 name='main', product=self.foo)
2837- self.foo.official_rosetta = True
2838
2839 self.potemplate = self.factory.makePOTemplate(
2840 productseries=self.foo_main, name="messages")
2841@@ -926,10 +929,10 @@
2842 # create TranslationMessage objects.
2843 super(TestPOTMsgSetResetTranslation, self).setUp()
2844 self.now = self.gen_now().next
2845- self.foo = self.factory.makeProduct()
2846+ self.foo = self.factory.makeProduct(
2847+ translations_usage=ServiceUsage.LAUNCHPAD)
2848 self.foo_main = self.factory.makeProductSeries(
2849 name='main', product=self.foo)
2850- self.foo.official_rosetta = True
2851
2852 self.potemplate = self.factory.makePOTemplate(
2853 productseries=self.foo_main, name="messages")
2854
2855=== modified file 'lib/lp/translations/tests/test_productserieslanguage.py'
2856--- lib/lp/translations/tests/test_productserieslanguage.py 2010-08-20 20:31:18 +0000
2857+++ lib/lp/translations/tests/test_productserieslanguage.py 2010-09-09 15:34:46 +0000
2858@@ -10,6 +10,7 @@
2859 from zope.security.proxy import removeSecurityProxy
2860
2861 from canonical.testing import ZopelessDatabaseLayer
2862+from lp.app.enums import ServiceUsage
2863 from lp.services.worlddata.interfaces.language import ILanguageSet
2864 from lp.testing import TestCaseWithFactory
2865 from lp.translations.interfaces.productserieslanguage import (
2866@@ -26,8 +27,10 @@
2867 def setUp(self):
2868 # Create a productseries that uses translations.
2869 TestCaseWithFactory.setUp(self)
2870- self.productseries = self.factory.makeProductSeries()
2871- self.productseries.product.official_rosetta = True
2872+ product = self.factory.makeProduct(
2873+ translations_usage=ServiceUsage.LAUNCHPAD)
2874+ self.productseries = self.factory.makeProductSeries(
2875+ product=product)
2876
2877 def test_no_templates_no_translation(self):
2878 # There are no templates and no translations.
2879@@ -125,8 +128,10 @@
2880 def setUp(self):
2881 # Create a productseries that uses translations.
2882 TestCaseWithFactory.setUp(self)
2883- self.productseries = self.factory.makeProductSeries()
2884- self.productseries.product.official_rosetta = True
2885+ product = self.factory.makeProduct(
2886+ translations_usage=ServiceUsage.LAUNCHPAD)
2887+ self.productseries = self.factory.makeProductSeries(
2888+ product=product)
2889 self.psl_set = getUtility(IProductSeriesLanguageSet)
2890 self.language = getUtility(ILanguageSet).getLanguageByCode('sr')
2891
2892
2893=== modified file 'lib/lp/translations/tests/test_shared_potemplate.py'
2894--- lib/lp/translations/tests/test_shared_potemplate.py 2010-08-20 20:31:18 +0000
2895+++ lib/lp/translations/tests/test_shared_potemplate.py 2010-09-09 15:34:46 +0000
2896@@ -10,6 +10,7 @@
2897 from zope.security.proxy import removeSecurityProxy
2898
2899 from canonical.testing import ZopelessDatabaseLayer
2900+from lp.app.enums import ServiceUsage
2901 from lp.testing.factory import LaunchpadObjectFactory
2902
2903
2904@@ -24,12 +25,12 @@
2905 # in different series ('devel' and 'stable').
2906 factory = LaunchpadObjectFactory()
2907 self.factory = factory
2908- self.foo = factory.makeProduct()
2909+ self.foo = self.factory.makeProduct(
2910+ translations_usage=ServiceUsage.LAUNCHPAD)
2911 self.foo_devel = factory.makeProductSeries(
2912 name='devel', product=self.foo)
2913 self.foo_stable = factory.makeProductSeries(
2914 name='stable', product=self.foo)
2915- self.foo.official_rosetta = True
2916
2917 # POTemplate is a 'sharing' one if it has the same name ('messages').
2918 self.devel_potemplate = factory.makePOTemplate(
2919
2920=== modified file 'lib/lp/translations/tests/test_suggestions.py'
2921--- lib/lp/translations/tests/test_suggestions.py 2010-08-20 20:31:18 +0000
2922+++ lib/lp/translations/tests/test_suggestions.py 2010-09-09 15:34:46 +0000
2923@@ -17,6 +17,7 @@
2924
2925 from canonical.config import config
2926 from canonical.testing import LaunchpadZopelessLayer
2927+from lp.app.enums import ServiceUsage
2928 from lp.services.worlddata.interfaces.language import ILanguageSet
2929 from lp.testing.factory import LaunchpadObjectFactory
2930 from lp.translations.interfaces.translationmessage import (
2931@@ -36,10 +37,14 @@
2932 # suggestions for the other.
2933 factory = LaunchpadObjectFactory()
2934 self.factory = factory
2935- self.foo_trunk = factory.makeProductSeries()
2936- self.bar_trunk = factory.makeProductSeries()
2937- self.foo_trunk.product.official_rosetta = True
2938- self.bar_trunk.product.official_rosetta = True
2939+ foo_product = factory.makeProduct(
2940+ translations_usage=ServiceUsage.LAUNCHPAD)
2941+ bar_product = factory.makeProduct(
2942+ translations_usage=ServiceUsage.LAUNCHPAD)
2943+ self.foo_trunk = factory.makeProductSeries(
2944+ product=foo_product)
2945+ self.bar_trunk = factory.makeProductSeries(
2946+ product=bar_product)
2947 self.foo_template = factory.makePOTemplate(self.foo_trunk)
2948 self.bar_template = factory.makePOTemplate(self.bar_trunk)
2949 self.nl = getUtility(ILanguageSet).getLanguageByCode('nl')
2950@@ -222,5 +227,6 @@
2951 "TranslationMessage with errors is not correctly"
2952 "marked as such in the database.")
2953
2954+
2955 def test_suite():
2956 return unittest.TestLoader().loadTestsFromName(__name__)
2957
2958=== modified file 'lib/lp/translations/tests/test_translatablemessage.py'
2959--- lib/lp/translations/tests/test_translatablemessage.py 2010-08-20 20:31:18 +0000
2960+++ lib/lp/translations/tests/test_translatablemessage.py 2010-09-09 15:34:46 +0000
2961@@ -15,6 +15,7 @@
2962 import transaction
2963
2964 from canonical.testing import ZopelessDatabaseLayer
2965+from lp.app.enums import ServiceUsage
2966 from lp.testing import TestCaseWithFactory
2967 from lp.translations.model.translatablemessage import TranslatableMessage
2968
2969@@ -31,8 +32,8 @@
2970 `POTMsgSet`, as well as a Esperanto translation.
2971 """
2972 super(TestTranslatableMessageBase, self).setUp()
2973- self.product = self.factory.makeProduct()
2974- self.product.official_rosetta = True
2975+ self.product = self.factory.makeProduct(
2976+ translations_usage=ServiceUsage.LAUNCHPAD)
2977 self.trunk = self.product.getSeries('trunk')
2978 self.potemplate = self.factory.makePOTemplate(
2979 productseries=self.trunk)
2980@@ -137,7 +138,8 @@
2981 super(TestTranslatableMessageExternal, self).setUp()
2982 common_msgid = self.potmsgset.singular_text
2983 self.external_potemplate = self.factory.makePOTemplate()
2984- self.external_potemplate.productseries.product.official_rosetta = True
2985+ product = self.external_potemplate.productseries.product
2986+ product.translations_usage = ServiceUsage.LAUNCHPAD
2987 self.external_potmsgset = self.factory.makePOTMsgSet(
2988 potemplate=self.external_potemplate,
2989 singular=common_msgid, sequence=1)
2990@@ -175,24 +177,24 @@
2991 super(TestTranslatableMessageSuggestions, self).setUp()
2992 self.now = self.gen_now().next
2993 self.suggestion1 = self._createTranslation(date_updated=self.now())
2994- self.current = self._createTranslation(is_current=True,
2995+ self.current = self._createTranslation(is_current=True,
2996 date_updated=self.now())
2997 self.suggestion2 = self._createTranslation(date_updated=self.now())
2998 self.message = TranslatableMessage(self.potmsgset, self.pofile)
2999
3000 def test_getAllSuggestions(self):
3001- # There are three different methods to return
3002+ # There are three different methods to return
3003 suggestions = self.message.getAllSuggestions()
3004 self.assertContentEqual([self.suggestion1, self.suggestion2],
3005 suggestions)
3006
3007 def test_getDismissedSuggestions(self):
3008- # There are three different methods to return
3009+ # There are three different methods to return
3010 suggestions = self.message.getDismissedSuggestions()
3011 self.assertContentEqual([self.suggestion1], suggestions)
3012
3013 def test_getUnreviewedSuggestions(self):
3014- # There are three different methods to return
3015+ # There are three different methods to return
3016 suggestions = self.message.getUnreviewedSuggestions()
3017 self.assertContentEqual([self.suggestion2], suggestions)
3018
3019
3020=== modified file 'lib/lp/translations/tests/test_translatedlanguage.py'
3021--- lib/lp/translations/tests/test_translatedlanguage.py 2010-08-20 20:31:18 +0000
3022+++ lib/lp/translations/tests/test_translatedlanguage.py 2010-09-09 15:34:46 +0000
3023@@ -8,6 +8,7 @@
3024 from zope.security.proxy import removeSecurityProxy
3025
3026 from canonical.testing import ZopelessDatabaseLayer
3027+from lp.app.enums import ServiceUsage
3028 from lp.testing import TestCaseWithFactory
3029 from lp.translations.interfaces.productserieslanguage import (
3030 IProductSeriesLanguageSet,
3031@@ -24,8 +25,10 @@
3032 def setUp(self):
3033 # Create a productseries that uses translations.
3034 TestCaseWithFactory.setUp(self)
3035- self.productseries = self.factory.makeProductSeries()
3036- self.productseries.product.official_rosetta = True
3037+ product = self.factory.makeProduct(
3038+ translations_usage = ServiceUsage.LAUNCHPAD)
3039+ self.productseries = self.factory.makeProductSeries(
3040+ product=product)
3041 self.parent = self.productseries
3042 self.psl_set = getUtility(IProductSeriesLanguageSet)
3043 self.language = self.factory.makeLanguage('sr@test')
3044
3045=== modified file 'lib/lp/translations/tests/test_translations_to_review.py'
3046--- lib/lp/translations/tests/test_translations_to_review.py 2010-08-20 20:31:18 +0000
3047+++ lib/lp/translations/tests/test_translations_to_review.py 2010-09-09 15:34:46 +0000
3048@@ -16,6 +16,7 @@
3049 from zope.security.proxy import removeSecurityProxy
3050
3051 from canonical.testing import DatabaseFunctionalLayer
3052+from lp.app.enums import ServiceUsage
3053 from lp.services.worlddata.model.language import LanguageSet
3054 from lp.testing import TestCaseWithFactory
3055 from lp.translations.interfaces.translationsperson import ITranslationsPerson
3056@@ -28,6 +29,7 @@
3057
3058 class ReviewTestMixin:
3059 """Base for testing which translations a reviewer can review."""
3060+
3061 def setUpMixin(self, for_product=True):
3062 """Set up test environment.
3063
3064@@ -68,7 +70,7 @@
3065 transaction.commit()
3066
3067 self.supercontext.translationgroup = self.translationgroup
3068- self.supercontext.official_rosetta = True
3069+ self.supercontext.translations_usage = ServiceUsage.LAUNCHPAD
3070
3071 self.potemplate = self.factory.makePOTemplate(
3072 productseries=self.productseries, distroseries=self.distroseries,
3073@@ -111,6 +113,7 @@
3074
3075 Can be applied to product or distribution setups.
3076 """
3077+
3078 def test_OneFileToReview(self):
3079 # In the base case, the method finds one POFile for self.person
3080 # to review.
3081@@ -131,7 +134,7 @@
3082 def test_getReviewableTranslationFiles_not_translating_in_launchpad(self):
3083 # We don't see products/distros that don't use Launchpad for
3084 # translations.
3085- self.supercontext.official_rosetta = False
3086+ self.supercontext.translations_usage = ServiceUsage.NOT_APPLICABLE
3087 self.assertEqual(self._getReviewables(), [])
3088
3089 def test_getReviewableTranslationFiles_non_reviewer(self):
3090@@ -200,7 +203,7 @@
3091 other_pofile = removeSecurityProxy(other_pofile)
3092
3093 product = other_pofile.potemplate.productseries.product
3094- product.official_rosetta = True
3095+ product.translations_usage = ServiceUsage.LAUNCHPAD
3096
3097 if with_unreviewed:
3098 other_pofile.unreviewed_count = 1
3099
3100=== modified file 'lib/lp/translations/windmill/tests/test_documentation_links.py'
3101--- lib/lp/translations/windmill/tests/test_documentation_links.py 2010-08-20 20:31:18 +0000
3102+++ lib/lp/translations/windmill/tests/test_documentation_links.py 2010-09-09 15:34:46 +0000
3103@@ -9,6 +9,7 @@
3104 from zope.security.proxy import removeSecurityProxy
3105
3106 from canonical.launchpad.windmill.testing import lpuser
3107+from lp.app.enums import ServiceUsage
3108 from lp.testing import WindmillTestCase
3109 from lp.translations.windmill.testing import TranslationsWindmillLayer
3110
3111@@ -52,7 +53,7 @@
3112 project = self.factory.makeProduct(
3113 name='test-product',
3114 displayname='Test Product',
3115- official_rosetta=True)
3116+ translations_usage=ServiceUsage.LAUNCHPAD)
3117 removeSecurityProxy(project).translationgroup = group
3118
3119 potemplate = self.createPOTemplateWithPOTMsgSets(
3120
3121=== modified file 'lib/lp/translations/windmill/tests/test_import_queue.py'
3122--- lib/lp/translations/windmill/tests/test_import_queue.py 2010-08-20 20:31:18 +0000
3123+++ lib/lp/translations/windmill/tests/test_import_queue.py 2010-09-09 15:34:46 +0000
3124@@ -8,7 +8,6 @@
3125
3126 import transaction
3127 from zope.component import getUtility
3128-from zope.security.proxy import removeSecurityProxy
3129
3130 from canonical.launchpad.webapp import canonical_url
3131 from canonical.launchpad.windmill.testing import lpuser
3132@@ -18,6 +17,7 @@
3133 SLEEP,
3134 )
3135 from canonical.launchpad.windmill.testing.lpuser import login_person
3136+from lp.app.enums import ServiceUsage
3137 from lp.testing import WindmillTestCase
3138 from lp.translations.interfaces.translationimportqueue import (
3139 ITranslationImportQueue,
3140@@ -41,8 +41,8 @@
3141 'field.potemplate',
3142 'field.potemplate_name',
3143 'field.language',
3144- ]
3145- }
3146+ ],
3147+ }
3148 SELECT_FIELDS = [
3149 'field.potemplate',
3150 'field.language',
3151@@ -55,8 +55,7 @@
3152 input_tag = 'input'
3153 return (
3154 u"//tr[contains(@class,'unseen')]"
3155- u"//%s[@id='%s']" % (input_tag, field_id)
3156- )
3157+ u"//%s[@id='%s']" % (input_tag, field_id))
3158
3159 def _assertAllFieldsVisible(self, client, fields):
3160 """Assert that all given fields are visible.
3161@@ -279,8 +278,9 @@
3162 name="hubert", displayname="Hubert Hunt", password="test",
3163 email="hubert@example.com")
3164 # Create a project and an import entry with it.
3165- product = self.factory.makeProduct(owner=hubert)
3166- removeSecurityProxy(product).official_rosetta = True
3167+ product = self.factory.makeProduct(
3168+ owner=hubert,
3169+ translations_usage=ServiceUsage.LAUNCHPAD)
3170 productseries = product.getSeries('trunk')
3171 queue = getUtility(ITranslationImportQueue)
3172 potemplate = self.factory.makePOTemplate(productseries=productseries)