Merge lp:~wgrant/launchpad/tm-performance-2-model into lp:launchpad

Proposed by William Grant
Status: Work in progress
Proposed branch: lp:~wgrant/launchpad/tm-performance-2-model
Merge into: lp:launchpad
Prerequisite: lp:~wgrant/launchpad/tm-performance-0-db
Diff against target: 498 lines (+175/-22)
10 files modified
lib/lp/testing/factory.py (+4/-2)
lib/lp/translations/interfaces/potemplate.py (+9/-0)
lib/lp/translations/interfaces/potmsgset.py (+3/-0)
lib/lp/translations/model/potemplate.py (+22/-3)
lib/lp/translations/model/potmsgset.py (+21/-11)
lib/lp/translations/model/translationmessage.py (+9/-0)
lib/lp/translations/model/translationtemplateitem.py (+4/-0)
lib/lp/translations/tests/test_potemplate.py (+41/-0)
lib/lp/translations/tests/test_potmsgset.py (+39/-3)
lib/lp/translations/tests/test_translationmessage.py (+23/-3)
To merge this branch: bzr merge lp:~wgrant/launchpad/tm-performance-2-model
Reviewer Review Type Date Requested Status
Launchpad code reviewers Pending
Review via email: mp+251223@code.launchpad.net
To post a comment you must log in.
17371. By William Grant

Set POTemplate.suggestive based on normal suggestiveness criteria, and add POTemplateSet.filterSuggestiveTargets with the same.

17372. By William Grant

Fix POTMsgSet.suggestive clone and tests.

17373. By William Grant

Merge tm-performance-0-db.

Unmerged revisions

17373. By William Grant

Merge tm-performance-0-db.

17372. By William Grant

Fix POTMsgSet.suggestive clone and tests.

17371. By William Grant

Set POTemplate.suggestive based on normal suggestiveness criteria, and add POTemplateSet.filterSuggestiveTargets with the same.

17370. By William Grant

Propagate suggestive down from POTemplate to POTMsgSet to TranslationMessage.

17369. By William Grant

submitSuggestion now uses _makeTranslationMessage.

17368. By William Grant

Set TranslationMessage.msgid_* from the POTMsgSet.

17367. By William Grant

Set TranslationTemplateItem.msgid_* from the POTMsgSet.

17366. By William Grant

Cached -> denormalised where appropriate.

17365. By William Grant

Add denormalised columns to the model.

17364. By William Grant

Merge tm-performance--1-disambiguate.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'lib/lp/testing/factory.py'
--- lib/lp/testing/factory.py 2015-02-20 00:56:57 +0000
+++ lib/lp/testing/factory.py 2015-02-28 00:25:08 +0000
@@ -2923,7 +2923,7 @@
2923 sourcepackagename=None, owner=None, name=None,2923 sourcepackagename=None, owner=None, name=None,
2924 translation_domain=None, path=None,2924 translation_domain=None, path=None,
2925 copy_pofiles=True, side=None, sourcepackage=None,2925 copy_pofiles=True, side=None, sourcepackage=None,
2926 iscurrent=True):2926 iscurrent=True, suggestive=None):
2927 """Make a new translation template."""2927 """Make a new translation template."""
2928 if sourcepackage is not None:2928 if sourcepackage is not None:
2929 assert distroseries is None, (2929 assert distroseries is None, (
@@ -2964,7 +2964,9 @@
2964 if path is None:2964 if path is None:
2965 path = 'messages.pot'2965 path = 'messages.pot'
29662966
2967 pot = subset.new(name, translation_domain, path, owner, copy_pofiles)2967 pot = subset.new(
2968 name, translation_domain, path, owner, copy_pofiles,
2969 suggestive)
2968 removeSecurityProxy(pot).iscurrent = iscurrent2970 removeSecurityProxy(pot).iscurrent = iscurrent
2969 return pot2971 return pot
29702972
29712973
=== modified file 'lib/lp/translations/interfaces/potemplate.py'
--- lib/lp/translations/interfaces/potemplate.py 2014-07-01 16:01:39 +0000
+++ lib/lp/translations/interfaces/potemplate.py 2015-02-28 00:25:08 +0000
@@ -317,6 +317,9 @@
317 translation_side = Int(317 translation_side = Int(
318 title=_("Translation side"), required=True, readonly=True)318 title=_("Translation side"), required=True, readonly=True)
319319
320 suggestive = Bool(title=_(
321 "Translations can provide suggestions to other templates (cached)."))
322
320 def __iter__():323 def __iter__():
321 """Return an iterator over current `IPOTMsgSet` in this template."""324 """Return an iterator over current `IPOTMsgSet` in this template."""
322325
@@ -719,6 +722,12 @@
719 :return: Number of rows inserted.722 :return: Number of rows inserted.
720 """723 """
721724
725 def filterSuggestiveTargets(templates):
726 """Return templates whose translations can be suggested to others.
727
728 This is cached as POTemplate.suggestive, but that can be out of date.
729 """
730
722731
723class IPOTemplateSharingSubset(Interface):732class IPOTemplateSharingSubset(Interface):
724 """A subset of sharing PO templates."""733 """A subset of sharing PO templates."""
725734
=== modified file 'lib/lp/translations/interfaces/potmsgset.py'
--- lib/lp/translations/interfaces/potmsgset.py 2013-01-07 02:40:55 +0000
+++ lib/lp/translations/interfaces/potmsgset.py 2015-02-28 00:25:08 +0000
@@ -124,6 +124,9 @@
124 queries that search for credits messages.124 queries that search for credits messages.
125 """))125 """))
126126
127 suggestive = Bool(title=_(
128 "Translations can provide suggestions to other templates (cached)."))
129
127 def clone():130 def clone():
128 """Return a new copy of this POTMsgSet."""131 """Return a new copy of this POTMsgSet."""
129132
130133
=== modified file 'lib/lp/translations/model/potemplate.py'
--- lib/lp/translations/model/potemplate.py 2014-08-28 05:08:23 +0000
+++ lib/lp/translations/model/potemplate.py 2015-02-28 00:25:08 +0000
@@ -237,6 +237,9 @@
237 date_last_updated = UtcDateTimeCol(dbName='date_last_updated',237 date_last_updated = UtcDateTimeCol(dbName='date_last_updated',
238 default=DEFAULT)238 default=DEFAULT)
239239
240 # Cached.
241 suggestive = BoolCol(dbName='suggestive', default=False)
242
240 # joins243 # joins
241 pofiles = SQLMultipleJoin('POFile', joinColumn='potemplate')244 pofiles = SQLMultipleJoin('POFile', joinColumn='potemplate')
242245
@@ -849,7 +852,8 @@
849 commenttext=None,852 commenttext=None,
850 filereferences=None,853 filereferences=None,
851 sourcecomment=None,854 sourcecomment=None,
852 flagscomment=None)855 flagscomment=None,
856 suggestive=self.suggestive)
853857
854 potmsgset.setSequence(self, sequence)858 potmsgset.setSequence(self, sequence)
855 if potmsgset.is_translation_credit:859 if potmsgset.is_translation_credit:
@@ -1188,7 +1192,8 @@
1188 """See `IPOTemplateSubset`."""1192 """See `IPOTemplateSubset`."""
1189 return self._getSuperSet().getPOTemplateByName(name) is None1193 return self._getSuperSet().getPOTemplateByName(name) is None
11901194
1191 def new(self, name, translation_domain, path, owner, copy_pofiles=True):1195 def new(self, name, translation_domain, path, owner, copy_pofiles=True,
1196 suggestive=None):
1192 """See `IPOTemplateSubset`."""1197 """See `IPOTemplateSubset`."""
1193 existing_template = self._getSuperSet().getPOTemplateByName(name)1198 existing_template = self._getSuperSet().getPOTemplateByName(name)
1194 if existing_template is not None:1199 if existing_template is not None:
@@ -1201,6 +1206,10 @@
1201 'languagename': 'LANGUAGE',1206 'languagename': 'LANGUAGE',
1202 'languagecode': 'LL',1207 'languagecode': 'LL',
1203 }1208 }
1209 if suggestive is None:
1210 series = self.productseries or self.distroseries
1211 suggestive = series.pillar.translations_usage in (
1212 ServiceUsage.LAUNCHPAD, ServiceUsage.EXTERNAL)
1204 template = POTemplate(name=name,1213 template = POTemplate(name=name,
1205 translation_domain=translation_domain,1214 translation_domain=translation_domain,
1206 sourcepackagename=self.sourcepackagename,1215 sourcepackagename=self.sourcepackagename,
@@ -1208,7 +1217,8 @@
1208 productseries=self.productseries,1217 productseries=self.productseries,
1209 path=path,1218 path=path,
1210 owner=owner,1219 owner=owner,
1211 header=standardTemplateHeader % header_params)1220 header=standardTemplateHeader % header_params,
1221 suggestive=suggestive)
1212 if copy_pofiles:1222 if copy_pofiles:
1213 self._copyPOFilesFromSharingTemplates(template)1223 self._copyPOFilesFromSharingTemplates(template)
1214 return template1224 return template
@@ -1380,10 +1390,19 @@
1380 """See `IPOTemplateSet`."""1390 """See `IPOTemplateSet`."""
1381 from lp.registry.model.product import Product1391 from lp.registry.model.product import Product
1382 from lp.registry.model.productseries import ProductSeries1392 from lp.registry.model.productseries import ProductSeries
1393 templates = [removeSecurityProxy(t) for t in templates]
1383 pses = load_related(ProductSeries, templates, ['productseriesID'])1394 pses = load_related(ProductSeries, templates, ['productseriesID'])
1384 load_related(Product, pses, ['productID'])1395 load_related(Product, pses, ['productID'])
1385 load_related(SourcePackageName, templates, ['sourcepackagenameID'])1396 load_related(SourcePackageName, templates, ['sourcepackagenameID'])
13861397
1398 def filterSuggestiveTargets(self, templates):
1399 """See `IPOTemplateSet`."""
1400 return [
1401 template for template in templates
1402 if (template.product.translations_usage if template.product
1403 else template.distribution.translations_usage) in (
1404 ServiceUsage.LAUNCHPAD, ServiceUsage.EXTERNAL)]
1405
1387 def wipeSuggestivePOTemplatesCache(self):1406 def wipeSuggestivePOTemplatesCache(self):
1388 """See `IPOTemplateSet`."""1407 """See `IPOTemplateSet`."""
1389 return IMasterStore(POTemplate).execute(1408 return IMasterStore(POTemplate).execute(
13901409
=== modified file 'lib/lp/translations/model/potmsgset.py'
--- lib/lp/translations/model/potmsgset.py 2015-02-27 05:47:55 +0000
+++ lib/lp/translations/model/potmsgset.py 2015-02-28 00:25:08 +0000
@@ -15,6 +15,7 @@
15import re15import re
1616
17from sqlobject import (17from sqlobject import (
18 BoolCol,
18 ForeignKey,19 ForeignKey,
19 SQLObjectNotFound,20 SQLObjectNotFound,
20 StringCol,21 StringCol,
@@ -143,6 +144,9 @@
143144
144 credits_message_ids = credits_message_info.keys()145 credits_message_ids = credits_message_info.keys()
145146
147 # Cached from POTemplate.
148 suggestive = BoolCol(dbName='suggestive', default=False)
149
146 def clone(self):150 def clone(self):
147 return POTMsgSet(151 return POTMsgSet(
148 context=self.context,152 context=self.context,
@@ -152,6 +156,7 @@
152 filereferences=self.filereferences,156 filereferences=self.filereferences,
153 sourcecomment=self.sourcecomment,157 sourcecomment=self.sourcecomment,
154 flagscomment=self.flagscomment,158 flagscomment=self.flagscomment,
159 suggestive=self.suggestive,
155 )160 )
156161
157 def _conflictsExistingSourceFileFormats(self, source_file_format=None):162 def _conflictsExistingSourceFileFormats(self, source_file_format=None):
@@ -609,10 +614,6 @@
609 if existing_message is not None:614 if existing_message is not None:
610 return existing_message615 return existing_message
611616
612 forms = dict(
613 ('msgstr%d' % form, potranslation)
614 for form, potranslation in potranslations.iteritems())
615
616 if from_import:617 if from_import:
617 origin = RosettaTranslationOrigin.SCM618 origin = RosettaTranslationOrigin.SCM
618 else:619 else:
@@ -620,10 +621,9 @@
620 pofile.potemplate.awardKarma(621 pofile.potemplate.awardKarma(
621 submitter, 'translationsuggestionadded')622 submitter, 'translationsuggestionadded')
622623
623 return TranslationMessage(624 return self._makeTranslationMessage(
624 potmsgset=self, language=pofile.language,625 pofile, submitter, potranslations, origin,
625 origin=origin, submitter=submitter,626 validation_status=TranslationValidationStatus.UNKNOWN)
626 **forms)
627627
628 def _checkForConflict(self, current_message, lock_timestamp,628 def _checkForConflict(self, current_message, lock_timestamp,
629 potranslations=None):629 potranslations=None):
@@ -733,7 +733,7 @@
733 return 'shared'733 return 'shared'
734734
735 def _makeTranslationMessage(self, pofile, submitter, translations, origin,735 def _makeTranslationMessage(self, pofile, submitter, translations, origin,
736 diverged=False):736 diverged=False, validation_status=None):
737 """Create a new `TranslationMessage`.737 """Create a new `TranslationMessage`.
738738
739 The message will not be made current on either side (Ubuntu or739 The message will not be made current on either side (Ubuntu or
@@ -741,6 +741,9 @@
741 current should be diverged, but it's up to the caller to ensure741 current should be diverged, but it's up to the caller to ensure
742 the right state.742 the right state.
743 """743 """
744 if validation_status is None:
745 validation_status = TranslationValidationStatus.OK
746
744 if diverged:747 if diverged:
745 potemplate = pofile.potemplate748 potemplate = pofile.potemplate
746 else:749 else:
@@ -750,7 +753,7 @@
750 ('msgstr%d' % form, translation)753 ('msgstr%d' % form, translation)
751 for form, translation in translations.iteritems())754 for form, translation in translations.iteritems())
752755
753 return TranslationMessage(756 tm = TranslationMessage(
754 potmsgset=self,757 potmsgset=self,
755 potemplate=potemplate,758 potemplate=potemplate,
756 pofile=pofile,759 pofile=pofile,
@@ -758,7 +761,12 @@
758 origin=origin,761 origin=origin,
759 submitter=submitter,762 submitter=submitter,
760 validation_status=TranslationValidationStatus.OK,763 validation_status=TranslationValidationStatus.OK,
764 msgid_singular=self.msgid_singularID,
765 msgid_plural=self.msgid_pluralID,
766 suggestive=self.suggestive,
761 **translation_args)767 **translation_args)
768 Store.of(tm).flush()
769 return tm
762770
763 def approveSuggestion(self, pofile, suggestion, reviewer,771 def approveSuggestion(self, pofile, suggestion, reviewer,
764 share_with_other_side=False, lock_timestamp=None):772 share_with_other_side=False, lock_timestamp=None):
@@ -1236,7 +1244,9 @@
1236 return TranslationTemplateItem(1244 return TranslationTemplateItem(
1237 potemplate=potemplate,1245 potemplate=potemplate,
1238 sequence=sequence,1246 sequence=sequence,
1239 potmsgset=self)1247 potmsgset=self,
1248 msgid_singular=self.msgid_singular,
1249 msgid_plural=self.msgid_plural)
1240 else:1250 else:
1241 # There is no entry for this potmsgset in TranslationTemplateItem1251 # There is no entry for this potmsgset in TranslationTemplateItem
1242 # table, neither we need to create one, given that the sequence is1252 # table, neither we need to create one, given that the sequence is
12431253
=== modified file 'lib/lp/translations/model/translationmessage.py'
--- lib/lp/translations/model/translationmessage.py 2014-07-10 05:30:29 +0000
+++ lib/lp/translations/model/translationmessage.py 2015-02-28 00:25:08 +0000
@@ -289,6 +289,13 @@
289 was_obsolete_in_last_import = BoolCol(289 was_obsolete_in_last_import = BoolCol(
290 dbName='was_obsolete_in_last_import', notNull=True, default=False)290 dbName='was_obsolete_in_last_import', notNull=True, default=False)
291291
292 # Denormalised from POTMsgSet.
293 msgid_singular = ForeignKey(foreignKey='POMsgID', dbName='msgid_singular')
294 msgid_plural = ForeignKey(foreignKey='POMsgID', dbName='msgid_plural')
295
296 # Cached.
297 suggestive = BoolCol(dbName='suggestive', default=False)
298
292 # XXX jamesh 2008-05-02:299 # XXX jamesh 2008-05-02:
293 # This method is not being called anymore. The Storm300 # This method is not being called anymore. The Storm
294 # validator code doesn't handle getters.301 # validator code doesn't handle getters.
@@ -526,6 +533,8 @@
526 is_current_ubuntu=self.is_current_ubuntu,533 is_current_ubuntu=self.is_current_ubuntu,
527 is_current_upstream=self.is_current_upstream,534 is_current_upstream=self.is_current_upstream,
528 was_obsolete_in_last_import=self.was_obsolete_in_last_import,535 was_obsolete_in_last_import=self.was_obsolete_in_last_import,
536 msgid_singular=self.msgid_singular,
537 msgid_plural=self.msgid_plural, suggestive=self.suggestive,
529 )538 )
530 return clone539 return clone
531540
532541
=== modified file 'lib/lp/translations/model/translationtemplateitem.py'
--- lib/lp/translations/model/translationtemplateitem.py 2011-12-30 06:14:56 +0000
+++ lib/lp/translations/model/translationtemplateitem.py 2015-02-28 00:25:08 +0000
@@ -29,3 +29,7 @@
29 sequence = IntCol(dbName='sequence', notNull=True)29 sequence = IntCol(dbName='sequence', notNull=True)
30 potmsgset = ForeignKey(30 potmsgset = ForeignKey(
31 foreignKey='POTMsgSet', dbName='potmsgset', notNull=True)31 foreignKey='POTMsgSet', dbName='potmsgset', notNull=True)
32
33 # Denormalised from POTMsgSet.
34 msgid_singular = ForeignKey(foreignKey='POMsgID', dbName='msgid_singular')
35 msgid_plural = ForeignKey(foreignKey='POMsgID', dbName='msgid_plural')
3236
=== modified file 'lib/lp/translations/tests/test_potemplate.py'
--- lib/lp/translations/tests/test_potemplate.py 2014-08-28 01:17:14 +0000
+++ lib/lp/translations/tests/test_potemplate.py 2015-02-28 00:25:08 +0000
@@ -12,6 +12,7 @@
12from lp.registry.interfaces.distribution import IDistributionSet12from lp.registry.interfaces.distribution import IDistributionSet
13from lp.services.worlddata.interfaces.language import ILanguageSet13from lp.services.worlddata.interfaces.language import ILanguageSet
14from lp.testing import (14from lp.testing import (
15 admin_logged_in,
15 person_logged_in,16 person_logged_in,
16 TestCaseWithFactory,17 TestCaseWithFactory,
17 )18 )
@@ -1078,3 +1079,43 @@
1078 productseries=self.factory.makeProductSeries())1079 productseries=self.factory.makeProductSeries())
1079 self.assertEqual(1080 self.assertEqual(
1080 0, subset.getPOTemplatesByTranslationDomain("foo").count())1081 0, subset.getPOTemplatesByTranslationDomain("foo").count())
1082
1083
1084class TestPOTemplateSet(TestCaseWithFactory):
1085
1086 layer = DatabaseFunctionalLayer
1087
1088 def test_suggestiveness(self):
1089 # POTemplateSubset.new and POTemplateSet.filterSuggestiveTargets
1090 # say a template is able to make suggestions if its pillar has
1091 # LAUNCHPAD or EXTERNAL translations usage.
1092 with admin_logged_in():
1093 pg = self.factory.makeProduct()
1094 pg.translations_usage = ServiceUsage.EXTERNAL
1095 dg = self.factory.makeDistribution()
1096 dg.translations_usage = ServiceUsage.LAUNCHPAD
1097 self.factory.makeDistroSeries(distribution=dg)
1098 pb = self.factory.makeProduct()
1099 pb.translations_usage = ServiceUsage.UNKNOWN
1100 db = self.factory.makeDistribution()
1101 db.translations_usage = ServiceUsage.NOT_APPLICABLE
1102 self.factory.makeDistroSeries(distribution=db)
1103 spn = self.factory.makeSourcePackageName()
1104
1105 pots = {
1106 pg: self.factory.makePOTemplate(productseries=pg.series[0]),
1107 pb: self.factory.makePOTemplate(productseries=pb.series[0]),
1108 dg: self.factory.makePOTemplate(
1109 distroseries=dg.series[0], sourcepackagename=spn),
1110 db: self.factory.makePOTemplate(
1111 distroseries=db.series[0], sourcepackagename=spn),
1112 }
1113
1114 self.assertContentEqual(
1115 [pots[pg], pots[dg]],
1116 getUtility(IPOTemplateSet).filterSuggestiveTargets(
1117 pots.values()))
1118
1119 self.assertEqual(
1120 {pg: True, pb: False, dg: True, db: False},
1121 {pillar: pot.suggestive for pillar, pot in pots.iteritems()})
10811122
=== modified file 'lib/lp/translations/tests/test_potmsgset.py'
--- lib/lp/translations/tests/test_potmsgset.py 2014-01-30 15:04:06 +0000
+++ lib/lp/translations/tests/test_potmsgset.py 2015-02-28 00:25:08 +0000
@@ -9,12 +9,14 @@
9 )9 )
1010
11import pytz11import pytz
12from testtools.matchers import MatchesStructure
12import transaction13import transaction
13from zope.component import getUtility14from zope.component import getUtility
14from zope.security.proxy import removeSecurityProxy15from zope.security.proxy import removeSecurityProxy
1516
16from lp.app.enums import ServiceUsage17from lp.app.enums import ServiceUsage
17from lp.app.interfaces.launchpad import ILaunchpadCelebrities18from lp.app.interfaces.launchpad import ILaunchpadCelebrities
19from lp.services.database.interfaces import IStore
18from lp.services.propertycache import get_property_cache20from lp.services.propertycache import get_property_cache
19from lp.testing import TestCaseWithFactory21from lp.testing import TestCaseWithFactory
20from lp.testing.layers import (22from lp.testing.layers import (
@@ -38,6 +40,9 @@
38 TranslationConflict,40 TranslationConflict,
39 )41 )
40from lp.translations.model.translationmessage import DummyTranslationMessage42from lp.translations.model.translationmessage import DummyTranslationMessage
43from lp.translations.model.translationtemplateitem import (
44 TranslationTemplateItem,
45 )
4146
4247
43class TestTranslationSharedPOTMsgSets(TestCaseWithFactory):48class TestTranslationSharedPOTMsgSets(TestCaseWithFactory):
@@ -67,21 +72,51 @@
67 # Create a single POTMsgSet that is used across all tests,72 # Create a single POTMsgSet that is used across all tests,
68 # and add it to only one of the POTemplates.73 # and add it to only one of the POTemplates.
69 self.potmsgset = self.factory.makePOTMsgSet(74 self.potmsgset = self.factory.makePOTMsgSet(
70 self.devel_potemplate)75 self.devel_potemplate, singular=self.factory.getUniqueString(),
76 plural=self.factory.getUniqueString())
7177
72 def _refreshSuggestiveTemplatesCache(self):78 def _refreshSuggestiveTemplatesCache(self):
73 """Refresh the `SuggestivePOTemplate` cache."""79 """Refresh the `SuggestivePOTemplate` cache."""
74 getUtility(IPOTemplateSet).populateSuggestivePOTemplatesCache()80 getUtility(IPOTemplateSet).populateSuggestivePOTemplatesCache()
7581
82 def test_suggestive(self):
83 # POTMsgSet.suggestive is set to the initial POTemplate's
84 # suggestive value, and updated later by a garbo job.
85 pot1 = self.factory.makePOTemplate(suggestive=False)
86 pot2 = self.factory.makePOTemplate(suggestive=True)
87
88 # If created in a non-suggestive template, suggestive is false.
89 potmsgset1 = self.factory.makePOTMsgSet(potemplate=pot1)
90 self.assertFalse(potmsgset1.suggestive)
91 potmsgset1.setSequence(pot2, 1)
92 self.assertFalse(potmsgset1.suggestive)
93
94 # But when created in a suggestive template, suggestive is true.
95 potmsgset2 = self.factory.makePOTMsgSet(potemplate=pot2)
96 self.assertTrue(potmsgset2.suggestive)
97
76 def test_TranslationTemplateItem(self):98 def test_TranslationTemplateItem(self):
77 self.potmsgset.setSequence(self.stable_potemplate, 1)99 self.potmsgset.setSequence(self.stable_potemplate, 1)
78100
79 devel_potmsgsets = list(self.devel_potemplate.getPOTMsgSets())101 devel_potmsgsets = list(self.devel_potemplate.getPOTMsgSets())
80 stable_potmsgsets = list(self.stable_potemplate.getPOTMsgSets())102 stable_potmsgsets = list(self.stable_potemplate.getPOTMsgSets())
81103
104 # Both templates reference the same POTMsgSet.
82 self.assertEquals(devel_potmsgsets, [self.potmsgset])105 self.assertEquals(devel_potmsgsets, [self.potmsgset])
83 self.assertEquals(devel_potmsgsets, stable_potmsgsets)106 self.assertEquals(devel_potmsgsets, stable_potmsgsets)
84107
108 # The msgids are denormalised from the POTMsgSet.
109 ttis = IStore(TranslationTemplateItem).find(
110 TranslationTemplateItem,
111 TranslationTemplateItem.potemplateID.is_in(
112 (self.devel_potemplate.id, self.stable_potemplate.id)))
113 for tti in ttis:
114 self.assertThat(
115 tti,
116 MatchesStructure.byEquality(
117 msgid_singular=self.potmsgset.msgid_singular,
118 msgid_plural=self.potmsgset.msgid_plural))
119
85 def test_POTMsgSetInIncompatiblePOTemplates(self):120 def test_POTMsgSetInIncompatiblePOTemplates(self):
86 # Make sure a POTMsgSet cannot be used in two POTemplates with121 # Make sure a POTMsgSet cannot be used in two POTemplates with
87 # different incompatible source_file_format (like XPI and PO).122 # different incompatible source_file_format (like XPI and PO).
@@ -1926,7 +1961,9 @@
19261961
1927 def test_clone(self):1962 def test_clone(self):
1928 """Cloning a POTMsgSet should produce a near-identical copy."""1963 """Cloning a POTMsgSet should produce a near-identical copy."""
1964 pot = self.factory.makePOTemplate(suggestive=True)
1929 msgset = self.factory.makePOTMsgSet(1965 msgset = self.factory.makePOTMsgSet(
1966 potemplate=pot,
1930 context=self.factory.getUniqueString('context'),1967 context=self.factory.getUniqueString('context'),
1931 plural=self.factory.getUniqueString('plural'),1968 plural=self.factory.getUniqueString('plural'),
1932 singular=self.factory.getUniqueString('singular'),1969 singular=self.factory.getUniqueString('singular'),
@@ -1936,8 +1973,6 @@
1936 flagscomment=self.factory.getUniqueString('flagscomment'),1973 flagscomment=self.factory.getUniqueString('flagscomment'),
1937 )1974 )
1938 new_msgset = msgset.clone()1975 new_msgset = msgset.clone()
1939 naked_msgset = removeSecurityProxy(msgset)
1940 naked_new_msgset = removeSecurityProxy(new_msgset)
1941 self.assertNotEqual(msgset.id, new_msgset.id)1976 self.assertNotEqual(msgset.id, new_msgset.id)
1942 self.assertEqual(msgset.context, new_msgset.context)1977 self.assertEqual(msgset.context, new_msgset.context)
1943 self.assertEqual(msgset.msgid_singular, new_msgset.msgid_singular)1978 self.assertEqual(msgset.msgid_singular, new_msgset.msgid_singular)
@@ -1947,3 +1982,4 @@
1947 self.assertEqual(msgset.filereferences, new_msgset.filereferences)1982 self.assertEqual(msgset.filereferences, new_msgset.filereferences)
1948 self.assertEqual(msgset.sourcecomment, new_msgset.sourcecomment)1983 self.assertEqual(msgset.sourcecomment, new_msgset.sourcecomment)
1949 self.assertEqual(msgset.flagscomment, new_msgset.flagscomment)1984 self.assertEqual(msgset.flagscomment, new_msgset.flagscomment)
1985 self.assertEqual(msgset.suggestive, new_msgset.suggestive)
19501986
=== modified file 'lib/lp/translations/tests/test_translationmessage.py'
--- lib/lp/translations/tests/test_translationmessage.py 2014-07-10 05:30:29 +0000
+++ lib/lp/translations/tests/test_translationmessage.py 2015-02-28 00:25:08 +0000
@@ -107,16 +107,33 @@
107 tm.potmsgset.setSequence(pofile.potemplate, 0)107 tm.potmsgset.setSequence(pofile.potemplate, 0)
108 self.assertEquals(None, tm.getOnePOFile())108 self.assertEquals(None, tm.getOnePOFile())
109109
110 def test_denormalised(self):
111 # msgid_singular and msgid_plural are denormalised from
112 # POTMsgSet for suggestion performance.
113 pot = self.factory.makePOTemplate(suggestive=True)
114 singular = self.factory.getUniqueString()
115 plural = self.factory.getUniqueString()
116 potmsgset = self.factory.makePOTMsgSet(
117 potemplate=pot, singular=singular, plural=plural)
118 self.assertTrue(potmsgset.suggestive)
119 tm = self.factory.makeCurrentTranslationMessage(
120 potmsgset=potmsgset)
121 naked_tm = removeSecurityProxy(tm)
122 self.assertEqual(singular, naked_tm.msgid_singular.msgid)
123 self.assertEqual(plural, naked_tm.msgid_plural.msgid)
124 self.assertTrue(naked_tm.suggestive)
125
110 def test_clone(self):126 def test_clone(self):
111 """Cloning a translation should produce a near-identical copy."""127 """Cloning a translation should produce a near-identical copy."""
112 translations = [self.factory.getUniqueString() for x in range(6)]128 translations = [self.factory.getUniqueString() for x in range(6)]
113 tm = self.factory.makeCurrentTranslationMessage(129 tm = removeSecurityProxy(self.factory.makeCurrentTranslationMessage(
114 date_created=self.factory.getUniqueDate(),130 date_created=self.factory.getUniqueDate(),
115 translations=translations, current_other=True)131 translations=translations, current_other=True))
116 tm.comment = self.factory.getUniqueString()132 tm.comment = self.factory.getUniqueString()
117 tm.was_obsolete_in_last_import = True133 tm.was_obsolete_in_last_import = True
134 tm.suggestive = True
118 potmsgset = self.factory.makePOTMsgSet()135 potmsgset = self.factory.makePOTMsgSet()
119 clone = tm.clone(potmsgset)136 clone = removeSecurityProxy(tm.clone(potmsgset))
120 self.assertNotEqual(tm.id, clone.id)137 self.assertNotEqual(tm.id, clone.id)
121 self.assertIs(None, clone.potemplate)138 self.assertIs(None, clone.potemplate)
122 self.assertEqual(potmsgset, clone.potmsgset)139 self.assertEqual(potmsgset, clone.potmsgset)
@@ -138,6 +155,9 @@
138 self.assertEqual(tm.is_current_upstream, clone.is_current_upstream)155 self.assertEqual(tm.is_current_upstream, clone.is_current_upstream)
139 self.assertEqual(156 self.assertEqual(
140 tm.was_obsolete_in_last_import, clone.was_obsolete_in_last_import)157 tm.was_obsolete_in_last_import, clone.was_obsolete_in_last_import)
158 self.assertEqual(tm.msgid_singular, clone.msgid_singular)
159 self.assertEqual(tm.msgid_plural, clone.msgid_plural)
160 self.assertEqual(tm.suggestive, clone.suggestive)
141161
142162
143class TestApprove(TestCaseWithFactory):163class TestApprove(TestCaseWithFactory):