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
=== modified file 'lib/lp/app/enums.py'
--- lib/lp/app/enums.py 2010-08-20 20:31:18 +0000
+++ lib/lp/app/enums.py 2010-09-09 15:34:46 +0000
@@ -1,11 +1,12 @@
1# Copyright 2010 Canonical Ltd. This software is licensed under the1# Copyright 2010 Canonical Ltd. This software is licensed under the
2# GNU Affero General Public License version 3 (see the file LICENSE).2# GNU Affero General Public License version 3 (see the file LICENSE).
33
4"""Enumerations used in the lp/app modules."""4"""Enumerations and related utilities used in the lp/app modules."""
55
6__metaclass__ = type6__metaclass__ = type
7__all__ = [7__all__ = [
8 'ServiceUsage',8 'ServiceUsage',
9 'service_uses_launchpad',
9 ]10 ]
1011
11from lazr.enum import (12from lazr.enum import (
@@ -45,3 +46,7 @@
4546
46 The pillar does not use this type of service in Launchpad or externally.47 The pillar does not use this type of service in Launchpad or externally.
47 """)48 """)
49
50
51def service_uses_launchpad(usage_enum):
52 return usage_enum == ServiceUsage.LAUNCHPAD
4853
=== modified file 'lib/lp/registry/browser/distribution.py'
--- lib/lp/registry/browser/distribution.py 2010-09-03 03:12:39 +0000
+++ lib/lp/registry/browser/distribution.py 2010-09-09 15:34:46 +0000
@@ -74,6 +74,7 @@
74from canonical.launchpad.webapp.breadcrumb import Breadcrumb74from canonical.launchpad.webapp.breadcrumb import Breadcrumb
75from canonical.launchpad.webapp.interfaces import ILaunchBag75from canonical.launchpad.webapp.interfaces import ILaunchBag
76from canonical.widgets.image import ImageChangeWidget76from canonical.widgets.image import ImageChangeWidget
77from lp.app.enums import service_uses_launchpad
77from lp.answers.browser.faqtarget import FAQTargetNavigationMixin78from lp.answers.browser.faqtarget import FAQTargetNavigationMixin
78from lp.answers.browser.questiontarget import (79from lp.answers.browser.questiontarget import (
79 QuestionTargetFacetMixin,80 QuestionTargetFacetMixin,
@@ -135,7 +136,7 @@
135 if self.context.codehosting_usage == ServiceUsage.LAUNCHPAD:136 if self.context.codehosting_usage == ServiceUsage.LAUNCHPAD:
136 url = canonical_url(self.context, rootsite='code')137 url = canonical_url(self.context, rootsite='code')
137 uses.append(href_template % (url, 'Branches'))138 uses.append(href_template % (url, 'Branches'))
138 if self.context.official_rosetta:139 if service_uses_launchpad(self.context.translations_usage):
139 url = canonical_url(self.context, rootsite='translations')140 url = canonical_url(self.context, rootsite='translations')
140 uses.append(href_template % (url, 'Translations'))141 uses.append(href_template % (url, 'Translations'))
141142
142143
=== modified file 'lib/lp/registry/browser/pillar.py'
--- lib/lp/registry/browser/pillar.py 2010-09-03 03:12:39 +0000
+++ lib/lp/registry/browser/pillar.py 2010-09-09 15:34:46 +0000
@@ -30,7 +30,10 @@
30 nearest,30 nearest,
31 )31 )
32from canonical.launchpad.webapp.tales import MenuAPI32from canonical.launchpad.webapp.tales import MenuAPI
33from lp.app.enums import ServiceUsage33from lp.app.enums import (
34 ServiceUsage,
35 service_uses_launchpad,
36 )
34from lp.app.interfaces.launchpad import IServiceUsage37from lp.app.interfaces.launchpad import IServiceUsage
35from lp.registry.browser.structuralsubscription import (38from lp.registry.browser.structuralsubscription import (
36 StructuralSubscriptionMenuMixin,39 StructuralSubscriptionMenuMixin,
@@ -72,7 +75,7 @@
72 def help_translate(self):75 def help_translate(self):
73 return Link(76 return Link(
74 '', 'Help translate', site='translations', icon='translations',77 '', 'Help translate', site='translations', icon='translations',
75 enabled=self.pillar.official_rosetta)78 enabled=service_uses_launchpad(self.pillar.translations_usage))
7679
77 def submit_code(self):80 def submit_code(self):
78 if self.pillar.codehosting_usage in [81 if self.pillar.codehosting_usage in [
@@ -104,7 +107,7 @@
104 self.official_malone = False107 self.official_malone = False
105 self.official_answers = False108 self.official_answers = False
106 self.official_blueprints = False109 self.official_blueprints = False
107 self.official_rosetta = False110 self.translations_usage = ServiceUsage.UNKNOWN
108 self.codehosting_usage = ServiceUsage.UNKNOWN111 self.codehosting_usage = ServiceUsage.UNKNOWN
109 pillar = nearest(self.context, IPillar)112 pillar = nearest(self.context, IPillar)
110 if IProjectGroup.providedBy(pillar):113 if IProjectGroup.providedBy(pillar):
@@ -121,7 +124,7 @@
121 self.codehosting_usage = distribution.codehosting_usage124 self.codehosting_usage = distribution.codehosting_usage
122 elif IDistributionSourcePackage.providedBy(self.context):125 elif IDistributionSourcePackage.providedBy(self.context):
123 self.official_blueprints = False126 self.official_blueprints = False
124 self.official_rosetta = False127 self.translations_usage = ServiceUsage.UNKNOWN
125 else:128 else:
126 # The context is used by all apps.129 # The context is used by all apps.
127 pass130 pass
@@ -136,8 +139,7 @@
136 self.official_answers = True139 self.official_answers = True
137 if pillar.official_blueprints:140 if pillar.official_blueprints:
138 self.official_blueprints = True141 self.official_blueprints = True
139 if pillar.official_rosetta:142 self.translations_usage = IServiceUsage(pillar).translations_usage
140 self.official_rosetta = True
141 self.codehosting_usage = IServiceUsage(pillar).codehosting_usage143 self.codehosting_usage = IServiceUsage(pillar).codehosting_usage
142144
143 @property145 @property
@@ -145,8 +147,9 @@
145 """This `IPillar` uses Launchpad."""147 """This `IPillar` uses Launchpad."""
146 return (148 return (
147 self.official_malone or self.official_answers149 self.official_malone or self.official_answers
148 or self.official_blueprints or self.official_rosetta150 or self.official_blueprints
149 or self.codehosting_usage == ServiceUsage.LAUNCHPAD)151 or service_uses_launchpad(self.translations_usage)
152 or service_uses_launchpad(self.codehosting_usage))
150153
151 @property154 @property
152 def enabled_links(self):155 def enabled_links(self):
153156
=== modified file 'lib/lp/registry/browser/tests/pillar-views.txt'
--- lib/lp/registry/browser/tests/pillar-views.txt 2010-08-27 17:45:57 +0000
+++ lib/lp/registry/browser/tests/pillar-views.txt 2010-09-09 15:34:46 +0000
@@ -35,8 +35,8 @@
35 True35 True
36 >>> view.official_answers36 >>> view.official_answers
37 True37 True
38 >>> view.official_rosetta38 >>> view.translations_usage.name
39 False39 'UNKNOWN'
40 >>> view.official_blueprints40 >>> view.official_blueprints
41 False41 False
42 >>> view.codehosting_usage.name42 >>> view.codehosting_usage.name
@@ -230,9 +230,10 @@
230set the links. Despite the fact that the distribution uses blueprints,230set the links. Despite the fact that the distribution uses blueprints,
231and translations those links are not enabled for DistributionSourcePackages.231and translations those links are not enabled for DistributionSourcePackages.
232232
233 >>> from lp.app.enums import ServiceUsage
233 >>> login_person(distribution.owner)234 >>> login_person(distribution.owner)
234 >>> distribution.official_blueprints = True235 >>> distribution.official_blueprints = True
235 >>> distribution.official_rosetta = True236 >>> distribution.translations_usage = ServiceUsage.LAUNCHPAD
236 >>> package = factory.makeDistributionSourcePackage(237 >>> package = factory.makeDistributionSourcePackage(
237 ... sourcepackagename="box",238 ... sourcepackagename="box",
238 ... distribution=distribution)239 ... distribution=distribution)
239240
=== modified file 'lib/lp/registry/browser/tests/productseries-views.txt'
--- lib/lp/registry/browser/tests/productseries-views.txt 2010-09-03 06:06:40 +0000
+++ lib/lp/registry/browser/tests/productseries-views.txt 2010-09-09 15:34:46 +0000
@@ -23,11 +23,12 @@
23The ProductSeries involvement view uses the ProductSeriesInvolvedMenu when23The ProductSeries involvement view uses the ProductSeriesInvolvedMenu when
24rendering links:24rendering links:
2525
26 >>> from lp.app.enums import ServiceUsage
26 >>> login_person(product.owner)27 >>> login_person(product.owner)
27 >>> product.official_answers = True28 >>> product.official_answers = True
28 >>> product.official_blueprints = True29 >>> product.official_blueprints = True
29 >>> product.official_malone = True30 >>> product.official_malone = True
30 >>> product.official_rosetta = True31 >>> product.translations_usage = ServiceUsage.LAUNCHPAD
31 >>> view = create_view(series, '+get-involved')32 >>> view = create_view(series, '+get-involved')
3233
33 # official_answers is always false for product series.34 # official_answers is always false for product series.
@@ -37,10 +38,11 @@
37 True38 True
38 >>> print view.official_malone39 >>> print view.official_malone
39 True40 True
40 >>> print view.official_rosetta41 >>> print view.translations_usage.name
41 True42 LAUNCHPAD
42 >>> print view.codehosting_usage.name43 >>> print view.codehosting_usage.name
43 UNKNOWN44 UNKNOWN
45
44 >>> for link in view.enabled_links:46 >>> for link in view.enabled_links:
45 ... print link.url47 ... print link.url
46 http://bugs.launchpad.dev/app/simple/+filebug48 http://bugs.launchpad.dev/app/simple/+filebug
@@ -476,7 +478,7 @@
476A series cannot be deleted if it is has translation templates.478A series cannot be deleted if it is has translation templates.
477479
478 >>> translated_series = factory.makeProductSeries(product=product)480 >>> translated_series = factory.makeProductSeries(product=product)
479 >>> product.official_rosetta = True481 >>> product.translations_usage = ServiceUsage.LAUNCHPAD
480 >>> po_template = factory.makePOTemplate(482 >>> po_template = factory.makePOTemplate(
481 ... name='gibberish', productseries=translated_series)483 ... name='gibberish', productseries=translated_series)
482 >>> translated_view = create_initialized_view(484 >>> translated_view = create_initialized_view(
483485
=== modified file 'lib/lp/registry/doc/distribution.txt'
--- lib/lp/registry/doc/distribution.txt 2010-08-23 00:51:30 +0000
+++ lib/lp/registry/doc/distribution.txt 2010-09-09 15:34:46 +0000
@@ -1,4 +1,5 @@
1= Distributions =1Distributions
2=============
23
3From the DerivationOverview spec4From the DerivationOverview spec
4<https://launchpad.canonical.com/DerivationOverview>:5<https://launchpad.canonical.com/DerivationOverview>:
@@ -143,7 +144,8 @@
143 False144 False
144145
145146
146== Distribution Sorting ==147Distribution Sorting
148--------------------
147149
148If you ask for all the distributions in the DistributionSet you should get150If you ask for all the distributions in the DistributionSet you should get
149Ubuntu (and all flavours of it) first and the rest alphabetically:151Ubuntu (and all flavours of it) first and the rest alphabetically:
@@ -164,7 +166,8 @@
164 True166 True
165167
166168
167=== Searching for DistributionSourcePackages ===169Searching for DistributionSourcePackages
170........................................
168171
169The distribution also allows you to look for source packages that match172The distribution also allows you to look for source packages that match
170a certain string through the magic of fti. For instance:173a certain string through the magic of fti. For instance:
@@ -232,7 +235,8 @@
232 DistributionSourcePackage: alsa-utils235 DistributionSourcePackage: alsa-utils
233236
234237
235=== Searching for binary packages ===238Searching for binary packages
239.............................
236240
237There are two useful functions for searching binary packages related241There are two useful functions for searching binary packages related
238to the distribution, searchBinaryPackages() and searchBinaryPackagesFTI().242to the distribution, searchBinaryPackages() and searchBinaryPackagesFTI().
@@ -291,7 +295,8 @@
291 [u'mozilla-firefox']295 [u'mozilla-firefox']
292296
293297
294=== Finding distroseriess and pockets from distribution names ===298Finding distroseriess and pockets from distribution names
299.........................................................
295300
296A distribution knows what distroseriess it has. Those distroseriess have301A distribution knows what distroseriess it has. Those distroseriess have
297pockets which have suffixes used by the archive publisher. Because we302pockets which have suffixes used by the archive publisher. Because we
@@ -336,26 +341,27 @@
336 NotFoundError: 'hoary-bullshit'341 NotFoundError: 'hoary-bullshit'
337342
338343
339=== Upload related stuff ===344Upload related stuff
345....................
340346
341When uploading to a distribution we need to query its uploaders. Each347When uploading to a distribution we need to query its uploaders. Each
342uploader record is in fact an ArchivePermission record that tells us348uploader record is in fact an ArchivePermission record that tells us
343what component is uploadable to by what person or group of people.349what component is uploadable to by what person or group of people.
344350
345 >>> from operator import attrgetter351 >>> from operator import attrgetter
346 >>> for permission in sorted(352 >>> for permission in sorted(
347 ... ubuntu.uploaders, key=attrgetter("id")):353 ... ubuntu.uploaders, key=attrgetter("id")):
348 ... assert not permission.archive.is_ppa354 ... assert not permission.archive.is_ppa
349 ... print permission.component.name355 ... print permission.component.name
350 ... print permission.person.displayname356 ... print permission.person.displayname
351 universe357 universe
352 Ubuntu Team358 Ubuntu Team
353 restricted359 restricted
354 Ubuntu Team360 Ubuntu Team
355 main361 main
356 Ubuntu Team362 Ubuntu Team
357 partner363 partner
358 Canonical Partner Developers364 Canonical Partner Developers
359365
360When processing an upload we may want to find a file (E.g. if an366When processing an upload we may want to find a file (E.g. if an
361incomplete source is uploaded).367incomplete source is uploaded).
@@ -375,7 +381,8 @@
375 AssertionError: searching in an explicitly empty space is pointless381 AssertionError: searching in an explicitly empty space is pointless
376382
377383
378=== Launchpad Usage ===384Launchpad Usage
385...............
379386
380A distribution can specify if it uses Malone, Rosetta, or Answers387A distribution can specify if it uses Malone, Rosetta, or Answers
381officially. Ubuntu uses all of them:388officially. Ubuntu uses all of them:
@@ -385,8 +392,8 @@
385 >>> ubuntu = getUtility(ILaunchpadCelebrities).ubuntu392 >>> ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
386 >>> ubuntu.official_malone393 >>> ubuntu.official_malone
387 True394 True
388 >>> ubuntu.official_rosetta395 >>> ubuntu.translations_usage.name
389 True396 'LAUNCHPAD'
390 >>> ubuntu.official_answers397 >>> ubuntu.official_answers
391 True398 True
392 >>> ubuntu.official_blueprints399 >>> ubuntu.official_blueprints
@@ -397,12 +404,12 @@
397 >>> print ubuntu.bug_tracking_usage.name404 >>> print ubuntu.bug_tracking_usage.name
398 LAUNCHPAD405 LAUNCHPAD
399406
400While the other attributes track the other official_ attributes. 407While the other attributes track the other official_ attributes.
401408
402 >>> print ubuntu.official_rosetta409 >>> print ubuntu.official_rosetta
403 True410 True
404 >>> print ubuntu.translations_usage.name411 >>> print ubuntu.translations_usage.name
405 LAUNCHPAD 412 LAUNCHPAD
406 >>> print ubuntu.official_answers413 >>> print ubuntu.official_answers
407 True414 True
408 >>> print ubuntu.answers_usage.name415 >>> print ubuntu.answers_usage.name
@@ -412,7 +419,8 @@
412 >>> print ubuntu.blueprints_usage.name419 >>> print ubuntu.blueprints_usage.name
413 LAUNCHPAD420 LAUNCHPAD
414421
415If the official_ attributes are False, the usage enums don't know anything.422If the official_ attributes are False and the enum hasn't been set,
423the usage enums don't know anything.
416424
417 >>> login_person(ubuntu.owner.teamowner)425 >>> login_person(ubuntu.owner.teamowner)
418 >>> ubuntu.official_rosetta = False426 >>> ubuntu.official_rosetta = False
@@ -422,37 +430,35 @@
422A distribution *cannot* specify that it uses codehosting. Currently there's430A distribution *cannot* specify that it uses codehosting. Currently there's
423no way for a distribution to use codehosting.431no way for a distribution to use codehosting.
424432
425 >>> ubuntu.official_codehosting433 >>> from lp.app.enums import ServiceUsage
426 False
427 >>> ubuntu.official_codehosting = True
428 Traceback (most recent call last):
429 ForbiddenAttribute: ('official_codehosting', ...)
430
431 >>> print ubuntu.codehosting_usage.name434 >>> print ubuntu.codehosting_usage.name
432 NOT_APPLICABLE435 NOT_APPLICABLE
436 >>> ubuntu.codehosting_usage = ServiceUsage.LAUNCHPAD
437 Traceback (most recent call last):
438 AttributeError: can't set attribute...
433439
434While Debian uses none:440While Debian uses none:
435441
436 >>> debian = getUtility(ILaunchpadCelebrities).debian442 >>> debian = getUtility(ILaunchpadCelebrities).debian
437 >>> debian.official_malone443 >>> print debian.bug_tracking_usage.name
438 False444 UNKNOWN
439 >>> debian.official_rosetta445 >>> print debian.translations_usage.name
440 False446 UNKNOWN
441 >>> debian.official_answers447 >>> print debian.answers_usage.name
442 False448 UNKNOWN
443 >>> debian.official_codehosting449 >>> print debian.codehosting_usage.name
444 False450 NOT_APPLICABLE
445 >>> debian.official_blueprints451 >>> print debian.blueprints_usage.name
446 False452 UNKNOWN
447453
448Gentoo only uses Malone454Gentoo only uses Malone
449455
450 >>> print gentoo.official_malone456 >>> print gentoo.bug_tracking_usage.name
451 True457 LAUNCHPAD
452 >>> print gentoo.official_rosetta458 >>> print gentoo.translations_usage.name
453 False459 UNKNOWN
454 >>> print gentoo.official_answers460 >>> print gentoo.answers_usage.name
455 False461 UNKNOWN
456462
457Launchpad admins and the distro owner can set these fields.463Launchpad admins and the distro owner can set these fields.
458464
@@ -464,9 +470,9 @@
464 >>> debian.official_malone = True470 >>> debian.official_malone = True
465 >>> debian.official_malone471 >>> debian.official_malone
466 True472 True
467 >>> debian.official_rosetta = True473 >>> debian.translations_usage = ServiceUsage.LAUNCHPAD
468 >>> debian.official_rosetta474 >>> debian.translations_usage.name
469 True475 'LAUNCHPAD'
470476
471 >>> debian_owner = factory.makePerson()477 >>> debian_owner = factory.makePerson()
472 >>> debian.owner = debian_owner478 >>> debian.owner = debian_owner
@@ -484,12 +490,13 @@
484 >>> debian.official_malone = True490 >>> debian.official_malone = True
485 Traceback (most recent call last):491 Traceback (most recent call last):
486 Unauthorized: (..., 'official_malone', 'launchpad.Edit')492 Unauthorized: (..., 'official_malone', 'launchpad.Edit')
487 >>> debian.official_rosetta = True493 >>> debian.translations_usage = ServiceUsage.LAUNCHPAD
488 Traceback (most recent call last):494 Traceback (most recent call last):
489 Unauthorized: (..., 'official_rosetta', 'launchpad.Edit')495 Unauthorized: (..., 'translations_usage', 'launchpad.Edit')
490496
491497
492=== Specification Listings ===498Specification Listings
499......................
493500
494We should be able to get lists of specifications in different states501We should be able to get lists of specifications in different states
495related to a distro.502related to a distro.
@@ -497,90 +504,93 @@
497Basically, we can filter by completeness, and by whether or not the spec is504Basically, we can filter by completeness, and by whether or not the spec is
498informational.505informational.
499506
500 >>> kubuntu = distroset.getByName("kubuntu")507 >>> kubuntu = distroset.getByName("kubuntu")
501508
502 >>> from canonical.launchpad.interfaces import SpecificationFilter509 >>> from canonical.launchpad.interfaces import SpecificationFilter
503510
504First, there should be one informational spec for kubuntu, but it is511First, there should be one informational spec for kubuntu, but it is
505complete so it will not show up unless we explicitly ask for complete specs:512complete so it will not show up unless we explicitly ask for complete specs:
506513
507 >>> filter = [SpecificationFilter.INFORMATIONAL]514 >>> filter = [SpecificationFilter.INFORMATIONAL]
508 >>> kubuntu.specifications(filter=filter).count()515 >>> kubuntu.specifications(filter=filter).count()
509 0516 0
510 >>> filter = [SpecificationFilter.INFORMATIONAL,517 >>> filter = [SpecificationFilter.INFORMATIONAL,
511 ... SpecificationFilter.COMPLETE]518 ... SpecificationFilter.COMPLETE]
512 >>> kubuntu.specifications(filter=filter).count()519 >>> kubuntu.specifications(filter=filter).count()
513 1520 1
514521
515522
516There are 2 completed specs for Kubuntu:523There are 2 completed specs for Kubuntu:
517524
518 >>> filter = [SpecificationFilter.COMPLETE]525 >>> filter = [SpecificationFilter.COMPLETE]
519 >>> for spec in kubuntu.specifications(filter=filter):526 >>> for spec in kubuntu.specifications(filter=filter):
520 ... print spec.name, spec.is_complete527 ... print spec.name, spec.is_complete
521 thinclient-local-devices True528 thinclient-local-devices True
522 usplash-on-hibernation True529 usplash-on-hibernation True
523530
524531
525And there are four incomplete specs:532And there are four incomplete specs:
526533
527 >>> filter = [SpecificationFilter.INCOMPLETE]534 >>> filter = [SpecificationFilter.INCOMPLETE]
528 >>> for spec in kubuntu.specifications(filter=filter):535 >>> for spec in kubuntu.specifications(filter=filter):
529 ... print spec.name, spec.is_complete536 ... print spec.name, spec.is_complete
530 cluster-installation False537 cluster-installation False
531 revu False538 revu False
532 kde-desktopfile-langpacks False539 kde-desktopfile-langpacks False
533 krunch-desktop-plan False540 krunch-desktop-plan False
534541
535542
536If we ask for all specs, we get them in the order of priority.543If we ask for all specs, we get them in the order of priority.
537544
538 >>> filter = [SpecificationFilter.ALL]545 >>> filter = [SpecificationFilter.ALL]
539 >>> for spec in kubuntu.specifications(filter=filter):546 >>> for spec in kubuntu.specifications(filter=filter):
540 ... print spec.priority.title, spec.name547 ... print spec.priority.title, spec.name
541 Essential cluster-installation548 Essential cluster-installation
542 High revu549 High revu
543 Medium thinclient-local-devices550 Medium thinclient-local-devices
544 Low usplash-on-hibernation551 Low usplash-on-hibernation
545 Undefined kde-desktopfile-langpacks552 Undefined kde-desktopfile-langpacks
546 Not krunch-desktop-plan553 Not krunch-desktop-plan
547554
548555
549And if we ask just for specs, we get the incomplete ones.556And if we ask just for specs, we get the incomplete ones.
550557
551 >>> for spec in kubuntu.specifications():558 >>> for spec in kubuntu.specifications():
552 ... print spec.name, spec.is_complete559 ... print spec.name, spec.is_complete
553 cluster-installation False560 cluster-installation False
554 revu False561 revu False
555 kde-desktopfile-langpacks False562 kde-desktopfile-langpacks False
556 krunch-desktop-plan False563 krunch-desktop-plan False
557564
558We can filter for specifications that contain specific text:565We can filter for specifications that contain specific text:
559566
560 >>> for spec in kubuntu.specifications(filter=['package']):567 >>> for spec in kubuntu.specifications(filter=['package']):
561 ... print spec.name568 ... print spec.name
562 revu569 revu
563570
564We can get only valid specs (those that are not obsolete or superseded):571We can get only valid specs (those that are not obsolete or superseded):
565572
566 >>> from canonical.launchpad.interfaces import SpecificationDefinitionStatus573 >>> from canonical.launchpad.interfaces import (
567 >>> login('mark@example.com')574 ... SpecificationDefinitionStatus,
568 >>> for spec in kubuntu.specifications():575 ... )
569 ... # Do this here, otherwise, the change will be flush before576 >>> login('mark@example.com')
570 ... # updateLifecycleStatus() acts and an IntegrityError will be577 >>> for spec in kubuntu.specifications():
571 ... # raised.578 ... # Do this here, otherwise, the change will be flush before
572 ... owner = spec.owner579 ... # updateLifecycleStatus() acts and an IntegrityError will be
573 ... if spec.name in ['cluster-installation', 'revu']:580 ... # raised.
574 ... spec.definition_status = SpecificationDefinitionStatus.OBSOLETE581 ... owner = spec.owner
575 ... if spec.name in ['krunch-desktop-plan']:582 ... if spec.name in ['cluster-installation', 'revu']:
576 ... spec.definition_status = SpecificationDefinitionStatus.SUPERSEDED583 ... spec.definition_status = SpecificationDefinitionStatus.OBSOLETE
577 ... shim = spec.updateLifecycleStatus(owner)584 ... if spec.name in ['krunch-desktop-plan']:
578 >>> for spec in kubuntu.valid_specifications:585 ... spec.definition_status = SpecificationDefinitionStatus.SUPERSEDED
579 ... print spec.name586 ... shim = spec.updateLifecycleStatus(owner)
580 kde-desktopfile-langpacks587 >>> for spec in kubuntu.valid_specifications:
581588 ... print spec.name
582589 kde-desktopfile-langpacks
583== Milestones ==590
591
592Milestones
593----------
584594
585We can use IDistribution.milestones to get all milestones associated with any595We can use IDistribution.milestones to get all milestones associated with any
586series of a distribution.596series of a distribution.
@@ -623,7 +633,8 @@
623 [u'3.1', u'3.1-rc1', u'woody-rc1']633 [u'3.1', u'3.1-rc1', u'woody-rc1']
624634
625635
626== Archives ==636Archives
637--------
627638
628A distribution archive (primary, partner, debug or copy) can be retrieved639A distribution archive (primary, partner, debug or copy) can be retrieved
629by name using IDistribution.getArchive.640by name using IDistribution.getArchive.
630641
=== modified file 'lib/lp/registry/doc/product.txt'
--- lib/lp/registry/doc/product.txt 2010-08-25 15:48:05 +0000
+++ lib/lp/registry/doc/product.txt 2010-09-09 15:34:46 +0000
@@ -1,4 +1,5 @@
1= Product =1Product
2=======
23
3Launchpad keeps track of the "upstream" world as well as the "distro" world.4Launchpad keeps track of the "upstream" world as well as the "distro" world.
4The anchorpiece of the "upstream" world is the Product, which is a piece of5The anchorpiece of the "upstream" world is the Product, which is a piece of
@@ -162,7 +163,8 @@
162 Obsolete Junk163 Obsolete Junk
163164
164165
165== Translatable Products ==166Translatable Products
167---------------------
166168
167IProductSet will also tell us which products can be translated:169IProductSet will also tell us which products can be translated:
168170
@@ -217,11 +219,11 @@
217The packaging table allows us to list source and distro source packages219The packaging table allows us to list source and distro source packages
218related to a certain upstream:220related to a certain upstream:
219221
220 >>> alsa = productset.getByName('alsa-utils')222 >>> alsa = productset.getByName('alsa-utils')
221 >>> [(sp.name, sp.distroseries.name) for sp in alsa.sourcepackages]223 >>> [(sp.name, sp.distroseries.name) for sp in alsa.sourcepackages]
222 [(u'alsa-utils', u'sid'), (u'alsa-utils', u'warty')]224 [(u'alsa-utils', u'sid'), (u'alsa-utils', u'warty')]
223 >>> [(sp.name, sp.distribution.name) for sp in alsa.distrosourcepackages]225 >>> [(sp.name, sp.distribution.name) for sp in alsa.distrosourcepackages]
224 [(u'alsa-utils', u'debian'), (u'alsa-utils', u'ubuntu')]226 [(u'alsa-utils', u'debian'), (u'alsa-utils', u'ubuntu')]
225227
226The date_next_suggest_packaging attribute records the date when Launchpad can228The date_next_suggest_packaging attribute records the date when Launchpad can
227resume suggesting Ubuntu packages that the project provides. A value of None229resume suggesting Ubuntu packages that the project provides. A value of None
@@ -270,7 +272,8 @@
270 >>> from canonical.launchpad.interfaces import IBugTrackerSet272 >>> from canonical.launchpad.interfaces import IBugTrackerSet
271273
272 >>> login_person(firefox.owner)274 >>> login_person(firefox.owner)
273 >>> gnome_bugzilla = getUtility(IBugTrackerSet).getByName('gnome-bugzilla')275 >>> bug_tracker_set = getUtility(IBugTrackerSet)
276 >>> gnome_bugzilla = bug_tracker_set.getByName('gnome-bugzilla')
274 >>> firefox.project.bugtracker = gnome_bugzilla277 >>> firefox.project.bugtracker = gnome_bugzilla
275 >>> firefox.getExternalBugTracker() is None278 >>> firefox.getExternalBugTracker() is None
276 True279 True
@@ -307,7 +310,8 @@
307 True310 True
308311
309312
310== Answer Tracking ==313Answer Tracking
314---------------
311315
312Firefox uses the Answer Tracker as the official application to provide316Firefox uses the Answer Tracker as the official application to provide
313answers to questions.317answers to questions.
@@ -321,7 +325,8 @@
321 False325 False
322326
323327
324== Product Creation ==328Product Creation
329----------------
325330
326We can create new products with the createProduct() method:331We can create new products with the createProduct() method:
327332
@@ -374,20 +379,21 @@
374 True379 True
375380
376381
377== Specification Listings ==382Specification Listings
383----------------------
378384
379We should be able to set whether or not a Product uses specifications385We should be able to set whether or not a Product uses specifications
380officially. It defaults to False.386officially. It defaults to False.
381387
382 >>> firefox = productset.getByName('firefox')388 >>> firefox = productset.getByName('firefox')
383 >>> firefox.official_blueprints389 >>> firefox.official_blueprints
384 False390 False
385391
386We can change it to True.392We can change it to True.
387393
388 >>> firefox.official_blueprints = True394 >>> firefox.official_blueprints = True
389 >>> firefox.official_blueprints395 >>> firefox.official_blueprints
390 True396 True
391397
392We should be able to get lists of specifications in different states398We should be able to get lists of specifications in different states
393related to a product.399related to a product.
@@ -395,39 +401,40 @@
395Basically, we can filter by completeness, and by whether or not the spec is401Basically, we can filter by completeness, and by whether or not the spec is
396informational.402informational.
397403
398 >>> firefox = productset.getByName('firefox')404 >>> firefox = productset.getByName('firefox')
399 >>> from canonical.launchpad.interfaces import SpecificationFilter405 >>> from canonical.launchpad.interfaces import SpecificationFilter
400406
401First, there should be only one informational spec for firefox:407First, there should be only one informational spec for firefox:
402408
403 >>> filter = [SpecificationFilter.INFORMATIONAL]409 >>> filter = [SpecificationFilter.INFORMATIONAL]
404 >>> for spec in firefox.specifications(filter=filter):410 >>> for spec in firefox.specifications(filter=filter):
405 ... print spec.name411 ... print spec.name
406 extension-manager-upgrades412 extension-manager-upgrades
407413
408414
409There are no completed specs for firefox:415There are no completed specs for firefox:
410416
411 >>> filter = [SpecificationFilter.COMPLETE]417 >>> filter = [SpecificationFilter.COMPLETE]
412 >>> for spec in firefox.specifications(filter=filter):418 >>> for spec in firefox.specifications(filter=filter):
413 ... print spec.name419 ... print spec.name
414420
415421
416And there are five incomplete specs:422And there are five incomplete specs:
417423
418 >>> filter = [SpecificationFilter.INCOMPLETE]424 >>> filter = [SpecificationFilter.INCOMPLETE]
419 >>> firefox.specifications(filter=filter).count()425 >>> firefox.specifications(filter=filter).count()
420 5426 5
421427
422We can filter for specifications that contain specific text:428We can filter for specifications that contain specific text:
423429
424 >>> for spec in firefox.specifications(filter=['new']):430 >>> for spec in firefox.specifications(filter=['new']):
425 ... print spec.name431 ... print spec.name
426 canvas432 canvas
427 e4x433 e4x
428434
429435
430== Milestones ==436Milestones
437----------
431438
432We can use IProduct.milestones to get all milestones associated with any439We can use IProduct.milestones to get all milestones associated with any
433ProductSeries of a product.440ProductSeries of a product.
@@ -470,7 +477,8 @@
470 [u'1.0.0', u'0.9.2', u'0.9.1', u'0.9', u'1.0', u'1.0-rc1']477 [u'1.0.0', u'0.9.2', u'0.9.1', u'0.9', u'1.0', u'1.0-rc1']
471478
472479
473== Release ==480Release
481-------
474482
475All the releases for a Product can be retrieved through the releases property.483All the releases for a Product can be retrieved through the releases property.
476484
@@ -489,7 +497,8 @@
489 0.9.1497 0.9.1
490498
491499
492== Products With Branches ==500Products With Branches
501----------------------
493502
494Products are considered to officially support Launchpad as a location503Products are considered to officially support Launchpad as a location
495for their branches after a branch is set for the development focus504for their branches after a branch is set for the development focus
@@ -568,7 +577,8 @@
568 landscape577 landscape
569578
570579
571== Primary translatable ==580Primary translatable
581--------------------
572582
573Primary translatable series in a product should follow series where583Primary translatable series in a product should follow series where
574development is focused on. To be able to do changes to facilitate584development is focused on. To be able to do changes to facilitate
@@ -583,12 +593,18 @@
583 >>> from lp.translations.interfaces.potemplate import IPOTemplateSet593 >>> from lp.translations.interfaces.potemplate import IPOTemplateSet
584 >>> potemplate_set = getUtility(IPOTemplateSet)594 >>> potemplate_set = getUtility(IPOTemplateSet)
585595
596We're going to be setting the ServiceUsage values for products, so we
597need those enums.
598
599 >>> from lp.app.enums import ServiceUsage
600
586Firefox has two series, but no translatable series either:601Firefox has two series, but no translatable series either:
587602
588 >>> firefox = productset.getByName('firefox')603 >>> firefox = productset.getByName('firefox')
589 >>> for firefoxseries in firefox.series:604 >>> for firefoxseries in firefox.series:
590 ... print '%s %s' % (firefoxseries.displayname,605 ... print '%s %s' % (
591 ... list(firefoxseries.getCurrentTranslationTemplates()))606 ... firefoxseries.displayname,
607 ... list(firefoxseries.getCurrentTranslationTemplates()))
592 1.0 []608 1.0 []
593 trunk []609 trunk []
594 >>> print firefox.primary_translatable610 >>> print firefox.primary_translatable
@@ -616,7 +632,7 @@
616And set that product as using translations officially. We need it so632And set that product as using translations officially. We need it so
617translations are available.633translations are available.
618634
619 >>> firefox.official_rosetta = True635 >>> firefox.translations_usage = ServiceUsage.LAUNCHPAD
620636
621The primary_translatable now points at firefox 1.0:637The primary_translatable now points at firefox 1.0:
622638
@@ -642,7 +658,8 @@
642 1.0658 1.0
643659
644660
645= Series list =661Series list
662===========
646663
647The series for a product are returned as a sorted list, with the664The series for a product are returned as a sorted list, with the
648exception that the current development focus is first.665exception that the current development focus is first.
@@ -697,7 +714,8 @@
697 ... print series.name714 ... print series.name
698 trunk715 trunk
699716
700= Changing ownership =717Changing ownership
718==================
701719
702If the owner of a project changes, all series and productreleases720If the owner of a project changes, all series and productreleases
703owned by the old owner are transfered to the new owner.721owned by the old owner are transfered to the new owner.
704722
=== modified file 'lib/lp/registry/doc/project.txt'
--- lib/lp/registry/doc/project.txt 2010-06-07 07:52:45 +0000
+++ lib/lp/registry/doc/project.txt 2010-09-09 15:34:46 +0000
@@ -1,4 +1,5 @@
1= ProjectGroups =1ProjectGroups
2=============
23
3A ProjectGroup is a group of Products, making it possible to for4A ProjectGroup is a group of Products, making it possible to for
4example see all bugs in the ProjectGroup's Product, or make them share a5example see all bugs in the ProjectGroup's Product, or make them share a
@@ -11,7 +12,8 @@
11 >>> projectset = getUtility(IProjectGroupSet)12 >>> projectset = getUtility(IProjectGroupSet)
1213
1314
14== Creating new projects ==15Creating new projects
16---------------------
1517
16When creating a new project there are a bunch of things we need to provide.18When creating a new project there are a bunch of things we need to provide.
17While some of them (homepageurl, icon, logo and mugshot) are optional, others19While some of them (homepageurl, icon, logo and mugshot) are optional, others
@@ -28,7 +30,8 @@
28 u'project-test'30 u'project-test'
2931
3032
31== Looking up existing projects ==33Looking up existing projects
34----------------------------
3235
33To fetch a project we use IProjectGroupSet.getByName() or36To fetch a project we use IProjectGroupSet.getByName() or
34IProjectGroupSet.__getitem__. The former will, by default, return active and37IProjectGroupSet.__getitem__. The former will, by default, return active and
@@ -98,7 +101,8 @@
98 >>> print projectgroups.getByName('gnome', ignore_inactive=True)101 >>> print projectgroups.getByName('gnome', ignore_inactive=True)
99 None102 None
100103
101== Products which are part of a project ==104Products which are part of a project
105------------------------------------
102106
103The products which are part of a given project are given by a project's107The products which are part of a given project are given by a project's
104.products property. Note that only active products are included and they're108.products property. Note that only active products are included and they're
@@ -122,7 +126,8 @@
122 >>> flush_database_updates()126 >>> flush_database_updates()
123127
124128
125== Specification Listings ==129Specification Listings
130----------------------
126131
127We should be able to generate filtered lists of specs on a project.132We should be able to generate filtered lists of specs on a project.
128133
@@ -200,7 +205,8 @@
200 e4x205 e4x
201206
202207
203== Specification Listings for a ProjectGroupSeries ==208Specification Listings for a ProjectGroupSeries
209-----------------------------------------------
204210
205An IProjectGroupSeries object can be retrieved by IProjectGroup.getSeries.211An IProjectGroupSeries object can be retrieved by IProjectGroup.getSeries.
206212
@@ -314,7 +320,8 @@
314 e4x320 e4x
315321
316322
317== translatables ==323Translatables
324-------------
318325
319A project would have IProduct objects that have resources to translate. This326A project would have IProduct objects that have resources to translate. This
320method return us the ones that are translatable and officially using Rosetta327method return us the ones that are translatable and officially using Rosetta
@@ -349,8 +356,8 @@
349356
350That is using Rosetta officially.357That is using Rosetta officially.
351358
352 >>> evolution.official_rosetta359 >>> print evolution.translations_usage.name
353 True360 LAUNCHPAD
354361
355GNOME project has also another product, netapplet.362GNOME project has also another product, netapplet.
356363
@@ -361,8 +368,8 @@
361But it was not returned from 'translatables' method because it's not using368But it was not returned from 'translatables' method because it's not using
362Rosetta officially.369Rosetta officially.
363370
364 >>> netapplet.official_rosetta371 >>> print netapplet.translations_usage.name
365 False372 UNKNOWN
366373
367And thus, it doesn't have any translatable series.374And thus, it doesn't have any translatable series.
368375
@@ -376,7 +383,8 @@
376 1383 1
377384
378385
379== Milestones ==386Milestones
387----------
380388
381A project can have virtual milestones. If any of its products has milestones,389A project can have virtual milestones. If any of its products has milestones,
382these milestones are also associated with the project.390these milestones are also associated with the project.
@@ -398,7 +406,8 @@
398 1.1. active: True406 1.1. active: True
399 1.1 active: True407 1.1 active: True
400408
401ProjectGroup.all_milestones is a list of all milestones associated with a project.409ProjectGroup.all_milestones is a list of all milestones associated with a
410project.
402411
403 >>> milestones = gnome.all_milestones412 >>> milestones = gnome.all_milestones
404 >>> for milestone in milestones:413 >>> for milestone in milestones:
@@ -410,8 +419,8 @@
410 1.1. active: True419 1.1. active: True
411 1.1 active: True420 1.1 active: True
412421
413ProjectGroup.getMilestone(name) returns the project milestone with the name `name'422ProjectGroup.getMilestone(name) returns the project milestone with the name
414or None, if no milestone with this name exists.423`name' or None, if no milestone with this name exists.
415424
416 >>> milestone = gnome.getMilestone('1.1')425 >>> milestone = gnome.getMilestone('1.1')
417 >>> print milestone.name426 >>> print milestone.name
418427
=== modified file 'lib/lp/registry/model/projectgroup.py'
--- lib/lp/registry/model/projectgroup.py 2010-08-24 19:06:33 +0000
+++ lib/lp/registry/model/projectgroup.py 2010-09-09 15:34:46 +0000
@@ -202,6 +202,9 @@
202202
203 def translatables(self):203 def translatables(self):
204 """See `IProjectGroup`."""204 """See `IProjectGroup`."""
205 # XXX j.c.sackett 2010-08-30 bug=627631 Once data migration has
206 # happened for the usage enums, this sql needs to be updated to
207 # check for the translations_usage, not official_rosetta.
205 return Product.select('''208 return Product.select('''
206 Product.project = %s AND209 Product.project = %s AND
207 Product.official_rosetta = TRUE AND210 Product.official_rosetta = TRUE AND
@@ -271,7 +274,7 @@
271274
272 # filter based on completion. see the implementation of275 # filter based on completion. see the implementation of
273 # Specification.is_complete() for more details276 # Specification.is_complete() for more details
274 completeness = Specification.completeness_clause277 completeness = Specification.completeness_clause
275278
276 if SpecificationFilter.COMPLETE in filter:279 if SpecificationFilter.COMPLETE in filter:
277 query += ' AND ( %s ) ' % completeness280 query += ' AND ( %s ) ' % completeness
278281
=== modified file 'lib/lp/testing/factory.py'
--- lib/lp/testing/factory.py 2010-09-09 14:11:43 +0000
+++ lib/lp/testing/factory.py 2010-09-09 15:34:46 +0000
@@ -93,6 +93,7 @@
93 IStoreSelector,93 IStoreSelector,
94 MAIN_STORE,94 MAIN_STORE,
95 )95 )
96from lp.app.enums import ServiceUsage
96from lp.archiveuploader.dscfile import DSCFile97from lp.archiveuploader.dscfile import DSCFile
97from lp.archiveuploader.uploadpolicy import BuildDaemonUploadPolicy98from lp.archiveuploader.uploadpolicy import BuildDaemonUploadPolicy
98from lp.blueprints.interfaces.specification import (99from lp.blueprints.interfaces.specification import (
@@ -838,7 +839,7 @@
838 self, name=None, project=None, displayname=None,839 self, name=None, project=None, displayname=None,
839 licenses=None, owner=None, registrant=None,840 licenses=None, owner=None, registrant=None,
840 title=None, summary=None, official_malone=None,841 title=None, summary=None, official_malone=None,
841 official_rosetta=None, bug_supervisor=None):842 translations_usage=None, bug_supervisor=None):
842 """Create and return a new, arbitrary Product."""843 """Create and return a new, arbitrary Product."""
843 if owner is None:844 if owner is None:
844 owner = self.makePerson()845 owner = self.makePerson()
@@ -867,8 +868,9 @@
867 registrant=registrant)868 registrant=registrant)
868 if official_malone is not None:869 if official_malone is not None:
869 removeSecurityProxy(product).official_malone = official_malone870 removeSecurityProxy(product).official_malone = official_malone
870 if official_rosetta is not None:871 if translations_usage is not None:
871 removeSecurityProxy(product).official_rosetta = official_rosetta872 naked_product = removeSecurityProxy(product)
873 naked_product.translations_usage = translations_usage
872 if bug_supervisor is not None:874 if bug_supervisor is not None:
873 naked_product = removeSecurityProxy(product)875 naked_product = removeSecurityProxy(product)
874 naked_product.bug_supervisor = bug_supervisor876 naked_product.bug_supervisor = bug_supervisor
@@ -2176,7 +2178,8 @@
2176 productseries = self.makeProductSeries(owner=owner)2178 productseries = self.makeProductSeries(owner=owner)
2177 # Make it use Translations, otherwise there's little point2179 # Make it use Translations, otherwise there's little point
2178 # to us creating a template for it.2180 # to us creating a template for it.
2179 removeSecurityProxy(productseries).product.official_rosetta = True2181 naked_series = removeSecurityProxy(productseries)
2182 naked_series.product.translations_usage = ServiceUsage.LAUNCHPAD
2180 templateset = getUtility(IPOTemplateSet)2183 templateset = getUtility(IPOTemplateSet)
2181 subset = templateset.getSubset(2184 subset = templateset.getSubset(
2182 distroseries, sourcepackagename, productseries)2185 distroseries, sourcepackagename, productseries)
21832186
=== modified file 'lib/lp/translations/browser/potemplate.py'
--- lib/lp/translations/browser/potemplate.py 2010-08-25 20:04:40 +0000
+++ lib/lp/translations/browser/potemplate.py 2010-09-09 15:34:46 +0000
@@ -61,6 +61,7 @@
61from canonical.launchpad.webapp.launchpadform import ReturnToReferrerMixin61from canonical.launchpad.webapp.launchpadform import ReturnToReferrerMixin
62from canonical.launchpad.webapp.menu import structured62from canonical.launchpad.webapp.menu import structured
63from canonical.lazr.utils import smartquote63from canonical.lazr.utils import smartquote
64from lp.app.enums import service_uses_launchpad
64from lp.app.errors import NotFoundError65from lp.app.errors import NotFoundError
65from lp.registry.browser.productseries import ProductSeriesFacets66from lp.registry.browser.productseries import ProductSeriesFacets
66from lp.registry.browser.sourcepackage import SourcePackageFacets67from lp.registry.browser.sourcepackage import SourcePackageFacets
@@ -794,9 +795,10 @@
794 product_or_distro = potemplate.productseries.product795 product_or_distro = potemplate.productseries.product
795 else:796 else:
796 product_or_distro = potemplate.distroseries.distribution797 product_or_distro = potemplate.distroseries.distribution
797 official_rosetta = product_or_distro.official_rosetta798 translations_usage = product_or_distro.translations_usage
798799
799 if official_rosetta and potemplate.iscurrent:800 if (service_uses_launchpad(translations_usage) and
801 potemplate.iscurrent):
800 # This template is available for translation.802 # This template is available for translation.
801 return potemplate803 return potemplate
802 elif check_permission('launchpad.Edit', potemplate):804 elif check_permission('launchpad.Edit', potemplate):
803805
=== modified file 'lib/lp/translations/browser/product.py'
--- lib/lp/translations/browser/product.py 2010-08-24 10:45:57 +0000
+++ lib/lp/translations/browser/product.py 2010-09-09 15:34:46 +0000
@@ -19,6 +19,7 @@
19 )19 )
20from canonical.launchpad.webapp.authorization import check_permission20from canonical.launchpad.webapp.authorization import check_permission
21from canonical.launchpad.webapp.menu import NavigationMenu21from canonical.launchpad.webapp.menu import NavigationMenu
22from lp.app.enums import service_uses_launchpad
22from lp.registry.browser.product import ProductEditView23from lp.registry.browser.product import ProductEditView
23from lp.registry.interfaces.product import IProduct24from lp.registry.interfaces.product import IProduct
24from lp.registry.interfaces.productseries import IProductSeries25from lp.registry.interfaces.productseries import IProductSeries
@@ -51,12 +52,14 @@
51 def translationdownload(self):52 def translationdownload(self):
52 text = 'Download'53 text = 'Download'
53 preferred_series = self.context.primary_translatable54 preferred_series = self.context.primary_translatable
54 enabled = (self.context.official_rosetta and55 enabled = (service_uses_launchpad(self.context.translations_usage)
55 preferred_series is not None)56 and preferred_series is not None)
56 link = ''57 link = ''
57 if enabled:58 if enabled:
58 link = canonical_url(59 link = canonical_url(
59 preferred_series, rootsite='translations', view_name='+export')60 preferred_series,
61 rootsite='translations',
62 view_name='+export')
60 text = 'Download "%s"' % preferred_series.name63 text = 'Download "%s"' % preferred_series.name
6164
62 return Link(link, text, icon='download', enabled=enabled)65 return Link(link, text, icon='download', enabled=enabled)
@@ -90,19 +93,19 @@
90 @cachedproperty93 @cachedproperty
91 def uses_translations(self):94 def uses_translations(self):
92 """Whether this product has translatable templates."""95 """Whether this product has translatable templates."""
93 return (self.context.official_rosetta and96 return (service_uses_launchpad(self.context.translations_usage)
94 self.primary_translatable is not None)97 and self.primary_translatable is not None)
9598
96 @cachedproperty99 @cachedproperty
97 def no_translations_available(self):100 def no_translations_available(self):
98 """Has no translation templates but does support translations."""101 """Has no translation templates but does support translations."""
99 return (self.context.official_rosetta and102 return (service_uses_launchpad(self.context.translations_usage)
100 self.primary_translatable is None)103 and self.primary_translatable is None)
101104
102 @cachedproperty105 @cachedproperty
103 def show_page_content(self):106 def show_page_content(self):
104 """Whether the main content of the page should be shown."""107 """Whether the main content of the page should be shown."""
105 return (self.context.official_rosetta or108 return (service_uses_launchpad(self.context.translations_usage) or
106 check_permission("launchpad.TranslationsAdmin", self.context))109 check_permission("launchpad.TranslationsAdmin", self.context))
107110
108 @cachedproperty111 @cachedproperty
109112
=== modified file 'lib/lp/translations/browser/tests/language-views.txt'
--- lib/lp/translations/browser/tests/language-views.txt 2010-07-16 16:51:52 +0000
+++ lib/lp/translations/browser/tests/language-views.txt 2010-09-09 15:34:46 +0000
@@ -143,7 +143,10 @@
143143
144Create a product, a template with one msgset and a pofile144Create a product, a template with one msgset and a pofile
145145
146 >>> product = factory.makeProduct(official_rosetta=True)146 >>> from lp.app.enums import ServiceUsage
147
148 >>> product = factory.makeProduct(
149 ... translations_usage=ServiceUsage.LAUNCHPAD)
147 >>> template = factory.makePOTemplate(150 >>> template = factory.makePOTemplate(
148 ... productseries=product.getSeries('trunk'))151 ... productseries=product.getSeries('trunk'))
149 >>> potmsgset = factory.makePOTMsgSet(template)152 >>> potmsgset = factory.makePOTMsgSet(template)
150153
=== modified file 'lib/lp/translations/browser/tests/test_breadcrumbs.py'
--- lib/lp/translations/browser/tests/test_breadcrumbs.py 2010-08-20 20:31:18 +0000
+++ lib/lp/translations/browser/tests/test_breadcrumbs.py 2010-09-09 15:34:46 +0000
@@ -6,6 +6,7 @@
6from zope.component import getUtility6from zope.component import getUtility
77
8from canonical.lazr.utils import smartquote8from canonical.lazr.utils import smartquote
9from lp.app.enums import ServiceUsage
9from lp.services.worlddata.interfaces.language import ILanguageSet10from lp.services.worlddata.interfaces.language import ILanguageSet
10from lp.testing.breadcrumbs import BaseBreadcrumbTestCase11from lp.testing.breadcrumbs import BaseBreadcrumbTestCase
11from lp.testing.factory import remove_security_proxy_and_shout_at_engineer12from lp.testing.factory import remove_security_proxy_and_shout_at_engineer
@@ -152,7 +153,7 @@
152 def test_potemplate(self):153 def test_potemplate(self):
153 product = self.factory.makeProduct(154 product = self.factory.makeProduct(
154 name='crumb-tester', displayname="Crumb Tester",155 name='crumb-tester', displayname="Crumb Tester",
155 official_rosetta=True)156 translations_usage=ServiceUsage.LAUNCHPAD)
156 series = self.factory.makeProductSeries(157 series = self.factory.makeProductSeries(
157 name="test", product=product)158 name="test", product=product)
158 potemplate = self.factory.makePOTemplate(159 potemplate = self.factory.makePOTemplate(
@@ -176,7 +177,7 @@
176 def test_pofiletranslate(self):177 def test_pofiletranslate(self):
177 product = self.factory.makeProduct(178 product = self.factory.makeProduct(
178 name='crumb-tester', displayname="Crumb Tester",179 name='crumb-tester', displayname="Crumb Tester",
179 official_rosetta=True)180 translations_usage=ServiceUsage.LAUNCHPAD)
180 series = self.factory.makeProductSeries(name="test", product=product)181 series = self.factory.makeProductSeries(name="test", product=product)
181 potemplate = self.factory.makePOTemplate(series, name="test-template")182 potemplate = self.factory.makePOTemplate(series, name="test-template")
182 pofile = self.factory.makePOFile('eo', potemplate)183 pofile = self.factory.makePOFile('eo', potemplate)
183184
=== modified file 'lib/lp/translations/doc/potmsgset.txt'
--- lib/lp/translations/doc/potmsgset.txt 2010-09-01 10:03:11 +0000
+++ lib/lp/translations/doc/potmsgset.txt 2010-09-09 15:34:46 +0000
@@ -1,4 +1,5 @@
1= POTMsgSet tests =1POTMsgSet tests
2===============
23
3POTMsgSet represents messages to translate that a POTemplate file has.4POTMsgSet represents messages to translate that a POTemplate file has.
45
@@ -17,7 +18,9 @@
17 ... ILanguageSet, IPersonSet, IProductSet)18 ... ILanguageSet, IPersonSet, IProductSet)
1819
19 >>> potemplate = factory.makePOTemplate()20 >>> potemplate = factory.makePOTemplate()
20 >>> potmsgset = factory.makePOTMsgSet(potemplate=potemplate, singular="bla")21 >>> potmsgset = factory.makePOTMsgSet(
22 ... potemplate=potemplate,
23 ... singular="bla")
2124
22Verify interface.25Verify interface.
2326
@@ -31,7 +34,8 @@
31 >>> import pytz34 >>> import pytz
3235
3336
34== POTMsgSet.is_translation_credit and POTMsgSet.translation_credit_type ==37POTMsgSet.is_translation_credit and POTMsgSet.translation_credit_type
38---------------------------------------------------------------------
3539
36A POTMsgSet can be translation credits. These have special msgids that may40A POTMsgSet can be translation credits. These have special msgids that may
37differ for historical reason for the same type of credit. The property41differ for historical reason for the same type of credit. The property
@@ -51,7 +55,8 @@
51 Gnome credits message55 Gnome credits message
5256
5357
54== POTMsgSet.normalizeWhitespaces ==58POTMsgSet.normalizeWhitespaces
59------------------------------
5560
56This function copies the leading and trailing whitespaces from61This function copies the leading and trailing whitespaces from
57POTMsgSet's msgid into the 'text' argument.62POTMsgSet's msgid into the 'text' argument.
@@ -96,7 +101,8 @@
96 True101 True
97102
98103
99== POTMsgSet.convertDotToSpace ==104POTMsgSet.convertDotToSpace
105---------------------------
100106
101This method changes the u'\u2022' char by the normal white space.107This method changes the u'\u2022' char by the normal white space.
102108
@@ -126,14 +132,17 @@
126 u'a string with the char \u2022'132 u'a string with the char \u2022'
127133
128134
129== POTMsgSet.normalizeNewLines ==135POTMsgSet.normalizeNewLines
136---------------------------
130137
131This method syncs the new line chars to use the same as the associated msgid.138This method syncs the new line chars to use the same as the associated msgid.
132139
133As this test is too specific, we are going to change a msgid as we need for140As this test is too specific, we are going to change a msgid as we need for
134every test.141every test.
135142
136 >>> potmsgset_windows = factory.makePOTMsgSet(potemplate, singular=u'\r\n')143 >>> potmsgset_windows = factory.makePOTMsgSet(
144 ... potemplate,
145 ... singular=u'\r\n')
137 >>> potmsgset_unix = factory.makePOTMsgSet(potemplate, singular=u'\n')146 >>> potmsgset_unix = factory.makePOTMsgSet(potemplate, singular=u'\n')
138 >>> potmsgset_mac = factory.makePOTMsgSet(potemplate, singular=u'\r')147 >>> potmsgset_mac = factory.makePOTMsgSet(potemplate, singular=u'\r')
139 >>> text_windows = u'\r\n'148 >>> text_windows = u'\r\n'
@@ -180,7 +189,8 @@
180 BrokenTextError: ...189 BrokenTextError: ...
181190
182191
183== POTMsgSet.applySanityFixes ==192POTMsgSet.applySanityFixes
193--------------------------
184194
185This function applies all checks we know to fix broken input195This function applies all checks we know to fix broken input
186196
@@ -199,7 +209,8 @@
199 u'\nTranslation\nto test\n'209 u'\nTranslation\nto test\n'
200210
201211
202== POTMsgSet.updateTranslation ==212POTMsgSet.updateTranslation
213---------------------------
203214
204This method is the core piece of Translations infrastructure: it215This method is the core piece of Translations infrastructure: it
205updates a single language translation for a POTMsgSet, and modifies a216updates a single language translation for a POTMsgSet, and modifies a
@@ -309,7 +320,8 @@
309 >>> current.date_created is None320 >>> current.date_created is None
310 False321 False
311322
312=== Unsetting a translation from the import ===323Unsetting a translation from the import
324.......................................
313325
314A translation can be removed from the import by being set to an empty string.326A translation can be removed from the import by being set to an empty string.
315327
@@ -349,7 +361,8 @@
349 >>> upstream_pofile.updateStatistics()361 >>> upstream_pofile.updateStatistics()
350 (0, 0, 0, 2)362 (0, 0, 0, 2)
351363
352=== Activating an existing suggestion ===364Activating an existing suggestion
365.................................
353366
354Foo Bar is a privileged translator who can do reviews and submit translations367Foo Bar is a privileged translator who can do reviews and submit translations
355directly, while No Privileges user can only submit suggestions.368directly, while No Privileges user can only submit suggestions.
@@ -438,7 +451,8 @@
438 u'Foo Bar'451 u'Foo Bar'
439452
440453
441== Plural forms ==454Plural forms
455------------
442456
443Let's focus on handling of messages with plural forms.457Let's focus on handling of messages with plural forms.
444458
@@ -513,7 +527,8 @@
513 [None, None, None]527 [None, None, None]
514528
515529
516=== Missing forms ===530Missing forms
531.............
517532
518Even when a message has a singular and a plural in English, a533Even when a message has a singular and a plural in English, a
519translation does not have to cover all plural forms available in the534translation does not have to cover all plural forms available in the
@@ -538,7 +553,8 @@
538 False553 False
539554
540555
541=== Extraneous forms ===556Extraneous forms
557................
542558
543It's not normally possible to input more plural forms for a translated559It's not normally possible to input more plural forms for a translated
544message than the language has. But that number is configurable, and can560message than the language has. But that number is configurable, and can
@@ -614,7 +630,8 @@
614possible.630possible.
615631
616632
617== isTranslationNewerThan ==633isTranslationNewerThan
634----------------------
618635
619This method tells us whether the active translation was reviewed after636This method tells us whether the active translation was reviewed after
620the given timestamp.637the given timestamp.
@@ -633,7 +650,8 @@
633 False650 False
634651
635652
636== External translation suggestions ==653External translation suggestions
654--------------------------------
637655
638External translation suggestions are current, imported or suggested656External translation suggestions are current, imported or suggested
639translation for exactly the same English string, but in a different657translation for exactly the same English string, but in a different
@@ -670,7 +688,8 @@
670 ... print line688 ... print line
671689
672690
673== POTMsgSet.getExternallyUsedTranslationMessages ==691POTMsgSet.getExternallyUsedTranslationMessages
692----------------------------------------------
674693
675 On one side, we have a translation template for the evolution product.694 On one side, we have a translation template for the evolution product.
676695
@@ -692,10 +711,10 @@
692711
693Both, product and distribution use Launchpad Translations.712Both, product and distribution use Launchpad Translations.
694713
695 >>> evolution.official_rosetta714 >>> evolution.translations_usage.name
696 True715 'LAUNCHPAD'
697 >>> ubuntu.official_rosetta716 >>> ubuntu.translations_usage.name
698 True717 'LAUNCHPAD'
699718
700And both translation templates are current719And both translation templates are current
701720
@@ -754,7 +773,9 @@
754The same happens if the distribution is not officially using773The same happens if the distribution is not officially using
755translations.774translations.
756775
757 >>> ubuntu.official_rosetta = False776 >>> from lp.app.enums import ServiceUsage
777
778 >>> ubuntu.translations_usage = ServiceUsage.NOT_APPLICABLE
758779
759 # We set the template as current again so we are sure that we don't show780 # We set the template as current again so we are sure that we don't show
760 # suggestions just due to the change to the official_rosetta flag.781 # suggestions just due to the change to the official_rosetta flag.
@@ -767,7 +788,7 @@
767788
768And products not using translations officially have the same behaviour.789And products not using translations officially have the same behaviour.
769790
770 >>> evolution.official_rosetta = False791 >>> evolution.translations_usage = ServiceUsage.NOT_APPLICABLE
771 >>> transaction.commit()792 >>> transaction.commit()
772 >>> suggestions = evo_distro_message.getExternallyUsedTranslationMessages(793 >>> suggestions = evo_distro_message.getExternallyUsedTranslationMessages(
773 ... spanish)794 ... spanish)
@@ -776,12 +797,13 @@
776797
777Let's restore the flags for next section.798Let's restore the flags for next section.
778799
779 >>> ubuntu.official_rosetta = True800 >>> ubuntu.translations_usage = ServiceUsage.LAUNCHPAD
780 >>> evolution.official_rosetta = True801 >>> evolution.translations_usage = ServiceUsage.LAUNCHPAD
781 >>> transaction.commit()802 >>> transaction.commit()
782803
783804
784== POTMsgSet.getExternallySuggestedTranslationMessages ==805POTMsgSet.getExternallySuggestedTranslationMessages
806---------------------------------------------------
785807
786This method returns a set of submissions that have suggested translations808This method returns a set of submissions that have suggested translations
787for the same msgid as the given POTMsgSet across the whole system.809for the same msgid as the given POTMsgSet across the whole system.
@@ -876,7 +898,7 @@
876 # We set the template as current again so we are sure that we don't show898 # We set the template as current again so we are sure that we don't show
877 # suggestions just due to the change to the official_rosetta flag.899 # suggestions just due to the change to the official_rosetta flag.
878 >>> potmsgset_translated.potemplate.iscurrent = True900 >>> potmsgset_translated.potemplate.iscurrent = True
879 >>> ubuntu.official_rosetta = False901 >>> ubuntu.translations_usage = ServiceUsage.NOT_APPLICABLE
880 >>> transaction.commit()902 >>> transaction.commit()
881903
882 >>> wiki_submissions = (904 >>> wiki_submissions = (
@@ -886,7 +908,8 @@
886 0908 0
887909
888910
889== POTMsgSet.getCurrentDummyTranslationMessage ==911POTMsgSet.getCurrentDummyTranslationMessage
912-------------------------------------------
890913
891Sometimes, there are POTMsgSet objects with no translations to a language,914Sometimes, there are POTMsgSet objects with no translations to a language,
892and we need to get dummy objects which emulate them to do read operations.915and we need to get dummy objects which emulate them to do read operations.
@@ -908,7 +931,8 @@
908 AssertionError: There is already a translation message ...931 AssertionError: There is already a translation message ...
909932
910933
911== Suggestions for translator credits ==934Suggestions for translator credits
935----------------------------------
912936
913Messages with translator credits are translated automatically by937Messages with translator credits are translated automatically by
914Launchpad, so we should not get any suggestions for them.938Launchpad, so we should not get any suggestions for them.
@@ -936,8 +960,8 @@
936960
937Now, let's add 'translation-credits' message to a different POTemplate:961Now, let's add 'translation-credits' message to a different POTemplate:
938962
939 >>> new_credits = evolution_potemplate.createMessageSetFromText(963 >>> new_credits = evolution_potemplate.createMessageSetFromText(
940 ... singular_text=u'translation-credits', plural_text=None)964 ... singular_text=u'translation-credits', plural_text=None)
941965
942However, this one doesn't show up as external suggestion for Spanish.966However, this one doesn't show up as external suggestion for Spanish.
943967
@@ -946,7 +970,8 @@
946 >>> new_credits.getExternallySuggestedTranslationMessages(spanish)970 >>> new_credits.getExternallySuggestedTranslationMessages(spanish)
947 []971 []
948972
949== POTMsgSet.setSequence ==973POTMsgSet.setSequence
974---------------------
950975
951Finally, the new `IPOTMsgSet` should have an entry in the976Finally, the new `IPOTMsgSet` should have an entry in the
952`TranslationTemplateItem` table once we assign a sequence number.977`TranslationTemplateItem` table once we assign a sequence number.
@@ -998,7 +1023,8 @@
998 01023 0
9991024
10001025
1001== POTMsgSet.flags ==1026POTMsgSet.flags
1027---------------
10021028
1003The gettext format can associate flags with a POTMsgSet, such as "this1029The gettext format can associate flags with a POTMsgSet, such as "this
1004is a fuzzily matched message" or "this message follows C format-string1030is a fuzzily matched message" or "this message follows C format-string
10051031
=== modified file 'lib/lp/translations/doc/translationimportqueue.txt'
--- lib/lp/translations/doc/translationimportqueue.txt 2010-07-13 21:49:34 +0000
+++ lib/lp/translations/doc/translationimportqueue.txt 2010-09-09 15:34:46 +0000
@@ -1,4 +1,5 @@
1= TranslationImportQueueEntry =1TranslationImportQueueEntry
2===========================
23
3The TranslationImportQueueEntry is an entry of the queue that will be imported4The TranslationImportQueueEntry is an entry of the queue that will be imported
4into Rosetta.5into Rosetta.
@@ -14,7 +15,8 @@
14 ... store.find(TranslationImportQueueEntry).remove()15 ... store.find(TranslationImportQueueEntry).remove()
1516
1617
17== getGuessedPOFile ==18getGuessedPOFile
19----------------
1820
19This property gives us the IPOFile where we think we should import this entry.21This property gives us the IPOFile where we think we should import this entry.
2022
@@ -59,7 +61,8 @@
59 ... u'po/sr.po', 'foo', True, rosetta_experts,61 ... u'po/sr.po', 'foo', True, rosetta_experts,
60 ... productseries=evolution_productseries)62 ... productseries=evolution_productseries)
6163
62This entry has no information about the IPOFile where it should be attached to:64This entry has no information about the IPOFile where it should be attached
65to:
6366
64 >>> entry.import_into is None67 >>> entry.import_into is None
65 True68 True
@@ -82,7 +85,8 @@
82 ... sourcepackagename=evolution_sourcepackagename)85 ... sourcepackagename=evolution_sourcepackagename)
83 >>> transaction.commit()86 >>> transaction.commit()
8487
85This entry has no information about the IPOFile where it should be attached to:88This entry has no information about the IPOFile where it should be attached
89to:
8690
87 >>> entry.import_into is None91 >>> entry.import_into is None
88 True92 True
@@ -225,7 +229,8 @@
225 >>> pofile.path229 >>> pofile.path
226 u'po/sr.po'230 u'po/sr.po'
227231
228=== getGuessedPOFile with KDE ===232getGuessedPOFile with KDE
233.........................
229234
230Official KDE packages have a non standard layout where the .pot files are235Official KDE packages have a non standard layout where the .pot files are
231stored inside the sourcepackage with the binaries that will use it and the236stored inside the sourcepackage with the binaries that will use it and the
@@ -363,7 +368,8 @@
363 >>> transaction.abort()368 >>> transaction.abort()
364369
365370
366=== getGuessedPOFile with KOffice ===371getGuessedPOFile with KOffice
372.............................
367373
368Like official KDE packages, KOffice stores the .pot and .po files in different374Like official KDE packages, KOffice stores the .pot and .po files in different
369packages, the only difference it has is that there is just one source package375packages, the only difference it has is that there is just one source package
@@ -403,7 +409,9 @@
403409
404And set this entry as already imported.410And set this entry as already imported.
405411
406 >>> koffice_pot_entry.setStatus(RosettaImportStatus.IMPORTED, rosetta_experts)412 >>> koffice_pot_entry.setStatus(
413 ... RosettaImportStatus.IMPORTED,
414 ... rosetta_experts)
407 >>> flush_database_updates()415 >>> flush_database_updates()
408416
409Let's attach a .po file from koffice-l10n417Let's attach a .po file from koffice-l10n
@@ -449,7 +457,8 @@
449 >>> transaction.abort()457 >>> transaction.abort()
450458
451459
452=== getGuessedPOFile with .po files in different directories ===460getGuessedPOFile with .po files in different directories
461........................................................
453462
454Some packages have translations and templates inside the same package, but463Some packages have translations and templates inside the same package, but
455they don't have them inside the same directory. The layout is:464they don't have them inside the same directory. The layout is:
@@ -500,7 +509,9 @@
500509
501And set this entry as already imported.510And set this entry as already imported.
502511
503 >>> adept_pot_entry.setStatus(RosettaImportStatus.IMPORTED, rosetta_experts)512 >>> adept_pot_entry.setStatus(
513 ... RosettaImportStatus.IMPORTED,
514 ... rosetta_experts)
504 >>> flush_database_updates()515 >>> flush_database_updates()
505516
506Let's attach a .po file now.517Let's attach a .po file now.
@@ -551,7 +562,9 @@
551562
552And set this entry as already imported.563And set this entry as already imported.
553564
554 >>> ktorrent_pot_entry.setStatus(RosettaImportStatus.IMPORTED, rosetta_experts)565 >>> ktorrent_pot_entry.setStatus(
566 ... RosettaImportStatus.IMPORTED,
567 ... rosetta_experts)
555 >>> flush_database_updates()568 >>> flush_database_updates()
556569
557Let's attach a .po file now.570Let's attach a .po file now.
@@ -739,7 +752,8 @@
739 >>> transaction.abort()752 >>> transaction.abort()
740753
741754
742== executeOptimisticBlock ==755executeOptimisticBlock
756----------------------
743757
744This method looks on the queue to find entries to block based on other .pot758This method looks on the queue to find entries to block based on other .pot
745entries that are stored on the same directory and are already blocked.759entries that are stored on the same directory and are already blocked.
@@ -803,7 +817,8 @@
803 True817 True
804818
805On the other hand, this other one is for the same819On the other hand, this other one is for the same
806distroseries/sourcepackagename than the .pot file we have so it's also blocked.820distroseries/sourcepackagename than the .pot file we have so it's also
821blocked.
807822
808 >>> entry4 = translationimportqueue.get(4)823 >>> entry4 = translationimportqueue.get(4)
809 >>> entry4.path824 >>> entry4.path
@@ -820,7 +835,8 @@
820 True835 True
821836
822837
823== getElapsedTimeText ==838getElapsedTimeText
839-----------------
824840
825This method returns a string representing the elapsed time since the entry841This method returns a string representing the elapsed time since the entry
826was added to the queue.842was added to the queue.
@@ -860,13 +876,15 @@
860 '2 days 13 hours 5 minutes ago'876 '2 days 13 hours 5 minutes ago'
861877
862878
863= TranslationImportQueue =879TranslationImportQueue
880======================
864881
865The translation import queue is the place where the new translation imports882The translation import queue is the place where the new translation imports
866end before being imported into Rosetta.883end before being imported into Rosetta.
867884
868885
869== getTemplatesOnSameDirectory ==886getTemplatesOnSameDirectory
887---------------------------
870888
871This method allows us to get the set of .pot files we have on the same889This method allows us to get the set of .pot files we have on the same
872directory that a given entry.890directory that a given entry.
@@ -905,7 +923,8 @@
905 0923 0
906924
907925
908== getRequestTargets ==926getRequestTargets
927-----------------
909928
910 >>> # Helper functions929 >>> # Helper functions
911 >>> def get_target_names(status=None):930 >>> def get_target_names(status=None):
@@ -1069,7 +1088,8 @@
1069 firefox Mozilla Firefox1088 firefox Mozilla Firefox
1070 ubuntu/hoary Hoary1089 ubuntu/hoary Hoary
10711090
1072== addOrUpdateEntry() ==1091addOrUpdateEntry()
1092------------------
10731093
1074addOrUpdateEntry adds a new entry to the import queue so we can handle it1094addOrUpdateEntry adds a new entry to the import queue so we can handle it
1075later with poimport script.1095later with poimport script.
@@ -1264,7 +1284,8 @@
1264 >>> print entry.content.read()1284 >>> print entry.content.read()
1265 New bar content1285 New bar content
12661286
1267= Filename filters =1287Filename filters
1288================
12681289
1269A tarball doesn't always have everything in quite the right place. If1290A tarball doesn't always have everything in quite the right place. If
1270you need to manipulate the file paths within a tarball before the files1291you need to manipulate the file paths within a tarball before the files
@@ -1307,7 +1328,8 @@
1307 netapplet | None | new-directory/fr.po1328 netapplet | None | new-directory/fr.po
13081329
13091330
1310= Invalid data =1331Invalid data
1332============
13111333
1312If administrators fail to correct certain errors in requests while approving1334If administrators fail to correct certain errors in requests while approving
1313them, and the admin user interface mistakenly accepts the approval, we may1335them, and the admin user interface mistakenly accepts the approval, we may
@@ -1385,7 +1407,8 @@
1385 >>> clear_queue(translationimportqueue)1407 >>> clear_queue(translationimportqueue)
13861408
13871409
1388== getRequestTargets output ordering ==1410getRequestTargets output ordering
1411---------------------------------
13891412
1390The queue is populated with a wild mix of requests: for packages in1413The queue is populated with a wild mix of requests: for packages in
1391different release series of Ubuntu, for packages in different distros,1414different release series of Ubuntu, for packages in different distros,
@@ -1472,7 +1495,8 @@
1472 evolution Evolution1495 evolution Evolution
14731496
14741497
1475== cleanUpQueue ==1498cleanUpQueue
1499------------
14761500
1477The queue is cleaned up regularly.1501The queue is cleaned up regularly.
14781502
@@ -1489,7 +1513,8 @@
1489 01513 0
14901514
14911515
1492=== State and Age ===1516State and Age
1517.............
14931518
1494Entries can be cleaned up because they have been in a specific state for1519Entries can be cleaned up because they have been in a specific state for
1495at least a specified period of time.1520at least a specified period of time.
@@ -1516,18 +1541,22 @@
1516 >>> print_queue_entries(translationimportqueue)1541 >>> print_queue_entries(translationimportqueue)
15171542
15181543
1519=== Deactivated Products ===1544Deactivated Products
1545....................
15201546
1521Another reason for deleting entries is that they belong to products that1547Another reason for deleting entries is that they belong to products that
1522have been deactivated.1548have been deactivated.
15231549
1524A user sets up Jokosher for translation, and uploads a template.1550A user sets up Jokosher for translation, and uploads a template.
15251551
1552 >>> from lp.app.enums import ServiceUsage
1553
1526 >>> jokosher = productset['jokosher']1554 >>> jokosher = productset['jokosher']
1527 >>> jokosher_trunk = jokosher.getSeries('trunk')1555 >>> jokosher_trunk = jokosher.getSeries('trunk')
1528 >>> jokosher.official_rosetta = True1556 >>> jokosher.translations_usage = ServiceUsage.LAUNCHPAD
1529 >>> syncUpdate(jokosher)1557 >>> syncUpdate(jokosher)
1530 >>> jokosher_subset = potemplateset.getSubset(productseries=jokosher_trunk)1558 >>> jokosher_subset = potemplateset.getSubset(
1559 ... productseries=jokosher_trunk)
1531 >>> template = jokosher_subset.new(1560 >>> template = jokosher_subset.new(
1532 ... 'jokosher', 'jokosher', 'jokosher.pot', rosetta_experts)1561 ... 'jokosher', 'jokosher', 'jokosher.pot', rosetta_experts)
1533 >>> syncUpdate(template)1562 >>> syncUpdate(template)
15341563
=== modified file 'lib/lp/translations/doc/translationmessage-destroy.txt'
--- lib/lp/translations/doc/translationmessage-destroy.txt 2009-07-02 17:16:50 +0000
+++ lib/lp/translations/doc/translationmessage-destroy.txt 2010-09-09 15:34:46 +0000
@@ -1,4 +1,5 @@
1== destroySelf ==1destroySelf
2===========
23
3(Note: this test runs as rosettaadmin to obtain the necessary4(Note: this test runs as rosettaadmin to obtain the necessary
4privileges)5privileges)
@@ -26,7 +27,8 @@
26 SQLObjectNotFound:...27 SQLObjectNotFound:...
2728
2829
29== POFileTranslator update on remove ==30POFileTranslator update on remove
31=================================
3032
31In two sharing POTemplates with one shared POTMsgSet with one shared33In two sharing POTemplates with one shared POTMsgSet with one shared
32translation, we get two POFileTranslator records for each of the POFiles.34translation, we get two POFileTranslator records for each of the POFiles.
@@ -35,16 +37,17 @@
35 >>> # a global 'postgres' permission which allows everything.37 >>> # a global 'postgres' permission which allows everything.
36 >>> LaunchpadZopelessLayer.switchDbUser('postgres')38 >>> LaunchpadZopelessLayer.switchDbUser('postgres')
37 >>> from canonical.database.sqlbase import sqlvalues39 >>> from canonical.database.sqlbase import sqlvalues
40 >>> from lp.app.enums import ServiceUsage
38 >>> from lp.translations.model.pofiletranslator import POFileTranslator41 >>> from lp.translations.model.pofiletranslator import POFileTranslator
39 >>> from lp.testing.factory import LaunchpadObjectFactory42 >>> from lp.testing.factory import LaunchpadObjectFactory
40 >>> factory = LaunchpadObjectFactory()43 >>> factory = LaunchpadObjectFactory()
4144
42 >>> foo = factory.makeProduct()45 >>> foo = factory.makeProduct(
46 ... translations_usage=ServiceUsage.LAUNCHPAD)
43 >>> foo_devel = factory.makeProductSeries(47 >>> foo_devel = factory.makeProductSeries(
44 ... name='devel', product=foo)48 ... name='devel', product=foo)
45 >>> foo_stable = factory.makeProductSeries(49 >>> foo_stable = factory.makeProductSeries(
46 ... name='stable', product=foo)50 ... name='stable', product=foo)
47 >>> foo.official_rosetta = True
48 >>> devel_potemplate = factory.makePOTemplate(51 >>> devel_potemplate = factory.makePOTemplate(
49 ... productseries=foo_devel, name="messages")52 ... productseries=foo_devel, name="messages")
50 >>> stable_potemplate = factory.makePOTemplate(foo_stable,53 >>> stable_potemplate = factory.makePOTemplate(foo_stable,
@@ -56,7 +59,9 @@
56 >>> potmsgset = factory.makePOTMsgSet(devel_potemplate, sequence=1)59 >>> potmsgset = factory.makePOTMsgSet(devel_potemplate, sequence=1)
57 >>> potmsgset.setSequence(stable_potemplate, 1)60 >>> potmsgset.setSequence(stable_potemplate, 1)
58 >>> tm = factory.makeTranslationMessage(61 >>> tm = factory.makeTranslationMessage(
59 ... pofile=devel_sr_pofile, potmsgset=potmsgset, translations=[u"blah"])62 ... pofile=devel_sr_pofile,
63 ... potmsgset=potmsgset,
64 ... translations=[u"blah"])
60 >>> print POFileTranslator.select(65 >>> print POFileTranslator.select(
61 ... "latest_message=%s" % sqlvalues(tm)).count()66 ... "latest_message=%s" % sqlvalues(tm)).count()
62 267 2
6368
=== modified file 'lib/lp/translations/doc/translations-export-to-branch.txt'
--- lib/lp/translations/doc/translations-export-to-branch.txt 2010-07-20 17:50:45 +0000
+++ lib/lp/translations/doc/translations-export-to-branch.txt 2010-09-09 15:34:46 +0000
@@ -1,4 +1,5 @@
1= Exporting translations to a bzr branch =1Exporting translations to a bzr branch
2======================================
23
3The translations-export-to-branch script visits all ProductSeries with a4The translations-export-to-branch script visits all ProductSeries with a
4translations_branch set, and for each, exports the series' translations5translations_branch set, and for each, exports the series' translations
@@ -76,10 +77,11 @@
76branch.77branch.
7778
78 >>> from zope.security.proxy import removeSecurityProxy79 >>> from zope.security.proxy import removeSecurityProxy
80 >>> from lp.app.enums import ServiceUsage
7981
80 >>> gazblachko = removeSecurityProxy(factory.makeProduct(82 >>> gazblachko = removeSecurityProxy(factory.makeProduct(
81 ... name='gazblachko', displayname='Gazblachko'))83 ... name='gazblachko', displayname='Gazblachko'))
82 >>> gazblachko.official_rosetta = True84 >>> gazblachko.translations_usage = ServiceUsage.LAUNCHPAD
8385
84 >>> branch = removeSecurityProxy(factory.makeBranch(86 >>> branch = removeSecurityProxy(factory.makeBranch(
85 ... name='gazpo', owner=gazblachko.owner, product=gazblachko))87 ... name='gazpo', owner=gazblachko.owner, product=gazblachko))
@@ -162,13 +164,13 @@
162When Gazblachko stops using Launchpad for Translations, the exports stop164When Gazblachko stops using Launchpad for Translations, the exports stop
163also.165also.
164166
165 >>> gazblachko.official_rosetta = False167 >>> gazblachko.translations_usage = ServiceUsage.NOT_APPLICABLE
166 >>> transaction.commit()168 >>> transaction.commit()
167 >>> script.main()169 >>> script.main()
168 INFO Exporting to translations branches.170 INFO Exporting to translations branches.
169 INFO Processed 0 item(s); 0 failure(s), 0 unpushed branch(es).171 INFO Processed 0 item(s); 0 failure(s), 0 unpushed branch(es).
170172
171 >>> gazblachko.official_rosetta = True173 >>> gazblachko.translations_usage = ServiceUsage.LAUNCHPAD
172 >>> transaction.commit()174 >>> transaction.commit()
173175
174176
@@ -271,7 +273,8 @@
271collected for import yet.273collected for import yet.
272274
273275
274=== Branch races ===276Branch races
277............
275278
276Any translations coming in through a branch push are safe once they're279Any translations coming in through a branch push are safe once they're
277in the translations import queue. So the race window spans from the280in the translations import queue. So the race window spans from the
@@ -299,7 +302,8 @@
299 INFO Processed 1 item(s); 1 failure(s), 0 unpushed branch(es).302 INFO Processed 1 item(s); 1 failure(s), 0 unpushed branch(es).
300303
301304
302=== Pending imports from same branch ===305Pending imports from same branch
306................................
303307
304Another race condition is detected by the script itself: there may be308Another race condition is detected by the script itself: there may be
305pending translations BranchJobs on the branch.309pending translations BranchJobs on the branch.
306310
=== modified file 'lib/lp/translations/doc/translationsoverview.txt'
--- lib/lp/translations/doc/translationsoverview.txt 2009-07-24 12:55:03 +0000
+++ lib/lp/translations/doc/translationsoverview.txt 2010-09-09 15:34:46 +0000
@@ -1,4 +1,5 @@
1= TranslationsOverview =1TranslationsOverview
2====================
23
3This class provides a basic overview of the Launchpad Translations component.4This class provides a basic overview of the Launchpad Translations component.
4It includes data such as projects which have so far received the most5It includes data such as projects which have so far received the most
@@ -45,14 +46,16 @@
45 1846 18
4647
4748
48== _normalizeSizes ==49_normalizeSizes
50---------------
4951
50This private method accepts a list of tuples (object, size) and52This private method accepts a list of tuples (object, size) and
51normalizes `size` values into the range [MINIMUM_SIZE, MAXIMUM_SIZE].53normalizes `size` values into the range [MINIMUM_SIZE, MAXIMUM_SIZE].
5254
53 >>> test_list = [('one', 3), ('two', 0), ('three', 1)]55 >>> test_list = [('one', 3), ('two', 0), ('three', 1)]
54 >>> from zope.security.proxy import removeSecurityProxy56 >>> from zope.security.proxy import removeSecurityProxy
55 >>> result = removeSecurityProxy(overview)._normalizeSizes(test_list, 0, 3)57 >>> naked_overview = removeSecurityProxy(overview)
58 >>> result = naked_overview._normalizeSizes(test_list, 0, 3)
56 >>> for pillar in result:59 >>> for pillar in result:
57 ... print "%s: %d" % (pillar['pillar'], pillar['weight'])60 ... print "%s: %d" % (pillar['pillar'], pillar['weight'])
58 one: 1861 one: 18
@@ -60,7 +63,8 @@
60 three: 1363 three: 13
6164
6265
63== Getting the most translated pillars ==66Getting the most translated pillars
67-----------------------------------
6468
65Method getMostTranslatedPillars() returns a list of dicts listing69Method getMostTranslatedPillars() returns a list of dicts listing
66pillars with most translations karma so far, along with a relative70pillars with most translations karma so far, along with a relative
@@ -104,10 +108,13 @@
104108
105Adding a little bit of karma to upstart will put it in the list as well.109Adding a little bit of karma to upstart will put it in the list as well.
106110
111 >>> from lp.app.enums import ServiceUsage
112
107 >>> start_karma_update()113 >>> start_karma_update()
108 >>> upstart = product_set.getByName('upstart')114 >>> upstart = product_set.getByName('upstart')
109 >>> upstart_id = upstart.id115 >>> upstart_id = upstart.id
110 >>> removeSecurityProxy(upstart).official_rosetta = True116 >>> naked_upstart = removeSecurityProxy(upstart)
117 >>> naked_upstart.translations_usage = ServiceUsage.LAUNCHPAD
111 >>> cache_entry = karmacachemanager.new(118 >>> cache_entry = karmacachemanager.new(
112 ... 50, carlos.id, translations.id, product_id=upstart_id)119 ... 50, carlos.id, translations.id, product_id=upstart_id)
113 >>> finish_karma_update()120 >>> finish_karma_update()
@@ -153,7 +160,8 @@
153 Ubuntu: 24160 Ubuntu: 24
154161
155162
156== Zero karma ==163Zero karma
164----------
157165
158Sometimes a pillar appears to be listed in the karma cache with zero166Sometimes a pillar appears to be listed in the karma cache with zero
159karma. Our algorithm takes the logarithm of its karma, but it's167karma. Our algorithm takes the logarithm of its karma, but it's
160168
=== modified file 'lib/lp/translations/model/potemplate.py'
--- lib/lp/translations/model/potemplate.py 2010-09-03 03:12:39 +0000
+++ lib/lp/translations/model/potemplate.py 2010-09-09 15:34:46 +0000
@@ -64,6 +64,7 @@
64 IMasterStore,64 IMasterStore,
65 IStore,65 IStore,
66 )66 )
67from lp.app.enums import service_uses_launchpad
67from lp.app.errors import NotFoundError68from lp.app.errors import NotFoundError
68from lp.registry.interfaces.person import validate_public_person69from lp.registry.interfaces.person import validate_public_person
69from lp.registry.model.sourcepackagename import SourcePackageName70from lp.registry.model.sourcepackagename import SourcePackageName
@@ -1322,8 +1323,7 @@
1322 preferred_matches = [1323 preferred_matches = [
1323 match1324 match
1324 for match in matches1325 for match in matches
1325 if match.from_sourcepackagename == sourcepackagename1326 if match.from_sourcepackagename == sourcepackagename]
1326 ]
13271327
1328 if len(preferred_matches) == 1:1328 if len(preferred_matches) == 1:
1329 return preferred_matches[0]1329 return preferred_matches[0]
@@ -1378,6 +1378,9 @@
13781378
1379 def populateSuggestivePOTemplatesCache(self):1379 def populateSuggestivePOTemplatesCache(self):
1380 """See `IPOTemplateSet`."""1380 """See `IPOTemplateSet`."""
1381 # XXX j.c.sackett 2010-08-30 bug=627631 Once data migration has
1382 # happened for the usage enums, this sql needs to be updated to
1383 # check for the translations_usage, not official_rosetta.
1381 return IMasterStore(POTemplate).execute("""1384 return IMasterStore(POTemplate).execute("""
1382 INSERT INTO SuggestivePOTemplate (1385 INSERT INTO SuggestivePOTemplate (
1383 SELECT POTemplate.id1386 SELECT POTemplate.id
@@ -1437,15 +1440,13 @@
1437 if self.product:1440 if self.product:
1438 subsets = [1441 subsets = [
1439 self.potemplateset.getSubset(productseries=series)1442 self.potemplateset.getSubset(productseries=series)
1440 for series in self.product.series1443 for series in self.product.series]
1441 ]
1442 else:1444 else:
1443 subsets = [1445 subsets = [
1444 self.potemplateset.getSubset(1446 self.potemplateset.getSubset(
1445 distroseries=series,1447 distroseries=series,
1446 sourcepackagename=self.sourcepackagename)1448 sourcepackagename=self.sourcepackagename)
1447 for series in self.distribution.series1449 for series in self.distribution.series]
1448 ]
1449 for subset in subsets:1450 for subset in subsets:
1450 for template in subset:1451 for template in subset:
1451 if name_pattern is None or re.match(name_pattern,1452 if name_pattern is None or re.match(name_pattern,
@@ -1548,8 +1549,7 @@
1548 msgset.flags = set([1549 msgset.flags = set([
1549 flag.strip()1550 flag.strip()
1550 for flag in row.flags_comment.split(',')1551 for flag in row.flags_comment.split(',')
1551 if flag1552 if flag])
1552 ])
15531553
1554 # Store the message.1554 # Store the message.
1555 messages.append(msgset)1555 messages.append(msgset)
@@ -1578,8 +1578,9 @@
1578 collection = self.getTemplatesCollection()1578 collection = self.getTemplatesCollection()
15791579
1580 # XXX JeroenVermeulen 2010-07-15 bug=605924: Move the1580 # XXX JeroenVermeulen 2010-07-15 bug=605924: Move the
1581 # official_rosetta distinction into browser code.1581 # translations_usage distinction into browser code.
1582 if collection.target_pillar.official_rosetta:1582 pillar = collection.target_pillar
1583 if service_uses_launchpad(pillar.translations_usage):
1583 return collection.restrictCurrent(current_value)1584 return collection.restrictCurrent(current_value)
1584 else:1585 else:
1585 # Product/Distribution does not have translation enabled.1586 # Product/Distribution does not have translation enabled.
15861587
=== modified file 'lib/lp/translations/model/potmsgset.py'
--- lib/lp/translations/model/potmsgset.py 2010-09-06 03:35:47 +0000
+++ lib/lp/translations/model/potmsgset.py 2010-09-09 15:34:46 +0000
@@ -361,6 +361,9 @@
361 query = ["(NOT %s)" % in_use_clause]361 query = ["(NOT %s)" % in_use_clause]
362 query.append('TranslationMessage.language = %s' % sqlvalues(language))362 query.append('TranslationMessage.language = %s' % sqlvalues(language))
363363
364 # XXX j.c.sackett 2010-08-30 bug=627631 Once data migration has
365 # happened for the usage enums, this sql needs to be updated
366 # to check for the translations_usage, not official_rosetta.
364 query.append('''367 query.append('''
365 potmsgset IN (368 potmsgset IN (
366 SELECT POTMsgSet.id369 SELECT POTMsgSet.id
@@ -381,7 +384,8 @@
381 POTMsgSet.id <> %s AND384 POTMsgSet.id <> %s AND
382 msgid_singular = %s AND385 msgid_singular = %s AND
383 POTemplate.iscurrent AND386 POTemplate.iscurrent AND
384 (Product.official_rosetta OR Distribution.official_rosetta)387 (Product.official_rosetta OR
388 Distribution.official_rosetta)
385 )''' % sqlvalues(self, self.msgid_singular))389 )''' % sqlvalues(self, self.msgid_singular))
386390
387 # Subquery to find the ids of TranslationMessages that are391 # Subquery to find the ids of TranslationMessages that are
@@ -396,8 +400,8 @@
396 for form in xrange(TranslationConstants.MAX_PLURAL_FORMS)])400 for form in xrange(TranslationConstants.MAX_PLURAL_FORMS)])
397 ids_query_params = {401 ids_query_params = {
398 'msgstrs': msgstrs,402 'msgstrs': msgstrs,
399 'where': ' AND '.join(query)403 'where': ' AND '.join(query),
400 }404 }
401 ids_query = '''405 ids_query = '''
402 SELECT DISTINCT ON (%(msgstrs)s)406 SELECT DISTINCT ON (%(msgstrs)s)
403 TranslationMessage.id407 TranslationMessage.id
@@ -565,8 +569,7 @@
565 # plural forms.569 # plural forms.
566 order.extend([570 order.extend([
567 'msgstr%s NULLS FIRST' % quote(form)571 'msgstr%s NULLS FIRST' % quote(form)
568 for form in remaining_plural_forms572 for form in remaining_plural_forms])
569 ])
570 matches = list(573 matches = list(
571 TranslationMessage.select(' AND '.join(clauses), orderBy=order))574 TranslationMessage.select(' AND '.join(clauses), orderBy=order))
572575
@@ -722,7 +725,6 @@
722 if is_imported or new_message == imported_message:725 if is_imported or new_message == imported_message:
723 new_message.is_imported = True726 new_message.is_imported = True
724727
725
726 def _isTranslationMessageASuggestion(self, force_suggestion,728 def _isTranslationMessageASuggestion(self, force_suggestion,
727 pofile, submitter,729 pofile, submitter,
728 force_edition_rights, is_imported,730 force_edition_rights, is_imported,
@@ -1178,4 +1180,3 @@
1178 """See `IPOTMsgSet`."""1180 """See `IPOTMsgSet`."""
1179 return TranslationTemplateItem.selectBy(1181 return TranslationTemplateItem.selectBy(
1180 potmsgset=self, orderBy=['id'])1182 potmsgset=self, orderBy=['id'])
1181
11821183
=== modified file 'lib/lp/translations/model/translationsoverview.py'
--- lib/lp/translations/model/translationsoverview.py 2010-08-20 20:31:18 +0000
+++ lib/lp/translations/model/translationsoverview.py 2010-09-09 15:34:46 +0000
@@ -39,13 +39,15 @@
39 new_size = int(round(39 new_size = int(round(
40 real_minimum +40 real_minimum +
41 (size - offset - real_minimum) * multiplier))41 (size - offset - real_minimum) * multiplier))
42 normalized_sizes.append({'pillar' : pillar,42 normalized_sizes.append({'pillar': pillar, 'weight': new_size})
43 'weight' : new_size })
44 return normalized_sizes43 return normalized_sizes
4544
46 def getMostTranslatedPillars(self, limit=50):45 def getMostTranslatedPillars(self, limit=50):
47 """See `ITranslationsOverview`."""46 """See `ITranslationsOverview`."""
4847
48 # XXX j.c.sackett 2010-08-30 bug=627631 Once data migration has
49 # happened for the usage enums, this sql needs to be updated
50 # to check for the translations_usage, not official_rosetta.
49 query = """51 query = """
50 SELECT LOWER(COALESCE(product_name, distro_name)) AS name,52 SELECT LOWER(COALESCE(product_name, distro_name)) AS name,
51 product_id,53 product_id,
@@ -65,7 +67,8 @@
65 distribution=distribution.id67 distribution=distribution.id
66 WHERE category=3 AND68 WHERE category=3 AND
67 (product IS NOT NULL OR distribution IS NOT NULL) AND69 (product IS NOT NULL OR distribution IS NOT NULL) AND
68 (product.official_rosetta OR distribution.official_rosetta)70 (product.official_rosetta OR
71 distribution.official_rosetta)
69 GROUP BY product.displayname, product.id,72 GROUP BY product.displayname, product.id,
70 distribution.displayname, distribution.id73 distribution.displayname, distribution.id
71 HAVING SUM(karmavalue) > 074 HAVING SUM(karmavalue) > 0
7275
=== modified file 'lib/lp/translations/model/translationsperson.py'
--- lib/lp/translations/model/translationsperson.py 2010-08-27 10:53:40 +0000
+++ lib/lp/translations/model/translationsperson.py 2010-09-09 15:34:46 +0000
@@ -262,6 +262,10 @@
262 The added joins may make the overall query non-distinct, so be262 The added joins may make the overall query non-distinct, so be
263 sure to enforce distinctness.263 sure to enforce distinctness.
264 """264 """
265 # XXX j.c.sackett 2010-08-30 bug=627631 Once data migration has
266 # happened for the usage enums, this query needs to be updated
267 # to check for the translations_usage, not official_rosetta.
268
265 POTemplateJoin = Join(POTemplate, And(269 POTemplateJoin = Join(POTemplate, And(
266 POTemplate.id == POFile.potemplateID,270 POTemplate.id == POFile.potemplateID,
267 POTemplate.iscurrent == True))271 POTemplate.iscurrent == True))
268272
=== modified file 'lib/lp/translations/scripts/translations_to_branch.py'
--- lib/lp/translations/scripts/translations_to_branch.py 2010-08-20 20:31:18 +0000
+++ lib/lp/translations/scripts/translations_to_branch.py 2010-09-09 15:34:46 +0000
@@ -306,6 +306,9 @@
306306
307 self.store = getUtility(IStoreSelector).get(MAIN_STORE, SLAVE_FLAVOR)307 self.store = getUtility(IStoreSelector).get(MAIN_STORE, SLAVE_FLAVOR)
308308
309 # XXX j.c.sackett 2010-08-30 bug=627631 Once data migration has
310 # happened for the usage enums, this sql needs to be updated to
311 # check for the translations_usage, not official_rosetta.
309 product_join = Join(312 product_join = Join(
310 ProductSeries, Product, ProductSeries.product == Product.id)313 ProductSeries, Product, ProductSeries.product == Product.id)
311 productseries = self.store.using(product_join).find(314 productseries = self.store.using(product_join).find(
312315
=== modified file 'lib/lp/translations/stories/buildfarm/xx-build-summary.txt'
--- lib/lp/translations/stories/buildfarm/xx-build-summary.txt 2010-07-20 17:50:45 +0000
+++ lib/lp/translations/stories/buildfarm/xx-build-summary.txt 2010-09-09 15:34:46 +0000
@@ -1,9 +1,11 @@
1= TranslationTemplatesBuildJob Build Summary =1TranslationTemplatesBuildJob Build Summary
2==========================================
23
3The builders UI can show TranslationTemplateBuildJobs, although they4The builders UI can show TranslationTemplateBuildJobs, although they
4look a little different from Soyuz-style jobs.5look a little different from Soyuz-style jobs.
56
6== Setup ==7Setup
8-----
79
8Create a builder working on a TranslationTemplatesBuildJob for a branch.10Create a builder working on a TranslationTemplatesBuildJob for a branch.
911
@@ -13,6 +15,7 @@
13 >>> from canonical.launchpad.interfaces.librarian import (15 >>> from canonical.launchpad.interfaces.librarian import (
14 ... ILibraryFileAliasSet)16 ... ILibraryFileAliasSet)
15 >>> from canonical.launchpad.scripts.logger import QuietFakeLogger17 >>> from canonical.launchpad.scripts.logger import QuietFakeLogger
18 >>> from lp.app.enums import ServiceUsage
16 >>> from lp.buildmaster.interfaces.buildqueue import IBuildQueueSet19 >>> from lp.buildmaster.interfaces.buildqueue import IBuildQueueSet
17 >>> from lp.testing.factory import (20 >>> from lp.testing.factory import (
18 ... remove_security_proxy_and_shout_at_engineer)21 ... remove_security_proxy_and_shout_at_engineer)
@@ -32,7 +35,7 @@
32 >>> productseries = factory.makeProductSeries(owner=owner)35 >>> productseries = factory.makeProductSeries(owner=owner)
33 >>> product = productseries.product36 >>> product = productseries.product
34 >>> naked_product = remove_security_proxy_and_shout_at_engineer(product)37 >>> naked_product = remove_security_proxy_and_shout_at_engineer(product)
35 >>> naked_product.official_rosetta = True38 >>> naked_product.translations_usage = ServiceUsage.LAUNCHPAD
36 >>> branch = factory.makeProductBranch(product=product, owner=owner)39 >>> branch = factory.makeProductBranch(product=product, owner=owner)
37 >>> branch_url = branch.unique_name40 >>> branch_url = branch.unique_name
3841
@@ -62,7 +65,8 @@
62 ... return find_tag_by_id(browser.contents, 'current-build-summary')65 ... return find_tag_by_id(browser.contents, 'current-build-summary')
6366
6467
65== Show summary ==68Show summary
69------------
6670
67The job's summary shows that what type of job this is. It also links71The job's summary shows that what type of job this is. It also links
68to the branch.72to the branch.
6973
=== modified file 'lib/lp/translations/stories/importqueue/xx-entry-details.txt'
--- lib/lp/translations/stories/importqueue/xx-entry-details.txt 2010-03-11 20:54:36 +0000
+++ lib/lp/translations/stories/importqueue/xx-entry-details.txt 2010-09-09 15:34:46 +0000
@@ -1,9 +1,11 @@
1= Entry details =1Entry details
2=============
23
3The translation import queue entry page shows various details about an4The translation import queue entry page shows various details about an
4entry and its target that may be helpful in queue review.5entry and its target that may be helpful in queue review.
56
6 >>> from zope.security.proxy import removeSecurityProxy7 >>> from zope.security.proxy import removeSecurityProxy
8 >>> from lp.app.enums import ServiceUsage
7 >>> from lp.translations.model.translationimportqueue import (9 >>> from lp.translations.model.translationimportqueue import (
8 ... TranslationImportQueue)10 ... TranslationImportQueue)
911
@@ -11,8 +13,8 @@
1113
12 >>> login(ANONYMOUS)14 >>> login(ANONYMOUS)
13 >>> queue = TranslationImportQueue()15 >>> queue = TranslationImportQueue()
14 >>> product = factory.makeProduct()16 >>> product = factory.makeProduct(
15 >>> removeSecurityProxy(product).official_rosetta = True17 ... translations_usage=ServiceUsage.LAUNCHPAD)
16 >>> trunk = product.getSeries('trunk')18 >>> trunk = product.getSeries('trunk')
17 >>> uploader = factory.makePerson()19 >>> uploader = factory.makePerson()
18 >>> entry = queue.addOrUpdateEntry(20 >>> entry = queue.addOrUpdateEntry(
@@ -47,7 +49,8 @@
47 http://...foo.pot49 http://...foo.pot
4850
4951
50== Existing templates ==52Existing templates
53------------------
5154
52If there are translatable templates in the series, this will be stated55If there are translatable templates in the series, this will be stated
53and there will be a link to the templates list.56and there will be a link to the templates list.
@@ -81,7 +84,8 @@
81 ...84 ...
8285
8386
84== Source packages ==87Source packages
88---------------
8589
86The portlet shows different (well, less) information for uploads90The portlet shows different (well, less) information for uploads
87attached to distribution packages.91attached to distribution packages.
8892
=== modified file 'lib/lp/translations/stories/productseries/xx-productseries-export-to-branch.txt'
--- lib/lp/translations/stories/productseries/xx-productseries-export-to-branch.txt 2009-09-02 16:35:54 +0000
+++ lib/lp/translations/stories/productseries/xx-productseries-export-to-branch.txt 2010-09-09 15:34:46 +0000
@@ -1,15 +1,16 @@
1= ProductSeries Translations Branch =1ProductSeries Translations Branch
2=================================
23
3If a ProductSeries has its translations_branch set, Launchpad will4If a ProductSeries has its translations_branch set, Launchpad will
4periodically commit snapshots of the series' translations to that5periodically commit snapshots of the series' translations to that
5branch.6branch.
67
7 >>> from zope.security.proxy import removeSecurityProxy8 >>> from lp.app.enums import ServiceUsage
89
9 >>> login(ANONYMOUS)10 >>> login(ANONYMOUS)
10 >>> owner = factory.makePerson(email='x@example.com', password='****')11 >>> owner = factory.makePerson(email='x@example.com', password='****')
11 >>> product = factory.makeProduct(owner=owner)12 >>> product = factory.makeProduct(owner=owner,
12 >>> removeSecurityProxy(product).official_rosetta = True13 ... translations_usage=ServiceUsage.LAUNCHPAD)
13 >>> productseries = product.getSeries('trunk')14 >>> productseries = product.getSeries('trunk')
14 >>> branch = factory.makeBranch(product=product, owner=owner)15 >>> branch = factory.makeBranch(product=product, owner=owner)
15 >>> branch_name = branch.name16 >>> branch_name = branch.name
@@ -99,7 +100,8 @@
99 </div>100 </div>
100101
101102
102== Disabling exports ==103Disabling exports
104-----------------
103105
104The field can also be cleared in order to disable the exports.106The field can also be cleared in order to disable the exports.
105107
@@ -125,7 +127,8 @@
125 None127 None
126128
127129
128== Security ==130Security
131--------
129132
130You can only set the translations_branch to a branch that you own.133You can only set the translations_branch to a branch that you own.
131Otherwise you'd be giving Launchpad a blanket license to commit134Otherwise you'd be giving Launchpad a blanket license to commit
132135
=== modified file 'lib/lp/translations/stories/productseries/xx-productseries-translations.txt'
--- lib/lp/translations/stories/productseries/xx-productseries-translations.txt 2010-03-31 20:25:33 +0000
+++ lib/lp/translations/stories/productseries/xx-productseries-translations.txt 2010-09-09 15:34:46 +0000
@@ -5,9 +5,10 @@
5a single product series, or instructions on how to set up a series for5a single product series, or instructions on how to set up a series for
6translation.6translation.
77
8 >>> from lp.app.enums import ServiceUsage
8 >>> login('foo.bar@canonical.com')9 >>> login('foo.bar@canonical.com')
9 >>> frobnicator = factory.makeProduct(name='frobnicator')10 >>> frobnicator = factory.makeProduct(name='frobnicator',
10 >>> frobnicator.official_rosetta = True11 ... translations_usage=ServiceUsage.LAUNCHPAD)
11 >>> frobnicator_trunk = frobnicator.getSeries('trunk')12 >>> frobnicator_trunk = frobnicator.getSeries('trunk')
12 >>> frobnicator_trunk_url = canonical_url(13 >>> frobnicator_trunk_url = canonical_url(
13 ... frobnicator_trunk, rootsite='translations')14 ... frobnicator_trunk, rootsite='translations')
@@ -148,7 +149,8 @@
148149
149 # Use the raw DB object to bypass the security proxy.150 # Use the raw DB object to bypass the security proxy.
150 >>> from lp.registry.model.product import Product151 >>> from lp.registry.model.product import Product
151 >>> Product.byName('bazaar').official_rosetta = False152 >>> product = Product.byName('bazaar')
153 >>> product.translations_usage = ServiceUsage.NOT_APPLICABLE
152154
153When the owner now visits the upload page for trunk, there's a notice.155When the owner now visits the upload page for trunk, there's a notice.
154156
155157
=== modified file 'lib/lp/translations/stories/standalone/custom-language-codes.txt'
--- lib/lp/translations/stories/standalone/custom-language-codes.txt 2010-03-11 20:54:36 +0000
+++ lib/lp/translations/stories/standalone/custom-language-codes.txt 2010-09-09 15:34:46 +0000
@@ -11,11 +11,11 @@
11Custom language codes are attached to either a product or a source11Custom language codes are attached to either a product or a source
12package.12package.
1313
14 >>> import re
15 >>> from zope.component import getUtility14 >>> from zope.component import getUtility
16 >>> from zope.security.proxy import removeSecurityProxy15 >>> from zope.security.proxy import removeSecurityProxy
17 >>> from canonical.launchpad.interfaces.launchpad import (16 >>> from canonical.launchpad.interfaces.launchpad import (
18 ... ILaunchpadCelebrities)17 ... ILaunchpadCelebrities)
18 >>> from lp.app.enums import ServiceUsage
1919
20 >>> def find_custom_language_codes_link(browser):20 >>> def find_custom_language_codes_link(browser):
21 ... """Find reference to custom language codes on a page."""21 ... """Find reference to custom language codes on a page."""
@@ -29,7 +29,8 @@
29 ... getUtility(ILaunchpadCelebrities).rosetta_experts)29 ... getUtility(ILaunchpadCelebrities).rosetta_experts)
30 >>> product = factory.makeProduct(displayname="Foo", owner=owner)30 >>> product = factory.makeProduct(displayname="Foo", owner=owner)
31 >>> trunk = product.getSeries('trunk')31 >>> trunk = product.getSeries('trunk')
32 >>> removeSecurityProxy(product).official_rosetta = True32 >>> naked_product = removeSecurityProxy(product)
33 >>> naked_product.translations_usage = ServiceUsage.LAUNCHPAD
33 >>> template = factory.makePOTemplate(productseries=trunk)34 >>> template = factory.makePOTemplate(productseries=trunk)
34 >>> product_page = canonical_url(product, rootsite='translations')35 >>> product_page = canonical_url(product, rootsite='translations')
35 >>> logout()36 >>> logout()
@@ -198,7 +199,8 @@
198 >>> sourcepackagename = SourcePackageName(name='bar')199 >>> sourcepackagename = SourcePackageName(name='bar')
199 >>> package = factory.makeSourcePackage(200 >>> package = factory.makeSourcePackage(
200 ... sourcepackagename=sourcepackagename, distroseries=distroseries)201 ... sourcepackagename=sourcepackagename, distroseries=distroseries)
201 >>> removeSecurityProxy(distro).official_rosetta = True202 >>> naked_distro = removeSecurityProxy(distro)
203 >>> naked_distro.translations_usage = ServiceUsage.LAUNCHPAD
202 >>> other_series = factory.makeDistroRelease(distribution=distro)204 >>> other_series = factory.makeDistroRelease(distribution=distro)
203 >>> template = factory.makePOTemplate(205 >>> template = factory.makePOTemplate(
204 ... distroseries=package.distroseries,206 ... distroseries=package.distroseries,
205207
=== modified file 'lib/lp/translations/stories/standalone/xx-potemplate-index.txt'
--- lib/lp/translations/stories/standalone/xx-potemplate-index.txt 2010-02-16 21:21:14 +0000
+++ lib/lp/translations/stories/standalone/xx-potemplate-index.txt 2010-09-09 15:34:46 +0000
@@ -6,7 +6,7 @@
6-----------6-----------
77
8The index page for a POTemplate lists all available translations8The index page for a POTemplate lists all available translations
9for a source package. No Privileges Person visits the 9for a source package. No Privileges Person visits the
10evolution-2.2 POTemplate page.10evolution-2.2 POTemplate page.
1111
12 >>> anon_browser.open("http://translations.launchpad.dev/"12 >>> anon_browser.open("http://translations.launchpad.dev/"
@@ -85,7 +85,7 @@
85 </p>85 </p>
8686
8787
88DistroSeries and ProductSeries links to related templates 88DistroSeries and ProductSeries links to related templates
89---------------------------------------------------------89---------------------------------------------------------
9090
91We are presented not only with links to alternate templates from the same91We are presented not only with links to alternate templates from the same
@@ -117,8 +117,8 @@
117A source package with five templates is created.117A source package with five templates is created.
118118
119 >>> from zope.component import getUtility119 >>> from zope.component import getUtility
120 >>> from canonical.launchpad.interfaces.launchpad import (120 >>> from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
121 ... ILaunchpadCelebrities)121
122 >>> login('admin@canonical.com')122 >>> login('admin@canonical.com')
123 >>> ubuntu = getUtility(ILaunchpadCelebrities).ubuntu123 >>> ubuntu = getUtility(ILaunchpadCelebrities).ubuntu
124 >>> hoary = ubuntu.getSeries('hoary')124 >>> hoary = ubuntu.getSeries('hoary')
@@ -212,8 +212,10 @@
212 >>> from zope.component import getUtility212 >>> from zope.component import getUtility
213 >>> from canonical.launchpad.interfaces.launchpad import (213 >>> from canonical.launchpad.interfaces.launchpad import (
214 ... ILaunchpadCelebrities)214 ... ILaunchpadCelebrities)
215 >>> from lp.app.enums import ServiceUsage
215 >>> login('admin@canonical.com')216 >>> login('admin@canonical.com')
216 >>> product = factory.makeProduct(name="fusa", official_rosetta=True)217 >>> product = factory.makeProduct(name="fusa",
218 ... translations_usage=ServiceUsage.LAUNCHPAD)
217 >>> product_trunk = product.getSeries('trunk')219 >>> product_trunk = product.getSeries('trunk')
218 >>> template = factory.makePOTemplate(220 >>> template = factory.makePOTemplate(
219 ... productseries=product_trunk, name='first')221 ... productseries=product_trunk, name='first')
@@ -253,7 +255,9 @@
253Anonymous visitors see only a list of all existing templates, with no255Anonymous visitors see only a list of all existing templates, with no
254administration or download/upload links.256administration or download/upload links.
255257
256 >>> anon_browser.open('http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2')258 >>> anon_browser.open(
259 ... 'http://translations.launchpad.dev/'
260 ... 'ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
257 >>> anon_browser.getLink('upload')261 >>> anon_browser.getLink('upload')
258 Traceback (most recent call last):262 Traceback (most recent call last):
259 ...263 ...
@@ -267,7 +271,9 @@
267As an authenticated user, you should see the download link,271As an authenticated user, you should see the download link,
268but not the one for uploading file to this potemplate.272but not the one for uploading file to this potemplate.
269273
270 >>> user_browser.open('http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2')274 >>> user_browser.open(
275 ... 'http://translations.launchpad.dev/'
276 ... 'ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
271 >>> user_browser.getLink('upload')277 >>> user_browser.getLink('upload')
272 Traceback (most recent call last):278 Traceback (most recent call last):
273 ...279 ...
@@ -281,27 +287,37 @@
281Beside administering this template, "Change permissions"287Beside administering this template, "Change permissions"
282and "Change details" should be also accessible.288and "Change details" should be also accessible.
283289
284 >>> admin_browser.open('http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2')290 >>> admin_browser.open(
291 ... 'http://translations.launchpad.dev/'
292 ... 'ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
285 >>> admin_browser.getLink('upload').click()293 >>> admin_browser.getLink('upload').click()
286 >>> print admin_browser.url294 >>> print admin_browser.url
287 http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2/+upload295 http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2/+upload
288296
289 >>> admin_browser.open('http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2')297 >>> admin_browser.open(
298 ... 'http://translations.launchpad.dev/'
299 ... 'ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
290 >>> admin_browser.getLink('download').click()300 >>> admin_browser.getLink('download').click()
291 >>> print admin_browser.url301 >>> print admin_browser.url
292 http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2/+export302 http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2/+export
293303
294 >>> admin_browser.open('http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2')304 >>> admin_browser.open(
305 ... 'http://translations.launchpad.dev/'
306 ... 'ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
295 >>> admin_browser.getLink('Administer this template').click()307 >>> admin_browser.getLink('Administer this template').click()
296 >>> print admin_browser.url308 >>> print admin_browser.url
297 http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2/+admin309 http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2/+admin
298310
299 >>> admin_browser.open('http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2')311 >>> admin_browser.open(
312 ... 'http://translations.launchpad.dev/'
313 ... 'ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
300 >>> admin_browser.getLink('Change details').click()314 >>> admin_browser.getLink('Change details').click()
301 >>> print admin_browser.url315 >>> print admin_browser.url
302 http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2/+edit316 http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2/+edit
303317
304 >>> admin_browser.open('http://translations.launchpad.dev/ubuntu/hoary/+source/evolution/+pots/evolution-2.2')318 >>> admin_browser.open(
319 ... 'http://translations.launchpad.dev/'
320 ... 'ubuntu/hoary/+source/evolution/+pots/evolution-2.2')
305 >>> admin_browser.getLink('Change permissions').click()321 >>> admin_browser.getLink('Change permissions').click()
306 >>> print admin_browser.url322 >>> print admin_browser.url
307 http://translations.launchpad.dev/ubuntu/+settings323 http://translations.launchpad.dev/ubuntu/+settings
308324
=== modified file 'lib/lp/translations/stories/standalone/xx-product-export.txt'
--- lib/lp/translations/stories/standalone/xx-product-export.txt 2009-09-18 15:42:19 +0000
+++ lib/lp/translations/stories/standalone/xx-product-export.txt 2010-09-09 15:34:46 +0000
@@ -1,4 +1,5 @@
1= Downloading Product Series Translations =1Downloading Product Series Translations
2=======================================
23
3Products and product series that use Translations offer complete4Products and product series that use Translations offer complete
4translation downloads.5translation downloads.
@@ -33,16 +34,18 @@
33 Your request has been received. Expect to receive an email shortly.34 Your request has been received. Expect to receive an email shortly.
3435
3536
36== Use of Launchpad Translations ==37Use of Launchpad Translations
38-----------------------------
3739
38The Download link is not shown if the product does not use Launchpad40The Download link is not shown if the product does not use Launchpad
39Translations.41Translations.
4042
41 # Use the DB classes directly to avoid having to setup a zope interaction43 # Use the DB classes directly to avoid having to setup a zope interaction
42 # (i.e. login()) and bypass the security proxy.44 # (i.e. login()) and bypass the security proxy.
45 >>> from lp.app.enums import ServiceUsage
43 >>> from lp.registry.model.product import Product46 >>> from lp.registry.model.product import Product
44 >>> product = Product.byName('evolution')47 >>> product = Product.byName('evolution')
45 >>> product.official_rosetta = False48 >>> product.translations_usage = ServiceUsage.NOT_APPLICABLE
46 >>> product.sync()49 >>> product.sync()
47 >>> user_browser.open('http://translations.launchpad.dev/evolution')50 >>> user_browser.open('http://translations.launchpad.dev/evolution')
48 >>> user_browser.getLink('download')51 >>> user_browser.getLink('download')
@@ -51,14 +54,15 @@
51 LinkNotFoundError54 LinkNotFoundError
5255
53 >>> # Restore previous state for subsequent tests, and verify56 >>> # Restore previous state for subsequent tests, and verify
54 >>> product.official_rosetta = True57 >>> product.translations_usage = ServiceUsage.LAUNCHPAD
55 >>> product.sync()58 >>> product.sync()
56 >>> user_browser.open('http://translations.launchpad.dev/evolution')59 >>> user_browser.open('http://translations.launchpad.dev/evolution')
57 >>> user_browser.getLink('download') is not None60 >>> user_browser.getLink('download') is not None
58 True61 True
5962
6063
61== Authorization ==64Authorization
65-------------
6266
63Only logged-in users get the option to request downloads.67Only logged-in users get the option to request downloads.
6468
6569
=== modified file 'lib/lp/translations/stories/standalone/xx-product-translations.txt'
--- lib/lp/translations/stories/standalone/xx-product-translations.txt 2010-08-25 00:01:57 +0000
+++ lib/lp/translations/stories/standalone/xx-product-translations.txt 2010-09-09 15:34:46 +0000
@@ -1,4 +1,3 @@
1====================
2Product Translations1Product Translations
3====================2====================
43
54
=== modified file 'lib/lp/translations/stories/standalone/xx-template-description-escaping.txt'
--- lib/lp/translations/stories/standalone/xx-template-description-escaping.txt 2009-09-14 15:41:21 +0000
+++ lib/lp/translations/stories/standalone/xx-template-description-escaping.txt 2010-09-09 15:34:46 +0000
@@ -1,12 +1,14 @@
1 >>> import re1 >>> import re
2 >>> from zope.security.proxy import removeSecurityProxy2 >>> from zope.security.proxy import removeSecurityProxy
3 >>> from lp.app.enums import ServiceUsage
34
4 >>> login('foo.bar@canonical.com')5 >>> login('foo.bar@canonical.com')
5 >>> package = factory.makeSourcePackage()6 >>> package = factory.makeSourcePackage()
6 >>> template = removeSecurityProxy(factory.makePOTemplate(7 >>> template = removeSecurityProxy(factory.makePOTemplate(
7 ... distroseries=package.distroseries,8 ... distroseries=package.distroseries,
8 ... sourcepackagename=package.sourcepackagename))9 ... sourcepackagename=package.sourcepackagename))
9 >>> template.distroseries.distribution.official_rosetta = True10 >>> distribution = template.distroseries.distribution
11 >>> distribution.translations_usage = ServiceUsage.LAUNCHPAD
10 >>> template.distroseries.hide_all_translations = False12 >>> template.distroseries.hide_all_translations = False
11 >>> template.description = "See http://example.com/ for an example!"13 >>> template.description = "See http://example.com/ for an example!"
12 >>> package_url = canonical_url(package, rootsite='translations')14 >>> package_url = canonical_url(package, rootsite='translations')
1315
=== modified file 'lib/lp/translations/stories/translationfocus/xx-product-translationfocus.txt'
--- lib/lp/translations/stories/translationfocus/xx-product-translationfocus.txt 2010-01-20 20:21:42 +0000
+++ lib/lp/translations/stories/translationfocus/xx-product-translationfocus.txt 2010-09-09 15:34:46 +0000
@@ -1,9 +1,10 @@
1The translation focus of a product can be explicitly set to a specific series.1The translation focus of a product can be explicitly set to a specific series.
2When not set, launchpad recommends the development focus to translate.2When not set, launchpad recommends the development focus to translate.
33
4 >>> from lp.app.enums import ServiceUsage
4 >>> login('admin@canonical.com')5 >>> login('admin@canonical.com')
5 >>> fooproject = factory.makeProduct(name="fooproject")6 >>> fooproject = factory.makeProduct(name="fooproject")
6 >>> fooproject.official_rosetta = True7 >>> fooproject.translations_usage = ServiceUsage.LAUNCHPAD
7 >>> fooproject_trunk = fooproject.getSeries("trunk")8 >>> fooproject_trunk = fooproject.getSeries("trunk")
8 >>> fooproject_url = canonical_url(9 >>> fooproject_url = canonical_url(
9 ... fooproject, rootsite="translations")10 ... fooproject, rootsite="translations")
@@ -25,7 +26,8 @@
25 ...26 ...
26 IndexError: list index out of range27 IndexError: list index out of range
2728
28== Setting the translation focus ==29Setting the translation focus
30=============================
2931
30 >>> login('admin@canonical.com')32 >>> login('admin@canonical.com')
31 >>> from zope.security.proxy import removeSecurityProxy33 >>> from zope.security.proxy import removeSecurityProxy
@@ -35,7 +37,7 @@
35 >>> pofile = factory.makePOFile("pt_BR", potemplate=pot_main)37 >>> pofile = factory.makePOFile("pt_BR", potemplate=pot_main)
36 >>> logout()38 >>> logout()
3739
38When the translation focus is not set, Launchpad suggests the 40When the translation focus is not set, Launchpad suggests the
39development focus as the current series to be translated.41development focus as the current series to be translated.
40It needs to be translatable.42It needs to be translatable.
4143
4244
=== modified file 'lib/lp/translations/stories/translationgroups/xx-change-translation-policy.txt'
--- lib/lp/translations/stories/translationgroups/xx-change-translation-policy.txt 2010-02-16 21:21:14 +0000
+++ lib/lp/translations/stories/translationgroups/xx-change-translation-policy.txt 2010-09-09 15:34:46 +0000
@@ -4,11 +4,15 @@
4A product owner, Rosetta expert, and Ubuntu translations coordinator4A product owner, Rosetta expert, and Ubuntu translations coordinator
5browser is created.5browser is created.
66
7 >>> from lp.app.enums import ServiceUsage
8
7 >>> login('admin@canonical.com')9 >>> login('admin@canonical.com')
8 >>> product_owner = factory.makePerson(10 >>> product_owner = factory.makePerson(
9 ... email="po@ex.com", password="test")11 ... email="po@ex.com", password="test")
10 >>> chestii = factory.makeProduct(12 >>> chestii = factory.makeProduct(
11 ... name='chestii', owner=product_owner, official_rosetta=True)13 ... name='chestii',
14 ... owner=product_owner,
15 ... translations_usage=ServiceUsage.LAUNCHPAD)
12 >>> logout()16 >>> logout()
13 >>> dtc_browser = setupDTCBrowser()17 >>> dtc_browser = setupDTCBrowser()
14 >>> re_browser = setupRosettaExpertBrowser()18 >>> re_browser = setupRosettaExpertBrowser()
1519
=== modified file 'lib/lp/translations/templates/product-portlet-not-using-launchpad.pt'
--- lib/lp/translations/templates/product-portlet-not-using-launchpad.pt 2010-03-15 20:17:21 +0000
+++ lib/lp/translations/templates/product-portlet-not-using-launchpad.pt 2010-09-09 15:34:46 +0000
@@ -5,7 +5,7 @@
5 omit-tag="">5 omit-tag="">
66
7 <div id="not-translated-in-launchpad"7 <div id="not-translated-in-launchpad"
8 tal:condition="not: context/official_rosetta">8 tal:condition="not: context/translations_usage/enumvalue:LAUNCHPAD">
9 <strong>9 <strong>
10 This project is not using Launchpad for translations.10 This project is not using Launchpad for translations.
11 </strong>11 </strong>
1212
=== modified file 'lib/lp/translations/templates/productseries-translations.pt'
--- lib/lp/translations/templates/productseries-translations.pt 2009-12-16 15:21:36 +0000
+++ lib/lp/translations/templates/productseries-translations.pt 2010-09-09 15:34:46 +0000
@@ -30,7 +30,7 @@
30 <a href="https://help.launchpad.net/Translations/YourProject">start30 <a href="https://help.launchpad.net/Translations/YourProject">start
31 translating your project</a>,31 translating your project</a>,
32 <tal:uses-translations condition="not:32 <tal:uses-translations condition="not:
33 context/product/official_rosetta">33 context/product/translations_usage/enumvalue:LAUNCHPAD">
34 you should enable translations in your project settings, and34 you should enable translations in your project settings, and
35 </tal:uses-translations>35 </tal:uses-translations>
36 you can either36 you can either
3737
=== modified file 'lib/lp/translations/tests/test_autoapproval.py'
--- lib/lp/translations/tests/test_autoapproval.py 2010-08-20 20:31:18 +0000
+++ lib/lp/translations/tests/test_autoapproval.py 2010-09-09 15:34:46 +0000
@@ -23,6 +23,7 @@
23from canonical.launchpad.interfaces.lpstorm import IMasterStore23from canonical.launchpad.interfaces.lpstorm import IMasterStore
24from canonical.launchpad.webapp.testing import verifyObject24from canonical.launchpad.webapp.testing import verifyObject
25from canonical.testing import LaunchpadZopelessLayer25from canonical.testing import LaunchpadZopelessLayer
26from lp.app.enums import ServiceUsage
26from lp.registry.interfaces.series import SeriesStatus27from lp.registry.interfaces.series import SeriesStatus
27from lp.registry.model.distribution import Distribution28from lp.registry.model.distribution import Distribution
28from lp.registry.model.sourcepackagename import (29from lp.registry.model.sourcepackagename import (
@@ -714,8 +715,8 @@
714 # _get_pofile_from_language will find an enabled template, and715 # _get_pofile_from_language will find an enabled template, and
715 # return either an existing POFile for the given language, or a716 # return either an existing POFile for the given language, or a
716 # newly created one.717 # newly created one.
717 product = self.factory.makeProduct()718 product = self.factory.makeProduct(
718 product.official_rosetta = True719 translations_usage=ServiceUsage.LAUNCHPAD)
719 trunk = product.getSeries('trunk')720 trunk = product.getSeries('trunk')
720 template = self.factory.makePOTemplate(721 template = self.factory.makePOTemplate(
721 productseries=trunk, translation_domain='domain')722 productseries=trunk, translation_domain='domain')
@@ -732,8 +733,8 @@
732 # _get_pofile_from_language will not consider a disabled733 # _get_pofile_from_language will not consider a disabled
733 # template as an auto-approval target, and so will not return a734 # template as an auto-approval target, and so will not return a
734 # POFile for it.735 # POFile for it.
735 product = self.factory.makeProduct()736 product = self.factory.makeProduct(
736 product.official_rosetta = True737 translations_usage=ServiceUsage.LAUNCHPAD)
737 trunk = product.getSeries('trunk')738 trunk = product.getSeries('trunk')
738 template = self.factory.makePOTemplate(739 template = self.factory.makePOTemplate(
739 productseries=trunk, translation_domain='domain')740 productseries=trunk, translation_domain='domain')
@@ -750,8 +751,8 @@
750 # When the template has translation credits, a new dummy translation751 # When the template has translation credits, a new dummy translation
751 # is created in the new POFile. Since this is running with gardener752 # is created in the new POFile. Since this is running with gardener
752 # privileges, we need to check that this works, too.753 # privileges, we need to check that this works, too.
753 product = self.factory.makeProduct()754 product = self.factory.makeProduct(
754 product.official_rosetta = True755 translations_usage=ServiceUsage.LAUNCHPAD)
755 trunk = product.getSeries('trunk')756 trunk = product.getSeries('trunk')
756 template = self.factory.makePOTemplate(757 template = self.factory.makePOTemplate(
757 productseries=trunk, translation_domain='domain')758 productseries=trunk, translation_domain='domain')
@@ -778,8 +779,8 @@
778779
779 def _makeProductEntry(self, path='foo.pot', status=None):780 def _makeProductEntry(self, path='foo.pot', status=None):
780 """Simulate upload for a product."""781 """Simulate upload for a product."""
781 product = self.factory.makeProduct()782 product = self.factory.makeProduct(
782 product.official_rosetta = True783 translations_usage=ServiceUsage.LAUNCHPAD)
783 trunk = product.getSeries('trunk')784 trunk = product.getSeries('trunk')
784 entry = self.queue.addOrUpdateEntry(785 entry = self.queue.addOrUpdateEntry(
785 path, '# contents', False, product.owner, productseries=trunk)786 path, '# contents', False, product.owner, productseries=trunk)
786787
=== modified file 'lib/lp/translations/tests/test_empty_messages.py'
--- lib/lp/translations/tests/test_empty_messages.py 2010-08-20 20:31:18 +0000
+++ lib/lp/translations/tests/test_empty_messages.py 2010-09-09 15:34:46 +0000
@@ -4,17 +4,17 @@
4__metaclass__ = type4__metaclass__ = type
55
6from datetime import datetime6from datetime import datetime
7import unittest
87
9from pytz import timezone8from pytz import timezone
10from zope.component import getUtility9from zope.component import getUtility
1110
12from canonical.testing import LaunchpadZopelessLayer11from canonical.testing import LaunchpadZopelessLayer
12from lp.app.enums import ServiceUsage
13from lp.services.worlddata.interfaces.language import ILanguageSet13from lp.services.worlddata.interfaces.language import ILanguageSet
14from lp.testing.factory import LaunchpadObjectFactory14from lp.testing import TestCaseWithFactory
1515
1616
17class TestTranslationEmptyMessages(unittest.TestCase):17class TestTranslationEmptyMessages(TestCaseWithFactory):
18 """Test behaviour of empty translation messages."""18 """Test behaviour of empty translation messages."""
1919
20 layer = LaunchpadZopelessLayer20 layer = LaunchpadZopelessLayer
@@ -23,13 +23,15 @@
23 """Set up context to test in."""23 """Set up context to test in."""
24 # Pretend we have a product being translated to Serbian.24 # Pretend we have a product being translated to Serbian.
25 # This is where we are going to be importing translations to.25 # This is where we are going to be importing translations to.
26 factory = LaunchpadObjectFactory()26 super(TestTranslationEmptyMessages, self).setUp()
27 self.factory = factory27 product = self.factory.makeProduct(
28 self.productseries = factory.makeProductSeries()28 translations_usage=ServiceUsage.LAUNCHPAD)
29 self.productseries.product.official_rosetta = True29 self.productseries = self.factory.makeProductSeries(product=product)
30 self.potemplate = factory.makePOTemplate(self.productseries)30 self.potemplate = self.factory.makePOTemplate(self.productseries)
31 self.serbian = getUtility(ILanguageSet).getLanguageByCode('sr')31 self.serbian = getUtility(ILanguageSet).getLanguageByCode('sr')
32 self.pofile_sr = factory.makePOFile('sr', potemplate=self.potemplate)32 self.pofile_sr = self.factory.makePOFile(
33 'sr',
34 potemplate=self.potemplate)
33 self.now = datetime.now(timezone('UTC'))35 self.now = datetime.now(timezone('UTC'))
3436
35 def test_NoEmptyImporedTranslation(self):37 def test_NoEmptyImporedTranslation(self):
3638
=== modified file 'lib/lp/translations/tests/test_hastranslationtemplates.py'
--- lib/lp/translations/tests/test_hastranslationtemplates.py 2010-08-20 20:31:18 +0000
+++ lib/lp/translations/tests/test_hastranslationtemplates.py 2010-09-09 15:34:46 +0000
@@ -6,6 +6,7 @@
6from zope.interface.verify import verifyObject6from zope.interface.verify import verifyObject
77
8from canonical.testing import ZopelessDatabaseLayer8from canonical.testing import ZopelessDatabaseLayer
9from lp.app.enums import ServiceUsage
9from lp.testing import TestCaseWithFactory10from lp.testing import TestCaseWithFactory
10from lp.translations.interfaces.potemplate import IHasTranslationTemplates11from lp.translations.interfaces.potemplate import IHasTranslationTemplates
11from lp.translations.interfaces.translationfileformat import (12from lp.translations.interfaces.translationfileformat import (
@@ -152,7 +153,7 @@
152153
153 # A product or distribution that doesn't use Launchpad for154 # A product or distribution that doesn't use Launchpad for
154 # translations has no current templates.155 # translations has no current templates.
155 self.product_or_distro.official_rosetta = False156 self.product_or_distro.translations_usage = ServiceUsage.EXTERNAL
156 self.assertFalse(self.container.has_current_translation_templates)157 self.assertFalse(self.container.has_current_translation_templates)
157158
158 def test_getTranslationTemplateFormats(self):159 def test_getTranslationTemplateFormats(self):
@@ -205,7 +206,7 @@
205 super(TestProductSeriesHasTranslationTemplates, self).setUp()206 super(TestProductSeriesHasTranslationTemplates, self).setUp()
206 self.container = self.factory.makeProductSeries()207 self.container = self.factory.makeProductSeries()
207 self.product_or_distro = self.container.product208 self.product_or_distro = self.container.product
208 self.product_or_distro.official_rosetta = True209 self.product_or_distro.translations_usage = ServiceUsage.LAUNCHPAD
209210
210211
211class TestSourcePackageHasTranslationTemplates(212class TestSourcePackageHasTranslationTemplates(
@@ -223,7 +224,7 @@
223 super(TestSourcePackageHasTranslationTemplates, self).setUp()224 super(TestSourcePackageHasTranslationTemplates, self).setUp()
224 self.container = self.factory.makeSourcePackage()225 self.container = self.factory.makeSourcePackage()
225 self.product_or_distro = self.container.distroseries.distribution226 self.product_or_distro = self.container.distroseries.distribution
226 self.product_or_distro.official_rosetta = True227 self.product_or_distro.translations_usage = ServiceUsage.LAUNCHPAD
227228
228229
229class TestDistroSeriesHasTranslationTemplates(230class TestDistroSeriesHasTranslationTemplates(
@@ -243,4 +244,4 @@
243 super(TestDistroSeriesHasTranslationTemplates, self).setUp()244 super(TestDistroSeriesHasTranslationTemplates, self).setUp()
244 self.container = self.factory.makeDistroRelease()245 self.container = self.factory.makeDistroRelease()
245 self.product_or_distro = self.container.distribution246 self.product_or_distro = self.container.distribution
246 self.product_or_distro.official_rosetta = True247 self.product_or_distro.translations_usage = ServiceUsage.LAUNCHPAD
247248
=== modified file 'lib/lp/translations/tests/test_pofile.py'
--- lib/lp/translations/tests/test_pofile.py 2010-09-03 14:38:20 +0000
+++ lib/lp/translations/tests/test_pofile.py 2010-09-09 15:34:46 +0000
@@ -24,6 +24,7 @@
24 LaunchpadZopelessLayer,24 LaunchpadZopelessLayer,
25 ZopelessDatabaseLayer,25 ZopelessDatabaseLayer,
26 )26 )
27from lp.app.enums import ServiceUsage
27from lp.testing import TestCaseWithFactory28from lp.testing import TestCaseWithFactory
28from lp.translations.interfaces.pofile import IPOFileSet29from lp.translations.interfaces.pofile import IPOFileSet
29from lp.translations.interfaces.translatablemessage import (30from lp.translations.interfaces.translatablemessage import (
@@ -46,12 +47,13 @@
46 # Create a product with two series and a shared POTemplate47 # Create a product with two series and a shared POTemplate
47 # in different series ('devel' and 'stable').48 # in different series ('devel' and 'stable').
48 super(TestTranslationSharedPOFile, self).setUp()49 super(TestTranslationSharedPOFile, self).setUp()
49 self.foo = self.factory.makeProduct(name='foo')50 self.foo = self.factory.makeProduct(
51 name='foo',
52 translations_usage=ServiceUsage.LAUNCHPAD)
50 self.foo_devel = self.factory.makeProductSeries(53 self.foo_devel = self.factory.makeProductSeries(
51 name='devel', product=self.foo)54 name='devel', product=self.foo)
52 self.foo_stable = self.factory.makeProductSeries(55 self.foo_stable = self.factory.makeProductSeries(
53 name='stable', product=self.foo)56 name='stable', product=self.foo)
54 self.foo.official_rosetta = True
5557
56 # POTemplate is 'shared' if it has the same name ('messages').58 # POTemplate is 'shared' if it has the same name ('messages').
57 self.devel_potemplate = self.factory.makePOTemplate(59 self.devel_potemplate = self.factory.makePOTemplate(
@@ -76,7 +78,8 @@
76 'http://translations.launchpad.dev/foo/devel/+pots/messages/sr',78 'http://translations.launchpad.dev/foo/devel/+pots/messages/sr',
77 canonical_url(self.devel_sr_pofile))79 canonical_url(self.devel_sr_pofile))
78 self.assertEqual(80 self.assertEqual(
79 'http://translations.launchpad.dev/foo/devel/+pots/messages/sr/+details',81 ('http://translations.launchpad.dev/'
82 'foo/devel/+pots/messages/sr/+details'),
80 canonical_url(self.devel_sr_pofile, view_name="+details"))83 canonical_url(self.devel_sr_pofile, view_name="+details"))
8184
82 def test_findPOTMsgSetsContaining(self):85 def test_findPOTMsgSetsContaining(self):
@@ -879,12 +882,12 @@
879 # Create a product with two series and a shared POTemplate882 # Create a product with two series and a shared POTemplate
880 # in different series ('devel' and 'stable').883 # in different series ('devel' and 'stable').
881 super(TestSharedPOFileCreation, self).setUp()884 super(TestSharedPOFileCreation, self).setUp()
882 self.foo = self.factory.makeProduct()885 self.foo = self.factory.makeProduct(
886 translations_usage=ServiceUsage.LAUNCHPAD)
883 self.foo_devel = self.factory.makeProductSeries(887 self.foo_devel = self.factory.makeProductSeries(
884 name='devel', product=self.foo)888 name='devel', product=self.foo)
885 self.foo_stable = self.factory.makeProductSeries(889 self.foo_stable = self.factory.makeProductSeries(
886 name='stable', product=self.foo)890 name='stable', product=self.foo)
887 self.foo.official_rosetta = True
888891
889 def test_pofile_creation_shared(self):892 def test_pofile_creation_shared(self):
890 # When a pofile is created in a POTemplate it is also created in893 # When a pofile is created in a POTemplate it is also created in
@@ -1009,12 +1012,12 @@
1009 # Create a product with two series and a shared POTemplate1012 # Create a product with two series and a shared POTemplate
1010 # in different series ('devel' and 'stable').1013 # in different series ('devel' and 'stable').
1011 super(TestTranslationPOFilePOTMsgSetOrdering, self).setUp()1014 super(TestTranslationPOFilePOTMsgSetOrdering, self).setUp()
1012 self.foo = self.factory.makeProduct()1015 self.foo = self.factory.makeProduct(
1016 translations_usage=ServiceUsage.LAUNCHPAD)
1013 self.foo_devel = self.factory.makeProductSeries(1017 self.foo_devel = self.factory.makeProductSeries(
1014 name='devel', product=self.foo)1018 name='devel', product=self.foo)
1015 self.foo_stable = self.factory.makeProductSeries(1019 self.foo_stable = self.factory.makeProductSeries(
1016 name='stable', product=self.foo)1020 name='stable', product=self.foo)
1017 self.foo.official_rosetta = True
10181021
1019 # POTemplate is 'shared' if it has the same name ('messages').1022 # POTemplate is 'shared' if it has the same name ('messages').
1020 self.devel_potemplate = self.factory.makePOTemplate(1023 self.devel_potemplate = self.factory.makePOTemplate(
@@ -1288,8 +1291,8 @@
1288 # We create a product with two series, and attach1291 # We create a product with two series, and attach
1289 # a POTemplate and Serbian POFile to each, making1292 # a POTemplate and Serbian POFile to each, making
1290 # sure they share translations (potemplates have the same name).1293 # sure they share translations (potemplates have the same name).
1291 product = self.factory.makeProduct()1294 product = self.factory.makeProduct(
1292 product.official_rosetta = True1295 translations_usage=ServiceUsage.LAUNCHPAD)
1293 series1 = self.factory.makeProductSeries(product=product,1296 series1 = self.factory.makeProductSeries(product=product,
1294 name='one')1297 name='one')
1295 series2 = self.factory.makeProductSeries(product=product,1298 series2 = self.factory.makeProductSeries(product=product,
@@ -1324,8 +1327,8 @@
1324 # This is a test for bug #414832 which caused sharing POFiles1327 # This is a test for bug #414832 which caused sharing POFiles
1325 # of the touched POFile not to be returned if they had1328 # of the touched POFile not to be returned if they had
1326 # IDs smaller than the touched POFile.1329 # IDs smaller than the touched POFile.
1327 product = self.factory.makeProduct()1330 product = self.factory.makeProduct(
1328 product.official_rosetta = True1331 translations_usage=ServiceUsage.LAUNCHPAD)
1329 series1 = self.factory.makeProductSeries(product=product,1332 series1 = self.factory.makeProductSeries(product=product,
1330 name='one')1333 name='one')
1331 series2 = self.factory.makeProductSeries(product=product,1334 series2 = self.factory.makeProductSeries(product=product,
@@ -1357,7 +1360,7 @@
1357 # POFile to each, making sure they share translations1360 # POFile to each, making sure they share translations
1358 # (potemplates have the same name).1361 # (potemplates have the same name).
1359 distro = self.factory.makeDistribution()1362 distro = self.factory.makeDistribution()
1360 distro.official_rosetta = True1363 distro.translations_usage = ServiceUsage.LAUNCHPAD
1361 series1 = self.factory.makeDistroRelease(distribution=distro,1364 series1 = self.factory.makeDistroRelease(distribution=distro,
1362 name='one')1365 name='one')
1363 sourcepackagename = self.factory.makeSourcePackageName()1366 sourcepackagename = self.factory.makeSourcePackageName()
@@ -1395,9 +1398,9 @@
1395 # Make sure POFiles which are in different products1398 # Make sure POFiles which are in different products
1396 # are not returned even though they have the same potemplate name.1399 # are not returned even though they have the same potemplate name.
1397 series1 = self.factory.makeProductSeries(name='one')1400 series1 = self.factory.makeProductSeries(name='one')
1398 series1.product.official_rosetta = True1401 series1.product.translations_usage = ServiceUsage.LAUNCHPAD
1399 series2 = self.factory.makeProductSeries(name='two')1402 series2 = self.factory.makeProductSeries(name='two')
1400 series2.product.official_rosetta = True1403 series1.product.translations_usage = ServiceUsage.LAUNCHPAD
1401 self.assertNotEqual(series1.product, series2.product)1404 self.assertNotEqual(series1.product, series2.product)
14021405
1403 potemplate1 = self.factory.makePOTemplate(name='shared',1406 potemplate1 = self.factory.makePOTemplate(name='shared',
14041407
=== modified file 'lib/lp/translations/tests/test_potemplate.py'
--- lib/lp/translations/tests/test_potemplate.py 2010-08-20 20:31:18 +0000
+++ lib/lp/translations/tests/test_potemplate.py 2010-09-09 15:34:46 +0000
@@ -7,6 +7,7 @@
7from zope.security.proxy import removeSecurityProxy7from zope.security.proxy import removeSecurityProxy
88
9from canonical.testing import DatabaseFunctionalLayer9from canonical.testing import DatabaseFunctionalLayer
10from lp.app.enums import ServiceUsage
10from lp.registry.interfaces.distribution import IDistributionSet11from lp.registry.interfaces.distribution import IDistributionSet
11from lp.services.worlddata.interfaces.language import ILanguageSet12from lp.services.worlddata.interfaces.language import ILanguageSet
12from lp.testing import TestCaseWithFactory13from lp.testing import TestCaseWithFactory
@@ -327,8 +328,8 @@
327328
328 def setUp(self):329 def setUp(self):
329 super(TestTemplatePrecedence, self).setUp(user='mark@example.com')330 super(TestTemplatePrecedence, self).setUp(user='mark@example.com')
330 self.product = self.factory.makeProduct()331 self.product = self.factory.makeProduct(
331 self.product.official_rosetta = True332 translations_usage=ServiceUsage.LAUNCHPAD)
332 self.trunk = self.product.getSeries('trunk')333 self.trunk = self.product.getSeries('trunk')
333 self.one_dot_oh = self.factory.makeProductSeries(334 self.one_dot_oh = self.factory.makeProductSeries(
334 product=self.product, name='one')335 product=self.product, name='one')
335336
=== modified file 'lib/lp/translations/tests/test_potmsgset.py'
--- lib/lp/translations/tests/test_potmsgset.py 2010-08-20 20:31:18 +0000
+++ lib/lp/translations/tests/test_potmsgset.py 2010-09-09 15:34:46 +0000
@@ -20,6 +20,7 @@
2020
21from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities21from canonical.launchpad.interfaces.launchpad import ILaunchpadCelebrities
22from canonical.testing import ZopelessDatabaseLayer22from canonical.testing import ZopelessDatabaseLayer
23from lp.app.enums import ServiceUsage
23from lp.registry.interfaces.person import IPersonSet24from lp.registry.interfaces.person import IPersonSet
24from lp.registry.interfaces.product import IProductSet25from lp.registry.interfaces.product import IProductSet
25from lp.services.worlddata.interfaces.language import ILanguageSet26from lp.services.worlddata.interfaces.language import ILanguageSet
@@ -45,12 +46,12 @@
45 # Create a product with two series and a shared POTemplate46 # Create a product with two series and a shared POTemplate
46 # in different series ('devel' and 'stable').47 # in different series ('devel' and 'stable').
47 super(TestTranslationSharedPOTMsgSets, self).setUp()48 super(TestTranslationSharedPOTMsgSets, self).setUp()
48 self.foo = self.factory.makeProduct()49 self.foo = self.factory.makeProduct(
50 translations_usage=ServiceUsage.LAUNCHPAD)
49 self.foo_devel = self.factory.makeProductSeries(51 self.foo_devel = self.factory.makeProductSeries(
50 name='devel', product=self.foo)52 name='devel', product=self.foo)
51 self.foo_stable = self.factory.makeProductSeries(53 self.foo_stable = self.factory.makeProductSeries(
52 name='stable', product=self.foo)54 name='stable', product=self.foo)
53 self.foo.official_rosetta = True
5455
55 # POTemplate is 'shared' if it has the same name ('messages').56 # POTemplate is 'shared' if it has the same name ('messages').
56 self.devel_potemplate = self.factory.makePOTemplate(57 self.devel_potemplate = self.factory.makePOTemplate(
@@ -324,7 +325,8 @@
324 # Create an external POTemplate with a POTMsgSet using325 # Create an external POTemplate with a POTMsgSet using
325 # the same English string as the one in self.potmsgset.326 # the same English string as the one in self.potmsgset.
326 external_template = self.factory.makePOTemplate()327 external_template = self.factory.makePOTemplate()
327 external_template.productseries.product.official_rosetta = True328 product = external_template.productseries.product
329 product.translations_usage = ServiceUsage.LAUNCHPAD
328 external_potmsgset = self.factory.makePOTMsgSet(330 external_potmsgset = self.factory.makePOTMsgSet(
329 external_template,331 external_template,
330 singular=self.potmsgset.singular_text)332 singular=self.potmsgset.singular_text)
@@ -383,7 +385,8 @@
383 # Create an external POTemplate with a POTMsgSet using385 # Create an external POTemplate with a POTMsgSet using
384 # the same English string as the one in self.potmsgset.386 # the same English string as the one in self.potmsgset.
385 external_template = self.factory.makePOTemplate()387 external_template = self.factory.makePOTemplate()
386 external_template.productseries.product.official_rosetta = True388 product = external_template.productseries.product
389 product.translations_usage = ServiceUsage.LAUNCHPAD
387 external_potmsgset = self.factory.makePOTMsgSet(390 external_potmsgset = self.factory.makePOTMsgSet(
388 external_template,391 external_template,
389 singular=self.potmsgset.singular_text)392 singular=self.potmsgset.singular_text)
@@ -738,10 +741,10 @@
738 # create TranslationMessage objects.741 # create TranslationMessage objects.
739 super(TestPOTMsgSetSuggestions, self).setUp()742 super(TestPOTMsgSetSuggestions, self).setUp()
740 self.now = self.gen_now().next743 self.now = self.gen_now().next
741 self.foo = self.factory.makeProduct()744 self.foo = self.factory.makeProduct(
745 translations_usage=ServiceUsage.LAUNCHPAD)
742 self.foo_main = self.factory.makeProductSeries(746 self.foo_main = self.factory.makeProductSeries(
743 name='main', product=self.foo)747 name='main', product=self.foo)
744 self.foo.official_rosetta = True
745748
746 self.potemplate = self.factory.makePOTemplate(749 self.potemplate = self.factory.makePOTemplate(
747 productseries=self.foo_main, name="messages")750 productseries=self.foo_main, name="messages")
@@ -926,10 +929,10 @@
926 # create TranslationMessage objects.929 # create TranslationMessage objects.
927 super(TestPOTMsgSetResetTranslation, self).setUp()930 super(TestPOTMsgSetResetTranslation, self).setUp()
928 self.now = self.gen_now().next931 self.now = self.gen_now().next
929 self.foo = self.factory.makeProduct()932 self.foo = self.factory.makeProduct(
933 translations_usage=ServiceUsage.LAUNCHPAD)
930 self.foo_main = self.factory.makeProductSeries(934 self.foo_main = self.factory.makeProductSeries(
931 name='main', product=self.foo)935 name='main', product=self.foo)
932 self.foo.official_rosetta = True
933936
934 self.potemplate = self.factory.makePOTemplate(937 self.potemplate = self.factory.makePOTemplate(
935 productseries=self.foo_main, name="messages")938 productseries=self.foo_main, name="messages")
936939
=== modified file 'lib/lp/translations/tests/test_productserieslanguage.py'
--- lib/lp/translations/tests/test_productserieslanguage.py 2010-08-20 20:31:18 +0000
+++ lib/lp/translations/tests/test_productserieslanguage.py 2010-09-09 15:34:46 +0000
@@ -10,6 +10,7 @@
10from zope.security.proxy import removeSecurityProxy10from zope.security.proxy import removeSecurityProxy
1111
12from canonical.testing import ZopelessDatabaseLayer12from canonical.testing import ZopelessDatabaseLayer
13from lp.app.enums import ServiceUsage
13from lp.services.worlddata.interfaces.language import ILanguageSet14from lp.services.worlddata.interfaces.language import ILanguageSet
14from lp.testing import TestCaseWithFactory15from lp.testing import TestCaseWithFactory
15from lp.translations.interfaces.productserieslanguage import (16from lp.translations.interfaces.productserieslanguage import (
@@ -26,8 +27,10 @@
26 def setUp(self):27 def setUp(self):
27 # Create a productseries that uses translations.28 # Create a productseries that uses translations.
28 TestCaseWithFactory.setUp(self)29 TestCaseWithFactory.setUp(self)
29 self.productseries = self.factory.makeProductSeries()30 product = self.factory.makeProduct(
30 self.productseries.product.official_rosetta = True31 translations_usage=ServiceUsage.LAUNCHPAD)
32 self.productseries = self.factory.makeProductSeries(
33 product=product)
3134
32 def test_no_templates_no_translation(self):35 def test_no_templates_no_translation(self):
33 # There are no templates and no translations.36 # There are no templates and no translations.
@@ -125,8 +128,10 @@
125 def setUp(self):128 def setUp(self):
126 # Create a productseries that uses translations.129 # Create a productseries that uses translations.
127 TestCaseWithFactory.setUp(self)130 TestCaseWithFactory.setUp(self)
128 self.productseries = self.factory.makeProductSeries()131 product = self.factory.makeProduct(
129 self.productseries.product.official_rosetta = True132 translations_usage=ServiceUsage.LAUNCHPAD)
133 self.productseries = self.factory.makeProductSeries(
134 product=product)
130 self.psl_set = getUtility(IProductSeriesLanguageSet)135 self.psl_set = getUtility(IProductSeriesLanguageSet)
131 self.language = getUtility(ILanguageSet).getLanguageByCode('sr')136 self.language = getUtility(ILanguageSet).getLanguageByCode('sr')
132137
133138
=== modified file 'lib/lp/translations/tests/test_shared_potemplate.py'
--- lib/lp/translations/tests/test_shared_potemplate.py 2010-08-20 20:31:18 +0000
+++ lib/lp/translations/tests/test_shared_potemplate.py 2010-09-09 15:34:46 +0000
@@ -10,6 +10,7 @@
10from zope.security.proxy import removeSecurityProxy10from zope.security.proxy import removeSecurityProxy
1111
12from canonical.testing import ZopelessDatabaseLayer12from canonical.testing import ZopelessDatabaseLayer
13from lp.app.enums import ServiceUsage
13from lp.testing.factory import LaunchpadObjectFactory14from lp.testing.factory import LaunchpadObjectFactory
1415
1516
@@ -24,12 +25,12 @@
24 # in different series ('devel' and 'stable').25 # in different series ('devel' and 'stable').
25 factory = LaunchpadObjectFactory()26 factory = LaunchpadObjectFactory()
26 self.factory = factory27 self.factory = factory
27 self.foo = factory.makeProduct()28 self.foo = self.factory.makeProduct(
29 translations_usage=ServiceUsage.LAUNCHPAD)
28 self.foo_devel = factory.makeProductSeries(30 self.foo_devel = factory.makeProductSeries(
29 name='devel', product=self.foo)31 name='devel', product=self.foo)
30 self.foo_stable = factory.makeProductSeries(32 self.foo_stable = factory.makeProductSeries(
31 name='stable', product=self.foo)33 name='stable', product=self.foo)
32 self.foo.official_rosetta = True
3334
34 # POTemplate is a 'sharing' one if it has the same name ('messages').35 # POTemplate is a 'sharing' one if it has the same name ('messages').
35 self.devel_potemplate = factory.makePOTemplate(36 self.devel_potemplate = factory.makePOTemplate(
3637
=== modified file 'lib/lp/translations/tests/test_suggestions.py'
--- lib/lp/translations/tests/test_suggestions.py 2010-08-20 20:31:18 +0000
+++ lib/lp/translations/tests/test_suggestions.py 2010-09-09 15:34:46 +0000
@@ -17,6 +17,7 @@
1717
18from canonical.config import config18from canonical.config import config
19from canonical.testing import LaunchpadZopelessLayer19from canonical.testing import LaunchpadZopelessLayer
20from lp.app.enums import ServiceUsage
20from lp.services.worlddata.interfaces.language import ILanguageSet21from lp.services.worlddata.interfaces.language import ILanguageSet
21from lp.testing.factory import LaunchpadObjectFactory22from lp.testing.factory import LaunchpadObjectFactory
22from lp.translations.interfaces.translationmessage import (23from lp.translations.interfaces.translationmessage import (
@@ -36,10 +37,14 @@
36 # suggestions for the other.37 # suggestions for the other.
37 factory = LaunchpadObjectFactory()38 factory = LaunchpadObjectFactory()
38 self.factory = factory39 self.factory = factory
39 self.foo_trunk = factory.makeProductSeries()40 foo_product = factory.makeProduct(
40 self.bar_trunk = factory.makeProductSeries()41 translations_usage=ServiceUsage.LAUNCHPAD)
41 self.foo_trunk.product.official_rosetta = True42 bar_product = factory.makeProduct(
42 self.bar_trunk.product.official_rosetta = True43 translations_usage=ServiceUsage.LAUNCHPAD)
44 self.foo_trunk = factory.makeProductSeries(
45 product=foo_product)
46 self.bar_trunk = factory.makeProductSeries(
47 product=bar_product)
43 self.foo_template = factory.makePOTemplate(self.foo_trunk)48 self.foo_template = factory.makePOTemplate(self.foo_trunk)
44 self.bar_template = factory.makePOTemplate(self.bar_trunk)49 self.bar_template = factory.makePOTemplate(self.bar_trunk)
45 self.nl = getUtility(ILanguageSet).getLanguageByCode('nl')50 self.nl = getUtility(ILanguageSet).getLanguageByCode('nl')
@@ -222,5 +227,6 @@
222 "TranslationMessage with errors is not correctly"227 "TranslationMessage with errors is not correctly"
223 "marked as such in the database.")228 "marked as such in the database.")
224229
230
225def test_suite():231def test_suite():
226 return unittest.TestLoader().loadTestsFromName(__name__)232 return unittest.TestLoader().loadTestsFromName(__name__)
227233
=== modified file 'lib/lp/translations/tests/test_translatablemessage.py'
--- lib/lp/translations/tests/test_translatablemessage.py 2010-08-20 20:31:18 +0000
+++ lib/lp/translations/tests/test_translatablemessage.py 2010-09-09 15:34:46 +0000
@@ -15,6 +15,7 @@
15import transaction15import transaction
1616
17from canonical.testing import ZopelessDatabaseLayer17from canonical.testing import ZopelessDatabaseLayer
18from lp.app.enums import ServiceUsage
18from lp.testing import TestCaseWithFactory19from lp.testing import TestCaseWithFactory
19from lp.translations.model.translatablemessage import TranslatableMessage20from lp.translations.model.translatablemessage import TranslatableMessage
2021
@@ -31,8 +32,8 @@
31 `POTMsgSet`, as well as a Esperanto translation.32 `POTMsgSet`, as well as a Esperanto translation.
32 """33 """
33 super(TestTranslatableMessageBase, self).setUp()34 super(TestTranslatableMessageBase, self).setUp()
34 self.product = self.factory.makeProduct()35 self.product = self.factory.makeProduct(
35 self.product.official_rosetta = True36 translations_usage=ServiceUsage.LAUNCHPAD)
36 self.trunk = self.product.getSeries('trunk')37 self.trunk = self.product.getSeries('trunk')
37 self.potemplate = self.factory.makePOTemplate(38 self.potemplate = self.factory.makePOTemplate(
38 productseries=self.trunk)39 productseries=self.trunk)
@@ -137,7 +138,8 @@
137 super(TestTranslatableMessageExternal, self).setUp()138 super(TestTranslatableMessageExternal, self).setUp()
138 common_msgid = self.potmsgset.singular_text139 common_msgid = self.potmsgset.singular_text
139 self.external_potemplate = self.factory.makePOTemplate()140 self.external_potemplate = self.factory.makePOTemplate()
140 self.external_potemplate.productseries.product.official_rosetta = True141 product = self.external_potemplate.productseries.product
142 product.translations_usage = ServiceUsage.LAUNCHPAD
141 self.external_potmsgset = self.factory.makePOTMsgSet(143 self.external_potmsgset = self.factory.makePOTMsgSet(
142 potemplate=self.external_potemplate,144 potemplate=self.external_potemplate,
143 singular=common_msgid, sequence=1)145 singular=common_msgid, sequence=1)
@@ -175,24 +177,24 @@
175 super(TestTranslatableMessageSuggestions, self).setUp()177 super(TestTranslatableMessageSuggestions, self).setUp()
176 self.now = self.gen_now().next178 self.now = self.gen_now().next
177 self.suggestion1 = self._createTranslation(date_updated=self.now())179 self.suggestion1 = self._createTranslation(date_updated=self.now())
178 self.current = self._createTranslation(is_current=True,180 self.current = self._createTranslation(is_current=True,
179 date_updated=self.now())181 date_updated=self.now())
180 self.suggestion2 = self._createTranslation(date_updated=self.now())182 self.suggestion2 = self._createTranslation(date_updated=self.now())
181 self.message = TranslatableMessage(self.potmsgset, self.pofile)183 self.message = TranslatableMessage(self.potmsgset, self.pofile)
182184
183 def test_getAllSuggestions(self):185 def test_getAllSuggestions(self):
184 # There are three different methods to return 186 # There are three different methods to return
185 suggestions = self.message.getAllSuggestions()187 suggestions = self.message.getAllSuggestions()
186 self.assertContentEqual([self.suggestion1, self.suggestion2],188 self.assertContentEqual([self.suggestion1, self.suggestion2],
187 suggestions)189 suggestions)
188190
189 def test_getDismissedSuggestions(self):191 def test_getDismissedSuggestions(self):
190 # There are three different methods to return 192 # There are three different methods to return
191 suggestions = self.message.getDismissedSuggestions()193 suggestions = self.message.getDismissedSuggestions()
192 self.assertContentEqual([self.suggestion1], suggestions)194 self.assertContentEqual([self.suggestion1], suggestions)
193195
194 def test_getUnreviewedSuggestions(self):196 def test_getUnreviewedSuggestions(self):
195 # There are three different methods to return 197 # There are three different methods to return
196 suggestions = self.message.getUnreviewedSuggestions()198 suggestions = self.message.getUnreviewedSuggestions()
197 self.assertContentEqual([self.suggestion2], suggestions)199 self.assertContentEqual([self.suggestion2], suggestions)
198200
199201
=== modified file 'lib/lp/translations/tests/test_translatedlanguage.py'
--- lib/lp/translations/tests/test_translatedlanguage.py 2010-08-20 20:31:18 +0000
+++ lib/lp/translations/tests/test_translatedlanguage.py 2010-09-09 15:34:46 +0000
@@ -8,6 +8,7 @@
8from zope.security.proxy import removeSecurityProxy8from zope.security.proxy import removeSecurityProxy
99
10from canonical.testing import ZopelessDatabaseLayer10from canonical.testing import ZopelessDatabaseLayer
11from lp.app.enums import ServiceUsage
11from lp.testing import TestCaseWithFactory12from lp.testing import TestCaseWithFactory
12from lp.translations.interfaces.productserieslanguage import (13from lp.translations.interfaces.productserieslanguage import (
13 IProductSeriesLanguageSet,14 IProductSeriesLanguageSet,
@@ -24,8 +25,10 @@
24 def setUp(self):25 def setUp(self):
25 # Create a productseries that uses translations.26 # Create a productseries that uses translations.
26 TestCaseWithFactory.setUp(self)27 TestCaseWithFactory.setUp(self)
27 self.productseries = self.factory.makeProductSeries()28 product = self.factory.makeProduct(
28 self.productseries.product.official_rosetta = True29 translations_usage = ServiceUsage.LAUNCHPAD)
30 self.productseries = self.factory.makeProductSeries(
31 product=product)
29 self.parent = self.productseries32 self.parent = self.productseries
30 self.psl_set = getUtility(IProductSeriesLanguageSet)33 self.psl_set = getUtility(IProductSeriesLanguageSet)
31 self.language = self.factory.makeLanguage('sr@test')34 self.language = self.factory.makeLanguage('sr@test')
3235
=== modified file 'lib/lp/translations/tests/test_translations_to_review.py'
--- lib/lp/translations/tests/test_translations_to_review.py 2010-08-20 20:31:18 +0000
+++ lib/lp/translations/tests/test_translations_to_review.py 2010-09-09 15:34:46 +0000
@@ -16,6 +16,7 @@
16from zope.security.proxy import removeSecurityProxy16from zope.security.proxy import removeSecurityProxy
1717
18from canonical.testing import DatabaseFunctionalLayer18from canonical.testing import DatabaseFunctionalLayer
19from lp.app.enums import ServiceUsage
19from lp.services.worlddata.model.language import LanguageSet20from lp.services.worlddata.model.language import LanguageSet
20from lp.testing import TestCaseWithFactory21from lp.testing import TestCaseWithFactory
21from lp.translations.interfaces.translationsperson import ITranslationsPerson22from lp.translations.interfaces.translationsperson import ITranslationsPerson
@@ -28,6 +29,7 @@
2829
29class ReviewTestMixin:30class ReviewTestMixin:
30 """Base for testing which translations a reviewer can review."""31 """Base for testing which translations a reviewer can review."""
32
31 def setUpMixin(self, for_product=True):33 def setUpMixin(self, for_product=True):
32 """Set up test environment.34 """Set up test environment.
3335
@@ -68,7 +70,7 @@
68 transaction.commit()70 transaction.commit()
6971
70 self.supercontext.translationgroup = self.translationgroup72 self.supercontext.translationgroup = self.translationgroup
71 self.supercontext.official_rosetta = True73 self.supercontext.translations_usage = ServiceUsage.LAUNCHPAD
7274
73 self.potemplate = self.factory.makePOTemplate(75 self.potemplate = self.factory.makePOTemplate(
74 productseries=self.productseries, distroseries=self.distroseries,76 productseries=self.productseries, distroseries=self.distroseries,
@@ -111,6 +113,7 @@
111113
112 Can be applied to product or distribution setups.114 Can be applied to product or distribution setups.
113 """115 """
116
114 def test_OneFileToReview(self):117 def test_OneFileToReview(self):
115 # In the base case, the method finds one POFile for self.person118 # In the base case, the method finds one POFile for self.person
116 # to review.119 # to review.
@@ -131,7 +134,7 @@
131 def test_getReviewableTranslationFiles_not_translating_in_launchpad(self):134 def test_getReviewableTranslationFiles_not_translating_in_launchpad(self):
132 # We don't see products/distros that don't use Launchpad for135 # We don't see products/distros that don't use Launchpad for
133 # translations.136 # translations.
134 self.supercontext.official_rosetta = False137 self.supercontext.translations_usage = ServiceUsage.NOT_APPLICABLE
135 self.assertEqual(self._getReviewables(), [])138 self.assertEqual(self._getReviewables(), [])
136139
137 def test_getReviewableTranslationFiles_non_reviewer(self):140 def test_getReviewableTranslationFiles_non_reviewer(self):
@@ -200,7 +203,7 @@
200 other_pofile = removeSecurityProxy(other_pofile)203 other_pofile = removeSecurityProxy(other_pofile)
201204
202 product = other_pofile.potemplate.productseries.product205 product = other_pofile.potemplate.productseries.product
203 product.official_rosetta = True206 product.translations_usage = ServiceUsage.LAUNCHPAD
204207
205 if with_unreviewed:208 if with_unreviewed:
206 other_pofile.unreviewed_count = 1209 other_pofile.unreviewed_count = 1
207210
=== modified file 'lib/lp/translations/windmill/tests/test_documentation_links.py'
--- lib/lp/translations/windmill/tests/test_documentation_links.py 2010-08-20 20:31:18 +0000
+++ lib/lp/translations/windmill/tests/test_documentation_links.py 2010-09-09 15:34:46 +0000
@@ -9,6 +9,7 @@
9from zope.security.proxy import removeSecurityProxy9from zope.security.proxy import removeSecurityProxy
1010
11from canonical.launchpad.windmill.testing import lpuser11from canonical.launchpad.windmill.testing import lpuser
12from lp.app.enums import ServiceUsage
12from lp.testing import WindmillTestCase13from lp.testing import WindmillTestCase
13from lp.translations.windmill.testing import TranslationsWindmillLayer14from lp.translations.windmill.testing import TranslationsWindmillLayer
1415
@@ -52,7 +53,7 @@
52 project = self.factory.makeProduct(53 project = self.factory.makeProduct(
53 name='test-product',54 name='test-product',
54 displayname='Test Product',55 displayname='Test Product',
55 official_rosetta=True)56 translations_usage=ServiceUsage.LAUNCHPAD)
56 removeSecurityProxy(project).translationgroup = group57 removeSecurityProxy(project).translationgroup = group
5758
58 potemplate = self.createPOTemplateWithPOTMsgSets(59 potemplate = self.createPOTemplateWithPOTMsgSets(
5960
=== modified file 'lib/lp/translations/windmill/tests/test_import_queue.py'
--- lib/lp/translations/windmill/tests/test_import_queue.py 2010-08-20 20:31:18 +0000
+++ lib/lp/translations/windmill/tests/test_import_queue.py 2010-09-09 15:34:46 +0000
@@ -8,7 +8,6 @@
88
9import transaction9import transaction
10from zope.component import getUtility10from zope.component import getUtility
11from zope.security.proxy import removeSecurityProxy
1211
13from canonical.launchpad.webapp import canonical_url12from canonical.launchpad.webapp import canonical_url
14from canonical.launchpad.windmill.testing import lpuser13from canonical.launchpad.windmill.testing import lpuser
@@ -18,6 +17,7 @@
18 SLEEP,17 SLEEP,
19 )18 )
20from canonical.launchpad.windmill.testing.lpuser import login_person19from canonical.launchpad.windmill.testing.lpuser import login_person
20from lp.app.enums import ServiceUsage
21from lp.testing import WindmillTestCase21from lp.testing import WindmillTestCase
22from lp.translations.interfaces.translationimportqueue import (22from lp.translations.interfaces.translationimportqueue import (
23 ITranslationImportQueue,23 ITranslationImportQueue,
@@ -41,8 +41,8 @@
41 'field.potemplate',41 'field.potemplate',
42 'field.potemplate_name',42 'field.potemplate_name',
43 'field.language',43 'field.language',
44 ]44 ],
45 }45 }
46 SELECT_FIELDS = [46 SELECT_FIELDS = [
47 'field.potemplate',47 'field.potemplate',
48 'field.language',48 'field.language',
@@ -55,8 +55,7 @@
55 input_tag = 'input'55 input_tag = 'input'
56 return (56 return (
57 u"//tr[contains(@class,'unseen')]"57 u"//tr[contains(@class,'unseen')]"
58 u"//%s[@id='%s']" % (input_tag, field_id)58 u"//%s[@id='%s']" % (input_tag, field_id))
59 )
6059
61 def _assertAllFieldsVisible(self, client, fields):60 def _assertAllFieldsVisible(self, client, fields):
62 """Assert that all given fields are visible.61 """Assert that all given fields are visible.
@@ -279,8 +278,9 @@
279 name="hubert", displayname="Hubert Hunt", password="test",278 name="hubert", displayname="Hubert Hunt", password="test",
280 email="hubert@example.com")279 email="hubert@example.com")
281 # Create a project and an import entry with it.280 # Create a project and an import entry with it.
282 product = self.factory.makeProduct(owner=hubert)281 product = self.factory.makeProduct(
283 removeSecurityProxy(product).official_rosetta = True282 owner=hubert,
283 translations_usage=ServiceUsage.LAUNCHPAD)
284 productseries = product.getSeries('trunk')284 productseries = product.getSeries('trunk')
285 queue = getUtility(ITranslationImportQueue)285 queue = getUtility(ITranslationImportQueue)
286 potemplate = self.factory.makePOTemplate(productseries=productseries)286 potemplate = self.factory.makePOTemplate(productseries=productseries)