Merge lp:~ursinha/launchpad/bug-391569-add-last-changed-column into lp:launchpad
- bug-391569-add-last-changed-column
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Ursula Junque |
Approved revision: | no longer in the source branch. |
Merged at revision: | not available |
Proposed branch: | lp:~ursinha/launchpad/bug-391569-add-last-changed-column |
Merge into: | lp:launchpad |
Diff against target: |
332 lines (+91/-25) 5 files modified
lib/lp/registry/model/productseries.py (+23/-7) lib/lp/translations/interfaces/productserieslanguage.py (+7/-2) lib/lp/translations/model/productserieslanguage.py (+10/-1) lib/lp/translations/templates/productseries-translations-languages.pt (+20/-0) lib/lp/translations/tests/test_productserieslanguage.py (+31/-15) |
To merge this branch: | bzr merge lp:~ursinha/launchpad/bug-391569-add-last-changed-column |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Graham Binns (community) | Approve | ||
Review via email: mp+14366@code.launchpad.net |
Commit message
[r=gmb][ui=none][bug=391569] Adds a Last Changed column to +translations pages.
Description of the change
Ursula Junque (ursinha) wrote : | # |
Graham Binns (gmb) wrote : | # |
Hi Ursula,
Nice branch! I've got a few comments but they're all stylistic nitpicks, so I'm happy to approve this with the changes I've requested.
> === modified file 'lib/lp/
> --- lib/lp/
> +++ lib/lp/
> @@ -526,10 +528,21 @@
> POTemplate.
> Language.
>
> - for (language, imported, changed, new, unreviewed) in (
> - query.order_
> + # XXX: Ursinha 2009-11-02: The Max(POFile.
> + # here is a naive datetime. My guess is that it happens
> + # because UTC awareness is attibuted to the field in the POFile
> + # model class, and in this case the Max function deals directly
> + # with the value returned from the database without
> + # instantiating it.
> + # This seems to be irrelevant to what we're trying to achieve
> + # here, but making a note either way.
> +
> + for (language, imported, changed, new, unreviewed,
> + last_changed) in (
> + query.order_
This is a little hard to read. Maybe something like:
ordered_results = query.order_
for (language, imported, changed, new, unreviewed,
...
Would be a little easier.
Also note that the indent on long loop definitions should still be four
spaces.
> psl = ProductSeriesLa
> - psl.setCounts(
> + psl.setCounts(
> + last_changed)
When we wrap long method calls, we should wrap them like this:
psl.setCounts(
total, imported, changed, new, unreviewed, last_changed)
> results.append(psl)
>
> return results
>
> === modified file 'lib/lp/
> --- lib/lp/
> +++ lib/lp/
> @@ -46,6 +46,7 @@
> # Add a Serbian translation.
> serbian = getUtility(
> sr_pofile = self.factory.
> +
> psls = list(self.
> self.assertEqua
>
> @@ -111,7 +112,8 @@
> removeSecurityP
> return potemplate
>
> - def setPOFileStatis
> + def setPOFileStatis
> + date_changed):
The wrapped lines of a method definition should start under the first
argument, thus:
def setPOFileStatis
Ursula Junque (ursinha) wrote : | # |
> Hi Ursula,
>
> Nice branch! I've got a few comments but they're all stylistic nitpicks, so
> I'm happy to approve this with the changes I've requested.
All changes applied, incremental diff below. Thanks!
=== modified file 'lib/lp/
--- lib/lp/
+++ lib/lp/
@@ -493,13 +493,15 @@
- for language, pofile in query.order_
+ ordered_results = query.order_
+
+ for language, pofile in ordered_results:
- pofile.
+ pofile.
else:
@@ -537,12 +539,13 @@
# This seems to be irrelevant to what we're trying to achieve
# here, but making a note either way.
- for (language, imported, changed, new, unreviewed,
- last_changed) in (
- query.order_
+ ordered_results = query.order_
+
+ for (language, imported, changed, new, unreviewed,
+ last_changed) in ordered_results:
- psl.setCounts(
- last_changed)
+ psl.setCounts(
+ total, imported, changed, new, unreviewed, last_changed)
return results
=== modified file 'lib/lp/
--- lib/lp/
+++ lib/lp/
@@ -113,7 +113,7 @@
return potemplate
def setPOFileStatis
- ...
Preview Diff
1 | === modified file 'lib/lp/registry/model/productseries.py' | |||
2 | --- lib/lp/registry/model/productseries.py 2009-10-16 15:00:55 +0000 | |||
3 | +++ lib/lp/registry/model/productseries.py 2009-11-10 18:11:11 +0000 | |||
4 | @@ -15,7 +15,7 @@ | |||
5 | 15 | 15 | ||
6 | 16 | from sqlobject import ( | 16 | from sqlobject import ( |
7 | 17 | ForeignKey, StringCol, SQLMultipleJoin, SQLObjectNotFound) | 17 | ForeignKey, StringCol, SQLMultipleJoin, SQLObjectNotFound) |
9 | 18 | from storm.expr import Sum | 18 | from storm.expr import Sum, Max |
10 | 19 | from zope.component import getUtility | 19 | from zope.component import getUtility |
11 | 20 | from zope.interface import implements | 20 | from zope.interface import implements |
12 | 21 | from storm.locals import And, Desc | 21 | from storm.locals import And, Desc |
13 | @@ -493,13 +493,16 @@ | |||
14 | 493 | POTemplate.iscurrent==True, | 493 | POTemplate.iscurrent==True, |
15 | 494 | Language.id!=english.id) | 494 | Language.id!=english.id) |
16 | 495 | 495 | ||
18 | 496 | for language, pofile in query.order_by(['Language.englishname']): | 496 | ordered_results = query.order_by(['Language.englishname']) |
19 | 497 | |||
20 | 498 | for language, pofile in ordered_results: | ||
21 | 497 | psl = ProductSeriesLanguage(self, language, pofile=pofile) | 499 | psl = ProductSeriesLanguage(self, language, pofile=pofile) |
22 | 498 | psl.setCounts(pofile.potemplate.messageCount(), | 500 | psl.setCounts(pofile.potemplate.messageCount(), |
23 | 499 | pofile.currentCount(), | 501 | pofile.currentCount(), |
24 | 500 | pofile.updatesCount(), | 502 | pofile.updatesCount(), |
25 | 501 | pofile.rosettaCount(), | 503 | pofile.rosettaCount(), |
27 | 502 | pofile.unreviewedCount()) | 504 | pofile.unreviewedCount(), |
28 | 505 | pofile.date_changed) | ||
29 | 503 | results.append(psl) | 506 | results.append(psl) |
30 | 504 | else: | 507 | else: |
31 | 505 | # If there is more than one template, do a single | 508 | # If there is more than one template, do a single |
32 | @@ -517,7 +520,8 @@ | |||
33 | 517 | Sum(POFile.currentcount), | 520 | Sum(POFile.currentcount), |
34 | 518 | Sum(POFile.updatescount), | 521 | Sum(POFile.updatescount), |
35 | 519 | Sum(POFile.rosettacount), | 522 | Sum(POFile.rosettacount), |
37 | 520 | Sum(POFile.unreviewed_count)), | 523 | Sum(POFile.unreviewed_count), |
38 | 524 | Max(POFile.date_changed)), | ||
39 | 521 | POFile.language==Language.id, | 525 | POFile.language==Language.id, |
40 | 522 | POFile.variant==None, | 526 | POFile.variant==None, |
41 | 523 | Language.visible==True, | 527 | Language.visible==True, |
42 | @@ -526,10 +530,22 @@ | |||
43 | 526 | POTemplate.iscurrent==True, | 530 | POTemplate.iscurrent==True, |
44 | 527 | Language.id!=english.id).group_by(Language) | 531 | Language.id!=english.id).group_by(Language) |
45 | 528 | 532 | ||
48 | 529 | for (language, imported, changed, new, unreviewed) in ( | 533 | # XXX: Ursinha 2009-11-02: The Max(POFile.date_changed) result |
49 | 530 | query.order_by(['Language.englishname'])): | 534 | # here is a naive datetime. My guess is that it happens |
50 | 535 | # because UTC awareness is attibuted to the field in the POFile | ||
51 | 536 | # model class, and in this case the Max function deals directly | ||
52 | 537 | # with the value returned from the database without | ||
53 | 538 | # instantiating it. | ||
54 | 539 | # This seems to be irrelevant to what we're trying to achieve | ||
55 | 540 | # here, but making a note either way. | ||
56 | 541 | |||
57 | 542 | ordered_results = query.order_by(['Language.englishname']) | ||
58 | 543 | |||
59 | 544 | for (language, imported, changed, new, unreviewed, | ||
60 | 545 | last_changed) in ordered_results: | ||
61 | 531 | psl = ProductSeriesLanguage(self, language) | 546 | psl = ProductSeriesLanguage(self, language) |
63 | 532 | psl.setCounts(total, imported, changed, new, unreviewed) | 547 | psl.setCounts( |
64 | 548 | total, imported, changed, new, unreviewed, last_changed) | ||
65 | 533 | results.append(psl) | 549 | results.append(psl) |
66 | 534 | 550 | ||
67 | 535 | return results | 551 | return results |
68 | 536 | 552 | ||
69 | === modified file 'lib/lp/translations/interfaces/productserieslanguage.py' | |||
70 | --- lib/lp/translations/interfaces/productserieslanguage.py 2009-09-11 09:29:51 +0000 | |||
71 | +++ lib/lp/translations/interfaces/productserieslanguage.py 2009-11-10 18:11:11 +0000 | |||
72 | @@ -7,7 +7,7 @@ | |||
73 | 7 | 7 | ||
74 | 8 | from zope.interface import Attribute, Interface | 8 | from zope.interface import Attribute, Interface |
75 | 9 | from zope.schema import ( | 9 | from zope.schema import ( |
77 | 10 | Choice, TextLine) | 10 | Choice, Datetime, TextLine) |
78 | 11 | 11 | ||
79 | 12 | from canonical.launchpad import _ | 12 | from canonical.launchpad import _ |
80 | 13 | from lp.translations.interfaces.pofile import IPOFile | 13 | from lp.translations.interfaces.pofile import IPOFile |
81 | @@ -45,6 +45,11 @@ | |||
82 | 45 | "language. This includes only the real pofiles where translations " | 45 | "language. This includes only the real pofiles where translations " |
83 | 46 | "exist.") | 46 | "exist.") |
84 | 47 | 47 | ||
85 | 48 | |||
86 | 49 | last_changed_date = Datetime( | ||
87 | 50 | title=_('When this file was last changed.')) | ||
88 | 51 | |||
89 | 52 | |||
90 | 48 | def getPOFilesFor(potemplates): | 53 | def getPOFilesFor(potemplates): |
91 | 49 | """Return `POFiles` for each of `potemplates`, in the same order. | 54 | """Return `POFiles` for each of `potemplates`, in the same order. |
92 | 50 | 55 | ||
93 | @@ -52,7 +57,7 @@ | |||
94 | 52 | required language, a `DummyPOFile` is provided. | 57 | required language, a `DummyPOFile` is provided. |
95 | 53 | """ | 58 | """ |
96 | 54 | 59 | ||
98 | 55 | def setCounts(total, imported, changed, new, unreviewed): | 60 | def setCounts(total, imported, changed, new, unreviewed, last_changed): |
99 | 56 | """Set aggregated message counts for ProductSeriesLanguage.""" | 61 | """Set aggregated message counts for ProductSeriesLanguage.""" |
100 | 57 | 62 | ||
101 | 58 | def recalculateCounts(total, imported, changed, new, unreviewed): | 63 | def recalculateCounts(total, imported, changed, new, unreviewed): |
102 | 59 | 64 | ||
103 | === modified file 'lib/lp/translations/model/productserieslanguage.py' | |||
104 | --- lib/lp/translations/model/productserieslanguage.py 2009-09-14 11:27:37 +0000 | |||
105 | +++ lib/lp/translations/model/productserieslanguage.py 2009-11-10 18:11:11 +0000 | |||
106 | @@ -36,12 +36,13 @@ | |||
107 | 36 | self.variant = variant | 36 | self.variant = variant |
108 | 37 | self.pofile = pofile | 37 | self.pofile = pofile |
109 | 38 | self.id = 0 | 38 | self.id = 0 |
110 | 39 | self._last_changed_date = None | ||
111 | 39 | 40 | ||
112 | 40 | # Reset all cached counts. | 41 | # Reset all cached counts. |
113 | 41 | self.setCounts() | 42 | self.setCounts() |
114 | 42 | 43 | ||
115 | 43 | def setCounts(self, total=None, imported=None, changed=None, new=None, | 44 | def setCounts(self, total=None, imported=None, changed=None, new=None, |
117 | 44 | unreviewed=None): | 45 | unreviewed=None, last_changed=None): |
118 | 45 | """See `IProductSeriesLanguage`.""" | 46 | """See `IProductSeriesLanguage`.""" |
119 | 46 | self._messagecount = total | 47 | self._messagecount = total |
120 | 47 | # "currentcount" in RosettaStats conflicts our recent terminology | 48 | # "currentcount" in RosettaStats conflicts our recent terminology |
121 | @@ -51,6 +52,9 @@ | |||
122 | 51 | self._updatescount = changed | 52 | self._updatescount = changed |
123 | 52 | self._rosettacount = new | 53 | self._rosettacount = new |
124 | 53 | self._unreviewed_count = unreviewed | 54 | self._unreviewed_count = unreviewed |
125 | 55 | if last_changed is not None: | ||
126 | 56 | self._last_changed_date = last_changed | ||
127 | 57 | |||
128 | 54 | 58 | ||
129 | 55 | def _getMessageCount(self): | 59 | def _getMessageCount(self): |
130 | 56 | store = Store.of(self.language) | 60 | store = Store.of(self.language) |
131 | @@ -112,6 +116,11 @@ | |||
132 | 112 | return self._unreviewed_count | 116 | return self._unreviewed_count |
133 | 113 | 117 | ||
134 | 114 | @property | 118 | @property |
135 | 119 | def last_changed_date(self): | ||
136 | 120 | """See `IProductSeriesLanguage`.""" | ||
137 | 121 | return self._last_changed_date | ||
138 | 122 | |||
139 | 123 | @property | ||
140 | 115 | def pofiles(self): | 124 | def pofiles(self): |
141 | 116 | """See `IProductSeriesLanguage`.""" | 125 | """See `IProductSeriesLanguage`.""" |
142 | 117 | store = Store.of(self.language) | 126 | store = Store.of(self.language) |
143 | 118 | 127 | ||
144 | === modified file 'lib/lp/translations/templates/productseries-translations-languages.pt' | |||
145 | --- lib/lp/translations/templates/productseries-translations-languages.pt 2009-09-10 07:24:24 +0000 | |||
146 | +++ lib/lp/translations/templates/productseries-translations-languages.pt 2009-11-10 18:11:11 +0000 | |||
147 | @@ -11,6 +11,7 @@ | |||
148 | 11 | <th>Untranslated</th> | 11 | <th>Untranslated</th> |
149 | 12 | <th>Needs review</th> | 12 | <th>Needs review</th> |
150 | 13 | <th>Changed</th> | 13 | <th>Changed</th> |
151 | 14 | <th>Last Changed</th> | ||
152 | 14 | </tr> | 15 | </tr> |
153 | 15 | </thead> | 16 | </thead> |
154 | 16 | <tbody> | 17 | <tbody> |
155 | @@ -47,6 +48,25 @@ | |||
156 | 47 | tal:content="language_stats/updatesCount">0</span> | 48 | tal:content="language_stats/updatesCount">0</span> |
157 | 48 | <tal:value content="language_stats/updatesCount" /> | 49 | <tal:value content="language_stats/updatesCount" /> |
158 | 49 | </td> | 50 | </td> |
159 | 51 | <td> | ||
160 | 52 | <span class="sortkey" | ||
161 | 53 | tal:condition="language_stats/last_changed_date" | ||
162 | 54 | tal:content="language_stats/last_changed_date/fmt:datetime"> | ||
163 | 55 | time sort key | ||
164 | 56 | </span> | ||
165 | 57 | <span | ||
166 | 58 | tal:condition="language_stats/last_changed_date" | ||
167 | 59 | tal:attributes=" | ||
168 | 60 | title language_stats/last_changed_date/fmt:datetime" | ||
169 | 61 | tal:content=" | ||
170 | 62 | language_stats/last_changed_date/fmt:approximatedate" | ||
171 | 63 | > | ||
172 | 64 | 2007-02-10 | ||
173 | 65 | </span> | ||
174 | 66 | <tal:block condition="not: language_stats/last_changed_date"> | ||
175 | 67 | — | ||
176 | 68 | </tal:block> | ||
177 | 69 | </td> | ||
178 | 50 | </tr> | 70 | </tr> |
179 | 51 | </tbody> | 71 | </tbody> |
180 | 52 | </table> | 72 | </table> |
181 | 53 | 73 | ||
182 | === modified file 'lib/lp/translations/tests/test_productserieslanguage.py' | |||
183 | --- lib/lp/translations/tests/test_productserieslanguage.py 2009-09-12 16:07:05 +0000 | |||
184 | +++ lib/lp/translations/tests/test_productserieslanguage.py 2009-11-10 18:11:11 +0000 | |||
185 | @@ -46,6 +46,7 @@ | |||
186 | 46 | # Add a Serbian translation. | 46 | # Add a Serbian translation. |
187 | 47 | serbian = getUtility(ILanguageSet).getLanguageByCode('sr') | 47 | serbian = getUtility(ILanguageSet).getLanguageByCode('sr') |
188 | 48 | sr_pofile = self.factory.makePOFile(serbian.code, potemplate) | 48 | sr_pofile = self.factory.makePOFile(serbian.code, potemplate) |
189 | 49 | |||
190 | 49 | psls = list(self.productseries.productserieslanguages) | 50 | psls = list(self.productseries.productserieslanguages) |
191 | 50 | self.assertEquals(len(psls), 1) | 51 | self.assertEquals(len(psls), 1) |
192 | 51 | 52 | ||
193 | @@ -111,7 +112,8 @@ | |||
194 | 111 | removeSecurityProxy(potemplate).messagecount = number_of_potmsgsets | 112 | removeSecurityProxy(potemplate).messagecount = number_of_potmsgsets |
195 | 112 | return potemplate | 113 | return potemplate |
196 | 113 | 114 | ||
198 | 114 | def setPOFileStatistics(self, pofile, imported, changed, new, unreviewed): | 115 | def setPOFileStatistics(self, pofile, imported, changed, new, unreviewed, |
199 | 116 | date_changed): | ||
200 | 115 | # Instead of creating all relevant translation messages, we | 117 | # Instead of creating all relevant translation messages, we |
201 | 116 | # just fake cached statistics instead. | 118 | # just fake cached statistics instead. |
202 | 117 | naked_pofile = removeSecurityProxy(pofile) | 119 | naked_pofile = removeSecurityProxy(pofile) |
203 | @@ -119,6 +121,7 @@ | |||
204 | 119 | naked_pofile.updatescount = changed | 121 | naked_pofile.updatescount = changed |
205 | 120 | naked_pofile.rosettacount = new | 122 | naked_pofile.rosettacount = new |
206 | 121 | naked_pofile.unreviewed_count = unreviewed | 123 | naked_pofile.unreviewed_count = unreviewed |
207 | 124 | naked_pofile.date_changed = date_changed | ||
208 | 122 | naked_pofile.sync() | 125 | naked_pofile.sync() |
209 | 123 | 126 | ||
210 | 124 | def setUp(self): | 127 | def setUp(self): |
211 | @@ -136,20 +139,22 @@ | |||
212 | 136 | psl.currentCount(), | 139 | psl.currentCount(), |
213 | 137 | psl.rosettaCount(), | 140 | psl.rosettaCount(), |
214 | 138 | psl.updatesCount(), | 141 | psl.updatesCount(), |
217 | 139 | psl.unreviewedCount()), | 142 | psl.unreviewedCount(), |
218 | 140 | stats) | 143 | psl.last_changed_date), |
219 | 144 | stats) | ||
220 | 141 | 145 | ||
221 | 142 | def test_DummyProductSeriesLanguage(self): | 146 | def test_DummyProductSeriesLanguage(self): |
222 | 143 | # With no templates all counts are zero. | 147 | # With no templates all counts are zero. |
223 | 144 | psl = self.psl_set.getDummy(self.productseries, self.language) | 148 | psl = self.psl_set.getDummy(self.productseries, self.language) |
224 | 145 | self.failUnless(verifyObject(IProductSeriesLanguage, psl)) | 149 | self.failUnless(verifyObject(IProductSeriesLanguage, psl)) |
226 | 146 | self.assertPSLStatistics(psl, (0, 0, 0, 0, 0, 0)) | 150 | self.assertPSLStatistics(psl, (0, 0, 0, 0, 0, 0, None)) |
227 | 147 | 151 | ||
228 | 148 | # Adding a single template with 10 messages makes the total | 152 | # Adding a single template with 10 messages makes the total |
229 | 149 | # count of messages go up to 10. | 153 | # count of messages go up to 10. |
230 | 150 | potemplate = self.createPOTemplateWithPOTMsgSets(10) | 154 | potemplate = self.createPOTemplateWithPOTMsgSets(10) |
231 | 151 | psl = self.psl_set.getDummy(self.productseries, self.language) | 155 | psl = self.psl_set.getDummy(self.productseries, self.language) |
233 | 152 | self.assertPSLStatistics(psl, (10, 0, 0, 0, 0, 0)) | 156 | self.assertPSLStatistics( |
234 | 157 | psl, (10, 0, 0, 0, 0, 0, None)) | ||
235 | 153 | 158 | ||
236 | 154 | def test_OneTemplate(self): | 159 | def test_OneTemplate(self): |
237 | 155 | # With only one template, statistics match those of the POFile. | 160 | # With only one template, statistics match those of the POFile. |
238 | @@ -158,7 +163,7 @@ | |||
239 | 158 | 163 | ||
240 | 159 | # Set statistics to 4 imported, 3 new in rosetta (out of which 2 | 164 | # Set statistics to 4 imported, 3 new in rosetta (out of which 2 |
241 | 160 | # are updates) and 5 with unreviewed suggestions. | 165 | # are updates) and 5 with unreviewed suggestions. |
243 | 161 | self.setPOFileStatistics(pofile, 4, 2, 3, 5) | 166 | self.setPOFileStatistics(pofile, 4, 2, 3, 5, pofile.date_changed) |
244 | 162 | 167 | ||
245 | 163 | # Getting PSL through PSLSet gives an uninitialized object. | 168 | # Getting PSL through PSLSet gives an uninitialized object. |
246 | 164 | psl = self.psl_set.getProductSeriesLanguage( | 169 | psl = self.psl_set.getProductSeriesLanguage( |
247 | @@ -173,7 +178,8 @@ | |||
248 | 173 | pofile.currentCount(), | 178 | pofile.currentCount(), |
249 | 174 | pofile.rosettaCount(), | 179 | pofile.rosettaCount(), |
250 | 175 | pofile.updatesCount(), | 180 | pofile.updatesCount(), |
252 | 176 | pofile.unreviewedCount())) | 181 | pofile.unreviewedCount(), |
253 | 182 | pofile.date_changed)) | ||
254 | 177 | 183 | ||
255 | 178 | def test_TwoTemplates(self): | 184 | def test_TwoTemplates(self): |
256 | 179 | # With two templates, statistics are added up. | 185 | # With two templates, statistics are added up. |
257 | @@ -181,27 +187,34 @@ | |||
258 | 181 | pofile1 = self.factory.makePOFile(self.language.code, potemplate1) | 187 | pofile1 = self.factory.makePOFile(self.language.code, potemplate1) |
259 | 182 | # Set statistics to 4 imported, 3 new in rosetta (out of which 2 | 188 | # Set statistics to 4 imported, 3 new in rosetta (out of which 2 |
260 | 183 | # are updates) and 5 with unreviewed suggestions. | 189 | # are updates) and 5 with unreviewed suggestions. |
262 | 184 | self.setPOFileStatistics(pofile1, 4, 2, 3, 5) | 190 | self.setPOFileStatistics(pofile1, 4, 2, 3, 5, pofile1.date_changed) |
263 | 185 | 191 | ||
264 | 186 | potemplate2 = self.createPOTemplateWithPOTMsgSets(20) | 192 | potemplate2 = self.createPOTemplateWithPOTMsgSets(20) |
265 | 187 | pofile2 = self.factory.makePOFile(self.language.code, potemplate2) | 193 | pofile2 = self.factory.makePOFile(self.language.code, potemplate2) |
266 | 188 | # Set statistics to 1 imported, 1 new in rosetta (which is also the | 194 | # Set statistics to 1 imported, 1 new in rosetta (which is also the |
267 | 189 | # 1 update) and 1 with unreviewed suggestions. | 195 | # 1 update) and 1 with unreviewed suggestions. |
269 | 190 | self.setPOFileStatistics(pofile2, 1, 1, 1, 1) | 196 | self.setPOFileStatistics(pofile2, 1, 1, 1, 1, pofile2.date_changed) |
270 | 191 | 197 | ||
271 | 192 | psl = self.productseries.productserieslanguages[0] | 198 | psl = self.productseries.productserieslanguages[0] |
272 | 193 | 199 | ||
273 | 200 | # The psl.last_changed_date here is a naive datetime. So, for sake of | ||
274 | 201 | # the tests, we should make pofile2 naive when checking if it matches | ||
275 | 202 | # the last calculated changed date, that should be the same as | ||
276 | 203 | # pofile2, created last. | ||
277 | 204 | |||
278 | 194 | # Total is a sum of totals in both POTemplates (10+20). | 205 | # Total is a sum of totals in both POTemplates (10+20). |
279 | 195 | # Translated is a sum of imported and rosetta translations, | 206 | # Translated is a sum of imported and rosetta translations, |
280 | 196 | # which adds up as (4+3)+(1+1). | 207 | # which adds up as (4+3)+(1+1). |
282 | 197 | self.assertPSLStatistics(psl, (30, 9, 5, 4, 3, 6)) | 208 | self.assertPSLStatistics(psl, (30, 9, 5, 4, 3, 6, |
283 | 209 | pofile2.date_changed.replace(tzinfo=None))) | ||
284 | 198 | self.assertPSLStatistics(psl, ( | 210 | self.assertPSLStatistics(psl, ( |
285 | 199 | pofile1.messageCount() + pofile2.messageCount(), | 211 | pofile1.messageCount() + pofile2.messageCount(), |
286 | 200 | pofile1.translatedCount() + pofile2.translatedCount(), | 212 | pofile1.translatedCount() + pofile2.translatedCount(), |
287 | 201 | pofile1.currentCount() + pofile2.currentCount(), | 213 | pofile1.currentCount() + pofile2.currentCount(), |
288 | 202 | pofile1.rosettaCount() + pofile2.rosettaCount(), | 214 | pofile1.rosettaCount() + pofile2.rosettaCount(), |
289 | 203 | pofile1.updatesCount() + pofile2.updatesCount(), | 215 | pofile1.updatesCount() + pofile2.updatesCount(), |
291 | 204 | pofile1.unreviewedCount() + pofile2.unreviewedCount())) | 216 | pofile1.unreviewedCount() + pofile2.unreviewedCount(), |
292 | 217 | pofile2.date_changed.replace(tzinfo=None))) | ||
293 | 205 | 218 | ||
294 | 206 | def test_recalculateCounts(self): | 219 | def test_recalculateCounts(self): |
295 | 207 | # Test that recalculateCounts works correctly. | 220 | # Test that recalculateCounts works correctly. |
296 | @@ -210,21 +223,23 @@ | |||
297 | 210 | 223 | ||
298 | 211 | # Set statistics to 1 imported, 3 new in rosetta (out of which 2 | 224 | # Set statistics to 1 imported, 3 new in rosetta (out of which 2 |
299 | 212 | # are updates) and 4 with unreviewed suggestions. | 225 | # are updates) and 4 with unreviewed suggestions. |
301 | 213 | self.setPOFileStatistics(pofile1, 1, 2, 3, 4) | 226 | self.setPOFileStatistics(pofile1, 1, 2, 3, 4, pofile1.date_changed) |
302 | 214 | 227 | ||
303 | 215 | potemplate2 = self.createPOTemplateWithPOTMsgSets(20) | 228 | potemplate2 = self.createPOTemplateWithPOTMsgSets(20) |
304 | 216 | pofile2 = self.factory.makePOFile(self.language.code, potemplate2) | 229 | pofile2 = self.factory.makePOFile(self.language.code, potemplate2) |
305 | 217 | # Set statistics to 1 imported, 1 new in rosetta (which is also the | 230 | # Set statistics to 1 imported, 1 new in rosetta (which is also the |
306 | 218 | # 1 update) and 1 with unreviewed suggestions. | 231 | # 1 update) and 1 with unreviewed suggestions. |
308 | 219 | self.setPOFileStatistics(pofile2, 1, 1, 1, 1) | 232 | self.setPOFileStatistics(pofile2, 1, 1, 1, 1, pofile2.date_changed) |
309 | 220 | 233 | ||
310 | 221 | psl = self.psl_set.getProductSeriesLanguage(self.productseries, | 234 | psl = self.psl_set.getProductSeriesLanguage(self.productseries, |
311 | 222 | self.language) | 235 | self.language) |
312 | 236 | # recalculateCounts() doesn't recalculate the last changed date. | ||
313 | 223 | psl.recalculateCounts() | 237 | psl.recalculateCounts() |
314 | 224 | # Total is a sum of totals in both POTemplates (10+20). | 238 | # Total is a sum of totals in both POTemplates (10+20). |
315 | 225 | # Translated is a sum of imported and rosetta translations, | 239 | # Translated is a sum of imported and rosetta translations, |
316 | 226 | # which adds up as (1+3)+(1+1). | 240 | # which adds up as (1+3)+(1+1). |
318 | 227 | self.assertPSLStatistics(psl, (30, 6, 2, 4, 3, 5)) | 241 | self.assertPSLStatistics(psl, (30, 6, 2, 4, 3, 5, |
319 | 242 | None)) | ||
320 | 228 | 243 | ||
321 | 229 | def test_recalculateCounts_no_pofiles(self): | 244 | def test_recalculateCounts_no_pofiles(self): |
322 | 230 | # Test that recalculateCounts works correctly even when there | 245 | # Test that recalculateCounts works correctly even when there |
323 | @@ -235,7 +250,8 @@ | |||
324 | 235 | self.language) | 250 | self.language) |
325 | 236 | psl.recalculateCounts() | 251 | psl.recalculateCounts() |
326 | 237 | # And all the counts are zero. | 252 | # And all the counts are zero. |
328 | 238 | self.assertPSLStatistics(psl, (3, 0, 0, 0, 0, 0)) | 253 | self.assertPSLStatistics(psl, (3, 0, 0, 0, 0, 0, |
329 | 254 | None)) | ||
330 | 239 | 255 | ||
331 | 240 | 256 | ||
332 | 241 | def test_suite(): | 257 | def test_suite(): |
= Summary =
https:/ /bugs.edge. launchpad. net/rosetta/ +bug/391569
This branch adds a "Last Changed" date in +translations pages, showing
the last date a translation in a given language was touched.
== Proposed fix ==
Added a last_changed_date property to the productseriesla nguages interface, and changed nguage to also return the last date changed among all POFiles
productseriesla
in a product, of a language.
== Pre-implementation notes ==
Discussed with Danilo.
== Tests ==
This should work:
bin/test -vvt lp.translations.*
(but I did a full test run just to be sure :)
== Demo and Q/A ==
To check the changed pages, go to: /translations. launchpad. dev/evolution/ trunk/+ translations /translations. launchpad. dev/alsa- utils/trunk
- https:/
- https:/
= Launchpad lint =
Checking for conflicts. and issues in doctests and templates.
Running jslint, xmllint, pyflakes, and pylint.
Using normal rules.
Linting changed files: registry/ model/productse ries.py translations/ interfaces/ productseriesla nguage. py translations/ tests/test_ productseriesla nguage. py translations/ templates/ productseries- translations- languages. pt translations/ model/productse rieslanguage. py
lib/lp/
lib/lp/
lib/lp/
lib/lp/
lib/lp/
== Pylint notices ==
lib/lp/ translations/ interfaces/ productseriesla nguage. py fields' (No module named restful)
6: [F0401] Unable to import 'lazr.restful.