Merge lp:~wgrant/launchpad/tm-performance-2-model into lp:launchpad
- tm-performance-2-model
- Merge into devel
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 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Launchpad code reviewers | Pending | ||
Review via email: mp+251223@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
- 17371. By William Grant
-
Set POTemplate.
suggestive based on normal suggestiveness criteria, and add POTemplateSet. filterSuggestiv eTargets 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. filterSuggestiv eTargets with the same. - 17370. By William Grant
-
Propagate suggestive down from POTemplate to POTMsgSet to TranslationMessage.
- 17369. By William Grant
-
submitSuggestion now uses _makeTranslatio
nMessage. - 17368. By William Grant
-
Set TranslationMess
age.msgid_ * from the POTMsgSet. - 17367. By William Grant
-
Set TranslationTemp
lateItem. 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
1 | === modified file 'lib/lp/testing/factory.py' | |||
2 | --- lib/lp/testing/factory.py 2015-02-20 00:56:57 +0000 | |||
3 | +++ lib/lp/testing/factory.py 2015-02-28 00:25:08 +0000 | |||
4 | @@ -2923,7 +2923,7 @@ | |||
5 | 2923 | sourcepackagename=None, owner=None, name=None, | 2923 | sourcepackagename=None, owner=None, name=None, |
6 | 2924 | translation_domain=None, path=None, | 2924 | translation_domain=None, path=None, |
7 | 2925 | copy_pofiles=True, side=None, sourcepackage=None, | 2925 | copy_pofiles=True, side=None, sourcepackage=None, |
9 | 2926 | iscurrent=True): | 2926 | iscurrent=True, suggestive=None): |
10 | 2927 | """Make a new translation template.""" | 2927 | """Make a new translation template.""" |
11 | 2928 | if sourcepackage is not None: | 2928 | if sourcepackage is not None: |
12 | 2929 | assert distroseries is None, ( | 2929 | assert distroseries is None, ( |
13 | @@ -2964,7 +2964,9 @@ | |||
14 | 2964 | if path is None: | 2964 | if path is None: |
15 | 2965 | path = 'messages.pot' | 2965 | path = 'messages.pot' |
16 | 2966 | 2966 | ||
18 | 2967 | pot = subset.new(name, translation_domain, path, owner, copy_pofiles) | 2967 | pot = subset.new( |
19 | 2968 | name, translation_domain, path, owner, copy_pofiles, | ||
20 | 2969 | suggestive) | ||
21 | 2968 | removeSecurityProxy(pot).iscurrent = iscurrent | 2970 | removeSecurityProxy(pot).iscurrent = iscurrent |
22 | 2969 | return pot | 2971 | return pot |
23 | 2970 | 2972 | ||
24 | 2971 | 2973 | ||
25 | === modified file 'lib/lp/translations/interfaces/potemplate.py' | |||
26 | --- lib/lp/translations/interfaces/potemplate.py 2014-07-01 16:01:39 +0000 | |||
27 | +++ lib/lp/translations/interfaces/potemplate.py 2015-02-28 00:25:08 +0000 | |||
28 | @@ -317,6 +317,9 @@ | |||
29 | 317 | translation_side = Int( | 317 | translation_side = Int( |
30 | 318 | title=_("Translation side"), required=True, readonly=True) | 318 | title=_("Translation side"), required=True, readonly=True) |
31 | 319 | 319 | ||
32 | 320 | suggestive = Bool(title=_( | ||
33 | 321 | "Translations can provide suggestions to other templates (cached).")) | ||
34 | 322 | |||
35 | 320 | def __iter__(): | 323 | def __iter__(): |
36 | 321 | """Return an iterator over current `IPOTMsgSet` in this template.""" | 324 | """Return an iterator over current `IPOTMsgSet` in this template.""" |
37 | 322 | 325 | ||
38 | @@ -719,6 +722,12 @@ | |||
39 | 719 | :return: Number of rows inserted. | 722 | :return: Number of rows inserted. |
40 | 720 | """ | 723 | """ |
41 | 721 | 724 | ||
42 | 725 | def filterSuggestiveTargets(templates): | ||
43 | 726 | """Return templates whose translations can be suggested to others. | ||
44 | 727 | |||
45 | 728 | This is cached as POTemplate.suggestive, but that can be out of date. | ||
46 | 729 | """ | ||
47 | 730 | |||
48 | 722 | 731 | ||
49 | 723 | class IPOTemplateSharingSubset(Interface): | 732 | class IPOTemplateSharingSubset(Interface): |
50 | 724 | """A subset of sharing PO templates.""" | 733 | """A subset of sharing PO templates.""" |
51 | 725 | 734 | ||
52 | === modified file 'lib/lp/translations/interfaces/potmsgset.py' | |||
53 | --- lib/lp/translations/interfaces/potmsgset.py 2013-01-07 02:40:55 +0000 | |||
54 | +++ lib/lp/translations/interfaces/potmsgset.py 2015-02-28 00:25:08 +0000 | |||
55 | @@ -124,6 +124,9 @@ | |||
56 | 124 | queries that search for credits messages. | 124 | queries that search for credits messages. |
57 | 125 | """)) | 125 | """)) |
58 | 126 | 126 | ||
59 | 127 | suggestive = Bool(title=_( | ||
60 | 128 | "Translations can provide suggestions to other templates (cached).")) | ||
61 | 129 | |||
62 | 127 | def clone(): | 130 | def clone(): |
63 | 128 | """Return a new copy of this POTMsgSet.""" | 131 | """Return a new copy of this POTMsgSet.""" |
64 | 129 | 132 | ||
65 | 130 | 133 | ||
66 | === modified file 'lib/lp/translations/model/potemplate.py' | |||
67 | --- lib/lp/translations/model/potemplate.py 2014-08-28 05:08:23 +0000 | |||
68 | +++ lib/lp/translations/model/potemplate.py 2015-02-28 00:25:08 +0000 | |||
69 | @@ -237,6 +237,9 @@ | |||
70 | 237 | date_last_updated = UtcDateTimeCol(dbName='date_last_updated', | 237 | date_last_updated = UtcDateTimeCol(dbName='date_last_updated', |
71 | 238 | default=DEFAULT) | 238 | default=DEFAULT) |
72 | 239 | 239 | ||
73 | 240 | # Cached. | ||
74 | 241 | suggestive = BoolCol(dbName='suggestive', default=False) | ||
75 | 242 | |||
76 | 240 | # joins | 243 | # joins |
77 | 241 | pofiles = SQLMultipleJoin('POFile', joinColumn='potemplate') | 244 | pofiles = SQLMultipleJoin('POFile', joinColumn='potemplate') |
78 | 242 | 245 | ||
79 | @@ -849,7 +852,8 @@ | |||
80 | 849 | commenttext=None, | 852 | commenttext=None, |
81 | 850 | filereferences=None, | 853 | filereferences=None, |
82 | 851 | sourcecomment=None, | 854 | sourcecomment=None, |
84 | 852 | flagscomment=None) | 855 | flagscomment=None, |
85 | 856 | suggestive=self.suggestive) | ||
86 | 853 | 857 | ||
87 | 854 | potmsgset.setSequence(self, sequence) | 858 | potmsgset.setSequence(self, sequence) |
88 | 855 | if potmsgset.is_translation_credit: | 859 | if potmsgset.is_translation_credit: |
89 | @@ -1188,7 +1192,8 @@ | |||
90 | 1188 | """See `IPOTemplateSubset`.""" | 1192 | """See `IPOTemplateSubset`.""" |
91 | 1189 | return self._getSuperSet().getPOTemplateByName(name) is None | 1193 | return self._getSuperSet().getPOTemplateByName(name) is None |
92 | 1190 | 1194 | ||
94 | 1191 | def new(self, name, translation_domain, path, owner, copy_pofiles=True): | 1195 | def new(self, name, translation_domain, path, owner, copy_pofiles=True, |
95 | 1196 | suggestive=None): | ||
96 | 1192 | """See `IPOTemplateSubset`.""" | 1197 | """See `IPOTemplateSubset`.""" |
97 | 1193 | existing_template = self._getSuperSet().getPOTemplateByName(name) | 1198 | existing_template = self._getSuperSet().getPOTemplateByName(name) |
98 | 1194 | if existing_template is not None: | 1199 | if existing_template is not None: |
99 | @@ -1201,6 +1206,10 @@ | |||
100 | 1201 | 'languagename': 'LANGUAGE', | 1206 | 'languagename': 'LANGUAGE', |
101 | 1202 | 'languagecode': 'LL', | 1207 | 'languagecode': 'LL', |
102 | 1203 | } | 1208 | } |
103 | 1209 | if suggestive is None: | ||
104 | 1210 | series = self.productseries or self.distroseries | ||
105 | 1211 | suggestive = series.pillar.translations_usage in ( | ||
106 | 1212 | ServiceUsage.LAUNCHPAD, ServiceUsage.EXTERNAL) | ||
107 | 1204 | template = POTemplate(name=name, | 1213 | template = POTemplate(name=name, |
108 | 1205 | translation_domain=translation_domain, | 1214 | translation_domain=translation_domain, |
109 | 1206 | sourcepackagename=self.sourcepackagename, | 1215 | sourcepackagename=self.sourcepackagename, |
110 | @@ -1208,7 +1217,8 @@ | |||
111 | 1208 | productseries=self.productseries, | 1217 | productseries=self.productseries, |
112 | 1209 | path=path, | 1218 | path=path, |
113 | 1210 | owner=owner, | 1219 | owner=owner, |
115 | 1211 | header=standardTemplateHeader % header_params) | 1220 | header=standardTemplateHeader % header_params, |
116 | 1221 | suggestive=suggestive) | ||
117 | 1212 | if copy_pofiles: | 1222 | if copy_pofiles: |
118 | 1213 | self._copyPOFilesFromSharingTemplates(template) | 1223 | self._copyPOFilesFromSharingTemplates(template) |
119 | 1214 | return template | 1224 | return template |
120 | @@ -1380,10 +1390,19 @@ | |||
121 | 1380 | """See `IPOTemplateSet`.""" | 1390 | """See `IPOTemplateSet`.""" |
122 | 1381 | from lp.registry.model.product import Product | 1391 | from lp.registry.model.product import Product |
123 | 1382 | from lp.registry.model.productseries import ProductSeries | 1392 | from lp.registry.model.productseries import ProductSeries |
124 | 1393 | templates = [removeSecurityProxy(t) for t in templates] | ||
125 | 1383 | pses = load_related(ProductSeries, templates, ['productseriesID']) | 1394 | pses = load_related(ProductSeries, templates, ['productseriesID']) |
126 | 1384 | load_related(Product, pses, ['productID']) | 1395 | load_related(Product, pses, ['productID']) |
127 | 1385 | load_related(SourcePackageName, templates, ['sourcepackagenameID']) | 1396 | load_related(SourcePackageName, templates, ['sourcepackagenameID']) |
128 | 1386 | 1397 | ||
129 | 1398 | def filterSuggestiveTargets(self, templates): | ||
130 | 1399 | """See `IPOTemplateSet`.""" | ||
131 | 1400 | return [ | ||
132 | 1401 | template for template in templates | ||
133 | 1402 | if (template.product.translations_usage if template.product | ||
134 | 1403 | else template.distribution.translations_usage) in ( | ||
135 | 1404 | ServiceUsage.LAUNCHPAD, ServiceUsage.EXTERNAL)] | ||
136 | 1405 | |||
137 | 1387 | def wipeSuggestivePOTemplatesCache(self): | 1406 | def wipeSuggestivePOTemplatesCache(self): |
138 | 1388 | """See `IPOTemplateSet`.""" | 1407 | """See `IPOTemplateSet`.""" |
139 | 1389 | return IMasterStore(POTemplate).execute( | 1408 | return IMasterStore(POTemplate).execute( |
140 | 1390 | 1409 | ||
141 | === modified file 'lib/lp/translations/model/potmsgset.py' | |||
142 | --- lib/lp/translations/model/potmsgset.py 2015-02-27 05:47:55 +0000 | |||
143 | +++ lib/lp/translations/model/potmsgset.py 2015-02-28 00:25:08 +0000 | |||
144 | @@ -15,6 +15,7 @@ | |||
145 | 15 | import re | 15 | import re |
146 | 16 | 16 | ||
147 | 17 | from sqlobject import ( | 17 | from sqlobject import ( |
148 | 18 | BoolCol, | ||
149 | 18 | ForeignKey, | 19 | ForeignKey, |
150 | 19 | SQLObjectNotFound, | 20 | SQLObjectNotFound, |
151 | 20 | StringCol, | 21 | StringCol, |
152 | @@ -143,6 +144,9 @@ | |||
153 | 143 | 144 | ||
154 | 144 | credits_message_ids = credits_message_info.keys() | 145 | credits_message_ids = credits_message_info.keys() |
155 | 145 | 146 | ||
156 | 147 | # Cached from POTemplate. | ||
157 | 148 | suggestive = BoolCol(dbName='suggestive', default=False) | ||
158 | 149 | |||
159 | 146 | def clone(self): | 150 | def clone(self): |
160 | 147 | return POTMsgSet( | 151 | return POTMsgSet( |
161 | 148 | context=self.context, | 152 | context=self.context, |
162 | @@ -152,6 +156,7 @@ | |||
163 | 152 | filereferences=self.filereferences, | 156 | filereferences=self.filereferences, |
164 | 153 | sourcecomment=self.sourcecomment, | 157 | sourcecomment=self.sourcecomment, |
165 | 154 | flagscomment=self.flagscomment, | 158 | flagscomment=self.flagscomment, |
166 | 159 | suggestive=self.suggestive, | ||
167 | 155 | ) | 160 | ) |
168 | 156 | 161 | ||
169 | 157 | def _conflictsExistingSourceFileFormats(self, source_file_format=None): | 162 | def _conflictsExistingSourceFileFormats(self, source_file_format=None): |
170 | @@ -609,10 +614,6 @@ | |||
171 | 609 | if existing_message is not None: | 614 | if existing_message is not None: |
172 | 610 | return existing_message | 615 | return existing_message |
173 | 611 | 616 | ||
174 | 612 | forms = dict( | ||
175 | 613 | ('msgstr%d' % form, potranslation) | ||
176 | 614 | for form, potranslation in potranslations.iteritems()) | ||
177 | 615 | |||
178 | 616 | if from_import: | 617 | if from_import: |
179 | 617 | origin = RosettaTranslationOrigin.SCM | 618 | origin = RosettaTranslationOrigin.SCM |
180 | 618 | else: | 619 | else: |
181 | @@ -620,10 +621,9 @@ | |||
182 | 620 | pofile.potemplate.awardKarma( | 621 | pofile.potemplate.awardKarma( |
183 | 621 | submitter, 'translationsuggestionadded') | 622 | submitter, 'translationsuggestionadded') |
184 | 622 | 623 | ||
189 | 623 | return TranslationMessage( | 624 | return self._makeTranslationMessage( |
190 | 624 | potmsgset=self, language=pofile.language, | 625 | pofile, submitter, potranslations, origin, |
191 | 625 | origin=origin, submitter=submitter, | 626 | validation_status=TranslationValidationStatus.UNKNOWN) |
188 | 626 | **forms) | ||
192 | 627 | 627 | ||
193 | 628 | def _checkForConflict(self, current_message, lock_timestamp, | 628 | def _checkForConflict(self, current_message, lock_timestamp, |
194 | 629 | potranslations=None): | 629 | potranslations=None): |
195 | @@ -733,7 +733,7 @@ | |||
196 | 733 | return 'shared' | 733 | return 'shared' |
197 | 734 | 734 | ||
198 | 735 | def _makeTranslationMessage(self, pofile, submitter, translations, origin, | 735 | def _makeTranslationMessage(self, pofile, submitter, translations, origin, |
200 | 736 | diverged=False): | 736 | diverged=False, validation_status=None): |
201 | 737 | """Create a new `TranslationMessage`. | 737 | """Create a new `TranslationMessage`. |
202 | 738 | 738 | ||
203 | 739 | The message will not be made current on either side (Ubuntu or | 739 | The message will not be made current on either side (Ubuntu or |
204 | @@ -741,6 +741,9 @@ | |||
205 | 741 | current should be diverged, but it's up to the caller to ensure | 741 | current should be diverged, but it's up to the caller to ensure |
206 | 742 | the right state. | 742 | the right state. |
207 | 743 | """ | 743 | """ |
208 | 744 | if validation_status is None: | ||
209 | 745 | validation_status = TranslationValidationStatus.OK | ||
210 | 746 | |||
211 | 744 | if diverged: | 747 | if diverged: |
212 | 745 | potemplate = pofile.potemplate | 748 | potemplate = pofile.potemplate |
213 | 746 | else: | 749 | else: |
214 | @@ -750,7 +753,7 @@ | |||
215 | 750 | ('msgstr%d' % form, translation) | 753 | ('msgstr%d' % form, translation) |
216 | 751 | for form, translation in translations.iteritems()) | 754 | for form, translation in translations.iteritems()) |
217 | 752 | 755 | ||
219 | 753 | return TranslationMessage( | 756 | tm = TranslationMessage( |
220 | 754 | potmsgset=self, | 757 | potmsgset=self, |
221 | 755 | potemplate=potemplate, | 758 | potemplate=potemplate, |
222 | 756 | pofile=pofile, | 759 | pofile=pofile, |
223 | @@ -758,7 +761,12 @@ | |||
224 | 758 | origin=origin, | 761 | origin=origin, |
225 | 759 | submitter=submitter, | 762 | submitter=submitter, |
226 | 760 | validation_status=TranslationValidationStatus.OK, | 763 | validation_status=TranslationValidationStatus.OK, |
227 | 764 | msgid_singular=self.msgid_singularID, | ||
228 | 765 | msgid_plural=self.msgid_pluralID, | ||
229 | 766 | suggestive=self.suggestive, | ||
230 | 761 | **translation_args) | 767 | **translation_args) |
231 | 768 | Store.of(tm).flush() | ||
232 | 769 | return tm | ||
233 | 762 | 770 | ||
234 | 763 | def approveSuggestion(self, pofile, suggestion, reviewer, | 771 | def approveSuggestion(self, pofile, suggestion, reviewer, |
235 | 764 | share_with_other_side=False, lock_timestamp=None): | 772 | share_with_other_side=False, lock_timestamp=None): |
236 | @@ -1236,7 +1244,9 @@ | |||
237 | 1236 | return TranslationTemplateItem( | 1244 | return TranslationTemplateItem( |
238 | 1237 | potemplate=potemplate, | 1245 | potemplate=potemplate, |
239 | 1238 | sequence=sequence, | 1246 | sequence=sequence, |
241 | 1239 | potmsgset=self) | 1247 | potmsgset=self, |
242 | 1248 | msgid_singular=self.msgid_singular, | ||
243 | 1249 | msgid_plural=self.msgid_plural) | ||
244 | 1240 | else: | 1250 | else: |
245 | 1241 | # There is no entry for this potmsgset in TranslationTemplateItem | 1251 | # There is no entry for this potmsgset in TranslationTemplateItem |
246 | 1242 | # table, neither we need to create one, given that the sequence is | 1252 | # table, neither we need to create one, given that the sequence is |
247 | 1243 | 1253 | ||
248 | === modified file 'lib/lp/translations/model/translationmessage.py' | |||
249 | --- lib/lp/translations/model/translationmessage.py 2014-07-10 05:30:29 +0000 | |||
250 | +++ lib/lp/translations/model/translationmessage.py 2015-02-28 00:25:08 +0000 | |||
251 | @@ -289,6 +289,13 @@ | |||
252 | 289 | was_obsolete_in_last_import = BoolCol( | 289 | was_obsolete_in_last_import = BoolCol( |
253 | 290 | dbName='was_obsolete_in_last_import', notNull=True, default=False) | 290 | dbName='was_obsolete_in_last_import', notNull=True, default=False) |
254 | 291 | 291 | ||
255 | 292 | # Denormalised from POTMsgSet. | ||
256 | 293 | msgid_singular = ForeignKey(foreignKey='POMsgID', dbName='msgid_singular') | ||
257 | 294 | msgid_plural = ForeignKey(foreignKey='POMsgID', dbName='msgid_plural') | ||
258 | 295 | |||
259 | 296 | # Cached. | ||
260 | 297 | suggestive = BoolCol(dbName='suggestive', default=False) | ||
261 | 298 | |||
262 | 292 | # XXX jamesh 2008-05-02: | 299 | # XXX jamesh 2008-05-02: |
263 | 293 | # This method is not being called anymore. The Storm | 300 | # This method is not being called anymore. The Storm |
264 | 294 | # validator code doesn't handle getters. | 301 | # validator code doesn't handle getters. |
265 | @@ -526,6 +533,8 @@ | |||
266 | 526 | is_current_ubuntu=self.is_current_ubuntu, | 533 | is_current_ubuntu=self.is_current_ubuntu, |
267 | 527 | is_current_upstream=self.is_current_upstream, | 534 | is_current_upstream=self.is_current_upstream, |
268 | 528 | was_obsolete_in_last_import=self.was_obsolete_in_last_import, | 535 | was_obsolete_in_last_import=self.was_obsolete_in_last_import, |
269 | 536 | msgid_singular=self.msgid_singular, | ||
270 | 537 | msgid_plural=self.msgid_plural, suggestive=self.suggestive, | ||
271 | 529 | ) | 538 | ) |
272 | 530 | return clone | 539 | return clone |
273 | 531 | 540 | ||
274 | 532 | 541 | ||
275 | === modified file 'lib/lp/translations/model/translationtemplateitem.py' | |||
276 | --- lib/lp/translations/model/translationtemplateitem.py 2011-12-30 06:14:56 +0000 | |||
277 | +++ lib/lp/translations/model/translationtemplateitem.py 2015-02-28 00:25:08 +0000 | |||
278 | @@ -29,3 +29,7 @@ | |||
279 | 29 | sequence = IntCol(dbName='sequence', notNull=True) | 29 | sequence = IntCol(dbName='sequence', notNull=True) |
280 | 30 | potmsgset = ForeignKey( | 30 | potmsgset = ForeignKey( |
281 | 31 | foreignKey='POTMsgSet', dbName='potmsgset', notNull=True) | 31 | foreignKey='POTMsgSet', dbName='potmsgset', notNull=True) |
282 | 32 | |||
283 | 33 | # Denormalised from POTMsgSet. | ||
284 | 34 | msgid_singular = ForeignKey(foreignKey='POMsgID', dbName='msgid_singular') | ||
285 | 35 | msgid_plural = ForeignKey(foreignKey='POMsgID', dbName='msgid_plural') | ||
286 | 32 | 36 | ||
287 | === modified file 'lib/lp/translations/tests/test_potemplate.py' | |||
288 | --- lib/lp/translations/tests/test_potemplate.py 2014-08-28 01:17:14 +0000 | |||
289 | +++ lib/lp/translations/tests/test_potemplate.py 2015-02-28 00:25:08 +0000 | |||
290 | @@ -12,6 +12,7 @@ | |||
291 | 12 | from lp.registry.interfaces.distribution import IDistributionSet | 12 | from lp.registry.interfaces.distribution import IDistributionSet |
292 | 13 | from lp.services.worlddata.interfaces.language import ILanguageSet | 13 | from lp.services.worlddata.interfaces.language import ILanguageSet |
293 | 14 | from lp.testing import ( | 14 | from lp.testing import ( |
294 | 15 | admin_logged_in, | ||
295 | 15 | person_logged_in, | 16 | person_logged_in, |
296 | 16 | TestCaseWithFactory, | 17 | TestCaseWithFactory, |
297 | 17 | ) | 18 | ) |
298 | @@ -1078,3 +1079,43 @@ | |||
299 | 1078 | productseries=self.factory.makeProductSeries()) | 1079 | productseries=self.factory.makeProductSeries()) |
300 | 1079 | self.assertEqual( | 1080 | self.assertEqual( |
301 | 1080 | 0, subset.getPOTemplatesByTranslationDomain("foo").count()) | 1081 | 0, subset.getPOTemplatesByTranslationDomain("foo").count()) |
302 | 1082 | |||
303 | 1083 | |||
304 | 1084 | class TestPOTemplateSet(TestCaseWithFactory): | ||
305 | 1085 | |||
306 | 1086 | layer = DatabaseFunctionalLayer | ||
307 | 1087 | |||
308 | 1088 | def test_suggestiveness(self): | ||
309 | 1089 | # POTemplateSubset.new and POTemplateSet.filterSuggestiveTargets | ||
310 | 1090 | # say a template is able to make suggestions if its pillar has | ||
311 | 1091 | # LAUNCHPAD or EXTERNAL translations usage. | ||
312 | 1092 | with admin_logged_in(): | ||
313 | 1093 | pg = self.factory.makeProduct() | ||
314 | 1094 | pg.translations_usage = ServiceUsage.EXTERNAL | ||
315 | 1095 | dg = self.factory.makeDistribution() | ||
316 | 1096 | dg.translations_usage = ServiceUsage.LAUNCHPAD | ||
317 | 1097 | self.factory.makeDistroSeries(distribution=dg) | ||
318 | 1098 | pb = self.factory.makeProduct() | ||
319 | 1099 | pb.translations_usage = ServiceUsage.UNKNOWN | ||
320 | 1100 | db = self.factory.makeDistribution() | ||
321 | 1101 | db.translations_usage = ServiceUsage.NOT_APPLICABLE | ||
322 | 1102 | self.factory.makeDistroSeries(distribution=db) | ||
323 | 1103 | spn = self.factory.makeSourcePackageName() | ||
324 | 1104 | |||
325 | 1105 | pots = { | ||
326 | 1106 | pg: self.factory.makePOTemplate(productseries=pg.series[0]), | ||
327 | 1107 | pb: self.factory.makePOTemplate(productseries=pb.series[0]), | ||
328 | 1108 | dg: self.factory.makePOTemplate( | ||
329 | 1109 | distroseries=dg.series[0], sourcepackagename=spn), | ||
330 | 1110 | db: self.factory.makePOTemplate( | ||
331 | 1111 | distroseries=db.series[0], sourcepackagename=spn), | ||
332 | 1112 | } | ||
333 | 1113 | |||
334 | 1114 | self.assertContentEqual( | ||
335 | 1115 | [pots[pg], pots[dg]], | ||
336 | 1116 | getUtility(IPOTemplateSet).filterSuggestiveTargets( | ||
337 | 1117 | pots.values())) | ||
338 | 1118 | |||
339 | 1119 | self.assertEqual( | ||
340 | 1120 | {pg: True, pb: False, dg: True, db: False}, | ||
341 | 1121 | {pillar: pot.suggestive for pillar, pot in pots.iteritems()}) | ||
342 | 1081 | 1122 | ||
343 | === modified file 'lib/lp/translations/tests/test_potmsgset.py' | |||
344 | --- lib/lp/translations/tests/test_potmsgset.py 2014-01-30 15:04:06 +0000 | |||
345 | +++ lib/lp/translations/tests/test_potmsgset.py 2015-02-28 00:25:08 +0000 | |||
346 | @@ -9,12 +9,14 @@ | |||
347 | 9 | ) | 9 | ) |
348 | 10 | 10 | ||
349 | 11 | import pytz | 11 | import pytz |
350 | 12 | from testtools.matchers import MatchesStructure | ||
351 | 12 | import transaction | 13 | import transaction |
352 | 13 | from zope.component import getUtility | 14 | from zope.component import getUtility |
353 | 14 | from zope.security.proxy import removeSecurityProxy | 15 | from zope.security.proxy import removeSecurityProxy |
354 | 15 | 16 | ||
355 | 16 | from lp.app.enums import ServiceUsage | 17 | from lp.app.enums import ServiceUsage |
356 | 17 | from lp.app.interfaces.launchpad import ILaunchpadCelebrities | 18 | from lp.app.interfaces.launchpad import ILaunchpadCelebrities |
357 | 19 | from lp.services.database.interfaces import IStore | ||
358 | 18 | from lp.services.propertycache import get_property_cache | 20 | from lp.services.propertycache import get_property_cache |
359 | 19 | from lp.testing import TestCaseWithFactory | 21 | from lp.testing import TestCaseWithFactory |
360 | 20 | from lp.testing.layers import ( | 22 | from lp.testing.layers import ( |
361 | @@ -38,6 +40,9 @@ | |||
362 | 38 | TranslationConflict, | 40 | TranslationConflict, |
363 | 39 | ) | 41 | ) |
364 | 40 | from lp.translations.model.translationmessage import DummyTranslationMessage | 42 | from lp.translations.model.translationmessage import DummyTranslationMessage |
365 | 43 | from lp.translations.model.translationtemplateitem import ( | ||
366 | 44 | TranslationTemplateItem, | ||
367 | 45 | ) | ||
368 | 41 | 46 | ||
369 | 42 | 47 | ||
370 | 43 | class TestTranslationSharedPOTMsgSets(TestCaseWithFactory): | 48 | class TestTranslationSharedPOTMsgSets(TestCaseWithFactory): |
371 | @@ -67,21 +72,51 @@ | |||
372 | 67 | # Create a single POTMsgSet that is used across all tests, | 72 | # Create a single POTMsgSet that is used across all tests, |
373 | 68 | # and add it to only one of the POTemplates. | 73 | # and add it to only one of the POTemplates. |
374 | 69 | self.potmsgset = self.factory.makePOTMsgSet( | 74 | self.potmsgset = self.factory.makePOTMsgSet( |
376 | 70 | self.devel_potemplate) | 75 | self.devel_potemplate, singular=self.factory.getUniqueString(), |
377 | 76 | plural=self.factory.getUniqueString()) | ||
378 | 71 | 77 | ||
379 | 72 | def _refreshSuggestiveTemplatesCache(self): | 78 | def _refreshSuggestiveTemplatesCache(self): |
380 | 73 | """Refresh the `SuggestivePOTemplate` cache.""" | 79 | """Refresh the `SuggestivePOTemplate` cache.""" |
381 | 74 | getUtility(IPOTemplateSet).populateSuggestivePOTemplatesCache() | 80 | getUtility(IPOTemplateSet).populateSuggestivePOTemplatesCache() |
382 | 75 | 81 | ||
383 | 82 | def test_suggestive(self): | ||
384 | 83 | # POTMsgSet.suggestive is set to the initial POTemplate's | ||
385 | 84 | # suggestive value, and updated later by a garbo job. | ||
386 | 85 | pot1 = self.factory.makePOTemplate(suggestive=False) | ||
387 | 86 | pot2 = self.factory.makePOTemplate(suggestive=True) | ||
388 | 87 | |||
389 | 88 | # If created in a non-suggestive template, suggestive is false. | ||
390 | 89 | potmsgset1 = self.factory.makePOTMsgSet(potemplate=pot1) | ||
391 | 90 | self.assertFalse(potmsgset1.suggestive) | ||
392 | 91 | potmsgset1.setSequence(pot2, 1) | ||
393 | 92 | self.assertFalse(potmsgset1.suggestive) | ||
394 | 93 | |||
395 | 94 | # But when created in a suggestive template, suggestive is true. | ||
396 | 95 | potmsgset2 = self.factory.makePOTMsgSet(potemplate=pot2) | ||
397 | 96 | self.assertTrue(potmsgset2.suggestive) | ||
398 | 97 | |||
399 | 76 | def test_TranslationTemplateItem(self): | 98 | def test_TranslationTemplateItem(self): |
400 | 77 | self.potmsgset.setSequence(self.stable_potemplate, 1) | 99 | self.potmsgset.setSequence(self.stable_potemplate, 1) |
401 | 78 | 100 | ||
402 | 79 | devel_potmsgsets = list(self.devel_potemplate.getPOTMsgSets()) | 101 | devel_potmsgsets = list(self.devel_potemplate.getPOTMsgSets()) |
403 | 80 | stable_potmsgsets = list(self.stable_potemplate.getPOTMsgSets()) | 102 | stable_potmsgsets = list(self.stable_potemplate.getPOTMsgSets()) |
404 | 81 | 103 | ||
405 | 104 | # Both templates reference the same POTMsgSet. | ||
406 | 82 | self.assertEquals(devel_potmsgsets, [self.potmsgset]) | 105 | self.assertEquals(devel_potmsgsets, [self.potmsgset]) |
407 | 83 | self.assertEquals(devel_potmsgsets, stable_potmsgsets) | 106 | self.assertEquals(devel_potmsgsets, stable_potmsgsets) |
408 | 84 | 107 | ||
409 | 108 | # The msgids are denormalised from the POTMsgSet. | ||
410 | 109 | ttis = IStore(TranslationTemplateItem).find( | ||
411 | 110 | TranslationTemplateItem, | ||
412 | 111 | TranslationTemplateItem.potemplateID.is_in( | ||
413 | 112 | (self.devel_potemplate.id, self.stable_potemplate.id))) | ||
414 | 113 | for tti in ttis: | ||
415 | 114 | self.assertThat( | ||
416 | 115 | tti, | ||
417 | 116 | MatchesStructure.byEquality( | ||
418 | 117 | msgid_singular=self.potmsgset.msgid_singular, | ||
419 | 118 | msgid_plural=self.potmsgset.msgid_plural)) | ||
420 | 119 | |||
421 | 85 | def test_POTMsgSetInIncompatiblePOTemplates(self): | 120 | def test_POTMsgSetInIncompatiblePOTemplates(self): |
422 | 86 | # Make sure a POTMsgSet cannot be used in two POTemplates with | 121 | # Make sure a POTMsgSet cannot be used in two POTemplates with |
423 | 87 | # different incompatible source_file_format (like XPI and PO). | 122 | # different incompatible source_file_format (like XPI and PO). |
424 | @@ -1926,7 +1961,9 @@ | |||
425 | 1926 | 1961 | ||
426 | 1927 | def test_clone(self): | 1962 | def test_clone(self): |
427 | 1928 | """Cloning a POTMsgSet should produce a near-identical copy.""" | 1963 | """Cloning a POTMsgSet should produce a near-identical copy.""" |
428 | 1964 | pot = self.factory.makePOTemplate(suggestive=True) | ||
429 | 1929 | msgset = self.factory.makePOTMsgSet( | 1965 | msgset = self.factory.makePOTMsgSet( |
430 | 1966 | potemplate=pot, | ||
431 | 1930 | context=self.factory.getUniqueString('context'), | 1967 | context=self.factory.getUniqueString('context'), |
432 | 1931 | plural=self.factory.getUniqueString('plural'), | 1968 | plural=self.factory.getUniqueString('plural'), |
433 | 1932 | singular=self.factory.getUniqueString('singular'), | 1969 | singular=self.factory.getUniqueString('singular'), |
434 | @@ -1936,8 +1973,6 @@ | |||
435 | 1936 | flagscomment=self.factory.getUniqueString('flagscomment'), | 1973 | flagscomment=self.factory.getUniqueString('flagscomment'), |
436 | 1937 | ) | 1974 | ) |
437 | 1938 | new_msgset = msgset.clone() | 1975 | new_msgset = msgset.clone() |
438 | 1939 | naked_msgset = removeSecurityProxy(msgset) | ||
439 | 1940 | naked_new_msgset = removeSecurityProxy(new_msgset) | ||
440 | 1941 | self.assertNotEqual(msgset.id, new_msgset.id) | 1976 | self.assertNotEqual(msgset.id, new_msgset.id) |
441 | 1942 | self.assertEqual(msgset.context, new_msgset.context) | 1977 | self.assertEqual(msgset.context, new_msgset.context) |
442 | 1943 | self.assertEqual(msgset.msgid_singular, new_msgset.msgid_singular) | 1978 | self.assertEqual(msgset.msgid_singular, new_msgset.msgid_singular) |
443 | @@ -1947,3 +1982,4 @@ | |||
444 | 1947 | self.assertEqual(msgset.filereferences, new_msgset.filereferences) | 1982 | self.assertEqual(msgset.filereferences, new_msgset.filereferences) |
445 | 1948 | self.assertEqual(msgset.sourcecomment, new_msgset.sourcecomment) | 1983 | self.assertEqual(msgset.sourcecomment, new_msgset.sourcecomment) |
446 | 1949 | self.assertEqual(msgset.flagscomment, new_msgset.flagscomment) | 1984 | self.assertEqual(msgset.flagscomment, new_msgset.flagscomment) |
447 | 1985 | self.assertEqual(msgset.suggestive, new_msgset.suggestive) | ||
448 | 1950 | 1986 | ||
449 | === modified file 'lib/lp/translations/tests/test_translationmessage.py' | |||
450 | --- lib/lp/translations/tests/test_translationmessage.py 2014-07-10 05:30:29 +0000 | |||
451 | +++ lib/lp/translations/tests/test_translationmessage.py 2015-02-28 00:25:08 +0000 | |||
452 | @@ -107,16 +107,33 @@ | |||
453 | 107 | tm.potmsgset.setSequence(pofile.potemplate, 0) | 107 | tm.potmsgset.setSequence(pofile.potemplate, 0) |
454 | 108 | self.assertEquals(None, tm.getOnePOFile()) | 108 | self.assertEquals(None, tm.getOnePOFile()) |
455 | 109 | 109 | ||
456 | 110 | def test_denormalised(self): | ||
457 | 111 | # msgid_singular and msgid_plural are denormalised from | ||
458 | 112 | # POTMsgSet for suggestion performance. | ||
459 | 113 | pot = self.factory.makePOTemplate(suggestive=True) | ||
460 | 114 | singular = self.factory.getUniqueString() | ||
461 | 115 | plural = self.factory.getUniqueString() | ||
462 | 116 | potmsgset = self.factory.makePOTMsgSet( | ||
463 | 117 | potemplate=pot, singular=singular, plural=plural) | ||
464 | 118 | self.assertTrue(potmsgset.suggestive) | ||
465 | 119 | tm = self.factory.makeCurrentTranslationMessage( | ||
466 | 120 | potmsgset=potmsgset) | ||
467 | 121 | naked_tm = removeSecurityProxy(tm) | ||
468 | 122 | self.assertEqual(singular, naked_tm.msgid_singular.msgid) | ||
469 | 123 | self.assertEqual(plural, naked_tm.msgid_plural.msgid) | ||
470 | 124 | self.assertTrue(naked_tm.suggestive) | ||
471 | 125 | |||
472 | 110 | def test_clone(self): | 126 | def test_clone(self): |
473 | 111 | """Cloning a translation should produce a near-identical copy.""" | 127 | """Cloning a translation should produce a near-identical copy.""" |
474 | 112 | translations = [self.factory.getUniqueString() for x in range(6)] | 128 | translations = [self.factory.getUniqueString() for x in range(6)] |
476 | 113 | tm = self.factory.makeCurrentTranslationMessage( | 129 | tm = removeSecurityProxy(self.factory.makeCurrentTranslationMessage( |
477 | 114 | date_created=self.factory.getUniqueDate(), | 130 | date_created=self.factory.getUniqueDate(), |
479 | 115 | translations=translations, current_other=True) | 131 | translations=translations, current_other=True)) |
480 | 116 | tm.comment = self.factory.getUniqueString() | 132 | tm.comment = self.factory.getUniqueString() |
481 | 117 | tm.was_obsolete_in_last_import = True | 133 | tm.was_obsolete_in_last_import = True |
482 | 134 | tm.suggestive = True | ||
483 | 118 | potmsgset = self.factory.makePOTMsgSet() | 135 | potmsgset = self.factory.makePOTMsgSet() |
485 | 119 | clone = tm.clone(potmsgset) | 136 | clone = removeSecurityProxy(tm.clone(potmsgset)) |
486 | 120 | self.assertNotEqual(tm.id, clone.id) | 137 | self.assertNotEqual(tm.id, clone.id) |
487 | 121 | self.assertIs(None, clone.potemplate) | 138 | self.assertIs(None, clone.potemplate) |
488 | 122 | self.assertEqual(potmsgset, clone.potmsgset) | 139 | self.assertEqual(potmsgset, clone.potmsgset) |
489 | @@ -138,6 +155,9 @@ | |||
490 | 138 | self.assertEqual(tm.is_current_upstream, clone.is_current_upstream) | 155 | self.assertEqual(tm.is_current_upstream, clone.is_current_upstream) |
491 | 139 | self.assertEqual( | 156 | self.assertEqual( |
492 | 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) |
493 | 158 | self.assertEqual(tm.msgid_singular, clone.msgid_singular) | ||
494 | 159 | self.assertEqual(tm.msgid_plural, clone.msgid_plural) | ||
495 | 160 | self.assertEqual(tm.suggestive, clone.suggestive) | ||
496 | 141 | 161 | ||
497 | 142 | 162 | ||
498 | 143 | class TestApprove(TestCaseWithFactory): | 163 | class TestApprove(TestCaseWithFactory): |