Merge lp:~jtv/launchpad/recife-new-resetcurrenttranslation into lp:~launchpad/launchpad/recife

Proposed by Jeroen T. Vermeulen
Status: Merged
Approved by: Michael Nelson
Approved revision: no longer in the source branch.
Merged at revision: 9164
Proposed branch: lp:~jtv/launchpad/recife-new-resetcurrenttranslation
Merge into: lp:~launchpad/launchpad/recife
Diff against target: 406 lines (+188/-90)
4 files modified
lib/lp/translations/browser/translationmessage.py (+15/-16)
lib/lp/translations/interfaces/potmsgset.py (+23/-10)
lib/lp/translations/model/potmsgset.py (+39/-17)
lib/lp/translations/tests/test_potmsgset.py (+111/-47)
To merge this branch: bzr merge lp:~jtv/launchpad/recife-new-resetcurrenttranslation
Reviewer Review Type Date Requested Status
Michael Nelson (community) code Approve
Review via email: mp+33747@code.launchpad.net

Commit message

resetCurrentTranslation

Description of the change

= resetCurrentTranslation =

For the Recife feature branch, upon discussion with Danilo. This re-implements POTMsgSet.resetCurrentTranslation based on the new data model.

However that change breaks a view test. The breakage would have been hard to fix (without getting very dirty and making it very brittle) because the one call to resetCurrentTranslation, from a view, is right next to POTMsgSet.updateTranslation. That's the huge, complex, convoluted, unmaintainable and inscrutable method that we're trying to get rid of with the old model. No matter what we do, a view method that combines the old-model updateTranslation and the new-model resetCurrentTranslation will be wrong.

So I renamed the old resetCurrentTranslation to old_resetCurrentTranslation and kept its tests (those that still make sense) for a fresh, totally revised, new-world version of resetCurrentTranslation. Once we rip out the updateTranslation-based view code and replace it with proper new-model code, that code will use the new resetCurrentTranslation.

You will see a few things in this branch that may shock you, dear reviewer:

1. old_resetCurrentTranslation is _not_ an acceptable method name.

2. There are no tests for old_resetCurrentTranslation.

How do I look myself in the mirror? Well, I feel it all makes sense if you'll give me a chance to explain.

First, we want old_resetCurrentTranslation to die. Quickly and painlessly, but die nonetheless. The more it stands out as a Thing That Should Not Be™, the less likely it is that we'll be forgetting to get rid of it, or uncertain about whether it can be cleaned out, or using it in more places, or tolerating its presence. So in this case, a bad name is a good one.

Second, we want old_resetCurrentTranslation to die. It has but a single callsite, and that needs to be completely rewritten. The only reason to keep the old method around is to satisfy existing tests until we can get the new model in place. In a shameless reversal of the normal relationships between working code and tests, the acceptance tests are what we really want to preserve here and old_resetCurrentTranslation is there only to make sure that we can. If future changes required this method to stand on its head and recite Shakespeare in order for the view tests to pass, I would happily make it do that—without a single unit test—and still sleep well at night.

With that I conclude my case. I hope I managed to convey the fact that we want old_resetCurrentTranslation to die. And if anything, we are the victims here. Trust us.

To test:
{{{
./bin/test -vvc -m lp.translations.tests.test_potmsgset
./bin/test -vvc -m lp.translations -t pofile-translate-needs-review-flags-preserved
}}}

No lint left, apart from a few pre-existing complaints about comments surrounded by blank lines. In all of the cases I didn't fix, I felt the code had a legitimate need for creative license. Plus, I don't want to avoid _too_ many conflicts with other people's ongoing work!

Jeroen

To post a comment you must log in.
Revision history for this message
Michael Nelson (michael.nelson) wrote :
Download full text (4.0 KiB)

Heh... I enjoyed reading your MP description :)

And yes, I've been in that position before too... the one case (a transition to new infrastructure) where a bad name is a good one.

I've just got one question below about "the other side". But r=me. And great tests :)

> === modified file 'lib/lp/translations/browser/translationmessage.py'
> --- lib/lp/translations/browser/translationmessage.py 2010-08-23 08:35:29 +0000
> +++ lib/lp/translations/browser/translationmessage.py 2010-08-26 10:24:07 +0000
> @@ -300,16 +299,16 @@
>
> if self.request.method == 'POST':
> if self.user is None:
> - raise UnexpectedFormData, (
> - 'Anonymous users or users who are not accepting our '
> - 'licensing terms cannot do POST submissions.')
> + raise UnexpectedFormData(
> + "Anonymous users or users who are not accepting our "
> + "licensing terms cannot do POST submissions.")

Out of interest, is switching to double-quotes by default a personal
preference or a new LP coding recommendation?

> === modified file 'lib/lp/translations/model/potmsgset.py'
> --- lib/lp/translations/model/potmsgset.py 2010-08-24 11:39:06 +0000
> +++ lib/lp/translations/model/potmsgset.py 2010-08-26 10:24:07 +0000
> @@ -1295,25 +1295,47 @@
>
> return message
>
> - def resetCurrentTranslation(self, pofile, lock_timestamp):
> - """See `IPOTMsgSet`."""
> -
> - assert(lock_timestamp is not None)
> -
> + def old_resetCurrentTranslation(self, pofile, lock_timestamp):
> + """See `POTMsgSet`.
> +
> + This message is OBSOLETE in the Recife feature branch. It's
> + still here only until we replace its one call with the new
> + method.
> + """
> + assert lock_timestamp is not None, "No lock timestamp given."
> current = self.getCurrentTranslationMessage(
> pofile.potemplate, pofile.language)
> -
> - if (current is not None):
> - # Check for translation conflicts and update the required
> - # attributes.
> - self._maybeRaiseTranslationConflict(current, lock_timestamp)
> - current.is_current_ubuntu = False
> - # Converge the current translation only if it is diverged and not
> - # current upstream.
> - is_diverged = current.potemplate is not None
> - if is_diverged and not current.is_current_upstream:
> - current.potemplate = None
> - pofile.date_changed = UTC_NOW
> + if current is None:
> + return

Nice... I prefer guard code like this too :)

> +
> + # Check for translation conflicts and update the required
> + # attributes.
> + self._maybeRaiseTranslationConflict(current, lock_timestamp)
> + current.is_current_ubuntu = False
> + # Converge the current translation only if it is diverged and
> + # not current upstream.
> + if current.is_diverged and not current.is_current_upstream:
> + current.potemplate = None
> + pofile.markChanged()
> +
> + def resetCurrentTranslation(...

Read more...

review: Approve (code)
Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :
Download full text (3.4 KiB)

Thanks for the review, and glad you enjoyed the MP. :)

> > === modified file 'lib/lp/translations/browser/translationmessage.py'
> > --- lib/lp/translations/browser/translationmessage.py 2010-08-23 08:35:29
> +0000
> > +++ lib/lp/translations/browser/translationmessage.py 2010-08-26 10:24:07
> +0000
> > @@ -300,16 +299,16 @@
> >
> > if self.request.method == 'POST':
> > if self.user is None:
> > - raise UnexpectedFormData, (
> > - 'Anonymous users or users who are not accepting our '
> > - 'licensing terms cannot do POST submissions.')
> > + raise UnexpectedFormData(
> > + "Anonymous users or users who are not accepting our "
> > + "licensing terms cannot do POST submissions.")
>
> Out of interest, is switching to double-quotes by default a personal
> preference or a new LP coding recommendation?

Personal preference. But I do think it's sensible for free-form text where an apostrophe would be perfectly appropriate. IIRC one of these strings even went so far as to backslash-escape an apostrophe. For God's sake, why!?

Personally I use single quotes (to minimize "ink on the page") for identifiers and such, where an apostrophe would not be appropriate, or for empty strings and things close to it.

> > === modified file 'lib/lp/translations/model/potmsgset.py'
> > --- lib/lp/translations/model/potmsgset.py 2010-08-24 11:39:06 +0000
> > +++ lib/lp/translations/model/potmsgset.py 2010-08-26 10:24:07 +0000

> > +
> > + # Check for translation conflicts and update the required
> > + # attributes.
> > + self._maybeRaiseTranslationConflict(current, lock_timestamp)
> > + current.is_current_ubuntu = False
> > + # Converge the current translation only if it is diverged and
> > + # not current upstream.
> > + if current.is_diverged and not current.is_current_upstream:
> > + current.potemplate = None
> > + pofile.markChanged()
> > +
> > + def resetCurrentTranslation(self, pofile, lock_timestamp=None,
> > + share_with_other_side=False):
>
> OK, I forgot to mention this on the IFace declaration, but I have no idea what
> the other side is (maybe the interface description could say a bit more to
> cater for non-translation folk?). From your tests, it looks like it is
> upstream/downstream?

Pretty much, yes: "project" and "Ubuntu." A TranslationMessage is selected as current on the "project" side if it has the is_current_upstream flag set, and on the Ubuntu side if it has the is_current_ubuntu flag set. See lp.translations.interfaces.side.

> > + """See `IPOTMsgSet`."""
> > + traits = getUtility(ITranslationSideTraitsSet).getTraits(
> > + pofile.potemplate.translation_side)
> > + current_message = traits.getCurrentMessage(
> > + self, pofile.potemplate, pofile.language)
> > +
> > + if current_message is None:
> > + # Nothing to do here.
>
> Is this an error? If a reset is called on a translation that doesn't yet have
> a translation? I'm sure you've though...

Read more...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/translations/browser/translationmessage.py'
2--- lib/lp/translations/browser/translationmessage.py 2010-08-23 08:35:29 +0000
3+++ lib/lp/translations/browser/translationmessage.py 2010-08-26 09:18:44 +0000
4@@ -1,4 +1,4 @@
5-# Copyright 2009 Canonical Ltd. This software is licensed under the
6+# Copyright 2009-2010 Canonical Ltd. This software is licensed under the
7 # GNU Affero General Public License version 3 (see the file LICENSE).
8
9 # pylint: disable-msg=W0404
10@@ -25,7 +25,6 @@
11 import re
12 import urllib
13
14-import gettextpo
15 import pytz
16 from z3c.ptcompat import ViewPageTemplateFile
17 from zope import datetime as zope_datetime
18@@ -300,16 +299,16 @@
19
20 if self.request.method == 'POST':
21 if self.user is None:
22- raise UnexpectedFormData, (
23- 'Anonymous users or users who are not accepting our '
24- 'licensing terms cannot do POST submissions.')
25+ raise UnexpectedFormData(
26+ "Anonymous users or users who are not accepting our "
27+ "licensing terms cannot do POST submissions.")
28 translations_person = ITranslationsPerson(self.user)
29 if (translations_person.translations_relicensing_agreement
30 is not None and
31 not translations_person.translations_relicensing_agreement):
32- raise UnexpectedFormData, (
33- 'Users who do not agree to licensing terms '
34- 'cannot do POST submissions.')
35+ raise UnexpectedFormData(
36+ "Users who do not agree to licensing terms "
37+ "cannot do POST submissions.")
38 try:
39 # Try to get the timestamp when the submitted form was
40 # created. We use it to detect whether someone else updated
41@@ -320,9 +319,9 @@
42 except zope_datetime.DateTimeError:
43 # invalid format. Either we don't have the timestamp in the
44 # submitted form or it has the wrong format.
45- raise UnexpectedFormData, (
46- 'We didn\'t find the timestamp that tells us when was'
47- ' generated the submitted form.')
48+ raise UnexpectedFormData(
49+ "We didn't find the timestamp that tells us when was"
50+ " generated the submitted form.")
51
52 # Check if this is really the form we are listening for..
53 if self.request.form.get("submit_translations"):
54@@ -436,13 +435,14 @@
55 force_suggestion=force_suggestion,
56 force_diverged=force_diverge)
57
58- # If suggestions were forced and user has the rights to do it,
59- # reset the current translation.
60 empty_suggestions = self._areSuggestionsEmpty(translations)
61 if (force_suggestion and
62 self.user_is_official_translator and
63 empty_suggestions):
64- potmsgset.resetCurrentTranslation(
65+ # The user requested that the message be reviewed,
66+ # without suggesting a new translation. Reset the
67+ # current translation so that it can be reviewed again.
68+ potmsgset.old_resetCurrentTranslation(
69 self.pofile, self.lock_timestamp)
70
71 except TranslationConflict:
72@@ -1481,7 +1481,6 @@
73 return "%s_dismissable_button" % self.html_id
74
75
76-
77 class CurrentTranslationMessageZoomedView(CurrentTranslationMessageView):
78 """A view that displays a `TranslationMessage`, but zoomed in.
79
80@@ -1515,7 +1514,6 @@
81 # Pseudo-content class
82 #
83
84-
85 class TranslationMessageSuggestions:
86 """See `ITranslationMessageSuggestions`."""
87
88@@ -1563,6 +1561,7 @@
89 class Submission:
90 """A submission generated from a TranslationMessage"""
91
92+
93 def convert_translationmessage_to_submission(
94 message, current_message, plural_form, pofile, legal_warning_needed,
95 is_empty=False, packaged=False):
96
97=== modified file 'lib/lp/translations/interfaces/potmsgset.py'
98--- lib/lp/translations/interfaces/potmsgset.py 2010-08-24 11:39:06 +0000
99+++ lib/lp/translations/interfaces/potmsgset.py 2010-08-26 09:18:44 +0000
100@@ -298,16 +298,29 @@
101 that this change is based on.
102 """
103
104- def resetCurrentTranslation(pofile, lock_timestamp):
105- """Reset the currently used translation.
106-
107- This will set the "is_current_ubuntu" attribute to False and if the
108- message is diverged, will try to converge it.
109- :param pofile: a `POFile` to dismiss suggestions from.
110- :param lock_timestamp: the timestamp when we checked the values we
111- want to update.
112-
113- If a translation conflict is detected, TranslationConflict is raised.
114+ def old_resetCurrentTranslation(pofile, lock_timestamp):
115+ """Reset a translation.
116+
117+ OBSOLETE in Recife. In the new model, use the new
118+ `resetCurrentTranslation` implementation instead.
119+ """
120+
121+ def resetCurrentTranslation(pofile, lock_timestamp=None,
122+ share_with_other_side=False):
123+ """Turn the current translation back into a suggestion.
124+
125+ This deactivates the message's current translation. The message
126+ becomes untranslated or, if it was diverged, reverts to its
127+ shared translation.
128+
129+ The previously current translation becomes visible as a new
130+ suggestion again, as do all suggestions that came after it.
131+
132+ :param pofile: The `POFile` to make the change in.
133+ :param lock_timestamp: Timestamp of the original translation state
134+ that this change is based on.
135+ :param share_with_other_side: Make the same change on the other
136+ translation side.
137 """
138
139 def clearCurrentTranslation(pofile, submitter, origin,
140
141=== modified file 'lib/lp/translations/model/potmsgset.py'
142--- lib/lp/translations/model/potmsgset.py 2010-08-24 11:39:06 +0000
143+++ lib/lp/translations/model/potmsgset.py 2010-08-26 09:18:44 +0000
144@@ -1295,25 +1295,47 @@
145
146 return message
147
148- def resetCurrentTranslation(self, pofile, lock_timestamp):
149- """See `IPOTMsgSet`."""
150-
151- assert(lock_timestamp is not None)
152-
153+ def old_resetCurrentTranslation(self, pofile, lock_timestamp):
154+ """See `POTMsgSet`.
155+
156+ This message is OBSOLETE in the Recife feature branch. It's
157+ still here only until we replace its one call with the new
158+ method.
159+ """
160+ assert lock_timestamp is not None, "No lock timestamp given."
161 current = self.getCurrentTranslationMessage(
162 pofile.potemplate, pofile.language)
163-
164- if (current is not None):
165- # Check for translation conflicts and update the required
166- # attributes.
167- self._maybeRaiseTranslationConflict(current, lock_timestamp)
168- current.is_current_ubuntu = False
169- # Converge the current translation only if it is diverged and not
170- # current upstream.
171- is_diverged = current.potemplate is not None
172- if is_diverged and not current.is_current_upstream:
173- current.potemplate = None
174- pofile.date_changed = UTC_NOW
175+ if current is None:
176+ return
177+
178+ # Check for translation conflicts and update the required
179+ # attributes.
180+ self._maybeRaiseTranslationConflict(current, lock_timestamp)
181+ current.is_current_ubuntu = False
182+ # Converge the current translation only if it is diverged and
183+ # not current upstream.
184+ if current.is_diverged and not current.is_current_upstream:
185+ current.potemplate = None
186+ pofile.markChanged()
187+
188+ def resetCurrentTranslation(self, pofile, lock_timestamp=None,
189+ share_with_other_side=False):
190+ """See `IPOTMsgSet`."""
191+ traits = getUtility(ITranslationSideTraitsSet).getTraits(
192+ pofile.potemplate.translation_side)
193+ current_message = traits.getCurrentMessage(
194+ self, pofile.potemplate, pofile.language)
195+
196+ if current_message is None:
197+ # Nothing to do here.
198+ return
199+
200+ self._checkForConflict(current_message, lock_timestamp)
201+ traits.setFlag(current_message, False)
202+ if share_with_other_side:
203+ traits.other_side_traits.setFlag(current_message, False)
204+ current_message.shareIfPossible()
205+ pofile.markChanged()
206
207 def clearCurrentTranslation(self, pofile, submitter, origin,
208 share_with_other_side=False,
209
210=== modified file 'lib/lp/translations/tests/test_potmsgset.py'
211--- lib/lp/translations/tests/test_potmsgset.py 2010-08-24 11:39:06 +0000
212+++ lib/lp/translations/tests/test_potmsgset.py 2010-08-26 09:18:44 +0000
213@@ -31,6 +31,7 @@
214 POTMsgSetInIncompatibleTemplatesError,
215 TranslationCreditsType,
216 )
217+from lp.translations.interfaces.side import ITranslationSideTraitsSet
218 from lp.translations.interfaces.translationfileformat import (
219 TranslationFileFormat,
220 )
221@@ -943,6 +944,12 @@
222 yield now
223 now += timedelta(milliseconds=1)
224
225+ def _getCurrentMessage(self):
226+ traits = getUtility(ITranslationSideTraitsSet).getTraits(
227+ self.potemplate.translation_side)
228+ return traits.getCurrentMessage(
229+ self.potmsgset, self.potemplate, self.pofile.language)
230+
231 def setUp(self):
232 # Create a product with all the boilerplate objects to be able to
233 # create TranslationMessage objects.
234@@ -960,59 +967,117 @@
235 self.pofile = self.factory.makePOFile('eo', template)
236
237 def test_resetCurrentTranslation_shared(self):
238- # Resetting a shared current translation will change iscurrent=False
239- # and there will be no other current translations for this POTMsgSet.
240-
241- translation = self.factory.makeTranslationMessage(
242- self.pofile, self.potmsgset, translations=[u'Shared translation'],
243- reviewer=self.factory.makePerson(),
244- is_current_upstream=False, force_diverged=False,
245- date_updated=self.now())
246-
247- self.potmsgset.resetCurrentTranslation(self.pofile, self.now())
248- current = self.potmsgset.getCurrentTranslationMessage(
249- self.potemplate, self.pofile.language)
250+ # Resetting a shared current translation deactivates it, and
251+ # leaves no other current translation in its place.
252+ translation = self.factory.makeCurrentTranslationMessage(
253+ pofile=self.pofile, potmsgset=self.potmsgset)
254+
255+ self.potmsgset.resetCurrentTranslation(self.pofile)
256+
257+ current = self._getCurrentMessage()
258 self.assertTrue(current is None)
259 self.assertFalse(translation.is_current_ubuntu)
260 self.assertFalse(translation.is_current_upstream)
261- self.assertTrue(translation.potemplate is None)
262+ self.assertFalse(translation.is_diverged)
263
264 def test_resetCurrentTranslation_diverged_not_imported(self):
265- # Resetting a diverged current translation that was not
266- # imported, will change is_current_ubuntu to False and will make
267- # it shared.
268- translation = self.factory.makeTranslationMessage(
269- self.pofile, self.potmsgset, translations=[u'Diverged text'],
270- reviewer=self.factory.makePerson(),
271- is_current_upstream=False, force_diverged=True,
272- date_updated=self.now())
273-
274- self.potmsgset.resetCurrentTranslation(self.pofile, self.now())
275- current = self.potmsgset.getCurrentTranslationMessage(
276- self.potemplate, self.pofile.language)
277+ # Resetting a diverged current translation disables it and makes
278+ # it shared. In other words, it becomes a suggestion.
279+ translation = self.factory.makeCurrentTranslationMessage(
280+ pofile=self.pofile, potmsgset=self.potmsgset)
281+
282+ self.potmsgset.resetCurrentTranslation(self.pofile)
283+
284+ current = self._getCurrentMessage()
285 self.assertTrue(current is None)
286 self.assertFalse(translation.is_current_ubuntu)
287 self.assertFalse(translation.is_current_upstream)
288- self.assertTrue(translation.potemplate is None)
289-
290- def test_resetCurrentTranslation_diverged_imported(self):
291- # Resetting a diverged current translation that was imported in
292- # Launchpad will change iscurrent to False but the translation
293- # message will be still diverged.
294-
295- translation = self.factory.makeTranslationMessage(
296- self.pofile, self.potmsgset, translations=[u'Imported diverged'],
297- reviewer=self.factory.makePerson(),
298- is_current_upstream=True, force_diverged=True,
299- date_updated=self.now())
300-
301- self.potmsgset.resetCurrentTranslation(self.pofile, self.now())
302- current = self.potmsgset.getCurrentTranslationMessage(
303- self.potemplate, self.pofile.language)
304- self.assertTrue(current is None)
305- self.assertFalse(translation.is_current_ubuntu)
306- self.assertTrue(translation.is_current_upstream)
307- self.assertFalse(translation.potemplate is None)
308+ self.assertFalse(translation.is_diverged)
309+
310+ def test_resetCurrentTranslation_unmasks_shared(self):
311+ # Resetting a diverged translation reverts the POTMsgSet to its
312+ # current shared translation.
313+ shared = self.factory.makeCurrentTranslationMessage(
314+ pofile=self.pofile, potmsgset=self.potmsgset)
315+ diverged = self.factory.makeDivergedTranslationMessage(
316+ pofile=self.pofile, potmsgset=self.potmsgset)
317+
318+ self.assertNotEqual(shared, diverged)
319+ self.assertTrue(diverged.is_current_upstream)
320+ self.assertTrue(shared.is_current_upstream)
321+ self.assertEqual(diverged, self._getCurrentMessage())
322+
323+ self.potmsgset.resetCurrentTranslation(self.pofile)
324+
325+ self.assertEqual(shared, self._getCurrentMessage())
326+
327+ def test_resetCurrentTranslation_resets_one_side(self):
328+ # By default, resetting a translation works only on one
329+ # translation side.
330+ current = self.factory.makeCurrentTranslationMessage(
331+ pofile=self.pofile, potmsgset=self.potmsgset, current_other=True)
332+ traits = getUtility(ITranslationSideTraitsSet).getTraits(
333+ self.potemplate.translation_side)
334+
335+ self.assertTrue(traits.getFlag(current))
336+ self.assertTrue(traits.other_side_traits.getFlag(current))
337+
338+ self.potmsgset.resetCurrentTranslation(
339+ self.pofile, share_with_other_side=False)
340+
341+ self.assertFalse(traits.getFlag(current))
342+ self.assertTrue(traits.other_side_traits.getFlag(current))
343+
344+ def test_resetCurrentTranslation_resets_both_sides(self):
345+ # The share_with_other_side parameter lets you reset a current
346+ # translation on both translation sides.
347+ current = self.factory.makeCurrentTranslationMessage(
348+ pofile=self.pofile, potmsgset=self.potmsgset, current_other=True)
349+
350+ self.assertTrue(current.is_current_upstream)
351+ self.assertTrue(current.is_current_ubuntu)
352+
353+ self.potmsgset.resetCurrentTranslation(
354+ self.pofile, share_with_other_side=True)
355+
356+ self.assertFalse(current.is_current_upstream)
357+ self.assertFalse(current.is_current_ubuntu)
358+
359+ def test_resetCurrentTranslation_does_not_override_other_message(self):
360+ # Resetting a message does not reset the current translation on
361+ # the other translation side if it's not the same one as on this
362+ # side.
363+ self.assertIs(None, self.potemplate.distroseries)
364+ other_potemplate = self.factory.makePOTemplate(
365+ distroseries=self.factory.makeDistroSeries(),
366+ sourcepackagename=self.factory.makeSourcePackageName())
367+ other_pofile = self.factory.makePOFile(
368+ self.pofile.language.code, potemplate=other_potemplate)
369+
370+ message_this = self.factory.makeCurrentTranslationMessage(
371+ pofile=self.pofile, potmsgset=self.potmsgset)
372+ message_other = self.factory.makeCurrentTranslationMessage(
373+ pofile=other_pofile, potmsgset=self.potmsgset)
374+ traits = getUtility(ITranslationSideTraitsSet).getTraits(
375+ self.potemplate.translation_side)
376+
377+ self.assertTrue(traits.other_side_traits.getFlag(message_other))
378+
379+ self.potmsgset.resetCurrentTranslation(
380+ self.pofile, share_with_other_side=True)
381+
382+ self.assertTrue(traits.other_side_traits.getFlag(message_other))
383+
384+ def test_resetCurrentTranslation_detects_conflict(self):
385+ now = self.now()
386+ current = self.factory.makeCurrentTranslationMessage(
387+ pofile=self.pofile, potmsgset=self.potmsgset)
388+ current.markReviewed(self.factory.makePerson(), now)
389+
390+ self.assertRaises(
391+ TranslationConflict,
392+ self.potmsgset.resetCurrentTranslation,
393+ self.pofile, now - timedelta(1))
394
395
396 class TestPOTMsgSetCornerCases(TestCaseWithFactory):
397@@ -1587,8 +1652,7 @@
398 def _makeTranslations(self, potmsgset, forms=1):
399 return removeSecurityProxy(potmsgset)._findPOTranslations([
400 self.factory.getUniqueString()
401- for counter in xrange(forms)
402- ])
403+ for counter in xrange(forms)])
404
405 def test_baseline(self):
406 # setCurrentTranslation sets the current upstream translation

Subscribers

People subscribed via source and target branches